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