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  }