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  }