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

     1  package amino_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  
    12  	amino "github.com/gnolang/gno/tm2/pkg/amino"
    13  	"github.com/gnolang/gno/tm2/pkg/amino/tests"
    14  )
    15  
    16  type SimpleStruct struct {
    17  	String string
    18  	Bytes  []byte
    19  	Time   time.Time
    20  }
    21  
    22  func newSimpleStruct() SimpleStruct {
    23  	s := SimpleStruct{
    24  		String: "hello",
    25  		Bytes:  []byte("goodbye"),
    26  		Time:   time.Now().UTC().Truncate(time.Millisecond), // strip monotonic and timezone.
    27  	}
    28  	return s
    29  }
    30  
    31  func TestMarshalUnmarshalPointer0(t *testing.T) {
    32  	t.Parallel()
    33  
    34  	s := newSimpleStruct()
    35  	cdc := amino.NewCodec()
    36  	b, err := cdc.MarshalSized(s) // no indirection
    37  	assert.NoError(t, err)
    38  
    39  	var s2 SimpleStruct
    40  	err = cdc.UnmarshalSized(b, &s2) // no indirection
    41  	assert.NoError(t, err)
    42  	assert.Equal(t, s, s2)
    43  }
    44  
    45  func TestMarshalUnmarshalPointer1(t *testing.T) {
    46  	t.Parallel()
    47  
    48  	s := newSimpleStruct()
    49  	cdc := amino.NewCodec()
    50  	b, err := cdc.MarshalSized(&s) // extra indirection
    51  	assert.NoError(t, err)
    52  
    53  	var s2 SimpleStruct
    54  	err = cdc.UnmarshalSized(b, &s2) // no indirection
    55  	assert.NoError(t, err)
    56  	assert.Equal(t, s, s2)
    57  }
    58  
    59  func TestMarshalUnmarshalPointer2(t *testing.T) {
    60  	t.Parallel()
    61  
    62  	s := newSimpleStruct()
    63  	ptr := &s
    64  	cdc := amino.NewCodec()
    65  	assert.Panics(t, func() {
    66  		cdc.MarshalSized(&ptr) // double extra indirection panics.
    67  		cdc.RegisterPackage(tests.Package)
    68  	})
    69  }
    70  
    71  func TestMarshalUnmarshalPointer3(t *testing.T) {
    72  	t.Parallel()
    73  
    74  	s := newSimpleStruct()
    75  	cdc := amino.NewCodec()
    76  	b, err := cdc.MarshalSized(s) // no indirection
    77  	assert.NoError(t, err)
    78  
    79  	var s2 *SimpleStruct
    80  	err = cdc.UnmarshalSized(b, &s2) // extra indirection
    81  	assert.NoError(t, err)
    82  	assert.Equal(t, s, *s2)
    83  }
    84  
    85  func TestDecodeVarint8(t *testing.T) {
    86  	t.Parallel()
    87  
    88  	// DecodeVarint8 uses binary.Varint so we need to make
    89  	// sure that all the values out of the range of [-128, 127]
    90  	// return an error.
    91  	tests := []struct {
    92  		in      int64
    93  		wantErr string
    94  		want    int8
    95  	}{
    96  		{in: 0x7F, want: 0x7F},
    97  		{in: -0x7F, want: -0x7F},
    98  		{in: -0x80, want: -0x80},
    99  		{in: 0x10, want: 0x10},
   100  
   101  		{in: -0xFF, wantErr: "decoding int8"},
   102  		{in: 0xFF, wantErr: "decoding int8"},
   103  		{in: 0x100, wantErr: "decoding int8"},
   104  		{in: -0x100, wantErr: "decoding int8"},
   105  	}
   106  
   107  	buf := make([]byte, 10)
   108  	for i, tt := range tests {
   109  		n := binary.PutVarint(buf, tt.in)
   110  		gotI8, gotN, err := amino.DecodeVarint8(buf[:n])
   111  		if tt.wantErr != "" {
   112  			if err == nil {
   113  				t.Errorf("#%d expected error=%q", i, tt.wantErr)
   114  			} else if !strings.Contains(err.Error(), tt.wantErr) {
   115  				t.Errorf("#%d\ngotErr=%q\nwantSegment=%q", i, err, tt.wantErr)
   116  			}
   117  			continue
   118  		}
   119  
   120  		if err != nil {
   121  			t.Errorf("#%d unexpected error: %v", i, err)
   122  			continue
   123  		}
   124  
   125  		if wantI8 := tt.want; gotI8 != wantI8 {
   126  			t.Errorf("#%d gotI8=%d wantI8=%d", i, gotI8, wantI8)
   127  		}
   128  		if wantN := n; gotN != wantN {
   129  			t.Errorf("#%d gotN=%d wantN=%d", i, gotN, wantN)
   130  		}
   131  	}
   132  }
   133  
   134  func TestDecodeVarint16(t *testing.T) {
   135  	t.Parallel()
   136  
   137  	// DecodeVarint16 uses binary.Varint so we need to make
   138  	// sure that all the values out of the range of [-32768, 32767]
   139  	// return an error.
   140  	tests := []struct {
   141  		in      int64
   142  		wantErr string
   143  		want    int16
   144  	}{
   145  		{in: -0x8000, want: -0x8000},
   146  		{in: -0x7FFF, want: -0x7FFF},
   147  		{in: -0x7F, want: -0x7F},
   148  		{in: -0x80, want: -0x80},
   149  		{in: 0x10, want: 0x10},
   150  
   151  		{in: -0xFFFF, wantErr: "decoding int16"},
   152  		{in: 0xFFFF, wantErr: "decoding int16"},
   153  		{in: 0x10000, wantErr: "decoding int16"},
   154  		{in: -0x10000, wantErr: "decoding int16"},
   155  	}
   156  
   157  	buf := make([]byte, 10)
   158  	for i, tt := range tests {
   159  		n := binary.PutVarint(buf, tt.in)
   160  		gotI16, gotN, err := amino.DecodeVarint16(buf[:n])
   161  		if tt.wantErr != "" {
   162  			if err == nil {
   163  				t.Errorf("#%d in=(%X) expected error=%q", i, tt.in, tt.wantErr)
   164  			} else if !strings.Contains(err.Error(), tt.wantErr) {
   165  				t.Errorf("#%d\ngotErr=%q\nwantSegment=%q", i, err, tt.wantErr)
   166  			}
   167  			continue
   168  		}
   169  
   170  		if err != nil {
   171  			t.Errorf("#%d unexpected error: %v", i, err)
   172  			continue
   173  		}
   174  
   175  		if wantI16 := tt.want; gotI16 != wantI16 {
   176  			t.Errorf("#%d gotI16=%d wantI16=%d", i, gotI16, wantI16)
   177  		}
   178  		if wantN := n; gotN != wantN {
   179  			t.Errorf("#%d gotN=%d wantN=%d", i, gotN, wantN)
   180  		}
   181  	}
   182  }
   183  
   184  func TestEncodeDecodeString(t *testing.T) {
   185  	t.Parallel()
   186  
   187  	s := "🔌🎉⛵︎♠️⎍"
   188  	bs := []byte(s)
   189  	di := len(bs) * 3 / 4
   190  	b1 := bs[:di]
   191  	b2 := bs[di:]
   192  
   193  	// Encoding phase
   194  	buf1 := new(bytes.Buffer)
   195  	if err := amino.EncodeByteSlice(buf1, b1); err != nil {
   196  		t.Fatalf("EncodeByteSlice(b1) = %v", err)
   197  	}
   198  	buf2 := new(bytes.Buffer)
   199  	if err := amino.EncodeByteSlice(buf2, b2); err != nil {
   200  		t.Fatalf("EncodeByteSlice(b2) = %v", err)
   201  	}
   202  
   203  	// Decoding phase
   204  	e1 := buf1.Bytes()
   205  	dec1, n, err := amino.DecodeByteSlice(e1)
   206  	if err != nil {
   207  		t.Errorf("DecodeByteSlice(e1) = %v", err)
   208  	}
   209  	if g, w := n, len(e1); g != w {
   210  		t.Errorf("e1: length:: got = %d want = %d", g, w)
   211  	}
   212  	e2 := buf2.Bytes()
   213  	dec2, n, err := amino.DecodeByteSlice(e2)
   214  	if err != nil {
   215  		t.Errorf("DecodeByteSlice(e2) = %v", err)
   216  	}
   217  	if g, w := n, len(e2); g != w {
   218  		t.Errorf("e2: length:: got = %d want = %d", g, w)
   219  	}
   220  	joined := bytes.Join([][]byte{dec1, dec2}, []byte(""))
   221  	if !bytes.Equal(joined, bs) {
   222  		t.Errorf("got joined=(% X) want=(% X)", joined, bs)
   223  	}
   224  	js := string(joined)
   225  	if js != s {
   226  		t.Errorf("got string=%q want=%q", js, s)
   227  	}
   228  }
   229  
   230  func TestCodecSeal(t *testing.T) {
   231  	t.Parallel()
   232  
   233  	cdc := amino.NewCodec()
   234  	cdc.Seal()
   235  
   236  	assert.Panics(t, func() { cdc.RegisterPackage(tests.Package) })
   237  }
   238  
   239  // XXX Test registering duplicate names or concrete types not in a package.