github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/amino/reflect_test.go (about)

     1  package amino_test
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"reflect"
     7  	"runtime/debug"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/davecgh/go-spew/spew"
    12  	fuzz "github.com/google/gofuzz"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  	proto "google.golang.org/protobuf/proto"
    16  
    17  	"github.com/gnolang/gno/tm2/pkg/amino"
    18  	"github.com/gnolang/gno/tm2/pkg/amino/tests"
    19  )
    20  
    21  // -------------------------------------
    22  // Non-interface Google fuzz tests
    23  
    24  func TestCodecStruct(t *testing.T) {
    25  	t.Parallel()
    26  
    27  	for _, ptr := range tests.StructTypes {
    28  		t.Logf("case %v", reflect.TypeOf(ptr))
    29  		rt := getTypeFromPointer(ptr)
    30  		name := rt.Name()
    31  		t.Run(name+":binary", func(t *testing.T) {
    32  			t.Parallel()
    33  			_testCodec(t, rt, "binary")
    34  		})
    35  		t.Run(name+":json", func(t *testing.T) {
    36  			t.Parallel()
    37  			_testCodec(t, rt, "json")
    38  		})
    39  	}
    40  }
    41  
    42  func TestCodecDef(t *testing.T) {
    43  	t.Parallel()
    44  
    45  	for _, ptr := range tests.DefTypes {
    46  		t.Logf("case %v", reflect.TypeOf(ptr))
    47  		rt := getTypeFromPointer(ptr)
    48  		name := rt.Name()
    49  		t.Run(name+":binary", func(t *testing.T) {
    50  			t.Parallel()
    51  			_testCodec(t, rt, "binary")
    52  		})
    53  		t.Run(name+":json", func(t *testing.T) {
    54  			t.Parallel()
    55  			_testCodec(t, rt, "json")
    56  		})
    57  	}
    58  }
    59  
    60  func TestDeepCopyStruct(t *testing.T) {
    61  	t.Parallel()
    62  
    63  	for _, ptr := range tests.StructTypes {
    64  		t.Logf("case %v", reflect.TypeOf(ptr))
    65  		rt := getTypeFromPointer(ptr)
    66  		name := rt.Name()
    67  		t.Run(name+":deepcopy", func(t *testing.T) {
    68  			t.Parallel()
    69  			_testDeepCopy(t, rt)
    70  		})
    71  	}
    72  }
    73  
    74  func TestDeepCopyDef(t *testing.T) {
    75  	t.Parallel()
    76  
    77  	for _, ptr := range tests.DefTypes {
    78  		t.Logf("case %v", reflect.TypeOf(ptr))
    79  		rt := getTypeFromPointer(ptr)
    80  		name := rt.Name()
    81  		t.Run(name+":deepcopy", func(t *testing.T) {
    82  			t.Parallel()
    83  			_testDeepCopy(t, rt)
    84  		})
    85  	}
    86  }
    87  
    88  func _testCodec(t *testing.T, rt reflect.Type, codecType string) {
    89  	t.Helper()
    90  
    91  	err := error(nil)
    92  	bz := []byte{}
    93  	cdc := amino.NewCodec()
    94  	f := fuzz.New()
    95  	rv := reflect.New(rt)
    96  	rv2 := reflect.New(rt)
    97  	ptr := rv.Interface()
    98  	ptr2 := rv2.Interface()
    99  	rnd := rand.New(rand.NewSource(10))
   100  	f.RandSource(rnd)
   101  	f.Funcs(fuzzFuncs...)
   102  
   103  	defer func() {
   104  		if r := recover(); r != nil {
   105  			t.Fatalf("panic'd:\nreason: %v\n%s\nerr: %v\nbz: %X\nrv: %#v\nrv2: %#v\nptr: %v\nptr2: %v\n",
   106  				r, debug.Stack(), err, bz, rv, rv2, spw(ptr), spw(ptr2),
   107  			)
   108  		}
   109  	}()
   110  
   111  	for i := 0; i < 1e4; i++ {
   112  		f.Fuzz(ptr)
   113  
   114  		// Reset, which makes debugging decoding easier.
   115  		rv2 = reflect.New(rt)
   116  		ptr2 = rv2.Interface()
   117  
   118  		// Encode to bz.
   119  		switch codecType {
   120  		case "binary":
   121  			bz, err = cdc.Marshal(ptr)
   122  		case "json":
   123  			bz, err = cdc.MarshalJSON(ptr)
   124  		default:
   125  			panic("should not happen")
   126  		}
   127  		require.Nil(t, err,
   128  			"failed to marshal %v to bytes: %v\n",
   129  			spw(ptr), err)
   130  
   131  		// Decode from bz.
   132  		switch codecType {
   133  		case "binary":
   134  			err = cdc.Unmarshal(bz, ptr2)
   135  		case "json":
   136  			err = cdc.UnmarshalJSON(bz, ptr2)
   137  		default:
   138  			panic("should not happen")
   139  		}
   140  		require.NoError(t, err,
   141  			"failed to unmarshal bytes %X (%s): %v\nptr: %v\n",
   142  			bz, bz, err, spw(ptr))
   143  		require.Equal(t, ptr, ptr2,
   144  			"end to end failed.\nstart: %v\nend: %v\nbytes: %X\nstring(bytes): %s\n",
   145  			spw(ptr), spw(ptr2), bz, bz)
   146  
   147  		if codecType == "binary" {
   148  			// Get pbo from rv. (go -> p3go)
   149  			pbm, ok := rv.Interface().(amino.PBMessager)
   150  			if !ok {
   151  				// typedefs that are not structs, for example,
   152  				// are not pbMessanger.
   153  				continue
   154  			}
   155  			pbo, err := pbm.ToPBMessage(cdc)
   156  			require.NoError(t, err)
   157  
   158  			// Get back to go from pbo, and ensure equality. (go -> p3go -> go vs go)
   159  			rv3 := reflect.New(rt)
   160  			ptr3 := rv3.Interface()
   161  			err = ptr3.(amino.PBMessager).FromPBMessage(cdc, pbo)
   162  			require.NoError(t, err)
   163  			require.Equal(t, ptr, ptr3,
   164  				"end to end through pbo failed.\nstart(goo): %v\nend(goo): %v\nmid(pbo): %v\n",
   165  				spw(ptr), spw(ptr3), spw(pbo))
   166  
   167  			// Marshal pbo and check for equality of bz and b3. (go -> p3go -> bz vs go -> bz)
   168  			bz3, err := proto.Marshal(pbo)
   169  			require.NoError(t, err)
   170  			require.Equal(t, bz, bz3,
   171  				"pbo serialization check failed.\nbz(go): %X\nbz(pb-go): %X\nstart(goo): %v\nend(pbo): %v\n",
   172  				bz, bz3, spw(ptr), spw(pbo))
   173  
   174  			// Decode from bz and check for equality (go -> bz -> p3go -> go vs go)
   175  			pbo2 := pbm.EmptyPBMessage(cdc)
   176  			err = proto.Unmarshal(bz, pbo2)
   177  			require.NoError(t, err)
   178  			rv4 := reflect.New(rt)
   179  			ptr4 := rv4.Interface()
   180  			err = ptr4.(amino.PBMessager).FromPBMessage(cdc, pbo2)
   181  			require.NoError(t, err)
   182  			require.Equal(t, ptr, ptr4,
   183  				"end to end through bytes and pbo failed.\nbz(go): %X\nstart(goo): %v\nend(goo): %v\nmid(pbo): %v\n",
   184  				bz, spw(ptr), spw(ptr3), spw(pbo))
   185  		}
   186  	}
   187  }
   188  
   189  func _testDeepCopy(t *testing.T, rt reflect.Type) {
   190  	t.Helper()
   191  
   192  	err := error(nil)
   193  	f := fuzz.New()
   194  	rv := reflect.New(rt)
   195  	ptr := rv.Interface()
   196  	rnd := rand.New(rand.NewSource(10))
   197  	f.RandSource(rnd)
   198  	f.Funcs(fuzzFuncs...)
   199  
   200  	defer func() {
   201  		if r := recover(); r != nil {
   202  			t.Fatalf("panic'd:\nreason: %v\n%s\nerr: %v\nrv: %#v\nptr: %v\n",
   203  				r, debug.Stack(), err, rv, spw(ptr),
   204  			)
   205  		}
   206  	}()
   207  
   208  	for i := 0; i < 1e4; i++ {
   209  		f.Fuzz(ptr)
   210  
   211  		ptr2 := amino.DeepCopy(ptr)
   212  
   213  		require.Equal(t, ptr, ptr2,
   214  			"end to end failed.\nstart: %v\nend: %v\nbytes: %X\nstring(bytes): %s\n",
   215  			spw(ptr), spw(ptr2))
   216  	}
   217  }
   218  
   219  // ----------------------------------------
   220  // Register/interface tests
   221  
   222  func TestCodecMashalFailsOnUnregisteredConcrete(t *testing.T) {
   223  	t.Parallel()
   224  
   225  	cdc := amino.NewCodec()
   226  
   227  	bz, err := cdc.Marshal(struct{ tests.Interface1 }{tests.Concrete1{}})
   228  	assert.Error(t, err, "concrete type not registered")
   229  	assert.Empty(t, bz)
   230  }
   231  
   232  func TestCodecMarshalPassesOnRegistered(t *testing.T) {
   233  	t.Parallel()
   234  
   235  	cdc := amino.NewCodec()
   236  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.Concrete1{}), tests.Package)
   237  
   238  	bz, err := cdc.Marshal(struct{ tests.Interface1 }{tests.Concrete1{}})
   239  	assert.NoError(t, err, "correctly registered")
   240  	assert.Equal(t,
   241  		//     0x0a --> field #1 Typ3ByteLength (anonymous struct)
   242  		//           0x12 --> length prefix (18 bytes)
   243  		//                 0x0a --> field #1 Typ3ByteLength (Any)
   244  		//                       0x10 --> length prefix (12 bytes)
   245  		//                             0x2f, ... 0x31 --> "/tests.Concrete1"
   246  		[]byte{0x0a, 0x12, 0x0a, 0x10, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x31},
   247  		bz,
   248  		"bytes did not match")
   249  }
   250  
   251  func TestCodecRegisterAndMarshalMultipleConcrete(t *testing.T) {
   252  	t.Parallel()
   253  
   254  	cdc := amino.NewCodec()
   255  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.Concrete1{}), tests.Package)
   256  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.Concrete2{}), tests.Package)
   257  
   258  	{ // test tests.Concrete1, no conflict.
   259  		bz, err := cdc.Marshal(struct{ tests.Interface1 }{tests.Concrete1{}})
   260  		assert.NoError(t, err, "correctly registered")
   261  		assert.Equal(t,
   262  			//     0x0a --> field #1 Typ3ByteLength (anonymous struct)
   263  			//           0x12 --> length prefix (18 bytes)
   264  			//                 0x0a --> field #1 Typ3ByteLength (Any)
   265  			//                       0x10 --> length prefix (12 bytes)
   266  			//                             0x2f, ... 0x31 --> "/tests.Concrete1"
   267  			[]byte{0x0a, 0x12, 0x0a, 0x10, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x31},
   268  			bz,
   269  			"bytes did not match")
   270  	}
   271  
   272  	{ // test tests.Concrete2, no conflict
   273  		bz, err := cdc.Marshal(struct{ tests.Interface1 }{tests.Concrete2{}})
   274  		assert.NoError(t, err, "correctly registered")
   275  		assert.Equal(t,
   276  			//     0x0a --> field #1 Typ3ByteLength (anonymous struct)
   277  			//           0x12 --> length prefix (18 bytes)
   278  			//                 0x0a --> field #1 Typ3ByteLength (Any TypeURL)
   279  			//                       0x10 --> length prefix (12 bytes)
   280  			//                             0x2f, ... 0x31 --> "/tests.Concrete2"
   281  			[]byte{0x0a, 0x12, 0x0a, 0x10, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x32},
   282  			bz,
   283  			"bytes did not match")
   284  	}
   285  }
   286  
   287  // Serialize and deserialize a registered typedef.
   288  func TestCodecRoundtripNonNilRegisteredTypeDef(t *testing.T) {
   289  	t.Parallel()
   290  
   291  	cdc := amino.NewCodec()
   292  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package)
   293  
   294  	c3 := tests.ConcreteTypeDef{}
   295  	copy(c3[:], []byte("0123"))
   296  
   297  	bz, err := cdc.Marshal(struct{ tests.Interface1 }{c3})
   298  	assert.Nil(t, err)
   299  	assert.Equal(t,
   300  		//     0x0a --> field #1 Typ3ByteLength (anonymous struct)
   301  		//           0x20 --> length prefix (32 bytes)
   302  		//                 0x0a --> field #1 Typ3ByteLength (Any TypeURL)
   303  		//                       0x16 --> length prefix (18 bytes)
   304  		//                             0x2f, ... 0x31 --> "/tests.ConcreteTypeDef"
   305  		[]byte{
   306  			0x0a, 0x20, 0x0a, 0x16, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x65, 0x66,
   307  			//   0x12 --> field #2 Typ3ByteLength (Any Value)
   308  			//         0x06 --> length prefix (6 bytes)
   309  			//               0x0a --> field #1, one and only, of implicit struct.
   310  			//                     0x04 --> length prefix (4 bytes)
   311  			/**/ 0x12, 0x06, 0x0a, 0x04, 0x30, 0x31, 0x32, 0x33,
   312  		},
   313  		bz,
   314  		"ConcreteTypeDef incorrectly serialized")
   315  
   316  	var i1 tests.Interface1
   317  	err = cdc.Unmarshal(bz, &i1)
   318  	assert.Error(t, err) // This fails, because the interface was wrapped in an anonymous struct.
   319  
   320  	// try wrapping it in an Any struct
   321  	// without changing the existing behavior.
   322  	type anyType struct {
   323  		TypeURL string
   324  		Value   []byte
   325  	}
   326  	anyc3 := anyType{
   327  		TypeURL: "/tests.ConcreteTypeDef",
   328  		Value:   []byte{0x0a, 0x04, 0x30, 0x31, 0x32, 0x33}, // An implicit struct, the first field which is the length-prefixed 4 bytes.
   329  	}
   330  
   331  	// var i1c3 tests.Interface1 = c3
   332  	// bz, err = cdc.Marshal(&i1c3)
   333  	bz, err = cdc.Marshal(anyc3)
   334  	assert.Nil(t, err)
   335  	assert.Equal(t,
   336  		//     0x0a --> field #1 Typ3ByteLength (Any TypeURL)
   337  		//           0x16 --> length prefix (22 bytes)
   338  		//                 0x2f, ... 0x33 --> "/tests.ConcreteTypeDef"
   339  		[]byte{
   340  			0x0a, 0x16, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x65, 0x66,
   341  			//   0x12 --> field #2 Typ3ByteLength (Any Value)
   342  			//         0x06 --> length prefix (6 bytes)
   343  			//               0x0a --> field #1, one and only, of implicit struct.
   344  			//                     0x04 --> length prefix (4 bytes)
   345  			/**/ 0x12, 0x06, 0x0a, 0x04, 0x30, 0x31, 0x32, 0x33,
   346  		},
   347  		bz,
   348  		"ConcreteTypeDef incorrectly serialized")
   349  
   350  	// This time it should work.
   351  	err = cdc.Unmarshal(bz, &i1)
   352  	assert.NoError(t, err)
   353  	assert.Equal(t, c3, i1)
   354  
   355  	// The easiest way is this:
   356  	bz2, err := cdc.MarshalAny(c3)
   357  	assert.Nil(t, err)
   358  	assert.Equal(t, bz, bz2)
   359  }
   360  
   361  // Exactly like TestCodecRoundtripNonNilRegisteredTypeDef but with struct
   362  // around the value instead of a type def.
   363  func TestCodecRoundtripNonNilRegisteredWrappedValue(t *testing.T) {
   364  	t.Parallel()
   365  
   366  	cdc := amino.NewCodec()
   367  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteWrappedBytes{}), tests.Package)
   368  
   369  	c3 := tests.ConcreteWrappedBytes{Value: []byte("0123")}
   370  
   371  	bz, err := cdc.MarshalAny(c3)
   372  	assert.Nil(t, err)
   373  	assert.Equal(t,
   374  		//     0x0a --> field #1 Typ3ByteLength (Any TypeURL)
   375  		//           0x1b --> length prefix (27 bytes)
   376  		//                 0x2f, ... 0x33 --> "/tests.ConcreteWrappedBytes"
   377  		[]byte{
   378  			0x0a, 0x1b, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73,
   379  			//   0x12 --> field #2 Typ3ByteLength (Any Value)
   380  			//         0x06 --> length prefix (6 bytes)
   381  			//               0x0a --> field #1, one and only, of implicit struct.
   382  			//                     0x04 --> length prefix (4 bytes)
   383  			/**/ 0x12, 0x06, 0x0a, 0x04, 0x30, 0x31, 0x32, 0x33,
   384  		},
   385  		bz,
   386  		"ConcreteWrappedBytes incorrectly serialized")
   387  
   388  	var i1 tests.Interface1
   389  	err = cdc.Unmarshal(bz, &i1)
   390  	assert.NoError(t, err)
   391  	assert.Equal(t, c3, i1)
   392  }
   393  
   394  // MarshalAny(msg) and Marshal(&msg) are the same.
   395  func TestCodecMarshalAny(t *testing.T) {
   396  	t.Parallel()
   397  
   398  	cdc := amino.NewCodec()
   399  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteWrappedBytes{}), tests.Package)
   400  
   401  	obj := tests.ConcreteWrappedBytes{Value: []byte("0123")}
   402  	ifc := (interface{})(obj)
   403  
   404  	bz1, err := cdc.MarshalAny(obj)
   405  	assert.Nil(t, err)
   406  
   407  	bz2, err := cdc.Marshal(&ifc)
   408  	assert.Nil(t, err)
   409  
   410  	assert.Equal(t, bz1, bz2, "Marshal(*interface) or MarshalAny(concrete) incorrectly serialized\nMarshalAny(concrete): %X\nMarshal(*interface):  %X", bz1, bz2)
   411  }
   412  
   413  // Like TestCodecRoundtripNonNilRegisteredTypeDef, but JSON.
   414  func TestCodecJSONRoundtripNonNilRegisteredTypeDef(t *testing.T) {
   415  	t.Parallel()
   416  
   417  	cdc := amino.NewCodec()
   418  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package)
   419  
   420  	var c3 tests.ConcreteTypeDef
   421  	copy(c3[:], []byte("0123"))
   422  
   423  	bz, err := cdc.MarshalJSONAny(c3)
   424  	assert.Nil(t, err)
   425  	assert.Equal(t,
   426  		`{"@type":"/tests.ConcreteTypeDef","value":"MDEyMw=="}`, string(bz),
   427  		"ConcreteTypeDef incorrectly serialized")
   428  
   429  	var i1 tests.Interface1
   430  	err = cdc.UnmarshalJSON(bz, &i1)
   431  	assert.Nil(t, err)
   432  	assert.Equal(t, c3, i1)
   433  }
   434  
   435  // Like TestCodecRoundtripNonNilRegisteredTypeDef, but serialize the concrete value directly.
   436  func TestCodecRoundtripMarshalOnConcreteNonNilRegisteredTypeDef(t *testing.T) {
   437  	t.Parallel()
   438  
   439  	cdc := amino.NewCodec()
   440  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package)
   441  
   442  	var c3 tests.ConcreteTypeDef
   443  	copy(c3[:], []byte("0123"))
   444  
   445  	bz, err := cdc.MarshalAny(c3)
   446  	assert.Nil(t, err)
   447  	assert.Equal(t,
   448  		//     0x0a --> field #1 Typ3ByteLength (Any TypeURL)
   449  		//           0x16 --> length prefix (18 bytes)
   450  		//                 0x2f, ... 0x31 --> "/tests.ConcreteTypeDef"
   451  		[]byte{
   452  			0x0a, 0x16, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x65, 0x66,
   453  			//   0x12 --> field #2 Typ3ByteLength (Any Value)
   454  			//         0x06 --> length prefix (6 bytes)
   455  			//               0x0a --> field #1, one and only, of implicit struct.
   456  			//                     0x04 --> length prefix (4 bytes)
   457  			/**/ 0x12, 0x06, 0x0a, 0x04, 0x30, 0x31, 0x32, 0x33,
   458  		},
   459  		bz,
   460  		"ConcreteTypeDef incorrectly serialized")
   461  
   462  	var i1 tests.Interface1
   463  	err = cdc.Unmarshal(bz, &i1)
   464  	assert.NoError(t, err)
   465  	assert.Equal(t, c3, i1)
   466  }
   467  
   468  // Like TestCodecRoundtripNonNilRegisteredTypeDef but read into concrete var.
   469  func TestCodecRoundtripUnmarshalOnConcreteNonNilRegisteredTypeDef(t *testing.T) {
   470  	t.Parallel()
   471  
   472  	cdc := amino.NewCodec()
   473  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.ConcreteTypeDef{}), tests.Package)
   474  
   475  	var c3a tests.ConcreteTypeDef
   476  	copy(c3a[:], []byte("0123"))
   477  
   478  	bz, err := cdc.Marshal(c3a)
   479  	assert.Nil(t, err)
   480  	assert.Equal(t,
   481  		[]byte{0xa, 0x4, 0x30, 0x31, 0x32, 0x33}, bz,
   482  		"ConcreteTypeDef incorrectly serialized")
   483  
   484  	var c3b tests.ConcreteTypeDef
   485  	err = cdc.Unmarshal(bz, &c3b)
   486  	assert.Nil(t, err)
   487  	assert.Equal(t, c3a, c3b)
   488  }
   489  
   490  func TestCodecBinaryStructFieldNilInterface(t *testing.T) {
   491  	t.Parallel()
   492  
   493  	cdc := amino.NewCodec()
   494  	cdc.RegisterTypeFrom(reflect.TypeOf(tests.InterfaceFieldsStruct{}), tests.Package)
   495  
   496  	i1 := &tests.InterfaceFieldsStruct{F1: new(tests.InterfaceFieldsStruct), F2: nil}
   497  	bz, err := cdc.MarshalSized(i1)
   498  	assert.NoError(t, err)
   499  
   500  	i2 := new(tests.InterfaceFieldsStruct)
   501  	err = cdc.UnmarshalSized(bz, i2)
   502  
   503  	assert.NoError(t, err)
   504  	require.Equal(t, i1, i2, "i1 and i2 should be the same after decoding")
   505  }
   506  
   507  // ----------------------------------------
   508  // Misc.
   509  
   510  func spw(o interface{}) string {
   511  	return spew.Sprintf("%#v", o)
   512  }
   513  
   514  var fuzzFuncs = []interface{}{
   515  	func(ptr **int8, c fuzz.Continue) {
   516  		var i int8
   517  		c.Fuzz(&i)
   518  		*ptr = &i
   519  	},
   520  	func(ptr **int16, c fuzz.Continue) {
   521  		var i int16
   522  		c.Fuzz(&i)
   523  		*ptr = &i
   524  	},
   525  	func(ptr **int32, c fuzz.Continue) {
   526  		var i int32
   527  		c.Fuzz(&i)
   528  		*ptr = &i
   529  	},
   530  	func(ptr **int64, c fuzz.Continue) {
   531  		var i int64
   532  		c.Fuzz(&i)
   533  		*ptr = &i
   534  	},
   535  	func(ptr **int, c fuzz.Continue) {
   536  		var i int
   537  		c.Fuzz(&i)
   538  		*ptr = &i
   539  	},
   540  	func(ptr **uint8, c fuzz.Continue) {
   541  		var ui uint8
   542  		c.Fuzz(&ui)
   543  		*ptr = &ui
   544  	},
   545  	/* go-amino 1.2 removed nested pointer support
   546  	func(ptr ***uint8, c fuzz.Continue) {
   547  		var ui uint8
   548  		c.Fuzz(&ui)
   549  		*ptr = new(*uint8)
   550  		**ptr = new(uint8)
   551  		***ptr = ui
   552  	},
   553  	func(ptr ****uint8, c fuzz.Continue) {
   554  		var ui uint8
   555  		c.Fuzz(&ui)
   556  		*ptr = new(**uint8)
   557  		**ptr = new(*uint8)
   558  		***ptr = new(uint8)
   559  		****ptr = ui
   560  	},
   561  	*/
   562  	func(ptr **uint16, c fuzz.Continue) {
   563  		var ui uint16
   564  		c.Fuzz(&ui)
   565  		*ptr = &ui
   566  	},
   567  	func(ptr **uint32, c fuzz.Continue) {
   568  		var ui uint32
   569  		c.Fuzz(&ui)
   570  		*ptr = &ui
   571  	},
   572  	func(ptr **uint64, c fuzz.Continue) {
   573  		var ui uint64
   574  		c.Fuzz(&ui)
   575  		*ptr = &ui
   576  	},
   577  	func(ptr **uint, c fuzz.Continue) {
   578  		var ui uint
   579  		c.Fuzz(&ui)
   580  		*ptr = &ui
   581  	},
   582  	func(ptr **string, c fuzz.Continue) {
   583  		// Prefer nil instead of zero, for deep equality.
   584  		// (go-amino decoder will always prefer nil).
   585  		s := randString(c)
   586  		if len(s) == 0 {
   587  			*ptr = nil
   588  		} else {
   589  			*ptr = &s
   590  		}
   591  	},
   592  	func(bz **[]byte, c fuzz.Continue) {
   593  		// Prefer nil instead of zero, for deep equality.
   594  		// (go-amino decoder will always prefer nil).
   595  		var by []byte
   596  		c.Fuzz(&by)
   597  		*bz = &by
   598  	},
   599  	func(tyme *time.Time, c fuzz.Continue) {
   600  		// Set time.Unix(_,_) to wipe .wal
   601  		switch c.Intn(4) {
   602  		case 0:
   603  			ns := c.Int63n(10)
   604  			*tyme = time.Unix(0, ns)
   605  		case 1:
   606  			ns := c.Int63n(1e10)
   607  			*tyme = time.Unix(0, ns)
   608  		case 2:
   609  			const maxSeconds = 4611686018 // (1<<63 - 1) / 1e9
   610  			s := c.Int63n(maxSeconds)
   611  			ns := c.Int63n(1e10)
   612  			*tyme = time.Unix(s, ns)
   613  		case 3:
   614  			s := c.Int63n(10)
   615  			ns := c.Int63n(1e10)
   616  			*tyme = time.Unix(s, ns)
   617  		}
   618  		// Strip timezone and monotonic for deep equality.
   619  		// Also set to UTC.
   620  		*tyme = tyme.Truncate(0).UTC()
   621  	},
   622  	func(ptr **time.Duration, c fuzz.Continue) {
   623  		// Zero should decode to ptr to zero duration,
   624  		// rather than a nil duration pointer.
   625  		switch c.Intn(4) {
   626  		case 0:
   627  			ns := c.Int63n(20) - 10
   628  			dur := time.Duration(ns)
   629  			*ptr = &dur
   630  		case 1:
   631  			ns := c.Int63n(2e10) - 1e10
   632  			dur := time.Duration(ns)
   633  			*ptr = &dur
   634  		case 2: // NOTE: not max p3 duration
   635  			ns := 1<<63 - 1
   636  			dur := time.Duration(ns)
   637  			*ptr = &dur
   638  		case 3: // NOTE: not min p3 duration
   639  			ns := -1<<63 + 1
   640  			dur := time.Duration(ns)
   641  			*ptr = &dur
   642  		}
   643  	},
   644  	func(esz *[]*tests.EmptyStruct, c fuzz.Continue) {
   645  		n := c.Intn(4)
   646  		switch n {
   647  		case 0:
   648  			// Prefer nil over empty slice.
   649  			*esz = nil
   650  		default:
   651  			// Empty slice elements should be non-nil,
   652  			// since we don't set amino:"nil_elements".
   653  			*esz = make([]*tests.EmptyStruct, n)
   654  			for i := 0; i < n; i++ {
   655  				(*esz)[i] = &tests.EmptyStruct{}
   656  			}
   657  		}
   658  	},
   659  }
   660  
   661  func getTypeFromPointer(ptr interface{}) reflect.Type {
   662  	rt := reflect.TypeOf(ptr)
   663  	if rt.Kind() != reflect.Ptr {
   664  		panic(fmt.Sprintf("expected pointer, got %v", rt))
   665  	}
   666  	return rt.Elem()
   667  }
   668  
   669  // ----------------------------------------
   670  // From https://github.com/google/gofuzz/blob/master/fuzz.go
   671  // (Apache2.0 License)
   672  
   673  type charRange struct {
   674  	first, last rune
   675  }
   676  
   677  // choose returns a random unicode character from the given range, using the
   678  // given randomness source.
   679  func (r *charRange) choose(rand fuzz.Continue) rune {
   680  	count := int64(r.last - r.first)
   681  	return r.first + rune(rand.Int63n(count))
   682  }
   683  
   684  var unicodeRanges = []charRange{
   685  	{' ', '~'},           // ASCII characters
   686  	{'\u00a0', '\u02af'}, // Multi-byte encoded characters
   687  	{'\u4e00', '\u9fff'}, // Common CJK (even longer encodings)
   688  }
   689  
   690  // randString makes a random string up to 20 characters long. The returned string
   691  // may include a variety of (valid) UTF-8 encodings.
   692  func randString(r fuzz.Continue) string {
   693  	n := r.Intn(19) + 1
   694  	runes := make([]rune, n)
   695  	for i := range runes {
   696  		runes[i] = unicodeRanges[r.Intn(len(unicodeRanges))].choose(r)
   697  	}
   698  	return string(runes)
   699  }