packages feed

genvalidity-mergeful 0.3.0.0 → 0.3.0.1

raw patch · 21 files changed

+552/−80 lines, 21 filesdep +autodocodecdep +autodocodec-yamldep +genvalidity-sydtestdep −genvalidity-hspecdep −genvalidity-hspec-aesondep −hspec

Dependencies added: autodocodec, autodocodec-yaml, genvalidity-sydtest, genvalidity-sydtest-aeson, safe-coloured-text, sydtest

Dependencies removed: genvalidity-hspec, genvalidity-hspec-aeson, hspec

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Changelog +## [0.3.0.1] - 2021-11-21++### Changed++* Compatibility with `GHC >= 9.8`+ ## [0.3.0.0] - 2021-11-21  ### Changed
genvalidity-mergeful.cabal view
@@ -1,24 +1,38 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.35.2. -- -- see: https://github.com/sol/hpack ----- hash: 218b3a60cb86fcedf2942fea48c5ee2dc351c552cd48ca944629761753bfc87b+-- hash: 394bb132a6d5e5a2cd9ef618e33cf81ac04d73a31dbd27e092e4fb732170f2af  name:           genvalidity-mergeful-version:        0.3.0.0+version:        0.3.0.1 description:    Please see the README on GitHub at <https://github.com/NorfairKing/mergeful#readme> homepage:       https://github.com/NorfairKing/mergeful#readme bug-reports:    https://github.com/NorfairKing/mergeful/issues author:         Tom Sydney Kerckhove maintainer:     syd@cs-syd.eu-copyright:      Copyright: (c) 2019-2021 Tom Sydney Kerckhove+copyright:      Copyright: (c) 2019-2023 Tom Sydney Kerckhove license:        MIT license-file:   LICENSE build-type:     Simple extra-source-files:     CHANGELOG.md+    test_resources/collection/client-addition.txt+    test_resources/collection/client-id.txt+    test_resources/collection/client-store.txt+    test_resources/collection/request.txt+    test_resources/collection/response.txt+    test_resources/collection/server-store.txt+    test_resources/item/client.txt+    test_resources/item/request.txt+    test_resources/item/response.txt+    test_resources/item/server.txt+    test_resources/value/client.txt+    test_resources/value/request.txt+    test_resources/value/response.txt+    test_resources/value/server.txt  source-repository head   type: git@@ -57,19 +71,24 @@   hs-source-dirs:       test   ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-tool-depends:+      sydtest-discover:sydtest-discover   build-depends:       QuickCheck+    , autodocodec+    , autodocodec-yaml     , base <5     , containers-    , genvalidity-hspec-    , genvalidity-hspec-aeson     , genvalidity-mergeful+    , genvalidity-sydtest+    , genvalidity-sydtest-aeson     , genvalidity-uuid-    , hspec     , mergeful     , mtl     , pretty-show     , random+    , safe-coloured-text+    , sydtest     , time     , uuid   default-language: Haskell2010
test/Data/Mergeful/CollectionSpec.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RankNTypes #-}@@ -10,7 +11,11 @@   ) where +import Autodocodec+import Autodocodec.Yaml+import Control.Monad import Control.Monad.State+import Data.Data import Data.Functor.Identity import Data.GenValidity.Mergeful () import Data.GenValidity.Mergeful.Item ()@@ -20,31 +25,52 @@ import Data.Mergeful import qualified Data.Set as S import Data.UUID+import Data.Word import GHC.Generics (Generic) import System.Random-import Test.Hspec-import Test.Hspec.QuickCheck import Test.QuickCheck-import Test.Validity-import Test.Validity.Aeson-import Text.Show.Pretty+import Test.Syd hiding (Timed (..))+import Test.Syd.Validity+import Test.Syd.Validity.Aeson+import Test.Syd.Validity.Utils+import Text.Colour  {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}  spec :: Spec spec = modifyMaxShrinks (min 0) $ do-  genValidSpec @ClientId-  jsonSpec @ClientId-  genValidSpec @(ClientStore ClientId Int Int)-  jsonSpec @(ClientStore ClientId Int Int)-  genValidSpec @(ServerStore Int Int)-  jsonSpec @(ServerStore Int Int)-  genValidSpec @(SyncRequest ClientId Int Int)-  jsonSpec @(SyncRequest ClientId Int Int)-  genValidSpec @(ClientAddition Int)-  jsonSpec @(ClientAddition Int)-  genValidSpec @(SyncResponse ClientId Int Int)-  jsonSpec @(SyncResponse ClientId Int Int)+  let yamlSchemaSpec :: forall a. (Typeable a, GenValid a, HasCodec a) => FilePath -> Spec+      yamlSchemaSpec filePath = do+        it ("outputs the same schema as before for " <> nameOf @a) $+          pureGoldenTextFile+            ("test_resources/collection/" <> filePath <> ".txt")+            (renderChunksText With24BitColours $ schemaChunksViaCodec @a)++  describe "ClientId" $ do+    genValidSpec @ClientId+    jsonSpec @ClientId+    yamlSchemaSpec @ClientId "client-id"+  describe "ClientStore" $ do+    genValidSpec @(ClientStore ClientId Word8 Word8)+    jsonSpec @(ClientStore ClientId Word8 Word8)+    yamlSchemaSpec @(ClientStore ClientId Word8 Word8) "client-store"+  describe "ServerStore" $ do+    genValidSpec @(ServerStore Word8 Word8)+    jsonSpec @(ServerStore Word8 Word8)+    yamlSchemaSpec @(ServerStore Word8 Word8) "server-store"+  describe "SyncRequest" $ do+    genValidSpec @(SyncRequest ClientId Word8 Word8)+    jsonSpec @(SyncRequest ClientId Word8 Word8)+    yamlSchemaSpec @(SyncRequest ClientId Word8 Word8) "request"+  describe "ClientAddition" $ do+    genValidSpec @(ClientAddition Word8)+    jsonSpec @(ClientAddition Word8)+    yamlSchemaSpec @(ClientAddition Word8) "client-addition"+  describe "SyncResponse" $ do+    genValidSpec @(SyncResponse ClientId Word8 Word8)+    jsonSpec @(SyncResponse ClientId Word8 Word8)+    yamlSchemaSpec @(SyncResponse ClientId Word8 Word8) "response"+   describe "initialClientStore" $     it "is valid" $       shouldBeValid $@@ -722,20 +748,20 @@                         not (S.null syncResponseConflictsServerDeleted)                       ]                   )-                  $ expectationFailure $-                    unlines-                      [ "There was a difference between mergeFunc1 and mergeFunc2 that was somehow unrelated to the conflicts:",-                        "syncResponseConflicts:",-                        ppShow syncResponseConflicts,-                        "syncResponseConflictsClientDeleted:",-                        ppShow syncResponseConflictsClientDeleted,-                        "syncResponseConflictsServerDeleted:",-                        ppShow syncResponseConflictsServerDeleted,-                        "client store after mergeFunc1:",-                        ppShow cstoreA,-                        "client store after mergeFunc2:",-                        ppShow cstoreB-                      ]+                  $ expectationFailure+                  $ unlines+                    [ "There was a difference between mergeFunc1 and mergeFunc2 that was somehow unrelated to the conflicts:",+                      "syncResponseConflicts:",+                      ppShow syncResponseConflicts,+                      "syncResponseConflictsClientDeleted:",+                      ppShow syncResponseConflictsClientDeleted,+                      "syncResponseConflictsServerDeleted:",+                      ppShow syncResponseConflictsServerDeleted,+                      "client store after mergeFunc1:",+                      ppShow cstoreA,+                      "client store after mergeFunc2:",+                      ppShow cstoreB+                    ]  newtype D m a = D   { unD :: StateT StdGen m a
test/Data/Mergeful/ItemSpec.hs view
@@ -1,4 +1,6 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}  module Data.Mergeful.ItemSpec@@ -6,13 +8,19 @@   ) where +import Autodocodec+import Autodocodec.Yaml+import Data.Data import Data.GenValidity.Mergeful.Item () import Data.Mergeful.Item import Data.Mergeful.Timed-import Test.Hspec+import Data.Word import Test.QuickCheck-import Test.Validity-import Test.Validity.Aeson+import Test.Syd hiding (Timed (..))+import Test.Syd.Validity+import Test.Syd.Validity.Aeson+import Test.Syd.Validity.Utils+import Text.Colour  {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} @@ -23,14 +31,28 @@  spec :: Spec spec = do-  genValidSpec @(ClientItem Int)-  jsonSpec @(ClientItem Int)-  genValidSpec @(ServerItem Int)-  jsonSpec @(ServerItem Int)-  genValidSpec @(ItemSyncRequest Int)-  jsonSpec @(ItemSyncRequest Int)-  genValidSpec @(ItemSyncResponse Int)-  jsonSpec @(ItemSyncResponse Int)+  let yamlSchemaSpec :: forall a. (Typeable a, GenValid a, HasCodec a) => FilePath -> Spec+      yamlSchemaSpec filePath = do+        it ("outputs the same schema as before for " <> nameOf @a) $+          pureGoldenTextFile+            ("test_resources/item/" <> filePath <> ".txt")+            (renderChunksText With24BitColours $ schemaChunksViaCodec @a)+  describe "ClientItem" $ do+    genValidSpec @(ClientItem Word8)+    jsonSpec @(ClientItem Word8)+    yamlSchemaSpec @(ClientItem Word8) "client"+  describe "ServerItem" $ do+    genValidSpec @(ServerItem Word8)+    jsonSpec @(ServerItem Word8)+    yamlSchemaSpec @(ServerItem Word8) "server"+  describe "ItemSyncRequest" $ do+    genValidSpec @(ItemSyncRequest Word8)+    jsonSpec @(ItemSyncRequest Word8)+    yamlSchemaSpec @(ItemSyncRequest Word8) "request"+  describe "ItemSyncResponse" $ do+    genValidSpec @(ItemSyncResponse Word8)+    jsonSpec @(ItemSyncResponse Word8)+    yamlSchemaSpec @(ItemSyncResponse Word8) "response"   describe "makeItemSyncRequest" $     it "produces valid requests" $       producesValid (makeItemSyncRequest @Int)@@ -133,24 +155,24 @@                 resp `shouldBe` ItemSyncResponseConflict (Timed i st')       it         "notices a server-deleted-conflict if the client has a deleted item and server has a modified item"-        $ forAllValid $-          \i ->-            forAllSubsequent $ \(st, st') -> do-              let store1 = ServerFull (Timed i st')-                  req = ItemSyncRequestDeletedLocally st-              let (resp, store2) = processServerItemSync @Int store1 req-              store2 `shouldBe` store1-              resp `shouldBe` ItemSyncResponseConflictClientDeleted (Timed i st')+        $ forAllValid+        $ \i ->+          forAllSubsequent $ \(st, st') -> do+            let store1 = ServerFull (Timed i st')+                req = ItemSyncRequestDeletedLocally st+            let (resp, store2) = processServerItemSync @Int store1 req+            store2 `shouldBe` store1+            resp `shouldBe` ItemSyncResponseConflictClientDeleted (Timed i st')       it         "notices a server-deleted-conflict if the client has a modified item and server has no item"-        $ forAllValid $-          \i ->-            forAllValid $ \st -> do-              let store1 = ServerEmpty-                  req = ItemSyncRequestKnownButChanged (Timed i st)-              let (resp, store2) = processServerItemSync @Int store1 req-              store2 `shouldBe` store1-              resp `shouldBe` ItemSyncResponseConflictServerDeleted+        $ forAllValid+        $ \i ->+          forAllValid $ \st -> do+            let store1 = ServerEmpty+                req = ItemSyncRequestKnownButChanged (Timed i st)+            let (resp, store2) = processServerItemSync @Int store1 req+            store2 `shouldBe` store1+            resp `shouldBe` ItemSyncResponseConflictServerDeleted   describe "syncing" $ do     describe "fromServer" $ do       syncingSpec @Int mergeFromServer
test/Data/Mergeful/TimedSpec.hs view
@@ -7,9 +7,9 @@  import Data.GenValidity.Mergeful.Item () import Data.Mergeful.Timed-import Test.Hspec-import Test.Validity-import Test.Validity.Aeson+import Test.Syd hiding (Timed (..))+import Test.Syd.Validity+import Test.Syd.Validity.Aeson  spec :: Spec spec = do
test/Data/Mergeful/ValueSpec.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}  module Data.Mergeful.ValueSpec@@ -5,13 +7,19 @@   ) where +import Autodocodec+import Autodocodec.Yaml+import Data.Data import Data.GenValidity.Mergeful.Value () import Data.Mergeful.Timed import Data.Mergeful.Value-import Test.Hspec+import Data.Word import Test.QuickCheck-import Test.Validity-import Test.Validity.Aeson+import Test.Syd hiding (Timed (..))+import Test.Syd.Validity+import Test.Syd.Validity.Aeson+import Test.Syd.Validity.Utils+import Text.Colour  {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} @@ -22,14 +30,30 @@  spec :: Spec spec = do-  genValidSpec @(ClientValue Int)-  jsonSpec @(ClientValue Int)-  genValidSpec @(ServerValue Int)-  jsonSpec @(ServerValue Int)-  genValidSpec @(ValueSyncRequest Int)-  jsonSpec @(ValueSyncRequest Int)-  genValidSpec @(ValueSyncResponse Int)-  jsonSpec @(ValueSyncResponse Int)+  let yamlSchemaSpec :: forall a. (Typeable a, GenValid a, HasCodec a) => FilePath -> Spec+      yamlSchemaSpec filePath = do+        it ("outputs the same schema as before for " <> nameOf @a) $+          pureGoldenTextFile+            ("test_resources/value/" <> filePath <> ".txt")+            (renderChunksText With24BitColours $ schemaChunksViaCodec @a)++  describe "ClientValue" $ do+    genValidSpec @(ClientValue Word8)+    jsonSpec @(ClientValue Word8)+    yamlSchemaSpec @(ClientValue Word8) "client"+  describe "ServerValue" $ do+    genValidSpec @(ServerValue Word8)+    jsonSpec @(ServerValue Word8)+    yamlSchemaSpec @(ServerValue Word8) "server"+  describe "ValueSyncRequest" $ do+    genValidSpec @(ValueSyncRequest Word8)+    jsonSpec @(ValueSyncRequest Word8)+    yamlSchemaSpec @(ValueSyncRequest Word8) "request"+  describe "ValueSyncResponse" $ do+    genValidSpec @(ValueSyncResponse Word8)+    jsonSpec @(ValueSyncResponse Word8)+    yamlSchemaSpec @(ValueSyncResponse Word8) "response"+   describe "makeValueSyncRequest" $     it "produces valid requests" $       producesValid (makeValueSyncRequest @Int)
test/Spec.hs view
@@ -1,1 +1,1 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+{-# OPTIONS_GHC -F -pgmF sydtest-discover #-}
+ test_resources/collection/client-addition.txt view
@@ -0,0 +1,8 @@+# ClientAddition+[37mid[m: # [31mrequired[m+  # client-side identifier+  [33m<number>[m # between [32m0[m and [32m255[m+[37mtime[m: # [31mrequired[m+  # server-side time+  # Server time+  [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+ test_resources/collection/client-id.txt view
@@ -0,0 +1,2 @@+# ClientId+[33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+ test_resources/collection/client-store.txt view
@@ -0,0 +1,36 @@+# ClientStore+[37madded[m: # [34moptional[m+  # default: [35m{}[m+  # added items+  [37m<key>[m: +    [33m<number>[m # between [32m0[m and [32m255[m+[37msynced[m: # [34moptional[m+  # default: [35m{}[m+  # synced items+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mchanged[m: # [34moptional[m+  # default: [35m{}[m+  # changed items+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mdeleted[m: # [34moptional[m+  # default: [35m{}[m+  # deleted items+  [37m<key>[m: +    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+ test_resources/collection/request.txt view
@@ -0,0 +1,30 @@+# SyncRequest+[37madded[m: # [34moptional[m+  # default: [35m{}[m+  # new items+  [37m<key>[m: +    [33m<number>[m # between [32m0[m and [32m255[m+[37msynced[m: # [34moptional[m+  # default: [35m{}[m+  # known items+  [37m<key>[m: +    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mchanged[m: # [34moptional[m+  # default: [35m{}[m+  # known but changed items+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mdeleted[m: # [34moptional[m+  # default: [35m{}[m+  # deleted items+  [37m<key>[m: +    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+ test_resources/collection/response.txt view
@@ -0,0 +1,79 @@+# SyncResponse+[37mclient-added[m: # [34moptional[m+  # default: [35m{}[m+  # items added by the client+  [37m<key>[m: +    # ClientAddition+    [37mid[m: # [31mrequired[m+      # client-side identifier+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # server-side time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mclient-changed[m: # [34moptional[m+  # default: [35m{}[m+  # items changed by the client+  [37m<key>[m: +    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mclient-deleted[m: # [34moptional[m+  # default: [35m[][m+  # items deleted by the client+  - [33m<number>[m # between [32m0[m and [32m255[m+[37mserver-added[m: # [34moptional[m+  # default: [35m{}[m+  # items added by the server+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mserver-changed[m: # [34moptional[m+  # default: [35m{}[m+  # items changed by the server+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mserver-deleted[m: # [34moptional[m+  # default: [35m[][m+  # items deleted by the server+  - [33m<number>[m # between [32m0[m and [32m255[m+[37mconflict[m: # [34moptional[m+  # default: [35m{}[m+  # items that were changed simultaneously+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mconflict-client-deleted[m: # [34moptional[m+  # default: [35m{}[m+  # items that the server changed while the client deleted it+  [37m<key>[m: +    # Timed+    [37mvalue[m: # [31mrequired[m+      # timed value+      [33m<number>[m # between [32m0[m and [32m255[m+    [37mtime[m: # [31mrequired[m+      # timed time+      # Server time+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mconflict-server-deleted[m: # [34moptional[m+  # default: [35m[][m+  # items that the client changed while the server deleted it+  - [33m<number>[m # between [32m0[m and [32m255[m
+ test_resources/collection/server-store.txt view
@@ -0,0 +1,9 @@+[37m<key>[m: +  # Timed+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+ test_resources/item/client.txt view
@@ -0,0 +1,35 @@+# ClientItem+# [32mone of[m+[ [37mtype[m: # [31mrequired[m+    empty+  <object>+, [37mtype[m: # [31mrequired[m+    added+  [37mvalue[m: # [31mrequired[m+    # item that was added, client-side+    [33m<number>[m # between [32m0[m and [32m255[m+, [37mtype[m: # [31mrequired[m+    synced+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    changed+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    deleted+  [37mtime[m: # [31mrequired[m+    # last time the server confirmed a change, from the client's perspective+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+]
+ test_resources/item/request.txt view
@@ -0,0 +1,32 @@+# ItemSyncRequest+# [32mone of[m+[ [37mtype[m: # [31mrequired[m+    empty+  <object>+, [37mtype[m: # [31mrequired[m+    added+  [37mvalue[m: # [31mrequired[m+    # item that was added, client-side+    [33m<number>[m # between [32m0[m and [32m255[m+, [37mtype[m: # [31mrequired[m+    synced+  [37mtime[m: # [31mrequired[m+    # last time the server confirmed a change, from the client's perspective+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    changed+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    deleted+  [37mtime[m: # [31mrequired[m+    # last time the server confirmed a change, from the client's perspective+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+]
+ test_resources/item/response.txt view
@@ -0,0 +1,66 @@+# ItemSyncResponse+# [32mone of[m+[ [37mtype[m: # [31mrequired[m+    in-sync-empty+  <object>+, [37mtype[m: # [31mrequired[m+    in-sync-full+  <object>+, [37mtype[m: # [31mrequired[m+    client-added+  [37mtime[m: # [31mrequired[m+    # server's confirmation of the addition+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    client-changed+  [37mtime[m: # [31mrequired[m+    # server's confirmation of the addition+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    client-deleted+  <object>+, [37mtype[m: # [31mrequired[m+    server-added+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    server-changed+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    server-deleted+  <object>+, [37mtype[m: # [31mrequired[m+    conflict+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    conflict-client-deleted+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    conflict-server-deleted+  <object>+]
+ test_resources/item/server.txt view
@@ -0,0 +1,11 @@+# ServerItem+# [32many of[m+[ [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, <object>+]
+ test_resources/value/client.txt view
@@ -0,0 +1,11 @@+# ClientValue+[37mvalue[m: # [31mrequired[m+  # timed value+  [33m<number>[m # between [32m0[m and [32m255[m+[37mtime[m: # [31mrequired[m+  # timed time+  # Server time+  [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+[37mchanged[m: # [31mrequired[m+  # whether the value has changed, client-side+  [33m<boolean>[m
+ test_resources/value/request.txt view
@@ -0,0 +1,18 @@+# ValueSyncRequest+# [32mone of[m+[ [37mtype[m: # [31mrequired[m+    synced+  [37mtime[m: # [31mrequired[m+    # time at which the server said the value was last synced+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    changed+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+]
+ test_resources/value/response.txt view
@@ -0,0 +1,30 @@+# ValueSyncResponse+# [32mone of[m+[ [37mtype[m: # [31mrequired[m+    in-sync+  <object>+, [37mtype[m: # [31mrequired[m+    client-changed+  [37mtime[m: # [31mrequired[m+    # server time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    server-changed+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+, [37mtype[m: # [31mrequired[m+    conflict+  [37mvalue[m: # [31mrequired[m+    # timed value+    [33m<number>[m # between [32m0[m and [32m255[m+  [37mtime[m: # [31mrequired[m+    # timed time+    # Server time+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m+]
+ test_resources/value/server.txt view
@@ -0,0 +1,8 @@+# ServerValue+[37mvalue[m: # [31mrequired[m+  # timed value+  [33m<number>[m # between [32m0[m and [32m255[m+[37mtime[m: # [31mrequired[m+  # timed time+  # Server time+  [33m<number>[m # between [32m0[m and [32m18446744073709551615[m