diff --git a/schema/testing/diff.go b/schema/testing/diff.go index 413a9384eec3..9cf320f4cf28 100644 --- a/schema/testing/diff.go +++ b/schema/testing/diff.go @@ -3,6 +3,9 @@ package schematesting import ( "bytes" "fmt" + "math/big" + + "github.com/cockroachdb/apd/v3" "cosmossdk.io/schema" ) @@ -77,6 +80,8 @@ func DiffFieldValues(field schema.Field, expected, actual any) string { // CompareKindValues compares the expected and actual values for the provided kind and returns true if they are equal, // false if they are not, and an error if the types are not valid for the kind. +// For IntegerStringKind and DecimalStringKind values, comparisons are made based on equality of the underlying numeric +// values rather than their string encoding. func CompareKindValues(kind schema.Kind, expected, actual any) (bool, error) { if kind.ValidateValueType(expected) != nil { return false, fmt.Errorf("unexpected type %T for kind %s", expected, kind) @@ -91,6 +96,36 @@ func CompareKindValues(kind schema.Kind, expected, actual any) (bool, error) { if !bytes.Equal(expected.([]byte), actual.([]byte)) { return false, nil } + case schema.IntegerStringKind: + expectedInt := big.NewInt(0) + expectedInt, ok := expectedInt.SetString(expected.(string), 10) + if !ok { + return false, fmt.Errorf("could not convert %v to big.Int", expected) + } + + actualInt := big.NewInt(0) + actualInt, ok = actualInt.SetString(actual.(string), 10) + if !ok { + return false, fmt.Errorf("could not convert %v to big.Int", actual) + } + + if expectedInt.Cmp(actualInt) != 0 { + return false, nil + } + case schema.DecimalStringKind: + expectedDec, _, err := apd.NewFromString(expected.(string)) + if err != nil { + return false, fmt.Errorf("could not decode %v as a decimal: %w", expected, err) + } + + actualDec, _, err := apd.NewFromString(actual.(string)) + if err != nil { + return false, fmt.Errorf("could not decode %v as a decimal: %w", actual, err) + } + + if expectedDec.Cmp(actualDec) != 0 { + return false, nil + } default: if expected != actual { return false, nil diff --git a/schema/testing/diff_test.go b/schema/testing/diff_test.go new file mode 100644 index 000000000000..70bed0d1763e --- /dev/null +++ b/schema/testing/diff_test.go @@ -0,0 +1,111 @@ +package schematesting + +import ( + "testing" + + "cosmossdk.io/schema" +) + +func TestCompareKindValues(t *testing.T) { + tt := []struct { + kind schema.Kind + expected any + actual any + equal bool + expectError bool + }{ + { + kind: schema.BoolKind, + expected: "true", + actual: false, + expectError: true, + }, + { + kind: schema.BoolKind, + expected: true, + actual: "false", + expectError: true, + }, + { + kind: schema.BoolKind, + expected: true, + actual: false, + equal: false, + }, + { + kind: schema.BoolKind, + expected: true, + actual: true, + equal: true, + }, + { + kind: schema.BytesKind, + expected: []byte("hello"), + actual: []byte("world"), + equal: false, + }, + { + kind: schema.IntegerStringKind, + expected: "a123", + actual: "123", + expectError: true, + }, + { + kind: schema.IntegerStringKind, + expected: "123", + actual: "123b", + expectError: true, + }, + { + kind: schema.IntegerStringKind, + expected: "123", + actual: "1234", + equal: false, + }, + { + kind: schema.IntegerStringKind, + expected: "000123", + actual: "123", + equal: true, + }, + { + kind: schema.DecimalStringKind, + expected: "abc", + actual: "100.001", + expectError: true, + }, + { + kind: schema.DecimalStringKind, + expected: "1", + actual: "b", + expectError: true, + }, + { + kind: schema.DecimalStringKind, + expected: "1.00001", + actual: "100.001", + equal: false, + }, + { + kind: schema.DecimalStringKind, + expected: "1.00001e2", + actual: "100.001", + equal: true, + }, + { + kind: schema.DecimalStringKind, + expected: "00000100.00100000", + actual: "100.001", + equal: true, + }, + } + for _, tc := range tt { + eq, err := CompareKindValues(tc.kind, tc.expected, tc.actual) + if eq != tc.equal { + t.Errorf("expected %v, got %v", tc.equal, eq) + } + if (err != nil) != tc.expectError { + t.Errorf("expected error: %v, got %v", tc.expectError, err) + } + } +} diff --git a/schema/testing/go.mod b/schema/testing/go.mod index e1cfc343bcdf..28b6d2670c0c 100644 --- a/schema/testing/go.mod +++ b/schema/testing/go.mod @@ -2,6 +2,7 @@ module cosmossdk.io/schema/testing require ( cosmossdk.io/schema v0.0.0 + github.com/cockroachdb/apd/v3 v3.2.1 github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.7.0 gotest.tools/v3 v3.5.1 diff --git a/schema/testing/go.sum b/schema/testing/go.sum index 393b537c2d4a..2ec1ed9ec0a3 100644 --- a/schema/testing/go.sum +++ b/schema/testing/go.sum @@ -1,7 +1,11 @@ +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=