github.com/vipernet-xyz/tendermint-core@v0.32.0/crypto/multisig/bitarray/compact_bit_array_test.go (about) 1 package bitarray 2 3 import ( 4 "encoding/json" 5 "math/rand" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 tmrand "github.com/tendermint/tendermint/libs/rand" 12 ) 13 14 func randCompactBitArray(bits int) (*CompactBitArray, []byte) { 15 numBytes := (bits + 7) / 8 16 src := tmrand.Bytes((bits + 7) / 8) 17 bA := NewCompactBitArray(bits) 18 19 for i := 0; i < numBytes-1; i++ { 20 for j := uint8(0); j < 8; j++ { 21 bA.SetIndex(i*8+int(j), src[i]&(uint8(1)<<(8-j)) > 0) 22 } 23 } 24 // Set remaining bits 25 for i := uint8(0); i < 8-bA.ExtraBitsStored; i++ { 26 bA.SetIndex(numBytes*8+int(i), src[numBytes-1]&(uint8(1)<<(8-i)) > 0) 27 } 28 return bA, src 29 } 30 31 func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { 32 bitList := []int{-127, -128, -1 << 31} 33 for _, bits := range bitList { 34 bA := NewCompactBitArray(bits) 35 require.Nil(t, bA) 36 } 37 } 38 39 func TestJSONMarshalUnmarshal(t *testing.T) { 40 41 bA1 := NewCompactBitArray(0) 42 bA2 := NewCompactBitArray(1) 43 44 bA3 := NewCompactBitArray(1) 45 bA3.SetIndex(0, true) 46 47 bA4 := NewCompactBitArray(5) 48 bA4.SetIndex(0, true) 49 bA4.SetIndex(1, true) 50 51 bA5 := NewCompactBitArray(9) 52 bA5.SetIndex(0, true) 53 bA5.SetIndex(1, true) 54 bA5.SetIndex(8, true) 55 56 bA6 := NewCompactBitArray(16) 57 bA6.SetIndex(0, true) 58 bA6.SetIndex(1, true) 59 bA6.SetIndex(8, false) 60 bA6.SetIndex(15, true) 61 62 testCases := []struct { 63 bA *CompactBitArray 64 marshalledBA string 65 }{ 66 {nil, `null`}, 67 {bA1, `null`}, 68 {bA2, `"_"`}, 69 {bA3, `"x"`}, 70 {bA4, `"xx___"`}, 71 {bA5, `"xx______x"`}, 72 {bA6, `"xx_____________x"`}, 73 } 74 75 for _, tc := range testCases { 76 tc := tc 77 t.Run(tc.bA.String(), func(t *testing.T) { 78 bz, err := json.Marshal(tc.bA) 79 require.NoError(t, err) 80 81 assert.Equal(t, tc.marshalledBA, string(bz)) 82 83 var unmarshalledBA *CompactBitArray 84 err = json.Unmarshal(bz, &unmarshalledBA) 85 require.NoError(t, err) 86 87 if tc.bA == nil { 88 require.Nil(t, unmarshalledBA) 89 } else { 90 require.NotNil(t, unmarshalledBA) 91 assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems) 92 if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) { 93 assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems) 94 } 95 } 96 }) 97 } 98 } 99 100 func TestCompactMarshalUnmarshal(t *testing.T) { 101 bA1 := NewCompactBitArray(0) 102 bA2 := NewCompactBitArray(1) 103 104 bA3 := NewCompactBitArray(1) 105 bA3.SetIndex(0, true) 106 107 bA4 := NewCompactBitArray(5) 108 bA4.SetIndex(0, true) 109 bA4.SetIndex(1, true) 110 111 bA5 := NewCompactBitArray(9) 112 bA5.SetIndex(0, true) 113 bA5.SetIndex(1, true) 114 bA5.SetIndex(8, true) 115 116 bA6 := NewCompactBitArray(16) 117 bA6.SetIndex(0, true) 118 bA6.SetIndex(1, true) 119 bA6.SetIndex(8, false) 120 bA6.SetIndex(15, true) 121 122 testCases := []struct { 123 bA *CompactBitArray 124 marshalledBA []byte 125 }{ 126 {nil, []byte("null")}, 127 {bA1, []byte("null")}, 128 {bA2, []byte{byte(1), byte(0)}}, 129 {bA3, []byte{byte(1), byte(128)}}, 130 {bA4, []byte{byte(5), byte(192)}}, 131 {bA5, []byte{byte(9), byte(192), byte(128)}}, 132 {bA6, []byte{byte(16), byte(192), byte(1)}}, 133 } 134 135 for _, tc := range testCases { 136 tc := tc 137 t.Run(tc.bA.String(), func(t *testing.T) { 138 bz := tc.bA.CompactMarshal() 139 140 assert.Equal(t, tc.marshalledBA, bz) 141 142 unmarshalledBA, err := CompactUnmarshal(bz) 143 require.NoError(t, err) 144 if tc.bA == nil { 145 require.Nil(t, unmarshalledBA) 146 } else { 147 require.NotNil(t, unmarshalledBA) 148 assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems) 149 if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) { 150 assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems) 151 } 152 } 153 }) 154 } 155 } 156 157 func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) { 158 testCases := []struct { 159 marshalledBA string 160 bAIndex []int 161 trueValueIndex []int 162 }{ 163 {`"_____"`, []int{0, 1, 2, 3, 4}, []int{0, 0, 0, 0, 0}}, 164 {`"x"`, []int{0}, []int{0}}, 165 {`"_x"`, []int{1}, []int{0}}, 166 {`"x___xxxx"`, []int{0, 4, 5, 6, 7}, []int{0, 1, 2, 3, 4}}, 167 {`"__x_xx_x__x_x___"`, []int{2, 4, 5, 7, 10, 12}, []int{0, 1, 2, 3, 4, 5}}, 168 {`"______________xx"`, []int{14, 15}, []int{0, 1}}, 169 } 170 for tcIndex, tc := range testCases { 171 tc := tc 172 tcIndex := tcIndex 173 t.Run(tc.marshalledBA, func(t *testing.T) { 174 var bA *CompactBitArray 175 err := json.Unmarshal([]byte(tc.marshalledBA), &bA) 176 require.NoError(t, err) 177 178 for i := 0; i < len(tc.bAIndex); i++ { 179 180 require.Equal(t, tc.trueValueIndex[i], bA.NumTrueBitsBefore(tc.bAIndex[i]), "tc %d, i %d", tcIndex, i) 181 } 182 }) 183 } 184 } 185 186 func TestCompactBitArrayGetSetIndex(t *testing.T) { 187 r := rand.New(rand.NewSource(100)) 188 numTests := 10 189 numBitsPerArr := 100 190 for i := 0; i < numTests; i++ { 191 bits := r.Intn(1000) 192 bA, _ := randCompactBitArray(bits) 193 194 for j := 0; j < numBitsPerArr; j++ { 195 copy := bA.Copy() 196 index := r.Intn(bits) 197 val := (r.Int63() % 2) == 0 198 bA.SetIndex(index, val) 199 require.Equal(t, val, bA.GetIndex(index), "bA.SetIndex(%d, %v) failed on bit array: %s", index, val, copy) 200 } 201 } 202 }