github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/io/binaryrw_test.go (about)

     1  package io
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  // mocks io.Reader and io.Writer, always fails to Write() or Read().
    12  type badRW struct{}
    13  
    14  func (w *badRW) Write(p []byte) (int, error) {
    15  	return 0, errors.New("it always fails")
    16  }
    17  
    18  func (w *badRW) Read(p []byte) (int, error) {
    19  	return w.Write(p)
    20  }
    21  
    22  func TestWriteU64LE(t *testing.T) {
    23  	var (
    24  		val     uint64 = 0xbadc0de15a11dead
    25  		readval uint64
    26  		bin     = []byte{0xad, 0xde, 0x11, 0x5a, 0xe1, 0x0d, 0xdc, 0xba}
    27  	)
    28  	bw := NewBufBinWriter()
    29  	bw.WriteU64LE(val)
    30  	assert.Nil(t, bw.Err)
    31  	wrotebin := bw.Bytes()
    32  	assert.Equal(t, wrotebin, bin)
    33  	br := NewBinReaderFromBuf(bin)
    34  	readval = br.ReadU64LE()
    35  	assert.Nil(t, br.Err)
    36  	assert.Equal(t, val, readval)
    37  }
    38  
    39  func TestWriteU32LE(t *testing.T) {
    40  	var (
    41  		val     uint32 = 0xdeadbeef
    42  		readval uint32
    43  		bin     = []byte{0xef, 0xbe, 0xad, 0xde}
    44  	)
    45  	bw := NewBufBinWriter()
    46  	bw.WriteU32LE(val)
    47  	assert.Nil(t, bw.Err)
    48  	wrotebin := bw.Bytes()
    49  	assert.Equal(t, wrotebin, bin)
    50  	br := NewBinReaderFromBuf(bin)
    51  	readval = br.ReadU32LE()
    52  	assert.Nil(t, br.Err)
    53  	assert.Equal(t, val, readval)
    54  }
    55  
    56  func TestWriteU16LE(t *testing.T) {
    57  	var (
    58  		val     uint16 = 0xbabe
    59  		readval uint16
    60  		bin     = []byte{0xbe, 0xba}
    61  	)
    62  	bw := NewBufBinWriter()
    63  	bw.WriteU16LE(val)
    64  	assert.Nil(t, bw.Err)
    65  	wrotebin := bw.Bytes()
    66  	assert.Equal(t, wrotebin, bin)
    67  	br := NewBinReaderFromBuf(bin)
    68  	readval = br.ReadU16LE()
    69  	assert.Nil(t, br.Err)
    70  	assert.Equal(t, val, readval)
    71  }
    72  
    73  func TestWriteU16BE(t *testing.T) {
    74  	var (
    75  		val     uint16 = 0xbabe
    76  		readval uint16
    77  		bin     = []byte{0xba, 0xbe}
    78  	)
    79  	bw := NewBufBinWriter()
    80  	bw.WriteU16BE(val)
    81  	assert.Nil(t, bw.Err)
    82  	wrotebin := bw.Bytes()
    83  	assert.Equal(t, wrotebin, bin)
    84  	br := NewBinReaderFromBuf(bin)
    85  	readval = br.ReadU16BE()
    86  	assert.Nil(t, br.Err)
    87  	assert.Equal(t, val, readval)
    88  }
    89  
    90  func TestWriteByte(t *testing.T) {
    91  	var (
    92  		val     byte = 0xa5
    93  		readval byte
    94  		bin     = []byte{0xa5}
    95  	)
    96  	bw := NewBufBinWriter()
    97  	bw.WriteB(val)
    98  	assert.Nil(t, bw.Err)
    99  	wrotebin := bw.Bytes()
   100  	assert.Equal(t, wrotebin, bin)
   101  	br := NewBinReaderFromBuf(bin)
   102  	readval = br.ReadB()
   103  	assert.Nil(t, br.Err)
   104  	assert.Equal(t, val, readval)
   105  }
   106  
   107  func TestWriteBool(t *testing.T) {
   108  	var (
   109  		bin = []byte{0x01, 0x00}
   110  	)
   111  	bw := NewBufBinWriter()
   112  	bw.WriteBool(true)
   113  	bw.WriteBool(false)
   114  	assert.Nil(t, bw.Err)
   115  	wrotebin := bw.Bytes()
   116  	assert.Equal(t, wrotebin, bin)
   117  	br := NewBinReaderFromBuf(bin)
   118  	assert.Equal(t, true, br.ReadBool())
   119  	assert.Equal(t, false, br.ReadBool())
   120  	assert.Nil(t, br.Err)
   121  }
   122  
   123  func TestReadLEErrors(t *testing.T) {
   124  	bin := []byte{0xad, 0xde, 0x11, 0x5a, 0xe1, 0x0d, 0xdc, 0xba}
   125  	br := NewBinReaderFromBuf(bin)
   126  	// Prime the buffers with something.
   127  	_ = br.ReadU64LE()
   128  	assert.Nil(t, br.Err)
   129  
   130  	assert.Equal(t, uint64(0), br.ReadU64LE())
   131  	assert.Equal(t, uint32(0), br.ReadU32LE())
   132  	assert.Equal(t, uint16(0), br.ReadU16LE())
   133  	assert.Equal(t, uint16(0), br.ReadU16BE())
   134  	assert.Equal(t, byte(0), br.ReadB())
   135  	assert.Equal(t, false, br.ReadBool())
   136  	assert.NotNil(t, br.Err)
   137  }
   138  
   139  func TestBufBinWriter_Len(t *testing.T) {
   140  	val := []byte{0xde}
   141  	bw := NewBufBinWriter()
   142  	bw.WriteBytes(val)
   143  	require.Equal(t, 1, bw.Len())
   144  }
   145  
   146  func TestBinReader_ReadVarBytes(t *testing.T) {
   147  	buf := make([]byte, 11)
   148  	for i := range buf {
   149  		buf[i] = byte(i)
   150  	}
   151  	w := NewBufBinWriter()
   152  	w.WriteVarBytes(buf)
   153  	require.NoError(t, w.Err)
   154  	data := w.Bytes()
   155  
   156  	t.Run("NoArguments", func(t *testing.T) {
   157  		r := NewBinReaderFromBuf(data)
   158  		actual := r.ReadVarBytes()
   159  		require.NoError(t, r.Err)
   160  		require.Equal(t, buf, actual)
   161  	})
   162  	t.Run("Good", func(t *testing.T) {
   163  		r := NewBinReaderFromBuf(data)
   164  		actual := r.ReadVarBytes(11)
   165  		require.NoError(t, r.Err)
   166  		require.Equal(t, buf, actual)
   167  	})
   168  	t.Run("Bad", func(t *testing.T) {
   169  		r := NewBinReaderFromBuf(data)
   170  		r.ReadVarBytes(10)
   171  		require.Error(t, r.Err)
   172  	})
   173  }
   174  
   175  func TestWriterErrHandling(t *testing.T) {
   176  	var badio = &badRW{}
   177  	bw := NewBinWriterFromIO(badio)
   178  	bw.WriteU32LE(uint32(0))
   179  	assert.NotNil(t, bw.Err)
   180  	// these should work (without panic), preserving the Err
   181  	bw.WriteU32LE(uint32(0))
   182  	bw.WriteU16BE(uint16(0))
   183  	bw.WriteVarUint(0)
   184  	bw.WriteVarBytes([]byte{0x55, 0xaa})
   185  	bw.WriteString("neo")
   186  	assert.NotNil(t, bw.Err)
   187  }
   188  
   189  func TestReaderErrHandling(t *testing.T) {
   190  	var (
   191  		badio = &badRW{}
   192  	)
   193  	br := NewBinReaderFromIO(badio)
   194  	br.ReadU32LE()
   195  	assert.NotNil(t, br.Err)
   196  	// these should work (without panic), preserving the Err
   197  	br.ReadU32LE()
   198  	br.ReadU16BE()
   199  	val := br.ReadVarUint()
   200  	assert.Equal(t, val, uint64(0))
   201  	b := br.ReadVarBytes()
   202  	assert.Equal(t, b, []byte{})
   203  	s := br.ReadString()
   204  	assert.Equal(t, s, "")
   205  	assert.NotNil(t, br.Err)
   206  }
   207  
   208  func TestBufBinWriterErr(t *testing.T) {
   209  	bw := NewBufBinWriter()
   210  	bw.WriteU32LE(uint32(0))
   211  	assert.Nil(t, bw.Err)
   212  	// inject error
   213  	bw.Err = errors.New("oopsie")
   214  	res := bw.Bytes()
   215  	assert.NotNil(t, bw.Err)
   216  	assert.Nil(t, res)
   217  }
   218  
   219  func TestBufBinWriterReset(t *testing.T) {
   220  	bw := NewBufBinWriter()
   221  	for i := 0; i < 3; i++ {
   222  		bw.WriteU32LE(uint32(i))
   223  		assert.Nil(t, bw.Err)
   224  		_ = bw.Bytes()
   225  		assert.NotNil(t, bw.Err)
   226  		bw.Reset()
   227  		assert.Nil(t, bw.Err)
   228  	}
   229  }
   230  
   231  func TestWriteString(t *testing.T) {
   232  	var (
   233  		str = "teststring"
   234  	)
   235  	bw := NewBufBinWriter()
   236  	bw.WriteString(str)
   237  	assert.Nil(t, bw.Err)
   238  	wrotebin := bw.Bytes()
   239  	// +1 byte for length
   240  	assert.Equal(t, len(wrotebin), len(str)+1)
   241  	br := NewBinReaderFromBuf(wrotebin)
   242  	readstr := br.ReadString()
   243  	assert.Nil(t, br.Err)
   244  	assert.Equal(t, str, readstr)
   245  }
   246  
   247  func TestWriteVarUint1(t *testing.T) {
   248  	var (
   249  		val = uint64(1)
   250  	)
   251  	bw := NewBufBinWriter()
   252  	bw.WriteVarUint(val)
   253  	assert.Nil(t, bw.Err)
   254  	buf := bw.Bytes()
   255  	assert.Equal(t, 1, len(buf))
   256  	br := NewBinReaderFromBuf(buf)
   257  	res := br.ReadVarUint()
   258  	assert.Nil(t, br.Err)
   259  	assert.Equal(t, val, res)
   260  }
   261  
   262  func TestWriteVarUint1000(t *testing.T) {
   263  	var (
   264  		val = uint64(1000)
   265  	)
   266  	bw := NewBufBinWriter()
   267  	bw.WriteVarUint(val)
   268  	assert.Nil(t, bw.Err)
   269  	buf := bw.Bytes()
   270  	assert.Equal(t, 3, len(buf))
   271  	assert.Equal(t, byte(0xfd), buf[0])
   272  	br := NewBinReaderFromBuf(buf)
   273  	res := br.ReadVarUint()
   274  	assert.Nil(t, br.Err)
   275  	assert.Equal(t, val, res)
   276  }
   277  
   278  func TestWriteVarUint100000(t *testing.T) {
   279  	var (
   280  		val = uint64(100000)
   281  	)
   282  	bw := NewBufBinWriter()
   283  	bw.WriteVarUint(val)
   284  	assert.Nil(t, bw.Err)
   285  	buf := bw.Bytes()
   286  	assert.Equal(t, 5, len(buf))
   287  	assert.Equal(t, byte(0xfe), buf[0])
   288  	br := NewBinReaderFromBuf(buf)
   289  	res := br.ReadVarUint()
   290  	assert.Nil(t, br.Err)
   291  	assert.Equal(t, val, res)
   292  }
   293  
   294  func TestWriteVarUint100000000000(t *testing.T) {
   295  	var (
   296  		val = uint64(1000000000000)
   297  	)
   298  	bw := NewBufBinWriter()
   299  	bw.WriteVarUint(val)
   300  	assert.Nil(t, bw.Err)
   301  	buf := bw.Bytes()
   302  	assert.Equal(t, 9, len(buf))
   303  	assert.Equal(t, byte(0xff), buf[0])
   304  	br := NewBinReaderFromBuf(buf)
   305  	res := br.ReadVarUint()
   306  	assert.Nil(t, br.Err)
   307  	assert.Equal(t, val, res)
   308  }
   309  
   310  func TestWriteBytes(t *testing.T) {
   311  	var (
   312  		bin = []byte{0xde, 0xad, 0xbe, 0xef}
   313  	)
   314  	bw := NewBufBinWriter()
   315  	bw.WriteBytes(bin)
   316  	assert.Nil(t, bw.Err)
   317  	buf := bw.Bytes()
   318  	assert.Equal(t, 4, len(buf))
   319  	assert.Equal(t, byte(0xde), buf[0])
   320  
   321  	bw = NewBufBinWriter()
   322  	bw.Err = errors.New("smth bad")
   323  	bw.WriteBytes(bin)
   324  	assert.Equal(t, 0, bw.Len())
   325  }
   326  
   327  type testSerializable uint16
   328  
   329  // EncodeBinary implements the io.Serializable interface.
   330  func (t testSerializable) EncodeBinary(w *BinWriter) {
   331  	w.WriteU16LE(uint16(t))
   332  }
   333  
   334  // DecodeBinary implements the io.Serializable interface.
   335  func (t *testSerializable) DecodeBinary(r *BinReader) {
   336  	*t = testSerializable(r.ReadU16LE())
   337  }
   338  
   339  type testPtrSerializable uint16
   340  
   341  // EncodeBinary implements the io.Serializable interface.
   342  func (t *testPtrSerializable) EncodeBinary(w *BinWriter) {
   343  	w.WriteU16LE(uint16(*t))
   344  }
   345  
   346  // DecodeBinary implements the io.Serializable interface.
   347  func (t *testPtrSerializable) DecodeBinary(r *BinReader) {
   348  	*t = testPtrSerializable(r.ReadU16LE())
   349  }
   350  
   351  func TestBinWriter_WriteArray(t *testing.T) {
   352  	var arr [3]testSerializable
   353  	for i := range arr {
   354  		arr[i] = testSerializable(i)
   355  	}
   356  
   357  	expected := []byte{3, 0, 0, 1, 0, 2, 0}
   358  
   359  	w := NewBufBinWriter()
   360  	w.WriteArray(arr)
   361  	require.NoError(t, w.Err)
   362  	require.Equal(t, expected, w.Bytes())
   363  
   364  	w.Reset()
   365  	w.WriteArray(arr[:])
   366  	require.NoError(t, w.Err)
   367  	require.Equal(t, expected, w.Bytes())
   368  
   369  	arrS := make([]Serializable, len(arr))
   370  	for i := range arrS {
   371  		arrS[i] = &arr[i]
   372  	}
   373  
   374  	w.Reset()
   375  	w.WriteArray(arr)
   376  	require.NoError(t, w.Err)
   377  	require.Equal(t, expected, w.Bytes())
   378  
   379  	w.Reset()
   380  	require.Panics(t, func() { w.WriteArray(1) })
   381  
   382  	w.Reset()
   383  	w.Err = errors.New("error")
   384  	w.WriteArray(arr[:])
   385  	require.Error(t, w.Err)
   386  	require.Equal(t, w.Bytes(), []byte(nil))
   387  
   388  	w.Reset()
   389  	require.Panics(t, func() { w.WriteArray([]int{1}) })
   390  
   391  	w.Reset()
   392  	w.Err = errors.New("error")
   393  	require.Panics(t, func() { w.WriteArray(make(chan testSerializable)) })
   394  
   395  	// Ptr receiver test
   396  	var arrPtr [3]testPtrSerializable
   397  	for i := range arrPtr {
   398  		arrPtr[i] = testPtrSerializable(i)
   399  	}
   400  	w.Reset()
   401  	w.WriteArray(arr[:])
   402  	require.NoError(t, w.Err)
   403  	require.Equal(t, expected, w.Bytes())
   404  }
   405  
   406  func TestBinReader_ReadArray(t *testing.T) {
   407  	data := []byte{3, 0, 0, 1, 0, 2, 0}
   408  	elems := []testSerializable{0, 1, 2}
   409  
   410  	r := NewBinReaderFromBuf(data)
   411  	arrPtr := []*testSerializable{}
   412  	r.ReadArray(&arrPtr)
   413  	require.Equal(t, []*testSerializable{&elems[0], &elems[1], &elems[2]}, arrPtr)
   414  
   415  	r = NewBinReaderFromBuf(data)
   416  	arrVal := []testSerializable{}
   417  	r.ReadArray(&arrVal)
   418  	require.NoError(t, r.Err)
   419  	require.Equal(t, elems, arrVal)
   420  
   421  	r = NewBinReaderFromBuf(data)
   422  	arrVal = []testSerializable{}
   423  	r.ReadArray(&arrVal, 3)
   424  	require.NoError(t, r.Err)
   425  	require.Equal(t, elems, arrVal)
   426  
   427  	r = NewBinReaderFromBuf(data)
   428  	arrVal = []testSerializable{}
   429  	r.ReadArray(&arrVal, 2)
   430  	require.Error(t, r.Err)
   431  
   432  	r = NewBinReaderFromBuf([]byte{0})
   433  	r.ReadArray(&arrVal)
   434  	require.NoError(t, r.Err)
   435  	require.Equal(t, []testSerializable{}, arrVal)
   436  
   437  	r = NewBinReaderFromBuf([]byte{0})
   438  	r.Err = errors.New("error")
   439  	arrVal = ([]testSerializable)(nil)
   440  	r.ReadArray(&arrVal)
   441  	require.Error(t, r.Err)
   442  	require.Equal(t, ([]testSerializable)(nil), arrVal)
   443  
   444  	r = NewBinReaderFromBuf([]byte{0})
   445  	r.Err = errors.New("error")
   446  	arrPtr = ([]*testSerializable)(nil)
   447  	r.ReadArray(&arrVal)
   448  	require.Error(t, r.Err)
   449  	require.Equal(t, ([]*testSerializable)(nil), arrPtr)
   450  
   451  	r = NewBinReaderFromBuf([]byte{0})
   452  	arrVal = []testSerializable{1, 2}
   453  	r.ReadArray(&arrVal)
   454  	require.NoError(t, r.Err)
   455  	require.Equal(t, []testSerializable{}, arrVal)
   456  
   457  	r = NewBinReaderFromBuf([]byte{1})
   458  	require.Panics(t, func() { r.ReadArray(&[]int{1}) })
   459  
   460  	r = NewBinReaderFromBuf([]byte{0})
   461  	r.Err = errors.New("error")
   462  	require.Panics(t, func() { r.ReadArray(1) })
   463  }
   464  
   465  func TestBinReader_ReadBytes(t *testing.T) {
   466  	data := []byte{0, 1, 2, 3, 4, 5, 6, 7}
   467  	r := NewBinReaderFromBuf(data)
   468  
   469  	buf := make([]byte, 4)
   470  	r.ReadBytes(buf)
   471  	require.NoError(t, r.Err)
   472  	require.Equal(t, data[:4], buf)
   473  
   474  	r.ReadBytes([]byte{})
   475  	require.NoError(t, r.Err)
   476  
   477  	buf = make([]byte, 3)
   478  	r.ReadBytes(buf)
   479  	require.NoError(t, r.Err)
   480  	require.Equal(t, data[4:7], buf)
   481  
   482  	buf = make([]byte, 2)
   483  	r.ReadBytes(buf)
   484  	require.Error(t, r.Err)
   485  
   486  	r.ReadBytes([]byte{})
   487  	require.Error(t, r.Err)
   488  }