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  }