package bintrie import ( "bytes" "encoding/binary" "math/bits" "testing" ) const ( ones63 = 0x7FFFFFFFFFFFFFFF // 63 bits of 1 ) func TestBytes(t *testing.T) { tests := []struct { name string ba BitArray want [32]byte }{ { name: "length == 0", ba: BitArray{len: 0, words: [4]uint64{0, 0, 0, 0}}, want: [32]byte{}, }, { name: "length < 64", ba: BitArray{len: 38, words: [4]uint64{0x3FFFFFFFFF, 0, 0, 0}}, want: func() [32]byte { var b [32]byte binary.BigEndian.PutUint64(b[24:32], 0x3FFFFFFFFF) return b }(), }, { name: "64 <= length < 128", ba: BitArray{len: 100, words: [4]uint64{maxUint64, 0xFFFFFFFFF, 0, 0}}, want: func() [32]byte { var b [32]byte binary.BigEndian.PutUint64(b[16:24], 0xFFFFFFFFF) binary.BigEndian.PutUint64(b[24:32], maxUint64) return b }(), }, { name: "128 <= length < 192", ba: BitArray{len: 130, words: [4]uint64{maxUint64, maxUint64, 0x3, 0}}, want: func() [32]byte { var b [32]byte binary.BigEndian.PutUint64(b[8:16], 0x3) binary.BigEndian.PutUint64(b[16:24], maxUint64) binary.BigEndian.PutUint64(b[24:32], maxUint64) return b }(), }, { name: "192 <= length < 255", ba: BitArray{len: 201, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0x1FF}}, want: func() [32]byte { var b [32]byte binary.BigEndian.PutUint64(b[0:8], 0x1FF) binary.BigEndian.PutUint64(b[8:16], maxUint64) binary.BigEndian.PutUint64(b[16:24], maxUint64) binary.BigEndian.PutUint64(b[24:32], maxUint64) return b }(), }, { name: "length == 254", ba: BitArray{len: 254, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0x3FFFFFFFFFFFFFFF}}, want: func() [32]byte { var b [32]byte binary.BigEndian.PutUint64(b[0:8], 0x3FFFFFFFFFFFFFFF) binary.BigEndian.PutUint64(b[8:16], maxUint64) binary.BigEndian.PutUint64(b[16:24], maxUint64) binary.BigEndian.PutUint64(b[24:32], maxUint64) return b }(), }, { name: "length == 255", ba: BitArray{len: 255, words: [4]uint64{maxUint64, maxUint64, maxUint64, ones63}}, want: func() [32]byte { var b [32]byte binary.BigEndian.PutUint64(b[0:8], ones63) binary.BigEndian.PutUint64(b[8:16], maxUint64) binary.BigEndian.PutUint64(b[16:24], maxUint64) binary.BigEndian.PutUint64(b[24:32], maxUint64) return b }(), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := tt.ba.Bytes() if !bytes.Equal(got[:], tt.want[:]) { t.Errorf("BitArray.Bytes() = %v, want %v", got, tt.want) } // check if the received bytes has the same bit count as the BitArray.len count := 0 for _, b := range got { count += bits.OnesCount8(b) } if count != int(tt.ba.len) { t.Errorf("BitArray.Bytes() bit count = %v, want %v", count, tt.ba.len) } }) } } func TestRsh(t *testing.T) { tests := []struct { name string initial *BitArray shiftBy uint8 expected *BitArray }{ { name: "zero length array", initial: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, shiftBy: 5, expected: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "shift by 0", initial: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, shiftBy: 0, expected: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "shift by more than length", initial: &BitArray{ len: 64, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, shiftBy: 65, expected: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "shift by less than 64", initial: &BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, shiftBy: 32, expected: &BitArray{ len: 96, words: [4]uint64{maxUint64, 0x00000000FFFFFFFF, 0, 0}, }, }, { name: "shift by exactly 64", initial: &BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, shiftBy: 64, expected: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "shift by 127", initial: &BitArray{ len: 255, words: [4]uint64{maxUint64, maxUint64, maxUint64, ones63}, }, shiftBy: 127, expected: &BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, }, { name: "shift by 128", initial: &BitArray{ len: 251, words: [4]uint64{maxUint64, maxUint64, maxUint64, maxUint64}, }, shiftBy: 128, expected: &BitArray{ len: 123, words: [4]uint64{maxUint64, 0x7FFFFFFFFFFFFFF, 0, 0}, }, }, { name: "shift by 192", initial: &BitArray{ len: 251, words: [4]uint64{maxUint64, maxUint64, maxUint64, maxUint64}, }, shiftBy: 192, expected: &BitArray{ len: 59, words: [4]uint64{0x7FFFFFFFFFFFFFF, 0, 0, 0}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := new(BitArray).rsh(tt.initial, tt.shiftBy) if !result.Equal(tt.expected) { t.Errorf("rsh() got = %+v, want %+v", result, tt.expected) } }) } } func TestLsh(t *testing.T) { tests := []struct { name string x *BitArray n uint8 want *BitArray }{ { name: "empty array", x: emptyBitArray, n: 5, want: emptyBitArray, }, { name: "shift by 0", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, n: 0, want: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "shift within first word", x: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, n: 4, want: &BitArray{ len: 8, words: [4]uint64{0xF0, 0, 0, 0}, // 11110000 }, }, { name: "shift across word boundary", x: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, n: 62, want: &BitArray{ len: 66, words: [4]uint64{0xC000000000000000, 0x3, 0, 0}, }, }, { name: "shift by 64 (full word)", x: &BitArray{ len: 8, words: [4]uint64{0xFF, 0, 0, 0}, // 11111111 }, n: 64, want: &BitArray{ len: 72, words: [4]uint64{0, 0xFF, 0, 0}, }, }, { name: "shift by 128", x: &BitArray{ len: 8, words: [4]uint64{0xFF, 0, 0, 0}, // 11111111 }, n: 128, want: &BitArray{ len: 136, words: [4]uint64{0, 0, 0xFF, 0}, }, }, { name: "shift by 192", x: &BitArray{ len: 8, words: [4]uint64{0xFF, 0, 0, 0}, // 11111111 }, n: 192, want: &BitArray{ len: 200, words: [4]uint64{0, 0, 0, 0xFF}, }, }, { name: "shift causing length overflow", x: &BitArray{ len: 200, words: [4]uint64{0xFF, 0, 0, 0}, }, n: 60, want: &BitArray{ len: 255, // capped at maxUint8 words: [4]uint64{ 0xF000000000000000, 0xF, 0, 0, }, }, }, { name: "shift sparse bits", x: &BitArray{ len: 8, words: [4]uint64{0xAA, 0, 0, 0}, // 10101010 }, n: 4, want: &BitArray{ len: 12, words: [4]uint64{0xAA0, 0, 0, 0}, // 101010100000 }, }, { name: "shift partial word across boundary", x: &BitArray{ len: 100, words: [4]uint64{0xFF, 0xFF, 0, 0}, }, n: 60, want: &BitArray{ len: 160, words: [4]uint64{ 0xF000000000000000, 0xF00000000000000F, 0xF, 0, }, }, }, { name: "near maximum length shift", x: &BitArray{ len: 251, words: [4]uint64{0xFF, 0, 0, 0}, }, n: 4, want: &BitArray{ len: 255, // capped at maxUint8 words: [4]uint64{0xFF0, 0, 0, 0}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := new(BitArray).lsh(tt.x, tt.n) if !got.Equal(tt.want) { t.Errorf("Lsh() = %v, want %v", got, tt.want) } }) } } func TestAppend(t *testing.T) { tests := []struct { name string x *BitArray y *BitArray want *BitArray }{ { name: "both empty arrays", x: emptyBitArray, y: emptyBitArray, want: emptyBitArray, }, { name: "first array empty", x: emptyBitArray, y: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, want: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, }, { name: "second array empty", x: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, y: emptyBitArray, want: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, }, { name: "within first word", x: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, y: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, want: &BitArray{ len: 8, words: [4]uint64{0xFF, 0, 0, 0}, // 11111111 }, }, { name: "different lengths within word", x: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, y: &BitArray{ len: 2, words: [4]uint64{0x3, 0, 0, 0}, // 11 }, want: &BitArray{ len: 6, words: [4]uint64{0x3F, 0, 0, 0}, // 111111 }, }, { name: "across word boundary", x: &BitArray{ len: 62, words: [4]uint64{0x3FFFFFFFFFFFFFFF, 0, 0, 0}, }, y: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, // 1111 }, want: &BitArray{ len: 66, words: [4]uint64{maxUint64, 0x3, 0, 0}, }, }, { name: "across multiple words", x: &BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, y: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, want: &BitArray{ len: 192, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0}, }, }, { name: "sparse bits", x: &BitArray{ len: 8, words: [4]uint64{0xAA, 0, 0, 0}, // 10101010 }, y: &BitArray{ len: 8, words: [4]uint64{0x55, 0, 0, 0}, // 01010101 }, want: &BitArray{ len: 16, words: [4]uint64{0xAA55, 0, 0, 0}, // 1010101001010101 }, }, { name: "result exactly at length limit", x: &BitArray{ len: 251, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0x7FFFFFFFFFFFFFFF}, }, y: &BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, }, want: &BitArray{ len: 255, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0x7FFFFFFFFFFFFFFF}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := new(BitArray).Append(tt.x, tt.y) if !got.Equal(tt.want) { t.Errorf("Append() = %v, want %v", got, tt.want) } }) } } func TestLSBs(t *testing.T) { tests := []struct { name string x *BitArray pos uint8 want *BitArray }{ { name: "zero position", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, pos: 0, want: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "position beyond length", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, pos: 65, want: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "get last 4 bits", x: &BitArray{ len: 8, words: [4]uint64{0xFF, 0, 0, 0}, // 11111111 }, pos: 4, want: &BitArray{ len: 4, words: [4]uint64{0x0F, 0, 0, 0}, // 1111 }, }, { name: "get bits across word boundary", x: &BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, pos: 64, want: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "get bits from max length array", x: &BitArray{ len: 251, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0x7FFFFFFFFFFFFFF}, }, pos: 200, want: &BitArray{ len: 51, words: [4]uint64{0x7FFFFFFFFFFFF, 0, 0, 0}, }, }, { name: "empty array", x: emptyBitArray, pos: 1, want: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "sparse bits", x: &BitArray{ len: 16, words: [4]uint64{0xAAAA, 0, 0, 0}, // 1010101010101010 }, pos: 8, want: &BitArray{ len: 8, words: [4]uint64{0xAA, 0, 0, 0}, // 10101010 }, }, { name: "position equals length", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, pos: 64, want: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := new(BitArray).lsb(tt.x, tt.pos) if !got.Equal(tt.want) { t.Errorf("LSBs() = %v, want %v", got, tt.want) } }) } } func TestLSBsFromLSB(t *testing.T) { tests := []struct { name string initial BitArray length uint8 expected BitArray }{ { name: "zero", initial: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, length: 0, expected: BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "get 32 LSBs", initial: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, length: 32, expected: BitArray{ len: 32, words: [4]uint64{0x00000000FFFFFFFF, 0, 0, 0}, }, }, { name: "get 1 LSB", initial: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, length: 1, expected: BitArray{ len: 1, words: [4]uint64{0x1, 0, 0, 0}, }, }, { name: "get 100 LSBs across words", initial: BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, length: 100, expected: BitArray{ len: 100, words: [4]uint64{maxUint64, 0x0000000FFFFFFFFF, 0, 0}, }, }, { name: "get 64 LSBs at word boundary", initial: BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, length: 64, expected: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "get 128 LSBs at word boundary", initial: BitArray{ len: 192, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0}, }, length: 128, expected: BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, }, { name: "get 150 LSBs in third word", initial: BitArray{ len: 192, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0}, }, length: 150, expected: BitArray{ len: 150, words: [4]uint64{maxUint64, maxUint64, 0x3FFFFF, 0}, }, }, { name: "get 220 LSBs in fourth word", initial: BitArray{ len: 255, words: [4]uint64{maxUint64, maxUint64, maxUint64, maxUint64}, }, length: 220, expected: BitArray{ len: 220, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0xFFFFFFF}, }, }, { name: "get 251 LSBs", initial: BitArray{ len: 255, words: [4]uint64{maxUint64, maxUint64, maxUint64, maxUint64}, }, length: 251, expected: BitArray{ len: 251, words: [4]uint64{maxUint64, maxUint64, maxUint64, 0x7FFFFFFFFFFFFFF}, }, }, { name: "get 100 LSBs from sparse bits", initial: BitArray{ len: 128, words: [4]uint64{0xAAAAAAAAAAAAAAAA, 0x5555555555555555, 0, 0}, }, length: 100, expected: BitArray{ len: 100, words: [4]uint64{0xAAAAAAAAAAAAAAAA, 0x0000000555555555, 0, 0}, }, }, { name: "no change when new length equals current length", initial: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, length: 64, expected: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "no change when new length greater than current length", initial: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, length: 128, expected: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := new(BitArray).copyLsb(&tt.initial, tt.length) if !result.Equal(&tt.expected) { t.Errorf("Truncate() got = %+v, want %+v", result, tt.expected) } }) } } func TestMSBs(t *testing.T) { tests := []struct { name string x *BitArray n uint8 want *BitArray }{ { name: "empty array", x: emptyBitArray, n: 0, want: emptyBitArray, }, { name: "get all bits", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, n: 64, want: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "get more bits than available", x: &BitArray{ len: 32, words: [4]uint64{0xFFFFFFFF, 0, 0, 0}, }, n: 64, want: &BitArray{ len: 32, words: [4]uint64{0xFFFFFFFF, 0, 0, 0}, }, }, { name: "get half of available bits", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, n: 32, want: &BitArray{ len: 32, words: [4]uint64{0xFFFFFFFF00000000 >> 32, 0, 0, 0}, }, }, { name: "get MSBs across word boundary", x: &BitArray{ len: 128, words: [4]uint64{maxUint64, maxUint64, 0, 0}, }, n: 100, want: &BitArray{ len: 100, words: [4]uint64{maxUint64, maxUint64 >> 28, 0, 0}, }, }, { name: "get MSBs from max length array", x: &BitArray{ len: 255, words: [4]uint64{maxUint64, maxUint64, maxUint64, ones63}, }, n: 64, want: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "get zero bits", x: &BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, n: 0, want: &BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "sparse bits", x: &BitArray{ len: 128, words: [4]uint64{0xAAAAAAAAAAAAAAAA, 0x5555555555555555, 0, 0}, }, n: 64, want: &BitArray{ len: 64, words: [4]uint64{0x5555555555555555, 0, 0, 0}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := new(BitArray).MSBs(tt.x, tt.n) if !got.Equal(tt.want) { t.Errorf("MSBs() = %v, want %v", got, tt.want) } if got.len != tt.want.len { t.Errorf("MSBs() = %v, want %v", got, tt.want) } }) } } func TestSetBit(t *testing.T) { tests := []struct { name string bit uint8 want BitArray }{ { name: "set bit 0", bit: 0, want: BitArray{ len: 1, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "set bit 1", bit: 1, want: BitArray{ len: 1, words: [4]uint64{1, 0, 0, 0}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := new(BitArray).SetBit(tt.bit) if !got.Equal(&tt.want) { t.Errorf("SetBit(%v) = %v, want %v", tt.bit, got, tt.want) } }) } } func TestSetBytes(t *testing.T) { tests := []struct { name string length uint8 data []byte want BitArray }{ { name: "empty data", length: 0, data: []byte{}, want: BitArray{ len: 0, words: [4]uint64{0, 0, 0, 0}, }, }, { name: "single byte", length: 8, data: []byte{0xFF}, want: BitArray{ len: 8, words: [4]uint64{0xFF, 0, 0, 0}, }, }, { name: "two bytes", length: 16, data: []byte{0xAA, 0xFF}, want: BitArray{ len: 16, words: [4]uint64{0xAAFF, 0, 0, 0}, }, }, { name: "three bytes", length: 24, data: []byte{0xAA, 0xBB, 0xCC}, want: BitArray{ len: 24, words: [4]uint64{0xAABBCC, 0, 0, 0}, }, }, { name: "four bytes", length: 32, data: []byte{0xAA, 0xBB, 0xCC, 0xDD}, want: BitArray{ len: 32, words: [4]uint64{0xAABBCCDD, 0, 0, 0}, }, }, { name: "eight bytes (full word)", length: 64, data: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, want: BitArray{ len: 64, words: [4]uint64{maxUint64, 0, 0, 0}, }, }, { name: "sixteen bytes (two words)", length: 128, data: []byte{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, }, want: BitArray{ len: 128, words: [4]uint64{ 0xAAAAAAAAAAAAAAAA, 0xFFFFFFFFFFFFFFFF, 0, 0, }, }, }, { name: "thirty-two bytes (full array)", length: 251, data: []byte{ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, want: BitArray{ len: 251, words: [4]uint64{ maxUint64, maxUint64, maxUint64, 0x7FFFFFFFFFFFFFF, }, }, }, { name: "truncate to length", length: 4, data: []byte{0xFF}, want: BitArray{ len: 4, words: [4]uint64{0xF, 0, 0, 0}, }, }, { name: "data larger than 32 bytes", length: 251, data: []byte{ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // extra bytes should be ignored }, want: BitArray{ len: 251, words: [4]uint64{ maxUint64, maxUint64, maxUint64, 0x7FFFFFFFFFFFFFF, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := new(BitArray).SetBytes(tt.length, tt.data) if !got.Equal(&tt.want) { t.Errorf("SetBytes(%d, %v) = %v, want %v", tt.length, tt.data, got, tt.want) } }) } }