github.com/tunabay/go-bitarray@v1.3.1/reader_test.go (about) 1 // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be found in 3 // the LICENSE file. 4 5 package bitarray_test 6 7 import ( 8 "bytes" 9 "errors" 10 "io" 11 "math/rand" 12 "testing" 13 "testing/iotest" 14 "time" 15 16 "github.com/tunabay/go-bitarray" 17 ) 18 19 func TestReader_byteAligned(t *testing.T) { 20 r := bitarray.NewReader(nil) 21 if err := iotest.TestReader(r, []byte{}); err != nil { 22 t.Errorf("TestReader: %+v", err) 23 } 24 25 var nilba *bitarray.BitArray 26 r = bitarray.NewReader(nilba) 27 if err := iotest.TestReader(r, []byte{}); err != nil { 28 t.Errorf("TestReader: %+v", err) 29 } 30 31 r = bitarray.NewReader(bitarray.New()) 32 if err := iotest.TestReader(r, []byte{}); err != nil { 33 t.Errorf("TestReader: %+v", err) 34 } 35 36 r = bitarray.NewReader(bitarray.NewZeroFilled(8)) 37 if err := iotest.TestReader(r, []byte{0}); err != nil { 38 t.Errorf("TestReader: %+v", err) 39 } 40 41 r = bitarray.NewReader(bitarray.NewOneFilled(8)) 42 if err := iotest.TestReader(r, []byte{0xff}); err != nil { 43 t.Errorf("TestReader: %+v", err) 44 } 45 46 r = bitarray.NewReader(bitarray.NewZeroFilled(8 * 256)) 47 if err := iotest.TestReader(r, bytes.Repeat([]byte{0}, 256)); err != nil { 48 t.Errorf("TestReader: %+v", err) 49 } 50 51 r = bitarray.NewReader(bitarray.NewOneFilled(8 * 256)) 52 if err := iotest.TestReader(r, bytes.Repeat([]byte{0xff}, 256)); err != nil { 53 t.Errorf("TestReader: %+v", err) 54 } 55 } 56 57 func TestReader_byteAlignedRand(t *testing.T) { 58 const testIterations = 5000 59 rand.Seed(time.Now().UnixNano()) 60 for i := 0; i < testIterations; i++ { 61 var nBits int 62 switch rand.Intn(10) { 63 case 0: 64 nBits = 1 + rand.Intn(64+1) 65 case 1: 66 nBits = 8*(1+rand.Intn(24)) - 1 + rand.Intn(3) 67 case 2: 68 nBits = 256 + rand.Intn(2048) 69 default: 70 nBits = 1 + rand.Intn(256) 71 } 72 ba := bitarray.PseudoRand(nBits, nil) 73 ba = ba.ToPadded8() 74 wantB, npad := ba.Bytes() 75 if npad != 0 { 76 t.Fatalf("unexpected npad=%d", npad) 77 } 78 r := bitarray.NewReader(ba) 79 80 if err := iotest.TestReader(r, wantB); err != nil { 81 t.Fatalf("TestReader: %+v", err) 82 } 83 } 84 } 85 86 func TestReader_Reset_edge(t *testing.T) { 87 ba := bitarray.MustParse("1010-1010") 88 r := bitarray.NewReader(ba) 89 90 b, err := r.ReadBit() 91 if b != 1 || err != nil { 92 t.Errorf("unexpected: %d, %v", b, err) 93 } 94 r.Reset(nil) 95 b, err = r.ReadBit() 96 if !errors.Is(err, io.EOF) { 97 t.Errorf("unexpected: %d, %v", b, err) 98 } 99 } 100 101 func TestReader_Read(t *testing.T) { 102 ba := bitarray.MustParse("0011-1111 0000-1111 1010-1010 1100-1100 11") 103 104 // full + 2 bits 105 r := bitarray.NewReader(ba) 106 gotB, err := io.ReadAll(r) 107 if err == nil || !errors.Is(err, bitarray.ErrFractionalBitsBeforeEOF) { 108 t.Errorf("unexpected err: got %s", err) 109 } 110 if !bytes.Equal(gotB, []byte{0b_0011_1111, 0b_0000_1111, 0b_1010_1010, 0b_1100_1100}) { 111 t.Errorf("unexpected data read: %b", gotB) 112 } 113 tail2ba, err := r.ReadBitArray(99) 114 if err != nil { 115 t.Errorf("unexpected err: got %s", err) 116 } 117 if !tail2ba.Equal(bitarray.MustParse("11")) { 118 t.Errorf("unexpected fractional bits read: got %#b", tail2ba) 119 } 120 buf1 := make([]byte, 1) 121 rn, err := io.ReadFull(r, buf1) 122 if rn != 0 || err == nil || !errors.Is(err, io.EOF) { 123 t.Errorf("unexpected read: n=%d, err=%v", rn, err) 124 } 125 126 // 4 bits + 3 bytes + 2 bits 127 r = bitarray.NewReader(ba) 128 head4ba, err := r.ReadBitArray(4) 129 if err != nil { 130 t.Errorf("unexpected err: got %s", err) 131 } 132 if !head4ba.Equal(bitarray.MustParse("0011")) { 133 t.Errorf("unexpected leading bits read: got %#b", head4ba) 134 } 135 buf3 := make([]byte, 3) 136 rn, err = io.ReadFull(r, buf3) 137 if rn != 3 || err != nil { 138 t.Errorf("unexpected read: n=%d, err=%v", rn, err) 139 t.Logf("%b", buf3) 140 } 141 if !bytes.Equal(buf3, []byte{0b_1111_0000, 0b_1111_1010, 0b_1010_1100}) { 142 t.Errorf("unexpected data read: %b", buf3) 143 } 144 rn, err = io.ReadFull(r, buf1) 145 if rn != 0 || err == nil || !errors.Is(err, bitarray.ErrFractionalBitsBeforeEOF) { 146 t.Errorf("unexpected read: n=%d, err=%v", rn, err) 147 } 148 149 tail6ba, err := r.ReadBitArray(6) 150 if err != nil { 151 t.Errorf("unexpected err: got %s", err) 152 } 153 if !tail6ba.Equal(bitarray.MustParse("110011")) { 154 t.Errorf("unexpected fractional bits read: got %#b", tail6ba) 155 } 156 rn, err = io.ReadFull(r, buf1) 157 if rn != 0 || err == nil || !errors.Is(err, io.EOF) { 158 t.Errorf("unexpected read: n=%d, err=%v", rn, err) 159 } 160 161 // 2 bits + full 162 r = bitarray.NewReader(ba) 163 head2b, err := r.ReadBit() 164 if err != nil { 165 t.Errorf("unexpected err: got %s", err) 166 } 167 if head2b != 0 { 168 t.Errorf("unexpected bit[0]: got %d, want 0", head2b) 169 } 170 head2b, err = r.ReadBit() 171 if err != nil { 172 t.Errorf("unexpected err: got %s", err) 173 } 174 if head2b != 0 { 175 t.Errorf("unexpected bit[1]: got %d, want 0", head2b) 176 } 177 gotB, err = io.ReadAll(r) 178 if err != nil { 179 t.Errorf("unexpected err: got %s", err) 180 } 181 if !bytes.Equal(gotB, []byte{0b_1111_1100, 0b_0011_1110, 0b_1010_1011, 0b_0011_0011}) { 182 t.Errorf("unexpected data read: %b", gotB) 183 } 184 rn, err = io.ReadFull(r, buf1) 185 if rn != 0 || err == nil || !errors.Is(err, io.EOF) { 186 t.Errorf("unexpected read: n=%d, err=%v", rn, err) 187 } 188 } 189 190 func TestReader_ReadByte(t *testing.T) { 191 ba := bitarray.MustParse("0011-1111 0000-1111 1010-1010 1100-1100 11") 192 193 // bytes + 2 bits 194 r := bitarray.NewReader(ba) 195 bs := make([]byte, 4) 196 for i := range bs { 197 b, err := r.ReadByte() 198 if err != nil { 199 t.Errorf("unexpected err: i=%d: %s", i, err) 200 } 201 bs[i] = b 202 } 203 if !bytes.Equal(bs, []byte{0b_0011_1111, 0b_0000_1111, 0b_1010_1010, 0b_1100_1100}) { 204 t.Errorf("unexpected data read: %b", bs) 205 } 206 b, err := r.ReadByte() 207 switch { 208 case err == nil: 209 t.Errorf("error expected, no error: %08b", b) 210 case !errors.Is(err, bitarray.ErrFractionalBitsBeforeEOF): 211 t.Errorf("unexpected error: %s", err) 212 } 213 tail2ba, err := r.ReadBitArray(99) 214 if err != nil { 215 t.Errorf("unexpected error: %s", err) 216 } 217 if !tail2ba.Equal(bitarray.MustParse("11")) { 218 t.Errorf("unexpected data read: got %#b, want 11", tail2ba) 219 } 220 221 // 2 bits + bytes 222 r = bitarray.NewReader(ba) 223 head2ba, err := r.ReadBitArray(2) 224 if err != nil { 225 t.Errorf("unexpected error: %s", err) 226 } 227 if !head2ba.Equal(bitarray.MustParse("00")) { 228 t.Errorf("unexpected data read: got %#b, want 00", head2ba) 229 } 230 bs = make([]byte, 5) 231 for i := range bs { 232 b, err := r.ReadByte() 233 if err != nil { 234 if errors.Is(err, io.EOF) { 235 break // expected 236 } 237 t.Errorf("unexpected error: %s", err) 238 } 239 bs[i] = b 240 if i == 4 { 241 t.Errorf("expected error, no error: %08b", bs[i]) 242 } 243 } 244 if !bytes.Equal(bs[:4], []byte{0b_1111_1100, 0b_0011_1110, 0b_1010_1011, 0b_0011_0011}) { 245 t.Errorf("unexpected data read: %b", bs[:4]) 246 } 247 248 // zero filled + 3 249 ba = bitarray.MustParse("0000-0000 0000-0000 0000-0000 000") 250 r = bitarray.NewReader(ba) 251 for i := 0; i < 3; i++ { 252 bit, err := r.ReadBit() 253 switch { 254 case err != nil: 255 t.Errorf("unexpected error: %s", err) 256 case bit != 0: 257 t.Errorf("unexpected bit: got %d, want 1", bit) 258 } 259 } 260 for i := 0; i < 3; i++ { 261 b, err := r.ReadByte() 262 switch { 263 case err != nil: 264 t.Errorf("unexpected error: %s", err) 265 case b != 0: 266 t.Errorf("unexpected byte: got %08b, want 0", b) 267 } 268 } 269 b, err = r.ReadByte() 270 switch { 271 case err == nil: 272 t.Errorf("expected error, no error: got %08b", b) 273 case !errors.Is(err, io.EOF): 274 t.Errorf("unexpected error: %s", err) 275 } 276 277 // nil ba 278 var nilba *bitarray.BitArray 279 r = bitarray.NewReader(nilba) 280 b, err = r.ReadByte() 281 switch { 282 case err == nil: 283 t.Errorf("error expected, no error: %08b", b) 284 case !errors.Is(err, io.EOF): 285 t.Errorf("unexpected error: %s", err) 286 } 287 } 288 289 func TestReader_ReadBitArray(t *testing.T) { 290 ba := bitarray.MustParse("0011-1111 0000-1111 1010-1010 1100-1100 11") 291 292 r := bitarray.NewReader(ba) 293 b, err := r.ReadBitArray(6) 294 switch { 295 case err != nil: 296 t.Errorf("unexpected error: %s", err) 297 case !b.Equal(bitarray.MustParse("001111")): 298 t.Errorf("unexpected read: got %#b, want 0011-11", b) 299 } 300 301 b, err = r.ReadBitArray(0) 302 switch { 303 case err != nil: 304 t.Errorf("unexpected error: %s", err) 305 case !b.IsZero(): 306 t.Errorf("unexpected read: got %#b, want zero", b) 307 } 308 309 func() { 310 defer func() { 311 if recover() == nil { 312 t.Errorf("panic expected: got %#b", b) 313 } 314 }() 315 b, err = r.ReadBitArray(-1) 316 t.Logf("err: %s", err) 317 }() 318 319 b, err = r.ReadBitArray(16) 320 switch { 321 case err != nil: 322 t.Errorf("unexpected error: %s", err) 323 case !b.Equal(bitarray.MustParse("11 0000-1111 1010-10")): 324 t.Errorf("unexpected read: got %#b, want 1100-0011 1110-1010", b) 325 } 326 327 b, err = r.ReadBitArray(1) 328 switch { 329 case err != nil: 330 t.Errorf("unexpected error: %s", err) 331 case !b.Equal(bitarray.MustParse("1")): 332 t.Errorf("unexpected read: got %#b, want 1", b) 333 } 334 335 b, err = r.ReadBitArray(99) 336 switch { 337 case err != nil: 338 t.Errorf("unexpected error: %s", err) 339 case !b.Equal(bitarray.MustParse("0 1100-1100 11")): 340 t.Errorf("unexpected read: got %#b, want 0110-0110 011", b) 341 } 342 343 b, err = r.ReadBitArray(8) 344 switch { 345 case err == nil: 346 t.Errorf("expected error, no error: got %#b", b) 347 case !errors.Is(err, io.EOF): 348 t.Errorf("unexpected error: %s", err) 349 } 350 351 var nilba *bitarray.BitArray 352 r = bitarray.NewReader(nilba) 353 b, err = r.ReadBitArray(99) 354 switch { 355 case err == nil: 356 t.Errorf("expected error, no error: got %#b", b) 357 case !errors.Is(err, io.EOF): 358 t.Errorf("unexpected error: %s", err) 359 } 360 } 361 362 func TestReader_ReadBit(t *testing.T) { 363 ba := bitarray.MustParse("0011-1111 0000-1111 1010-1010 1100-110") 364 r := bitarray.NewReader(ba) 365 for i := 0; i < ba.Len(); i++ { 366 bit, err := r.ReadBit() 367 switch { 368 case err != nil: 369 t.Errorf("unexpected error: %d: %s", i, err) 370 case bit != ba.BitAt(i): 371 t.Errorf("unexpected read: %d: got %d, want %d", i, bit, ba.BitAt(i)) 372 } 373 } 374 bit, err := r.ReadBit() 375 switch { 376 case err == nil: 377 t.Errorf("expected error, no error: got %d", bit) 378 case !errors.Is(err, io.EOF): 379 t.Errorf("unexpected error: %s", err) 380 } 381 382 ba = bitarray.NewZeroFilled(258) 383 r = bitarray.NewReader(ba) 384 for i := 0; i < ba.Len(); i++ { 385 bit, err := r.ReadBit() 386 switch { 387 case err != nil: 388 t.Errorf("unexpected error: %d: %s", i, err) 389 case bit != 0: 390 t.Errorf("unexpected read: %d: got %d, want 0", i, bit) 391 } 392 } 393 bit, err = r.ReadBit() 394 switch { 395 case err == nil: 396 t.Errorf("expected error, no error: got %d", bit) 397 case !errors.Is(err, io.EOF): 398 t.Errorf("unexpected error: %s", err) 399 } 400 401 var nilba *bitarray.BitArray 402 r = bitarray.NewReader(nilba) 403 bit, err = r.ReadBit() 404 switch { 405 case err == nil: 406 t.Errorf("expected error, no error: got %d", bit) 407 case !errors.Is(err, io.EOF): 408 t.Errorf("unexpected error: %s", err) 409 } 410 } 411 412 func TestReader_ReadBits_rand(t *testing.T) { 413 const testIterations = 200000 414 rand.Seed(time.Now().UnixNano()) 415 var r *bitarray.Reader 416 for i := 0; i < testIterations; i++ { 417 var nBits int 418 switch rand.Intn(10) { 419 case 0: 420 nBits = 1 + rand.Intn(64+1) 421 case 1: 422 nBits = 8*(1+rand.Intn(24)) - 1 + rand.Intn(3) 423 case 2: 424 nBits = 256 + rand.Intn(2048) 425 default: 426 nBits = 1 + rand.Intn(256) 427 } 428 var ba *bitarray.BitArray 429 switch rand.Intn(32) { 430 case 0: 431 ba = bitarray.NewZeroFilled(nBits) 432 case 1: 433 ba = bitarray.NewOneFilled(nBits) 434 default: 435 ba = bitarray.PseudoRand(nBits, nil) 436 } 437 438 var bufLen int 439 switch rand.Intn(10) { 440 case 0: 441 bufLen = 1 + rand.Intn(8) 442 case 1: 443 bufLen = 64 + rand.Intn(128+8) 444 case 2: 445 bufLen = 8*(1+rand.Intn(8)) - 1 + rand.Intn(3) 446 default: 447 bufLen = 1 + rand.Intn(256) 448 } 449 buf := bitarray.NewBuffer(bufLen) 450 bufRnd := bitarray.PseudoRand(buf.Len(), nil) 451 452 if r == nil { 453 r = bitarray.NewReader(ba) 454 } else { 455 r.Reset(ba) 456 } 457 458 nRead := 0 459 for nRead < ba.Len() { 460 buf.XorAt(0, bufRnd) 461 n, err := r.ReadBits(buf) 462 if err != nil { 463 t.Errorf("unexpected error: %s", err) 464 t.Logf("nRead=%d", nRead) 465 t.Logf("buf: %s", buf.String()) 466 t.Logf("src: %s", ba.String()) 467 t.FailNow() 468 } 469 if ba.Len() < nRead+n { 470 t.Errorf("too many read: %d for len=%d", nRead+n, ba.Len()) 471 t.FailNow() 472 } 473 got := buf.BitArrayAt(0, n) 474 want := ba.Slice(nRead, nRead+n) 475 if !got.Equal(want) { 476 t.Errorf("unexpected read: nRead=%d, n=%d", nRead, n) 477 t.Logf(" got: %#b", got) 478 t.Logf("want: %#b", want) 479 t.FailNow() 480 } 481 // if i < 32 { 482 // t.Logf("%3d: nRead=%d: %#b", i, nRead, got) 483 // } 484 nRead += n 485 } 486 487 n, err := r.ReadBits(buf) 488 switch { 489 case err == nil: 490 t.Errorf("expected error, no error: read %d bits", n) 491 case !errors.Is(err, io.EOF): 492 t.Errorf("unexpected error: %s", err) 493 } 494 } 495 } 496 497 func TestReader_ReadBits_edge(t *testing.T) { 498 ba := bitarray.MustParse("1010-1010") 499 r := bitarray.NewReader(ba) 500 501 buf := &bitarray.Buffer{} 502 503 n, err := r.ReadBits(buf) 504 switch { 505 case err != nil: 506 t.Errorf("unexpected error: %s", err) 507 case n != 0: 508 t.Errorf("unexpected read: n=%d, b=%s", n, buf.String()) 509 } 510 }