test: x/tx/signing/textual: fuzz CoinsValueRenderer (#16521)
Co-authored-by: Marko <marbar3778@yahoo.com> Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com>
This commit is contained in:
parent
13a752b063
commit
1afeca75a1
@ -22,6 +22,7 @@ require (
|
||||
github.com/cosmos/gogoproto v1.4.10 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||
golang.org/x/net v0.11.0 // indirect
|
||||
|
||||
@ -20,8 +20,9 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
|
||||
@ -71,7 +71,7 @@ func checkCoinsEqual(t *testing.T, l1, l2 protoreflect.List) {
|
||||
|
||||
for i := 0; i < l1.Len(); i++ {
|
||||
coin, ok := l1.Get(i).Message().Interface().(*basev1beta1.Coin)
|
||||
require.True(t, ok)
|
||||
require.True(t, ok, "not a *basev1beta1.Coin: %#v", l1.Get(i).Message().Interface())
|
||||
coinsMap[coin.Denom] = coin
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ func checkCoinEqual(t *testing.T, coin, coin1 *basev1beta1.Coin) {
|
||||
require.True(t, ok)
|
||||
v1, ok := math.NewIntFromString(coin1.Amount)
|
||||
require.True(t, ok)
|
||||
require.True(t, v.Equal(v1))
|
||||
require.True(t, v.Equal(v1), "Mismatch\n\tv: %+v\n\tv1: %+v", v, v1)
|
||||
}
|
||||
|
||||
// coinsJSONTest is the type of test cases in the testdata file.
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
tspb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1"
|
||||
"cosmossdk.io/x/tx/internal/testpb"
|
||||
"cosmossdk.io/x/tx/signing/textual"
|
||||
)
|
||||
@ -211,3 +213,87 @@ func FuzzMessageValueRendererParse(f *testing.F) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Copied from types/coin.go but pasted in here so as to avoid any imports
|
||||
// of that package as has been mandated by team decisions.
|
||||
var (
|
||||
reCoinDenom = regexp.MustCompile(`[a-zA-Z][a-zA-Z0-9/:._-]{2,127}`)
|
||||
reCoinAmount = regexp.MustCompile(`[[:digit:]]+(?:\.[[:digit:]]+)?|\.[[:digit:]]+`)
|
||||
)
|
||||
|
||||
func FuzzCoinsJSONTestcases(f *testing.F) {
|
||||
// Generate some seeds.
|
||||
seed, err := os.ReadFile("./internal/testdata/coins.json")
|
||||
if err != nil {
|
||||
f.Fatal(err)
|
||||
}
|
||||
f.Add(seed)
|
||||
|
||||
txt, err := textual.NewSignModeHandler(textual.SignModeOptions{CoinMetadataQuerier: mockCoinMetadataQuerier})
|
||||
if err != nil {
|
||||
f.Fatal(err)
|
||||
}
|
||||
rend, err := txt.GetFieldValueRenderer(fieldDescriptorFromName("COINS"))
|
||||
if err != nil {
|
||||
f.Fatal(err)
|
||||
}
|
||||
vrr := rend.(textual.RepeatedValueRenderer)
|
||||
|
||||
f.Fuzz(func(t *testing.T, input []byte) {
|
||||
var testCases []coinsJSONTest
|
||||
if err := json.Unmarshal(input, &testCases); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
if tc.Proto == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create a context.Context containing all coins metadata, to simulate
|
||||
// that they are in state.
|
||||
ctx := context.Background()
|
||||
for _, v := range tc.Metadata {
|
||||
ctx = addMetadataToContext(ctx, v)
|
||||
}
|
||||
|
||||
listValue := NewGenericList(tc.Proto)
|
||||
screens, err := vrr.FormatRepeated(ctx, protoreflect.ValueOf(listValue))
|
||||
if err != nil {
|
||||
cpt := tc.Proto[0]
|
||||
likeEmpty := err.Error() == "cannot format empty string" || err.Error() == "decimal string cannot be empty"
|
||||
if likeEmpty && (!reCoinDenom.MatchString(cpt.Denom) || cpt.Amount == "") {
|
||||
return
|
||||
}
|
||||
if !reCoinDenom.MatchString(cpt.Denom) {
|
||||
return
|
||||
}
|
||||
if !reCoinAmount.MatchString(cpt.Amount) {
|
||||
return
|
||||
}
|
||||
t.Fatalf("%v\n%q\n%#v => %t", err, tc.Text, cpt, cpt.Amount == "")
|
||||
}
|
||||
|
||||
if g, w := len(screens), 1; g != w {
|
||||
t.Fatalf("Screens mismatch: got=%d want=%d", g, w)
|
||||
}
|
||||
|
||||
wantContent := tc.Text
|
||||
if wantContent == "" {
|
||||
wantContent = "zero"
|
||||
}
|
||||
if false {
|
||||
if g, w := screens[0].Content, wantContent; g != w {
|
||||
t.Fatalf("Content mismatch:\n\tGot: %s\n\tWant: %s", g, w)
|
||||
}
|
||||
}
|
||||
|
||||
// Round trip.
|
||||
parsedValue := NewGenericList([]*basev1beta1.Coin{})
|
||||
if err := vrr.ParseRepeated(ctx, screens, parsedValue); err != nil {
|
||||
return
|
||||
}
|
||||
checkCoinsEqual(t, listValue, parsedValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
2
x/tx/signing/textual/testdata/fuzz/FuzzCoinsJSONTestcases/4d81af7cc74558bf
vendored
Normal file
2
x/tx/signing/textual/testdata/fuzz/FuzzCoinsJSONTestcases/4d81af7cc74558bf
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("[{\"proto\":[{\"Amount\":\"0\"},{\"Amount\":\"1\"}]}]")
|
||||
Loading…
Reference in New Issue
Block a user