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 }