diff --git a/schema/kind.go b/schema/kind.go index e5457420149b..1aec2b62f407 100644 --- a/schema/kind.go +++ b/schema/kind.go @@ -79,6 +79,8 @@ const ( // Go Encoding: string which matches the IntegerFormat regex // JSON Encoding: base10 integer string // Canonically encoded values should include no leading zeros. + // Equality comparison with integers should be done using numerical equality rather + // than string equality. IntegerStringKind // DecimalStringKind represents an arbitrary precision decimal or integer number. @@ -87,6 +89,8 @@ const ( // Canonically encoded values should include no leading zeros or trailing zeros, // and exponential notation with a lowercase 'e' should be used for any numbers // with an absolute value less than or equal to 1e-6 or greater than or equal to 1e6. + // Equality comparison with decimals should be done using numerical equality rather + // than string equality. DecimalStringKind // BoolKind represents a boolean true or false value. @@ -369,6 +373,18 @@ func (t Kind) ValidateValue(value interface{}) error { return nil } +// ValidKeyKind returns true if the kind is a valid key kind. +// All kinds except Float32Kind, Float64Kind, and JSONKind are valid key kinds +// because they do not define a strict form of equality. +func (t Kind) ValidKeyKind() bool { + switch t { + case Float32Kind, Float64Kind, JSONKind: + return false + default: + return true + } +} + var ( integerRegex = regexp.MustCompile(IntegerFormat) decimalRegex = regexp.MustCompile(DecimalFormat) diff --git a/schema/object_type.go b/schema/object_type.go index 379d7d4a8382..6555faf39ac5 100644 --- a/schema/object_type.go +++ b/schema/object_type.go @@ -11,7 +11,9 @@ type ObjectType struct { // KeyFields is a list of fields that make up the primary key of the object. // It can be empty in which case indexers should assume that this object is // a singleton and only has one value. Field names must be unique within the - // object between both key and value fields. Key fields CANNOT be nullable. + // object between both key and value fields. + // Key fields CANNOT be nullable and Float32Kind, Float64Kind, and JSONKind types + // are not allowed. KeyFields []Field // ValueFields is a list of fields that are not part of the primary key of the object. @@ -53,6 +55,10 @@ func (o ObjectType) validate(types map[string]Type) error { return fmt.Errorf("invalid key field %q: %v", field.Name, err) //nolint:errorlint // false positive due to using go1.12 } + if !field.Kind.ValidKeyKind() { + return fmt.Errorf("key field %q of kind %q uses an invalid key field kind", field.Name, field.Kind) + } + if field.Nullable { return fmt.Errorf("key field %q cannot be nullable", field.Name) } diff --git a/schema/object_type_test.go b/schema/object_type_test.go index 68a85111b7b6..b6039b9eed60 100644 --- a/schema/object_type_test.go +++ b/schema/object_type_test.go @@ -189,6 +189,45 @@ func TestObjectType_Validate(t *testing.T) { }, errContains: "enum \"enum1\" has different values", }, + { + name: "float32 key field", + objectType: ObjectType{ + Name: "o1", + KeyFields: []Field{ + { + Name: "field1", + Kind: Float32Kind, + }, + }, + }, + errContains: "invalid key field kind", + }, + { + name: "float64 key field", + objectType: ObjectType{ + Name: "o1", + KeyFields: []Field{ + { + Name: "field1", + Kind: Float64Kind, + }, + }, + }, + errContains: "invalid key field kind", + }, + { + name: "json key field", + objectType: ObjectType{ + Name: "o1", + KeyFields: []Field{ + { + Name: "field1", + Kind: JSONKind, + }, + }, + }, + errContains: "invalid key field kind", + }, } for _, tt := range tests { diff --git a/schema/testing/appdatasim/app_data.go b/schema/testing/appdatasim/app_data.go index 2f6138bfe824..471cf5cb2b1f 100644 --- a/schema/testing/appdatasim/app_data.go +++ b/schema/testing/appdatasim/app_data.go @@ -8,6 +8,7 @@ import ( "cosmossdk.io/schema" "cosmossdk.io/schema/appdata" + schematesting "cosmossdk.io/schema/testing" "cosmossdk.io/schema/testing/statesim" "cosmossdk.io/schema/view" ) @@ -92,10 +93,10 @@ func (a *Simulator) BlockDataGenN(minUpdatesPerBlock, maxUpdatesPerBlock int) *r packets = append(packets, appdata.StartBlockData{Height: a.blockNum + 1}) updateSet := map[string]bool{} - // filter out any updates to the same key from this block, otherwise we can end up with weird errors + // filter out any updates to the same key from this block, otherwise we can end up with hard to debug errors updateGen := a.state.UpdateGen().Filter(func(data appdata.ObjectUpdateData) bool { for _, update := range data.Updates { - _, existing := updateSet[fmt.Sprintf("%s:%v", data.ModuleName, update.Key)] + _, existing := updateSet[a.formatUpdateKey(data.ModuleName, update)] if existing { return false } @@ -106,7 +107,8 @@ func (a *Simulator) BlockDataGenN(minUpdatesPerBlock, maxUpdatesPerBlock int) *r for i := 0; i < numUpdates; i++ { data := updateGen.Draw(t, fmt.Sprintf("update[%d]", i)) for _, update := range data.Updates { - updateSet[fmt.Sprintf("%s:%v", data.ModuleName, update.Key)] = true + // we need to set the update here each time so that this is used to filter out duplicates in the next round + updateSet[a.formatUpdateKey(data.ModuleName, update)] = true } packets = append(packets, data) } @@ -117,6 +119,21 @@ func (a *Simulator) BlockDataGenN(minUpdatesPerBlock, maxUpdatesPerBlock int) *r }) } +func (a *Simulator) formatUpdateKey(moduleName string, update schema.ObjectUpdate) string { + mod, err := a.state.GetModule(moduleName) + if err != nil { + panic(err) + } + + objColl, err := mod.GetObjectCollection(update.TypeName) + if err != nil { + panic(err) + } + + ks := fmt.Sprintf("%s:%s:%s", moduleName, update.TypeName, schematesting.ObjectKeyString(objColl.ObjectType(), update.Key)) + return ks +} + // ProcessBlockData processes the given block data, advancing the app state based on the object updates in the block // and forwarding all packets to the attached listener. It is expected that the data passed came from BlockDataGen, // however, other data can be passed as long as any StartBlockData packet has the height set to the current height + 1. diff --git a/schema/testing/appdatasim/testdata/app_sim_example_schema.txt b/schema/testing/appdatasim/testdata/app_sim_example_schema.txt index 117d557ba5a4..fb1682175228 100644 --- a/schema/testing/appdatasim/testdata/app_sim_example_schema.txt +++ b/schema/testing/appdatasim/testdata/app_sim_example_schema.txt @@ -7,155 +7,155 @@ OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_integer","Key":"11598611","Value":["016807","-016339012"],"Delete":false},{"TypeName":"test_uint16","Key":9407,"Value":{"valNotNull":0,"valNullable":null},"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int16","Key":-4371,"Value":{"valNotNull":-3532,"valNullable":-15},"Delete":false}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"\u000b𝜛࣢Ⱥ +\u001c","Value":{"Value1":-28,"Value2":"AAE5AAAAATgB"},"Delete":false},{"TypeName":"RetainDeletions","Key":".(","Value":[116120837,"/wwIyAAUciAC"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":[false,false],"Delete":false},{"TypeName":"test_float64","Key":0,"Value":[-0.819610595703125,0.08682777894820155],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"+!𐅫a⍦","Value":[36,"fi07",0.000005021243239880513,2],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["˖|󺪆𝅲=鄖_.;ǀ⃣%; #~",16,512578],"Value":686,"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int16","Key":-988,"Value":[6,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"?൙ဴ𑇑\".+AB","Value":{"Value1":-75,"Value2":"FdQcnKoeAAIB"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int8","Key":6,"Value":[6,null],"Delete":false},{"TypeName":"test_int32","Key":-7573,"Value":[-57,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["\tA𐞙?\t",-5317218,1],"Value":6450,"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AwMbGS8=","Value":["AwQA3EBwHgCEABQBAw==",null],"Delete":false},{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":true,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":[false,false],"Delete":false},{"TypeName":"test_float64","Key":2818,"Value":{"valNotNull":1.036618793083456e+225,"valNullable":-0.0006897732815340143},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"561415.19400226923121396E-2","Value":{"valNotNull":"-24080E11","valNullable":"192.3"},"Delete":false},{"TypeName":"test_int8","Key":-95,"Value":{"valNotNull":-101,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"?Ⱥ","Value":{"Value1":2,"Value2":"2w==","Value3":0.05580937396734953,"Value4":16164100},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["৴ि𐞬a",-681,12863],"Value":1,"Delete":false},{"TypeName":"RetainDeletions","Key":"৯aࠤာAᬺⅤaȺ£Ρᵧa󠁳|𝙮 A","Value":{"Value1":440,"Value2":"9Q=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float32","Key":-874,"Value":[-0.8046875,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"CB4HBgJQBuoBFAIs4xcFRwfaoUJr4f4ACzQ5wX4qPkMAACsA1Ev/Fg==","Value":["xRQCHzcOCGqADAZNAQExHwAaBQISEagYGF4F5wEWFN/JGgHkAsYchgUCA2YRUneug+wEABUjRaAKBOoQAOATEg==","CUXz/xMEAP8BNw0PvPUBNF7rSPPDAQHTBg71MEsKHg=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":-1168504079346,"Value":{"valNotNull":-9566526662547645,"valNullable":-1936738738498935},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"+","Value":[3,"A2k="],"Delete":false}]} Commit: {} StartBlock: {2 } OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"ᾢ","Value":[3,"AQQF3LYA"],"Delete":false}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"_; ᾚ DzA{˭҄\nA ^$?ᾦ,:\u003c\"?_\u0014;|","Value":{"Value1":-15,"Value2":"PED/","Value3":7.997156312768529e-26,"Value4":33975920899014},"Delete":false},{"TypeName":"Simple","Key":"","Value":[-2,"FwY="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AgDYbdMBAZ31DGsBs7UGnAp/BgX/BkQFAQ3Si9sd6x8Hrw==","Value":{"valNotNull":"/2ADvYQC/wATggAAAwYBLjQCAv8=","valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"GJQSAs0BGAILARUXAwIrnf8pBgIrRQOrSQNOEgfvA8ATAAEMVw8s/w==","Value":["GwADWP8AMB6z0AZCDgEDMv8DfQEQ","DAHaBAOt3g16AQAfNQEBeQYBAlv/AfgKUi0YAgg="],"Delete":false},{"TypeName":"test_duration","Key":468,"Value":[-52600,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":": Ⱥ","Value":[-14,"fmoD3wY="],"Delete":false},{"TypeName":"TwoKeys","Key":["Ⱥ꙱Lj",12],"Value":null,"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"$","Value":[13,"Uf8VAgYltOwK"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["",-4],"Value":null,"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":false,"valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"\t;𞄱𑨁௺ⅦA×~ႂᛯaA","Value":{"Value1":2147483647,"Value2":"AAMBAgADGA4="},"Delete":false},{"TypeName":"RetainDeletions","Key":"\nȺ*|𑀾","Value":{"Value1":0,"Value2":"ChoCY0w="},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Singleton","Key":null,"Value":["\u000b!","OQ=="],"Delete":false},{"TypeName":"Singleton","Key":null,"Value":["a",""],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"NACQYgAaAwcFAK/IAQEFWgcArAEpMAA=","Value":["Bz4X2gtkAw4DU4hgA72EAv8AE4IAAAMGAS40AgL/",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"CB4HBgJQBuoBFAIs4xcFRwfaoUJr4f4ACzQ5wX4qPkMAACsA1Ev/Fg==","Value":null,"Delete":true},{"TypeName":"test_address","Key":"CB4HBgJQBuoBFAIs4xcFRwfaoUJr4f4ACzQ5wX4qPkMAACsA1Ev/Fg==","Value":{"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AA==","Value":{"valNotNull":"FRcD","valNullable":"K53/"},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Singleton","Key":null,"Value":{"Value":"℘A⤯","Value2":"ALZMCik="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":[" (弡𞥃",124],"Value":null,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":[false,null],"Delete":false},{"TypeName":"test_integer","Key":"64","Value":["-307711","-2"],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"?Ⱥ","Value":[-278,"AgYltOwK",-6.0083863735198975,429016],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"-97E-70","Value":{"valNotNull":"-650530110","valNullable":null},"Delete":false},{"TypeName":"test_decimal","Key":"561415.19400226923121396E-2","Value":null,"Delete":true}]} Commit: {} StartBlock: {3 } -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int32","Key":-103,"Value":{"valNotNull":-1887959808,"valNullable":2096073436},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"","Value":{"Value1":-4,"Value2":"","Value3":5.199354003997906e-290,"Value4":2703222758},"Delete":false},{"TypeName":"ThreeKeys","Key":["˖|󺪆𝅲=鄖_.;ǀ⃣%; #~",16,512578],"Value":11281,"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":{"valNotNull":1,"valNullable":150},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"?൙ဴ𑇑\".+AB","Value":[-1,"LP8="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_integer","Key":"72961530924372552","Value":["080207094","-598415299"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":-1.7392669057403718e+166,"Value":[1.556643269146063e-16,-1.1920928955078125e-7],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["ऻॉ~$𒐈+Xʱ:²-~?ʳ~$ₜ\\",-787],"Value":null,"Delete":false},{"TypeName":"Singleton","Key":null,"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"\u000b𝜛࣢Ⱥ +\u001c","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":14,"Value":[4,1],"Delete":false},{"TypeName":"test_address","Key":"AgDYbdMBAZ31DGsBs7UGnAp/BgX/BkQFAQ3Si9sd6x8Hrw==","Value":["BQEBAemXEjNqrx2kATMdGuUCESLnES4KAfAC//v/A9gJIaQNAQH/kcYdDw==","lMhHJAXnpQG+wgIzzAoNWjoAGTIABQ=="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["Ⱥ꙱Lj",12],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int32","Key":897,"Value":[454,-2],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float32","Key":-874,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":0,"Value":[1,null],"Delete":false},{"TypeName":"test_decimal","Key":"-97E-70","Value":["36141e01","50562961530924372552"],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["৴ि𐞬a",-681,12863],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AAD/AAAFAAEAUQ==","Value":{"valNotNull":"Nw==","valNullable":"AABdSw=="},"Delete":false},{"TypeName":"test_enum","Key":"baz","Value":["bar",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"CB4HBgJQBuoBFAIs4xcFRwfaoUJr4f4ACzQ5wX4qPkMAACsA1Ev/Fg==","Value":null,"Delete":true},{"TypeName":"test_uint16","Key":9407,"Value":[15,3],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_integer","Key":"433032","Value":{"valNotNull":"711","valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_string","Key":"~?ʳ~$ₜ\\","Value":["*¾",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint32","Key":995,"Value":{"valNotNull":7,"valNullable":null},"Delete":false},{"TypeName":"test_time","Key":"1969-12-31T18:59:59.999999971-05:00","Value":{"valNotNull":"1969-12-31T18:59:59.999999994-05:00","valNullable":"1969-12-31T18:59:59.999580498-05:00"},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_string","Key":"aή⃢\t{ǁ","Value":{"valNotNull":"ሢ϶","valNullable":null},"Delete":false},{"TypeName":"test_uint8","Key":2,"Value":{"valNotNull":17,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["A*۽~Dz₱ {",-8,2],"Value":{"Value1":1056454},"Delete":false},{"TypeName":"TwoKeys","Key":["mA৴ pa _〩ãᛮDž𑣠ʰA%a",1],"Value":null,"Delete":false}]} Commit: {} StartBlock: {4 } OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":-152,"Value":{"valNotNull":1476419818092,"valNullable":-163469},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"‮","Value":[-1,"GwE="],"Delete":false},{"TypeName":"ManyValues","Key":"","Value":[1,"",4.1017235364794545e-228,25],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":".(","Value":null,"Delete":true},{"TypeName":"Singleton","Key":null,"Value":{"Value":"ᾫ+=[฿́\u001b\u003cʰ+`𑱐@\u001b*Dž‮#₻\u0001῎ !a܏ῼ","Value2":"AgI="},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"?൙ဴ𑇑\".+AB","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":" ","Value":[-1,""],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["",11,107],"Value":{"Value1":-31402597},"Delete":false},{"TypeName":"Simple","Key":"\t;𞄱𑨁௺ⅦA×~ႂᛯaA","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint16","Key":0,"Value":{"valNotNull":68,"valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"PQYReIgDAAG/6fs+AVcXxgEGDXLQ30f0/w==","Value":["b+QAdJmb/0hGGAMzEoat/wYeAQcB/wO7Ae0BlgQFAP+i7A0rGA8ESIv+Oi+eFwIDHAMAygDjBogABwADAAC5Aw==",null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["\tA𐞙?\t",-5317218,1],"Value":{"Value1":-220},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_integer","Key":"617","Value":{"valNotNull":"688647620","valNullable":null},"Delete":false},{"TypeName":"test_bool","Key":false,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"‮","Value":[-1,"GwE="],"Delete":false},{"TypeName":"ManyValues","Key":"_; ᾚ DzA{˭҄\nA ^$?ᾦ,:\u003c\"?_\u0014;|","Value":[0,"APMAAh8=",2.6405210300043274e-261,4678],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"+","Value":[-265,"7v+nXKjOoQ=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":[" (弡𞥃",124],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int64","Key":-1,"Value":{"valNotNull":2070362465348116,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"NACQYgAaAwcFAK/IAQEFWgcArAEpMAA=","Value":["AKjiCQIBAyv/AAD8AcQADwD/AEP7eg==","C2YHNQMBaxQz0wAPGXQqGQYCAAPQAhUB05AB7QUAbnLpM7hyjBwAb+QAdJmb/0hGGAMzEoat/wYeAQ=="],"Delete":false},{"TypeName":"test_float64","Key":5224,"Value":[-1683.1097246298846,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AA==","Value":["Md4BCACgAADoAG8cHQ5tB0c1HAA=",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["a\u003c",-84],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":2,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float32","Key":-218792,"Value":[1.0914612,null],"Delete":false},{"TypeName":"test_duration","Key":-9223372036854775808,"Value":{"valNotNull":399806,"valNullable":-336},"Delete":false}]} Commit: {} StartBlock: {5 } -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":true,"valNullable":null},"Delete":false},{"TypeName":"test_uint64","Key":21,"Value":{"valNotNull":73,"valNullable":2},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AgDYbdMBAZ31DGsBs7UGnAp/BgX/BkQFAQ3Si9sd6x8Hrw==","Value":["BQBsCf9MAgQAGfzKAAu1AYAClAADAhlDAP+oChQBYQA5AA0LT19MujQyf/8FbQMDawAM",null],"Delete":false},{"TypeName":"test_enum","Key":"foo","Value":{"valNotNull":"foo","valNullable":"foo"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Singleton","Key":null,"Value":["𝔏؃\"ᵚ¡ $A\r",""],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["𒑏𑿞=A?¯ \t~",-6,53],"Value":-2,"Delete":false},{"TypeName":"Simple","Key":"?","Value":{"Value1":12,"Value2":"HAIBmK0D"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"⍦","Value":[-202,"EQTRAwAELg=="],"Delete":false},{"TypeName":"ManyValues","Key":"`ⅤaAះA~~⹗=\u000b","Value":[-17,"okMB1d0=",-3.643491752614398e+288,1382771530458],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":0,"Value":[-1014342049.3947449,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["a\u003c",-84],"Value":null,"Delete":true},{"TypeName":"Simple","Key":"d⹘:","Value":[3016,"AQ=="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AwMbGS8=","Value":null,"Delete":true},{"TypeName":"test_decimal","Key":"-02","Value":["1219101",null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"9.5E+8","Value":{"valNotNull":"13333140202.01031939e81","valNullable":"7210210.1e+1"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint16","Key":11,"Value":[6,14912],"Delete":false},{"TypeName":"test_duration","Key":-152,"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"`³Njॊ\u003c ?ᾩ‮₦~$","Value":{"Value1":2,"Value2":"lAAD4AAABQQbAwABAwHP"},"Delete":false},{"TypeName":"RetainDeletions","Key":"൴~𝔶ٞ蹯a_ ᛮ!؋aض©-?","Value":{"Value1":-6813,"Value2":"AhRPdlAC"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"BkiVAAcAAJ6xA/dutlmcBe8DAA1UZAsB","Value":["AA57GQP/oifkJ8aYJENTAwLxPhPSAwEI1AA9xQMWAwEoBA==",null],"Delete":false},{"TypeName":"test_address","Key":"7QTt/24APN4FBA/TAG8B/wMBWOoCqP+HNg0FBQIdAw8F5AI=","Value":["BQNcFhh01gEBAm4BAfAlGwMKkCo=","aQQTfSUg2RkZARH/EP8IGAxENIBOGwbPFAA="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int8","Key":6,"Value":[-8,null],"Delete":false},{"TypeName":"test_address","Key":"AACHBAjyAgFHOQAABo+PGAK3Bj7TwwBb/wAB3gE=","Value":["ASwojxUABA8BAf/9AgUBIs4WAq9lqAEKAP8FAAgCGwEMDQKHZwEABA82AVZZAHO/ngS7AA==",null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AWvYAbSo5gQCAz8XAQYGjwCaRx0DSAUpAWQV","Value":["/z/eNBkL5QAgCwXergJOUCEC/+ICAp4BTgBsVw==","HhoELBAPigABQwIDAxsB7KEAGlIOEAAEYQL/GQA37QAJWg0A"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":" ","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"79","Value":["-7872","53"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint32","Key":1322158439,"Value":{"valNotNull":2415,"valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"_; ᾚ DzA{˭҄\nA ^$?ᾦ,:\u003c\"?_\u0014;|","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["\tA𐞙?\t",-5317218,1],"Value":-2147483648,"Delete":false},{"TypeName":"ManyValues","Key":"‮۽𝅸\u003c#󠁋","Value":[-3,"",-5.385845077524242e-269,2468],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":null,"Delete":true},{"TypeName":"test_int8","Key":-6,"Value":{"valNotNull":122,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":{"valNullable":false},"Delete":false},{"TypeName":"test_address","Key":"UQMARFtfJYloAQ5FAQE+P5ezAZMCP82oChQBYQA5AA0LT19MujQyf/8FbQMDawAM","Value":["zQIdDAwCA1MfywMMFUrXCRcsAAC3OAYBAAyUCi36BQQAAuUkAACrBgAHAgUCAcYAJgM=","HAIBmK0DtgEBBwEBLzEFjXltUcIBBAFcAuZTALIBmAeVArgXLpEyAwAd2rwXD/+2wOT37ekWAr4EAEvnhw=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"?Ⱥ","Value":{"Value4":80},"Delete":false},{"TypeName":"RetainDeletions","Key":"@‮:","Value":[3016,"AQ=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AAD/AAAFAAEAUQ==","Value":null,"Delete":true},{"TypeName":"test_decimal","Key":"800","Value":["7119101",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"","Value":{"Value2":"LpIWCQoAbw=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint64","Key":96,"Value":[2,null],"Delete":false},{"TypeName":"test_uint8","Key":0,"Value":[178,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"৯aࠤာAᬺⅤaȺ£Ρᵧa󠁳|𝙮 A","Value":{"Value2":""},"Delete":false},{"TypeName":"Singleton","Key":null,"Value":{"Value":"/ᾪ蹯a_ ᛮ!؋aض©-?","Value2":"4A=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["Ⱥേ҈a҉Ⱥ",-114036639,4],"Value":2147483647,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_string","Key":"aή⃢\t{ǁ","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":-40715358873,"Value":{"valNotNull":-35986926993,"valNullable":null},"Delete":false},{"TypeName":"test_time","Key":"1969-12-31T18:59:59.981789806-05:00","Value":["1969-12-31T18:57:57.72625051-05:00","1969-12-26T16:36:45.679781385-05:00"],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"-40530.610059","Value":{"valNotNull":"-344079482.57151","valNullable":null},"Delete":false},{"TypeName":"test_enum","Key":"baz","Value":{"valNotNull":"bar","valNullable":"baz"},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float32","Key":-218792,"Value":null,"Delete":true},{"TypeName":"test_address","Key":"NACQYgAaAwcFAK/IAQEFWgcArAEpMAA=","Value":{"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"-97E-70","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AA==","Value":null,"Delete":true},{"TypeName":"test_bytes","Key":"Bw==","Value":["AwYGBg2V","EWShfAE="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"A","Value":[3939571,"oAE="],"Delete":false},{"TypeName":"ThreeKeys","Key":["a .౺ऻ\u0026",-1,0],"Value":-343368,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["`ҡ",-483],"Value":null,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"aⅭȺ\ta\u0026A୵","Value":{"Value1":1627290802,"Value2":"DQA=","Value3":70375169.64453125,"Value4":7578767657429368},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"󠇯$ aḍa\r","Value":[59,""],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["mA৴ pa _〩ãᛮDž𑣠ʰA%a",1],"Value":null,"Delete":true}]} Commit: {} StartBlock: {6 } OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["A𞥟",981],"Value":null,"Delete":false},{"TypeName":"ManyValues","Key":"ᵕ؏­􏿽A","Value":{"Value1":-317,"Value2":"AA==","Value3":-37.62890625,"Value4":232},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AACHBAjyAgFHOQAABo+PGAK3Bj7TwwBb/wAB3gE=","Value":{"valNotNull":"HBwBHAY6AAKO+UwDKRICAT0lgRRvCRvHFFoNAigBAUEDHoQUfB2qApRB/z41AAubARsBATQg3gCppQMAAQwHAQ=="},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"9.5E+8","Value":["-2","88111430.0122412446"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":null,"Delete":true},{"TypeName":"test_time","Key":"1969-12-31T18:59:59.999999999-05:00","Value":["1969-12-31T19:00:00.000000001-05:00",null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"൴~𝔶ٞ蹯a_ ᛮ!؋aض©-?","Value":{"Value2":""},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":14,"Value":{"valNotNull":116},"Delete":false},{"TypeName":"test_duration","Key":100403021838,"Value":[1547,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int64","Key":-34196421,"Value":[56,224549431],"Delete":false},{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":true,"valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["ⅷ_ŕ,A",-467,98],"Value":{"Value1":145},"Delete":false},{"TypeName":"RetainDeletions","Key":"?aa₽A\u001b=⇂́ᯫ𖽦ᩣ","Value":{"Value1":0,"Value2":""},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["",-4],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"NACQYgAaAwcFAK/IAQEFWgcArAEpMAA=","Value":{"valNotNull":"HBwBHAY6AAKO+UwDKRICAT0lgRRvCRvHFFoNAigBAUEDHoQUfB2qApRB/z41AAubARsBATQg3gCppQMAAQwHAQ=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"-40530.610059","Value":["-2","88111430.0122412446"],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":0,"Value":null,"Delete":true},{"TypeName":"test_time","Key":"1969-12-31T18:59:59.981789806-05:00","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Singleton","Key":null,"Value":{"Value":"","Value2":"NeIMrxEMAgI="},"Delete":false},{"TypeName":"RetainDeletions","Key":"꙲󽬺","Value":[835552366,"ngY="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["\u0026AȺ#˼%֘_ŕ,A",-467,98],"Value":{"Value1":145},"Delete":false},{"TypeName":"RetainDeletions","Key":"?aa₽A\u001b=⇂́ᯫ𖽦ᩣ","Value":{"Value1":0,"Value2":""},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["`ҡ",-483],"Value":null,"Delete":true}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"","Value":{"Value1":1174095848,"Value2":"AR//A0kBNVwGGGsHANYAAAAtJQ=="},"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint64","Key":3,"Value":[14481555953,496],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"ǃ^@❽\u2028!𑿞a‮a`","Value":{"Value1":-33730,"Value2":"qKQ="},"Delete":false},{"TypeName":"Singleton","Key":null,"Value":["𞤎𞤡","BAconQGXHRuHXQN/GTUCSQACEg=="],"Delete":false}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"ൌ{ ༿","Value":[1110340689,"AQ==",0.00018342199999210607,1],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AwcJA//C","Value":{"valNotNull":"DQ==","valNullable":null},"Delete":false},{"TypeName":"test_duration","Key":210213542904,"Value":[-207349773999415086,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":-3.0664227080502325e-103,"Value":[2.125936378595003e-239,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"৯aࠤာAᬺⅤaȺ£Ρᵧa󠁳|𝙮 A","Value":null,"Delete":true},{"TypeName":"ManyValues","Key":"aⅭȺ\ta\u0026A୵","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"A","Value":{"Value2":"NwIDBwkD/8I="},"Delete":false},{"TypeName":"Simple","Key":"a ¥𐅝`B܆Å$*","Value":{"Value1":2147483647,"Value2":"4gYDABg="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"19201864880978510.28381871008156E9","Value":["14793512",null],"Delete":false},{"TypeName":"test_enum","Key":"baz","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"󠇯$ aḍa\r","Value":[-9,"0AEFPHM="],"Delete":false},{"TypeName":"ThreeKeys","Key":["",0,3265605],"Value":-3703028,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["Ⱥേ҈a҉Ⱥ",-114036639,4],"Value":{"Value1":502},"Delete":false}]} Commit: {} StartBlock: {7 } OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":{"valNotNull":true,"valNullable":true},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"d⹘:","Value":{"Value2":""},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["ऻॉ~$𒐈+Xʱ:²-~?ʳ~$ₜ\\",-787],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"‮","Value":{"Value2":""},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":[false,null],"Delete":false},{"TypeName":"test_bool","Key":false,"Value":{"valNullable":true},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["A𞥟",981],"Value":null,"Delete":true}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["ः𒑨Dz؅",-2],"Value":null,"Delete":false}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["@(\u0001\u0001\tᛰᾚ𐺭a'ᵆᾭaa",16,817744173394],"Value":{"Value1":-2},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AwcJA//C","Value":{"valNotNull":"AWNXAw=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"Bw==","Value":{"valNotNull":"AWNXAw=="},"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"-85","Value":["-2511998","-077.01427082957E-7"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int16","Key":-988,"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_enum","Key":"foo","Value":null,"Delete":true},{"TypeName":"test_decimal","Key":"-02","Value":["-40892500970.58239","11e0"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_string","Key":"","Value":{"valNotNull":"実.*𑁤!؋A\u000b.{;?󠀮_? ‍*🄑󠇯","valNullable":"(Ⱥ#/\u003c_"},"Delete":false},{"TypeName":"test_integer","Key":"-1391361","Value":{"valNotNull":"-0105","valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AWvYAbSo5gQCAz8XAQYGjwCaRx0DSAUpAWQV","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int8","Key":98,"Value":[-40,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int16","Key":-4371,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_enum","Key":"foo","Value":{"valNotNull":"foo","valNullable":null},"Delete":false},{"TypeName":"test_uint32","Key":522395,"Value":[2730,3],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"sucDH0r/CmEAgjcBB7H1AgAcEtI=","Value":["GVr4AxwBAN14AAYApgFuif8HrpAE9FcABBcPAGpHAQLtE3UmLQwOAjgrEMMC4w//","irH/SwYtmFOeC3EE/wEdAxnJCn8Oapb/tWjEj28BLhs1"],"Delete":false},{"TypeName":"test_address","Key":"NACQYgAaAwcFAK/IAQEFWgcArAEpMAA=","Value":["AwIBAz8EAA5dZQEATgEBAnG+p3MPVwYAEV1dBwMDAQADCgYEJQcD+EgAAAcB","t3xyAAYBDQQHAgHH1ANoVw//Pv+nAP89Ao8OANr3BUIBAg=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":7,"Value":[190,null],"Delete":false}]} Commit: {} StartBlock: {8 } -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"$","Value":[0,""],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"\u000b𝜛࣢Ⱥ +\u001c","Value":[0,""],"Delete":false}]} OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"8E4","Value":{"valNotNull":"4043421E29","valNullable":null},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"AACHBAjyAgFHOQAABo+PGAK3Bj7TwwBb/wAB3gE=","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["A𞥟",981],"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["",55175],"Value":null,"Delete":false},{"TypeName":"RetainDeletions","Key":"`³Njॊ\u003c ?ᾩ‮₦~$","Value":{"Value1":3},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":468,"Value":[-4,-805402038367],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":true,"Value":null,"Delete":true},{"TypeName":"test_int32","Key":-24,"Value":[1,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"҉߃ ","Value":[-526,""],"Delete":false},{"TypeName":"Simple","Key":": Ⱥ","Value":[59,"Kw=="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_enum","Key":"bar","Value":{"valNotNull":"foo","valNullable":null},"Delete":false},{"TypeName":"test_int64","Key":2481611475,"Value":[136,6],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":-3.0664227080502325e-103,"Value":[-0.34326171875,-1.9202818317669984e-13],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Singleton","Key":null,"Value":null,"Delete":true},{"TypeName":"Singleton","Key":null,"Value":{"Value":"","Value2":"ClAs"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"?b⁠\r##﹍/$ͥ","Value":[10,"",5.231528162956238,42],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"ݙaس\u003cй?{E","Value":{"Value1":-15,"Value2":"o+MQ"},"Delete":false},{"TypeName":"RetainDeletions","Key":"൴~𝔶ٞ蹯a_ ᛮ!؋aض©-?","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"AwcJA//C","Value":{"valNullable":""},"Delete":false},{"TypeName":"test_uint32","Key":1322158439,"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["ꬵ[Ⰶ\u2029\u0026𒐗🕳c҉\u0026฿a\u0026",-79424],"Value":null,"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int8","Key":-128,"Value":[7,null],"Delete":false},{"TypeName":"test_int32","Key":-103,"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"ᾢ","Value":[-2356,"DA=="],"Delete":false},{"TypeName":"ManyValues","Key":"","Value":{"Value1":28,"Value2":"","Value3":-1.6098999622118156e+67,"Value4":14},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"?≚a'","Value":{"Value1":-611,"Value2":"AgqTAG4=","Value3":-2.0360732649240822e+100,"Value4":0},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":0,"Value":[2.5625,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint64","Key":3,"Value":{"valNotNull":59,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"NACQYgAaAwcFAK/IAQEFWgcArAEpMAA=","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["ः𒑨Dz؅",-2],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["",55175],"Value":null,"Delete":false},{"TypeName":"RetainDeletions","Key":"?aa₽A\u001b=⇂́ᯫ𖽦ᩣ","Value":{"Value1":3},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":-9223372036854775808,"Value":[-4,-805402038367],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":null,"Delete":true},{"TypeName":"test_int32","Key":-24,"Value":[1,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"҉߃ ","Value":[-526,""],"Delete":false},{"TypeName":"Simple","Key":"A","Value":[59,"Kw=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"UQMARFtfJYloAQ5FAQE+P5ezAZMCP82oChQBYQA5AA0LT19MujQyf/8FbQMDawAM","Value":["CRRWVxf/DVOzCAMAClAsCT0BAP8BPQ==",null],"Delete":false},{"TypeName":"test_enum","Key":"baz","Value":["bar","foo"],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bytes","Key":"BQ==","Value":{"valNotNull":"AQYYDVF9MQF2","valNullable":"qQU="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int64","Key":-1,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_integer","Key":"433032","Value":{"valNotNull":"25","valNullable":"937"},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int16","Key":9863,"Value":[1851,null],"Delete":false},{"TypeName":"test_decimal","Key":"800","Value":["0448127215514e88",null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"@‮:","Value":null,"Delete":true},{"TypeName":"ManyValues","Key":"ᵕ؏­􏿽A","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"'","Value":{"Value1":-611,"Value2":"AgqTAG4="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Singleton","Key":null,"Value":["$?A","BAtu"],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["h ʶ?\\A魘",47994411],"Value":null,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint64","Key":96,"Value":{"valNotNull":4576150250879893,"valNullable":329},"Delete":false},{"TypeName":"test_duration","Key":-152,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"󴵠","Value":[-3,"QwH/FQ=="],"Delete":false},{"TypeName":"ThreeKeys","Key":["_\u001b\u0026㉉",7,3662],"Value":{"Value1":-3316206},"Delete":false}]} Commit: {} StartBlock: {9 } -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["ः𒑨Dz؅",-2],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["h ʶ?\\A魘",47994411],"Value":null,"Delete":true}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"_�é","Value":{"Value1":9,"Value2":"Ywc="},"Delete":false},{"TypeName":"Singleton","Key":null,"Value":null,"Delete":true}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"A%aa ¹­ ᾏaĵ¨","Value":[9,"A/faBuYCCecZ3ATQAQcC3gAsizI="],"Delete":false},{"TypeName":"ThreeKeys","Key":[" {a",2790155,310794],"Value":{"Value1":312},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int32","Key":892,"Value":[-3,null],"Delete":false},{"TypeName":"test_duration","Key":210213542904,"Value":[-722503,113854019],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":468,"Value":[12,null],"Delete":false},{"TypeName":"test_int16","Key":0,"Value":[3089,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"79","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["",11,107],"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":[true,true],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":": Ⱥ","Value":{"Value1":-2147483648},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":14,"Value":null,"Delete":true},{"TypeName":"test_integer","Key":"-1391361","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"","Value":[-242379,"BngOEOsA"],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int8","Key":6,"Value":null,"Delete":true},{"TypeName":"test_address","Key":"BkiVAAcAAJ6xA/dutlmcBe8DAA1UZAsB","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":" 😖₱ ̄؀ा󠁿","Value":[7541152,""],"Delete":false},{"TypeName":"ThreeKeys","Key":["ⅷ_ŕ,A",-467,98],"Value":2,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_int32","Key":892,"Value":[-3,null],"Delete":false},{"TypeName":"test_duration","Key":-9223372036854775808,"Value":[-722503,113854019],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":-40715358873,"Value":[12,null],"Delete":false},{"TypeName":"test_int16","Key":0,"Value":[3089,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"19201864880978510.28381871008156E9","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["",0,3265605],"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":{"valNotNull":false,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"82509790016910","Value":{"valNotNull":"-51151","valNullable":null},"Delete":false},{"TypeName":"test_address","Key":"UQMARFtfJYloAQ5FAQE+P5ezAZMCP82oChQBYQA5AA0LT19MujQyf/8FbQMDawAM","Value":{"valNotNull":"xbA200EFExwKoFrhCgcAYwFvDgEBXAH8AADJAAQFDfgITwIFDh8BAXQMRUwBAgY8/wANBCQGANqvCWL/AYwA+g==","valNullable":"OgPvFo8DAA+2AgEBBM4BXSAA/wCBlzxUAVoC/wQBAbIMKiwD/0MBKAF4Bv8BAoIOUwALFSMuVgIAAZddBQEDBA=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_integer","Key":"64","Value":["13","-732"],"Delete":false},{"TypeName":"test_float32","Key":-2147483648,"Value":{"valNotNull":-0.38865662,"valNullable":null},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"ൌ{ ༿","Value":{"Value1":-152,"Value3":-204.96875},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"‮","Value":{"Value1":-44227},"Delete":false},{"TypeName":"Simple","Key":"A","Value":[837,"Aw=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"�-\u003e𝟆Ⱥ`Ṙ|¤﮺̺","Value":[1137505,"UQAXACIMig=="],"Delete":false}]} Commit: {} StartBlock: {10 } -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":87208838869,"Value":[-9725,4968373],"Delete":false},{"TypeName":"test_duration","Key":468,"Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_duration","Key":87208838869,"Value":[-9725,4968373],"Delete":false},{"TypeName":"test_duration","Key":-40715358873,"Value":null,"Delete":true}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"","Value":[-1,"FQIK"],"Delete":false},{"TypeName":"Singleton","Key":null,"Value":{"Value":"œLj$࿇ ᾙ☇؄ೲȺ","Value2":"ADei6AACZTMDDss="},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":[true,null],"Delete":false},{"TypeName":"test_enum","Key":"bar","Value":{"valNotNull":"baz","valNullable":"baz"},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["\tA𐞙?\t",-5317218,1],"Value":{"Value1":1},"Delete":false},{"TypeName":"RetainDeletions","Key":"\u0026 ٱȺ+҉@","Value":[63,"AAE="],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":-1.7392669057403718e+166,"Value":[-1.0781831287525041e+139,111.37014762980289],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"GJQSAs0BGAILARUXAwIrnf8pBgIrRQOrSQNOEgfvA8ATAAEMVw8s/w==","Value":{"valNotNull":"em2zQwR2O7EAAAYLk23QBADE/wA="},"Delete":false},{"TypeName":"test_address","Key":"PQYReIgDAAG/6fs+AVcXxgEGDXLQ30f0/w==","Value":null,"Delete":true}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_bool","Key":false,"Value":[true,null],"Delete":false},{"TypeName":"test_enum","Key":"baz","Value":{"valNotNull":"baz","valNullable":"baz"},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":[" {a",2790155,310794],"Value":{"Value1":1},"Delete":false},{"TypeName":"RetainDeletions","Key":"\u0026 ٱȺ+҉@","Value":[63,"AAE="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_float64","Key":2818,"Value":[-1.0781831287525041e+139,111.37014762980289],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_address","Key":"sucDH0r/CmEAgjcBB7H1AgAcEtI=","Value":{"valNotNull":"em2zQwR2O7EAAAYLk23QBADE/wA="},"Delete":false},{"TypeName":"test_address","Key":"UQMARFtfJYloAQ5FAQE+P5ezAZMCP82oChQBYQA5AA0LT19MujQyf/8FbQMDawAM","Value":null,"Delete":true}]} OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"","Value":[-188,"",-2632691.375,17],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["A]$",-125,43],"Value":12654289,"Delete":false},{"TypeName":"RetainDeletions","Key":"?aa₽A\u001b=⇂́ᯫ𖽦ᩣ","Value":{"Value2":"ARM="},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":0,"Value":{"valNotNull":0,"valNullable":null},"Delete":false},{"TypeName":"test_float32","Key":1.7852577e+32,"Value":[1.6582896,null],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"?b⁠\r##﹍/$ͥ","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"TwoKeys","Key":["",55175],"Value":null,"Delete":true},{"TypeName":"ThreeKeys","Key":["˖|󺪆𝅲=鄖_.;ǀ⃣%; #~",16,512578],"Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"RetainDeletions","Key":"A%aa ¹­ ᾏaĵ¨","Value":null,"Delete":true}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"Simple","Key":"‮","Value":{"Value2":"DAcBeTgAFAED"},"Delete":false},{"TypeName":"RetainDeletions","Key":"ʵ² *ᾍA@҂b⭗@‮൞","Value":{"Value1":547,"Value2":""},"Delete":false}]} -OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":4,"Value":[17,null],"Delete":false},{"TypeName":"test_uint8","Key":8,"Value":[2,12],"Delete":false}]} -OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"҉♰ᾜȺ൜堯Ⱥ៵\"","Value":{"Value1":-10,"Value2":"jg==","Value3":-0.11867497289509932,"Value4":24065},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["A]$",-125,43],"Value":12654289,"Delete":false},{"TypeName":"RetainDeletions","Key":"+","Value":{"Value2":"ARM="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_uint8","Key":35,"Value":[0,51],"Delete":false},{"TypeName":"test_uint8","Key":107,"Value":[4,null],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"all_kinds","Updates":[{"TypeName":"test_decimal","Key":"-85","Value":{"valNotNull":"-25"},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["_\u001b\u0026㉉",7,3662],"Value":{"Value1":-80},"Delete":false},{"TypeName":"RetainDeletions","Key":"'","Value":[5521,"kwsBjw=="],"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["@(\u0001\u0001\tᛰᾚ𐺭a'ᵆᾭaa",16,817744173394],"Value":-1,"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ManyValues","Key":"Nj#߁#҉♰ᾜȺ൜堯Ⱥ៵\"","Value":{"Value1":-10,"Value2":"jg==","Value3":-0.11867497289509932,"Value4":24065},"Delete":false},{"TypeName":"RetainDeletions","Key":"","Value":{"Value1":2204165,"Value2":"Jg=="},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["A*۽~Dz₱ {",-8,2],"Value":{"Value1":624},"Delete":false},{"TypeName":"ManyValues","Key":"ڥ\u0026\u000b","Value":{"Value1":0,"Value2":"BmQD","Value3":-6.822989118840796e-47,"Value4":654213},"Delete":false}]} +OnObjectUpdate: {"ModuleName":"test_cases","Updates":[{"TypeName":"ThreeKeys","Key":["{Ⱥ\t$࿐(#",117624,128273],"Value":14,"Delete":false},{"TypeName":"RetainDeletions","Key":"A%aa ¹­ ᾏaĵ¨","Value":{"Value2":"Av8="},"Delete":false}]} Commit: {} diff --git a/schema/testing/appdatasim/testdata/diff_example.txt b/schema/testing/appdatasim/testdata/diff_example.txt index fcdd45729de3..7c0ab0e14c34 100644 --- a/schema/testing/appdatasim/testdata/diff_example.txt +++ b/schema/testing/appdatasim/testdata/diff_example.txt @@ -2,78 +2,68 @@ App State Diff: MODULE COUNT ERROR: expected 2, got 1 Module all_kinds Object Collection test_address - OBJECT COUNT ERROR: expected 16, got 14 - Object key=0x0c6ff6530300000704ff285714816e0d0b03010d0102010302ff7400d60103c2110e3700c30105679f0910570048aa48f6b4680128821c98011d00240c2c00ff - valNotNull: expected [43 29 85 255 6 1 176 1 241 222 0 0 14 116 190 1 11 30 2 8 1 144 12 2 12 1 16 15 1 1 27 8 0 255 57 2 6 195 255 60 0 201 255 1 1 13 9 112 1 2 0 121 12 172 254 22 11 1 5 37 54 212 121 0], got [220 0 1 2 13 4 24 1 12 24 58 0 1 224 0 148 104 51 116 27 56 39 14 32 35 84 126 2 18 1 5 6] - valNullable: expected [189 125 119 246 192 0 3 170 24 6 10 123 0 7 34 118 1 212 187 7 1 249 110 146 10 14 0 3 223 134 65 0 15 248 153], got [29 201 1 2 1 63 13 0 191 75 1 2 240 10 209 58 15 137 184 141 148] - Object key=0x18f0037d00012c006d9c72096b011e01f600035108fe0303000100031f1f020f08002203000502010120060f1b0201180203006a00e0: NOT FOUND - Object key=0xa10f005de9c1010692980d213250ef13020697430007000bdc01010305054f4001b7ba39003a01d2ae0e59007eef4e19e9020e006974016d00001c00037b7028: NOT FOUND - Object key=0xff2619001c04b3031aa10d9d167f1f0046d6760216009c: NOT FOUND - Object Collection test_bytes - OBJECT COUNT ERROR: expected 5, got 4 - Object key=0x000a4f0f6e9b67f6: NOT FOUND - Object key=0x0e0827 - valNotNull: expected [159 2], got [41 6 2 75] - valNullable: expected [0 11 54 47 28], got [6] - Object key=0xff661b1c00 - valNullable: expected [15 20 0 1 132 7 37 3 28 2], got [0 8 1 170 90 0 1 201 97 138 53 2] - Object Collection test_decimal - OBJECT COUNT ERROR: expected 5, got 3 - Object key=-04360.6e32: NOT FOUND - Object key=-21918e-3: NOT FOUND - Object key=-37.02e01: NOT FOUND - Object key=41090120E-3 - valNotNull: expected 04.13921382165470301184220430, got 0255559.705E-4 - valNullable: expected -2e5, got nil - Object Collection test_duration - OBJECT COUNT ERROR: expected 1, got 2 - Object Collection test_enum - OBJECT COUNT ERROR: expected 1, got 2 + OBJECT COUNT ERROR: expected 14, got 13 + Object key=0x34009062001a03070500afc80101055a0700ac01293000: NOT FOUND + Object key=0x5b01cd8d349b030278030112d8e6020f00000600cc2f66016a016d01: NOT FOUND + Object Collection test_bool + Object key=false + valNotNull: expected true, got false + Object key=true + valNotNull: expected true, got false + Object Collection test_bytes + Object key=0x09: NOT FOUND + Object Collection test_decimal + OBJECT COUNT ERROR: expected 6, got 5 + Object key=-99910.16: NOT FOUND + Object key=309967364: NOT FOUND + Object Collection test_duration + OBJECT COUNT ERROR: expected 8, got 7 + Object key=-3m19.124749496s: NOT FOUND + Object key=45ns: NOT FOUND Object Collection test_float32 - OBJECT COUNT ERROR: expected 3, got 4 - Object Collection test_int16 - OBJECT COUNT ERROR: expected 9, got 8 - Object key=-44: NOT FOUND + Object key=-2: NOT FOUND Object Collection test_int32 - OBJECT COUNT ERROR: expected 2, got 1 - Object key=-453: NOT FOUND - Object key=205: NOT FOUND + OBJECT COUNT ERROR: expected 1, got 0 + Object key=-148250689: NOT FOUND Object Collection test_int64 - OBJECT COUNT ERROR: expected 3, got 5 - Object key=-41 - valNotNull: expected 244, got -5717 - valNullable: expected nil, got 0 - Object Collection test_int8 OBJECT COUNT ERROR: expected 4, got 3 - Object key=-2: NOT FOUND + Object key=1086011412347477: NOT FOUND + Object key=881248243728748743 + valNotNull: expected 1, got -154 + valNullable: expected 363352528, got nil + Object Collection test_int8 Object key=53 - valNotNull: expected 27, got 58 - valNullable: expected nil, got -10 + valNotNull: expected -7, got 58 + valNullable: expected 15, got -10 Object Collection test_integer - OBJECT COUNT ERROR: expected 7, got 6 - Object key=-31083911818: NOT FOUND - Object key=191 - valNotNull: expected 62, got -47110784 - valNullable: expected 9297555, got nil - Object Collection test_string - OBJECT COUNT ERROR: expected 2, got 1 - Object key=š℠¼々¢~;-Ⱥ!˃a[ʰᾌ?{ᪧ৵%ᾯ¦〈: NOT FOUND - Object Collection test_time OBJECT COUNT ERROR: expected 4, got 3 - Object key=1969-12-31 19:00:00.000000005 -0500 EST: NOT FOUND + Object key=12 + valNotNull: expected -3, got 101 + Object key=4: NOT FOUND + Object Collection test_string + Object key= + #[Dž¦&?=: NOT FOUND + Object Collection test_time Object key=1969-12-31 19:00:00.001598687 -0500 EST - valNotNull: expected 1969-12-31 19:00:00.007727197 -0500 EST, got 1969-12-31 19:00:00.034531678 -0500 EST - valNullable: expected 1969-12-31 19:00:00.000000484 -0500 EST, got 1969-12-31 19:00:00.000000033 -0500 EST + valNullable: expected nil, got 1969-12-31 19:00:00.000000033 -0500 EST Object Collection test_uint16 OBJECT COUNT ERROR: expected 4, got 3 - Object key=23712: NOT FOUND + Object key=1478: NOT FOUND Object Collection test_uint32 OBJECT COUNT ERROR: expected 3, got 2 - Object key=0: NOT FOUND + Object key=0 + valNotNull: expected 1, got 26 + valNullable: expected 321283034, got 2 + Object key=23067: NOT FOUND Object Collection test_uint64 - OBJECT COUNT ERROR: expected 1, got 2 - Object Collection test_uint8 - OBJECT COUNT ERROR: expected 3, got 2 + OBJECT COUNT ERROR: expected 2, got 0 Object key=1: NOT FOUND + Object key=50508131: NOT FOUND + Object Collection test_uint8 + OBJECT COUNT ERROR: expected 2, got 1 + Object key=119 + valNotNull: expected 6, got 30 + valNullable: expected nil, got 7 + Object key=72: NOT FOUND Module test_cases: actual module NOT FOUND BlockNum: expected 2, got 1 diff --git a/schema/testing/example_schema.go b/schema/testing/example_schema.go index 60ae8bba548e..36dd0a0b76dc 100644 --- a/schema/testing/example_schema.go +++ b/schema/testing/example_schema.go @@ -152,6 +152,9 @@ func mkTestObjectType(kind schema.Kind) schema.ObjectType { keyField := field keyField.Name = "key" + if !kind.ValidKeyKind() { + keyField.Kind = schema.Int32Kind + } val1Field := field val1Field.Name = "valNotNull" val2Field := field diff --git a/schema/testing/field.go b/schema/testing/field.go index 670f9356a681..b7debbc32c7a 100644 --- a/schema/testing/field.go +++ b/schema/testing/field.go @@ -35,6 +35,11 @@ var FieldGen = rapid.Custom(func(t *rapid.T) schema.Field { return field }) +// KeyFieldGen generates random key fields based on the validity criteria of key fields. +var KeyFieldGen = FieldGen.Filter(func(f schema.Field) bool { + return !f.Nullable && f.Kind.ValidKeyKind() +}) + // FieldValueGen generates random valid values for the field, aiming to exercise the full range of possible // values for the field. func FieldValueGen(field schema.Field) *rapid.Generator[any] { @@ -128,9 +133,8 @@ func ObjectKeyGen(keyFields []schema.Field) *rapid.Generator[any] { // Values that are for update may skip some fields in a ValueUpdates instance whereas values for insertion // will always contain all values. func ObjectValueGen(valueFields []schema.Field, forUpdate bool) *rapid.Generator[any] { - // special case where there are no value fields - // we shouldn't end up here, but just in case if len(valueFields) == 0 { + // if we have no value fields, always return nil return rapid.Just[any](nil) } diff --git a/schema/testing/fmt.go b/schema/testing/fmt.go new file mode 100644 index 000000000000..e486adfeb8b7 --- /dev/null +++ b/schema/testing/fmt.go @@ -0,0 +1,53 @@ +package schematesting + +import ( + "fmt" + + "github.com/cockroachdb/apd/v3" + + "cosmossdk.io/schema" +) + +// ObjectKeyString formats the object key as a string deterministically for storage in a map. +// The key must be valid for the object type and the object type must be valid. +// No validation is performed here. +func ObjectKeyString(objectType schema.ObjectType, key any) string { + keyFields := objectType.KeyFields + n := len(keyFields) + switch n { + case 0: + return "" + case 1: + valStr := fmtValue(keyFields[0].Kind, key) + return fmt.Sprintf("%s=%v", keyFields[0].Name, valStr) + default: + ks := key.([]interface{}) + res := "" + for i := 0; i < n; i++ { + if i != 0 { + res += ", " + } + valStr := fmtValue(keyFields[i].Kind, ks[i]) + res += fmt.Sprintf("%s=%v", keyFields[i].Name, valStr) + } + return res + } +} + +func fmtValue(kind schema.Kind, value any) string { + switch kind { + case schema.BytesKind, schema.AddressKind: + return fmt.Sprintf("0x%x", value) + case schema.DecimalStringKind, schema.IntegerStringKind: + // we need to normalize decimal & integer strings to remove leading & trailing zeros + d, _, err := apd.NewFromString(value.(string)) + if err != nil { + panic(err) + } + r := &apd.Decimal{} + r, _ = r.Reduce(d) + return r.String() + default: + return fmt.Sprintf("%v", value) + } +} diff --git a/schema/testing/fmt_test.go b/schema/testing/fmt_test.go new file mode 100644 index 000000000000..02cef05d5f1b --- /dev/null +++ b/schema/testing/fmt_test.go @@ -0,0 +1,61 @@ +package schematesting + +import ( + "testing" + + "cosmossdk.io/schema" +) + +func TestObjectKeyString(t *testing.T) { + tt := []struct { + objectType schema.ObjectType + key any + expected string + }{ + { + objectType: schema.ObjectType{ + Name: "Singleton", + ValueFields: []schema.Field{ + {Name: "Value", Kind: schema.StringKind}, + }, + }, + key: nil, + expected: "", + }, + { + objectType: schema.ObjectType{ + Name: "Simple", + KeyFields: []schema.Field{{Name: "Key", Kind: schema.StringKind}}, + }, + key: "key", + expected: "Key=key", + }, + { + objectType: schema.ObjectType{ + Name: "BytesAddressDecInt", + KeyFields: []schema.Field{ + {Name: "Bz", Kind: schema.BytesKind}, + {Name: "Addr", Kind: schema.AddressKind}, + {Name: "Dec", Kind: schema.DecimalStringKind}, + {Name: "Int", Kind: schema.IntegerStringKind}, + }, + }, + key: []interface{}{ + []byte{0x01, 0x02}, + []byte{0x03, 0x04}, + "123.4560000", // trailing zeros should get removed + "0000012345678900000000000", // leading zeros should get removed and this should be in exponential form + }, + expected: "Bz=0x0102, Addr=0x0304, Dec=123.456, Int=1.23456789E+19", + }, + } + + for _, tc := range tt { + t.Run(tc.objectType.Name, func(t *testing.T) { + actual := ObjectKeyString(tc.objectType, tc.key) + if actual != tc.expected { + t.Errorf("expected %s, got %s", tc.expected, actual) + } + }) + } +} diff --git a/schema/testing/module_schema.go b/schema/testing/module_schema.go index 9f62bfd2d281..8d25046540bf 100644 --- a/schema/testing/module_schema.go +++ b/schema/testing/module_schema.go @@ -29,7 +29,7 @@ var objectTypesGen = rapid.Custom(func(t *rapid.T) []schema.ObjectType { }).Filter(func(objectTypes []schema.ObjectType) bool { typeNames := map[string]bool{} for _, objectType := range objectTypes { - if hasDuplicateNames(typeNames, objectType.KeyFields) || hasDuplicateNames(typeNames, objectType.ValueFields) { + if hasDuplicateTypeNames(typeNames, objectType.KeyFields) || hasDuplicateTypeNames(typeNames, objectType.ValueFields) { return false } if typeNames[objectType.Name] { @@ -43,9 +43,9 @@ var objectTypesGen = rapid.Custom(func(t *rapid.T) []schema.ObjectType { // MustNewModuleSchema calls NewModuleSchema and panics if there's an error. This should generally be used // only in tests or initialization code. func MustNewModuleSchema(objectTypes []schema.ObjectType) schema.ModuleSchema { - schema, err := schema.NewModuleSchema(objectTypes) + sch, err := schema.NewModuleSchema(objectTypes) if err != nil { panic(err) } - return schema + return sch } diff --git a/schema/testing/object.go b/schema/testing/object.go index 8d7bd37a2a05..396e2537b383 100644 --- a/schema/testing/object.go +++ b/schema/testing/object.go @@ -7,7 +7,11 @@ import ( "cosmossdk.io/schema" ) -var fieldsGen = rapid.SliceOfNDistinct(FieldGen, 1, 12, func(f schema.Field) string { +var keyFieldsGen = rapid.SliceOfNDistinct(KeyFieldGen, 1, 6, func(f schema.Field) string { + return f.Name +}) + +var valueFieldsGen = rapid.SliceOfNDistinct(FieldGen, 1, 12, func(f schema.Field) string { return f.Name }) @@ -17,35 +21,44 @@ var ObjectTypeGen = rapid.Custom(func(t *rapid.T) schema.ObjectType { Name: NameGen.Draw(t, "name"), } - fields := fieldsGen.Draw(t, "fields") - numKeyFields := rapid.IntRange(0, len(fields)).Draw(t, "numKeyFields") - - typ.KeyFields = fields[:numKeyFields] - - for i := range typ.KeyFields { - // key fields can't be nullable - typ.KeyFields[i].Nullable = false - } - - typ.ValueFields = fields[numKeyFields:] - + typ.KeyFields = keyFieldsGen.Draw(t, "keyFields") + typ.ValueFields = valueFieldsGen.Draw(t, "valueFields") typ.RetainDeletions = boolGen.Draw(t, "retainDeletions") return typ }).Filter(func(typ schema.ObjectType) bool { - // filter out duplicate enum names + // filter out duplicate field names + fieldNames := map[string]bool{} + if hasDuplicateFieldNames(fieldNames, typ.KeyFields) { + return false + } + if hasDuplicateFieldNames(fieldNames, typ.ValueFields) { + return false + } + + // filter out duplicate type names typeNames := map[string]bool{typ.Name: true} - if hasDuplicateNames(typeNames, typ.KeyFields) { + if hasDuplicateTypeNames(typeNames, typ.KeyFields) { return false } - if hasDuplicateNames(typeNames, typ.ValueFields) { + if hasDuplicateTypeNames(typeNames, typ.ValueFields) { return false } return true }) -// hasDuplicateNames checks if there is type name in the fields -func hasDuplicateNames(typeNames map[string]bool, fields []schema.Field) bool { +func hasDuplicateFieldNames(typeNames map[string]bool, fields []schema.Field) bool { + for _, field := range fields { + if _, ok := typeNames[field.Name]; ok { + return true + } + typeNames[field.Name] = true + } + return false +} + +// hasDuplicateTypeNames checks if there is type name in the fields +func hasDuplicateTypeNames(typeNames map[string]bool, fields []schema.Field) bool { for _, field := range fields { if field.Kind != schema.EnumKind { continue @@ -68,60 +81,41 @@ func ObjectInsertGen(objectType schema.ObjectType) *rapid.Generator[schema.Objec // ObjectUpdateGen generates object updates that are valid for updates using the provided state map as a source // of valid existing keys. func ObjectUpdateGen(objectType schema.ObjectType, state *btree.Map[string, schema.ObjectUpdate]) *rapid.Generator[schema.ObjectUpdate] { - keyGen := ObjectKeyGen(objectType.KeyFields) - - if len(objectType.ValueFields) == 0 { - // special case where there are no value fields, - // so we just insert or delete, no updates - return rapid.Custom(func(t *rapid.T) schema.ObjectUpdate { - update := schema.ObjectUpdate{ - TypeName: objectType.Name, - } - - // 50% of the time delete existing key (when there are keys) - n := 0 - if state != nil { - n = state.Len() - } - if n > 0 && boolGen.Draw(t, "delete") { - i := rapid.IntRange(0, n-1).Draw(t, "index") - update.Key = state.Values()[i].Key - update.Delete = true - } else { - update.Key = keyGen.Draw(t, "key") - } + keyGen := ObjectKeyGen(objectType.KeyFields).Filter(func(key interface{}) bool { + // filter out keys that exist in the state + if state != nil { + _, exists := state.Get(ObjectKeyString(objectType, key)) + return !exists + } + return true + }) + insertValueGen := ObjectValueGen(objectType.ValueFields, false) + updateValueGen := ObjectValueGen(objectType.ValueFields, true) + return rapid.Custom(func(t *rapid.T) schema.ObjectUpdate { + update := schema.ObjectUpdate{ + TypeName: objectType.Name, + } - return update - }) - } else { - insertValueGen := ObjectValueGen(objectType.ValueFields, false) - updateValueGen := ObjectValueGen(objectType.ValueFields, true) - return rapid.Custom(func(t *rapid.T) schema.ObjectUpdate { - update := schema.ObjectUpdate{ - TypeName: objectType.Name, - } + // 50% of the time use existing key (when there are keys) + n := 0 + if state != nil { + n = state.Len() + } + if n > 0 && boolGen.Draw(t, "existingKey") { + i := rapid.IntRange(0, n-1).Draw(t, "index") + update.Key = state.Values()[i].Key - // 50% of the time use existing key (when there are keys) - n := 0 - if state != nil { - n = state.Len() - } - if n > 0 && boolGen.Draw(t, "existingKey") { - i := rapid.IntRange(0, n-1).Draw(t, "index") - update.Key = state.Values()[i].Key - - // delete 50% of the time - if boolGen.Draw(t, "delete") { - update.Delete = true - } else { - update.Value = updateValueGen.Draw(t, "value") - } + // delete 50% of the time + if boolGen.Draw(t, "delete") { + update.Delete = true } else { - update.Key = keyGen.Draw(t, "key") - update.Value = insertValueGen.Draw(t, "value") + update.Value = updateValueGen.Draw(t, "value") } + } else { + update.Key = keyGen.Draw(t, "key") + update.Value = insertValueGen.Draw(t, "value") + } - return update - }) - } + return update + }) } diff --git a/schema/testing/statesim/object_coll.go b/schema/testing/statesim/object_coll.go index 8531811de3c3..163a4205fcf3 100644 --- a/schema/testing/statesim/object_coll.go +++ b/schema/testing/statesim/object_coll.go @@ -48,7 +48,7 @@ func (o *ObjectCollection) ApplyUpdate(update schema.ObjectUpdate) error { return err } - keyStr := fmtObjectKey(o.objectType, update.Key) + keyStr := schematesting.ObjectKeyString(o.objectType, update.Key) cur, exists := o.objects.Get(keyStr) if update.Delete { if o.objectType.RetainDeletions && o.options.CanRetainDeletions { @@ -119,7 +119,7 @@ func (o *ObjectCollection) AllState(f func(schema.ObjectUpdate, error) bool) { // GetObject returns the object with the given key from the collection represented as an ObjectUpdate // itself. Deletions that are retained are returned as ObjectUpdate's with delete set to true. func (o *ObjectCollection) GetObject(key interface{}) (update schema.ObjectUpdate, found bool, err error) { - update, ok := o.objects.Get(fmtObjectKey(o.objectType, key)) + update, ok := o.objects.Get(schematesting.ObjectKeyString(o.objectType, key)) return update, ok, nil } @@ -132,37 +132,3 @@ func (o *ObjectCollection) ObjectType() schema.ObjectType { func (o *ObjectCollection) Len() (int, error) { return o.objects.Len(), nil } - -func fmtObjectKey(objectType schema.ObjectType, key any) string { - keyFields := objectType.KeyFields - n := len(keyFields) - switch n { - case 0: - return "" - case 1: - valStr := fmtValue(keyFields[0].Kind, key) - return fmt.Sprintf("%s=%v", keyFields[0].Name, valStr) - default: - ks := key.([]interface{}) - res := "" - for i := 0; i < n; i++ { - if i != 0 { - res += ", " - } - valStr := fmtValue(keyFields[i].Kind, ks[i]) - res += fmt.Sprintf("%s=%v", keyFields[i].Name, valStr) - } - return res - } -} - -func fmtValue(kind schema.Kind, value any) string { - switch kind { - case schema.BytesKind, schema.AddressKind: - return fmt.Sprintf("0x%x", value) - case schema.JSONKind: - return fmt.Sprintf("%s", value) - default: - return fmt.Sprintf("%v", value) - } -} diff --git a/schema/testing/statesim/object_coll_diff.go b/schema/testing/statesim/object_coll_diff.go index ce4f87efbef7..b38b577aec97 100644 --- a/schema/testing/statesim/object_coll_diff.go +++ b/schema/testing/statesim/object_coll_diff.go @@ -35,7 +35,7 @@ func DiffObjectCollections(expected, actual view.ObjectCollection) string { continue } - keyStr := fmtObjectKey(expected.ObjectType(), expectedUpdate.Key) + keyStr := schematesting.ObjectKeyString(expected.ObjectType(), expectedUpdate.Key) actualUpdate, found, err := actual.GetObject(expectedUpdate.Key) if err != nil { res += fmt.Sprintf("Object %s: ERROR: %v\n", keyStr, err)