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