github.com/koko1123/flow-go-1@v0.29.6/ledger/common/bitutils/utils_test.go (about) 1 package bitutils 2 3 import ( 4 "math/big" 5 "math/bits" 6 "math/rand" 7 "time" 8 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func TestBitVectorAllocation(t *testing.T) { 15 for bits := 0; bits <= 127; bits++ { 16 numBytes := bits / 8 // integer division with floor 17 if bits%8 > 0 { 18 numBytes += 1 19 } 20 21 vect := MakeBitVector(bits) 22 assert.Equal(t, numBytes, len(vect)) 23 } 24 } 25 26 // Test_PaddedByteSliceLength tests that MinimalByteSliceLength returns the 27 func Test_PaddedByteSliceLength(t *testing.T) { 28 for bits := 0; bits <= 127; bits++ { 29 numBytes := bits / 8 // integer division with floor 30 if bits%8 > 0 { 31 numBytes += 1 32 } 33 34 assert.Equal(t, numBytes, MinimalByteSliceLength(bits)) 35 } 36 } 37 38 func TestBitTools(t *testing.T) { 39 seed := time.Now().UnixNano() 40 t.Logf("rand seed is %d", seed) 41 rand.Seed(seed) 42 r := rand.NewSource(seed) 43 44 const maxBits = 131 * 8 // upper bound of indices to test 45 var b big.Int 46 47 t.Run("testing ReadBit", func(t *testing.T) { 48 var max big.Int 49 // set max to 2^maxBits 50 max.SetBit(&max, maxBits, 1) 51 // random big int less that 2^maxBits 52 b.Rand(rand.New(r), &max) 53 maxBitsLen := (maxBits + 7) / 8 // length in bytes needed for maxbits 54 bytes := make([]byte, maxBitsLen) 55 copy(bytes[maxBitsLen-len(b.Bytes()):], b.Bytes()) 56 57 // reverse the endianness (both bits and bytes) 58 for j := 0; j < len(bytes)/2; j++ { 59 bytes[j], bytes[len(bytes)-j-1] = bytes[len(bytes)-j-1], bytes[j] 60 } 61 for j := 0; j < len(bytes); j++ { 62 bytes[j] = bits.Reverse8(bytes[j]) 63 } 64 // test bit reads are equal for all indices 65 for i := 0; i < maxBits; i++ { 66 bit := int(b.Bit(i)) 67 assert.Equal(t, bit, ReadBit(bytes, i)) 68 } 69 }) 70 71 t.Run("testing WriteBit", func(t *testing.T) { 72 b.SetInt64(0) 73 bytes := MakeBitVector(maxBits) 74 rand.Read(bytes) // fill bytes with random values to verify that writing to each individual bit works 75 76 // build a random big bit by bit 77 for idx := 0; idx < maxBits; idx++ { 78 bit := rand.Intn(2) 79 // b = 2*b + bit 80 b.Lsh(&b, 1) 81 b.Add(&b, big.NewInt(int64(bit))) 82 WriteBit(bytes, idx, bit) // sets the bit at index `idx` 83 } 84 85 // get the big int from the random slice 86 var randomBig big.Int 87 randomBig.SetBytes(bytes) 88 assert.Equal(t, 0, randomBig.Cmp(&b)) 89 }) 90 91 t.Run("testing ClearBit and SetBit", func(t *testing.T) { 92 b.SetInt64(0) 93 bytes := MakeBitVector(maxBits) 94 rand.Read(bytes) // fill bytes with random values to verify that writing to each individual bit works 95 96 // build a random big bit by bit 97 for idx := 0; idx < maxBits; idx++ { 98 bit := rand.Intn(2) 99 // b = 2*b + bit 100 b.Lsh(&b, 1) 101 b.Add(&b, big.NewInt(int64(bit))) 102 // sets the bit at index i 103 if bit == 1 { 104 SetBit(bytes, idx) 105 } else { 106 ClearBit(bytes, idx) 107 } 108 } 109 110 // get the big int from the random slice 111 var randomBig big.Int 112 randomBig.SetBytes(bytes) 113 assert.Equal(t, 0, randomBig.Cmp(&b)) 114 }) 115 }