github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/chains/tm34/libs/bits/bit_array_test.go (about) 1 package bits 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 12 tmrand "github.com/supragya/TendermintConnector/chains/tm34/libs/rand" 13 ) 14 15 func randBitArray(bits int) (*BitArray, []byte) { 16 src := tmrand.Bytes((bits + 7) / 8) 17 bA := NewBitArray(bits) 18 for i := 0; i < len(src); i++ { 19 for j := 0; j < 8; j++ { 20 if i*8+j >= bits { 21 return bA, src 22 } 23 setBit := src[i]&(1<<uint(j)) > 0 24 bA.SetIndex(i*8+j, setBit) 25 } 26 } 27 return bA, src 28 } 29 30 func TestAnd(t *testing.T) { 31 32 bA1, _ := randBitArray(51) 33 bA2, _ := randBitArray(31) 34 bA3 := bA1.And(bA2) 35 36 var bNil *BitArray 37 require.Equal(t, bNil.And(bA1), (*BitArray)(nil)) 38 require.Equal(t, bA1.And(nil), (*BitArray)(nil)) 39 require.Equal(t, bNil.And(nil), (*BitArray)(nil)) 40 41 if bA3.Bits != 31 { 42 t.Error("Expected min bits", bA3.Bits) 43 } 44 if len(bA3.Elems) != len(bA2.Elems) { 45 t.Error("Expected min elems length") 46 } 47 for i := 0; i < bA3.Bits; i++ { 48 expected := bA1.GetIndex(i) && bA2.GetIndex(i) 49 if bA3.GetIndex(i) != expected { 50 t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i)) 51 } 52 } 53 } 54 55 func TestOr(t *testing.T) { 56 57 bA1, _ := randBitArray(51) 58 bA2, _ := randBitArray(31) 59 bA3 := bA1.Or(bA2) 60 61 bNil := (*BitArray)(nil) 62 require.Equal(t, bNil.Or(bA1), bA1) 63 require.Equal(t, bA1.Or(nil), bA1) 64 require.Equal(t, bNil.Or(nil), (*BitArray)(nil)) 65 66 if bA3.Bits != 51 { 67 t.Error("Expected max bits") 68 } 69 if len(bA3.Elems) != len(bA1.Elems) { 70 t.Error("Expected max elems length") 71 } 72 for i := 0; i < bA3.Bits; i++ { 73 expected := bA1.GetIndex(i) || bA2.GetIndex(i) 74 if bA3.GetIndex(i) != expected { 75 t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i)) 76 } 77 } 78 } 79 80 func TestSub(t *testing.T) { 81 testCases := []struct { 82 initBA string 83 subtractingBA string 84 expectedBA string 85 }{ 86 {`null`, `null`, `null`}, 87 {`"x"`, `null`, `null`}, 88 {`null`, `"x"`, `null`}, 89 {`"x"`, `"x"`, `"_"`}, 90 {`"xxxxxx"`, `"x_x_x_"`, `"_x_x_x"`}, 91 {`"x_x_x_"`, `"xxxxxx"`, `"______"`}, 92 {`"xxxxxx"`, `"x_x_x_xxxx"`, `"_x_x_x"`}, 93 {`"x_x_x_xxxx"`, `"xxxxxx"`, `"______xxxx"`}, 94 {`"xxxxxxxxxx"`, `"x_x_x_"`, `"_x_x_xxxxx"`}, 95 {`"x_x_x_"`, `"xxxxxxxxxx"`, `"______"`}, 96 } 97 for _, tc := range testCases { 98 var bA *BitArray 99 err := json.Unmarshal([]byte(tc.initBA), &bA) 100 require.Nil(t, err) 101 102 var o *BitArray 103 err = json.Unmarshal([]byte(tc.subtractingBA), &o) 104 require.Nil(t, err) 105 106 got, _ := json.Marshal(bA.Sub(o)) 107 require.Equal( 108 t, 109 tc.expectedBA, 110 string(got), 111 "%s minus %s doesn't equal %s", 112 tc.initBA, 113 tc.subtractingBA, 114 tc.expectedBA, 115 ) 116 } 117 } 118 119 func TestPickRandom(t *testing.T) { 120 empty16Bits := "________________" 121 empty64Bits := empty16Bits + empty16Bits + empty16Bits + empty16Bits 122 testCases := []struct { 123 bA string 124 ok bool 125 }{ 126 {`null`, false}, 127 {`"x"`, true}, 128 {`"` + empty16Bits + `"`, false}, 129 {`"x` + empty16Bits + `"`, true}, 130 {`"` + empty16Bits + `x"`, true}, 131 {`"x` + empty16Bits + `x"`, true}, 132 {`"` + empty64Bits + `"`, false}, 133 {`"x` + empty64Bits + `"`, true}, 134 {`"` + empty64Bits + `x"`, true}, 135 {`"x` + empty64Bits + `x"`, true}, 136 } 137 for _, tc := range testCases { 138 var bitArr *BitArray 139 err := json.Unmarshal([]byte(tc.bA), &bitArr) 140 require.NoError(t, err) 141 _, ok := bitArr.PickRandom() 142 require.Equal(t, tc.ok, ok, "PickRandom got an unexpected result on input %s", tc.bA) 143 } 144 } 145 146 func TestBytes(t *testing.T) { 147 bA := NewBitArray(4) 148 bA.SetIndex(0, true) 149 check := func(bA *BitArray, bz []byte) { 150 if !bytes.Equal(bA.Bytes(), bz) { 151 panic(fmt.Sprintf("Expected %X but got %X", bz, bA.Bytes())) 152 } 153 } 154 check(bA, []byte{0x01}) 155 bA.SetIndex(3, true) 156 check(bA, []byte{0x09}) 157 158 bA = NewBitArray(9) 159 check(bA, []byte{0x00, 0x00}) 160 bA.SetIndex(7, true) 161 check(bA, []byte{0x80, 0x00}) 162 bA.SetIndex(8, true) 163 check(bA, []byte{0x80, 0x01}) 164 165 bA = NewBitArray(16) 166 check(bA, []byte{0x00, 0x00}) 167 bA.SetIndex(7, true) 168 check(bA, []byte{0x80, 0x00}) 169 bA.SetIndex(8, true) 170 check(bA, []byte{0x80, 0x01}) 171 bA.SetIndex(9, true) 172 check(bA, []byte{0x80, 0x03}) 173 } 174 175 func TestEmptyFull(t *testing.T) { 176 ns := []int{47, 123} 177 for _, n := range ns { 178 bA := NewBitArray(n) 179 if !bA.IsEmpty() { 180 t.Fatal("Expected bit array to be empty") 181 } 182 for i := 0; i < n; i++ { 183 bA.SetIndex(i, true) 184 } 185 if !bA.IsFull() { 186 t.Fatal("Expected bit array to be full") 187 } 188 } 189 } 190 191 func TestUpdateNeverPanics(t *testing.T) { 192 newRandBitArray := func(n int) *BitArray { 193 ba, _ := randBitArray(n) 194 return ba 195 } 196 pairs := []struct { 197 a, b *BitArray 198 }{ 199 {nil, nil}, 200 {newRandBitArray(10), newRandBitArray(12)}, 201 {newRandBitArray(23), newRandBitArray(23)}, 202 {newRandBitArray(37), nil}, 203 {nil, NewBitArray(10)}, 204 } 205 206 for _, pair := range pairs { 207 a, b := pair.a, pair.b 208 a.Update(b) 209 b.Update(a) 210 } 211 } 212 213 func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { 214 bitList := []int{-127, -128, -1 << 31} 215 for _, bits := range bitList { 216 _ = NewBitArray(bits) 217 } 218 } 219 220 func TestJSONMarshalUnmarshal(t *testing.T) { 221 222 bA1 := NewBitArray(0) 223 224 bA2 := NewBitArray(1) 225 226 bA3 := NewBitArray(1) 227 bA3.SetIndex(0, true) 228 229 bA4 := NewBitArray(5) 230 bA4.SetIndex(0, true) 231 bA4.SetIndex(1, true) 232 233 testCases := []struct { 234 bA *BitArray 235 marshalledBA string 236 }{ 237 {nil, `null`}, 238 {bA1, `null`}, 239 {bA2, `"_"`}, 240 {bA3, `"x"`}, 241 {bA4, `"xx___"`}, 242 } 243 244 for _, tc := range testCases { 245 tc := tc 246 t.Run(tc.bA.String(), func(t *testing.T) { 247 bz, err := json.Marshal(tc.bA) 248 require.NoError(t, err) 249 250 assert.Equal(t, tc.marshalledBA, string(bz)) 251 252 var unmarshalledBA *BitArray 253 err = json.Unmarshal(bz, &unmarshalledBA) 254 require.NoError(t, err) 255 256 if tc.bA == nil { 257 require.Nil(t, unmarshalledBA) 258 } else { 259 require.NotNil(t, unmarshalledBA) 260 assert.EqualValues(t, tc.bA.Bits, unmarshalledBA.Bits) 261 if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) { 262 assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems) 263 } 264 } 265 }) 266 } 267 } 268 269 func TestBitArrayProtoBuf(t *testing.T) { 270 testCases := []struct { 271 msg string 272 bA1 *BitArray 273 expPass bool 274 }{ 275 {"success empty", &BitArray{}, true}, 276 {"success", NewBitArray(1), true}, 277 {"success", NewBitArray(2), true}, 278 {"negative", NewBitArray(-1), false}, 279 } 280 for _, tc := range testCases { 281 protoBA := tc.bA1.ToProto() 282 ba := new(BitArray) 283 ba.FromProto(protoBA) 284 if tc.expPass { 285 require.Equal(t, tc.bA1, ba, tc.msg) 286 } else { 287 require.NotEqual(t, tc.bA1, ba, tc.msg) 288 } 289 } 290 }