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  }