github.com/okex/exchain@v1.8.0/libs/tendermint/crypto/multisig/bitarray/compact_bit_array_test.go (about)

     1  package bitarray
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math"
     7  	"math/rand"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	tmrand "github.com/okex/exchain/libs/tendermint/libs/rand"
    14  )
    15  
    16  func randCompactBitArray(bits int) (*CompactBitArray, []byte) {
    17  	numBytes := (bits + 7) / 8
    18  	src := tmrand.Bytes((bits + 7) / 8)
    19  	bA := NewCompactBitArray(bits)
    20  
    21  	for i := 0; i < numBytes-1; i++ {
    22  		for j := uint8(0); j < 8; j++ {
    23  			bA.SetIndex(i*8+int(j), src[i]&(uint8(1)<<(8-j)) > 0)
    24  		}
    25  	}
    26  	// Set remaining bits
    27  	for i := uint8(0); i < 8-bA.ExtraBitsStored; i++ {
    28  		bA.SetIndex(numBytes*8+int(i), src[numBytes-1]&(uint8(1)<<(8-i)) > 0)
    29  	}
    30  	return bA, src
    31  }
    32  
    33  func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) {
    34  	bitList := []int{-127, -128, -1 << 31}
    35  	for _, bits := range bitList {
    36  		bA := NewCompactBitArray(bits)
    37  		require.Nil(t, bA)
    38  	}
    39  }
    40  
    41  func TestJSONMarshalUnmarshal(t *testing.T) {
    42  
    43  	bA1 := NewCompactBitArray(0)
    44  	bA2 := NewCompactBitArray(1)
    45  
    46  	bA3 := NewCompactBitArray(1)
    47  	bA3.SetIndex(0, true)
    48  
    49  	bA4 := NewCompactBitArray(5)
    50  	bA4.SetIndex(0, true)
    51  	bA4.SetIndex(1, true)
    52  
    53  	bA5 := NewCompactBitArray(9)
    54  	bA5.SetIndex(0, true)
    55  	bA5.SetIndex(1, true)
    56  	bA5.SetIndex(8, true)
    57  
    58  	bA6 := NewCompactBitArray(16)
    59  	bA6.SetIndex(0, true)
    60  	bA6.SetIndex(1, true)
    61  	bA6.SetIndex(8, false)
    62  	bA6.SetIndex(15, true)
    63  
    64  	testCases := []struct {
    65  		bA           *CompactBitArray
    66  		marshalledBA string
    67  	}{
    68  		{nil, `null`},
    69  		{bA1, `null`},
    70  		{bA2, `"_"`},
    71  		{bA3, `"x"`},
    72  		{bA4, `"xx___"`},
    73  		{bA5, `"xx______x"`},
    74  		{bA6, `"xx_____________x"`},
    75  	}
    76  
    77  	for _, tc := range testCases {
    78  		tc := tc
    79  		t.Run(tc.bA.String(), func(t *testing.T) {
    80  			bz, err := json.Marshal(tc.bA)
    81  			require.NoError(t, err)
    82  
    83  			assert.Equal(t, tc.marshalledBA, string(bz))
    84  
    85  			var unmarshalledBA *CompactBitArray
    86  			err = json.Unmarshal(bz, &unmarshalledBA)
    87  			require.NoError(t, err)
    88  
    89  			if tc.bA == nil {
    90  				require.Nil(t, unmarshalledBA)
    91  			} else {
    92  				require.NotNil(t, unmarshalledBA)
    93  				assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
    94  				if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) {
    95  					assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
    96  				}
    97  			}
    98  		})
    99  	}
   100  }
   101  
   102  func TestCompactMarshalUnmarshal(t *testing.T) {
   103  	bA1 := NewCompactBitArray(0)
   104  	bA2 := NewCompactBitArray(1)
   105  
   106  	bA3 := NewCompactBitArray(1)
   107  	bA3.SetIndex(0, true)
   108  
   109  	bA4 := NewCompactBitArray(5)
   110  	bA4.SetIndex(0, true)
   111  	bA4.SetIndex(1, true)
   112  
   113  	bA5 := NewCompactBitArray(9)
   114  	bA5.SetIndex(0, true)
   115  	bA5.SetIndex(1, true)
   116  	bA5.SetIndex(8, true)
   117  
   118  	bA6 := NewCompactBitArray(16)
   119  	bA6.SetIndex(0, true)
   120  	bA6.SetIndex(1, true)
   121  	bA6.SetIndex(8, false)
   122  	bA6.SetIndex(15, true)
   123  
   124  	testCases := []struct {
   125  		bA           *CompactBitArray
   126  		marshalledBA []byte
   127  	}{
   128  		{nil, []byte("null")},
   129  		{bA1, []byte("null")},
   130  		{bA2, []byte{byte(1), byte(0)}},
   131  		{bA3, []byte{byte(1), byte(128)}},
   132  		{bA4, []byte{byte(5), byte(192)}},
   133  		{bA5, []byte{byte(9), byte(192), byte(128)}},
   134  		{bA6, []byte{byte(16), byte(192), byte(1)}},
   135  	}
   136  
   137  	for _, tc := range testCases {
   138  		tc := tc
   139  		t.Run(tc.bA.String(), func(t *testing.T) {
   140  			bz := tc.bA.CompactMarshal()
   141  
   142  			assert.Equal(t, tc.marshalledBA, bz)
   143  
   144  			unmarshalledBA, err := CompactUnmarshal(bz)
   145  			require.NoError(t, err)
   146  			if tc.bA == nil {
   147  				require.Nil(t, unmarshalledBA)
   148  			} else {
   149  				require.NotNil(t, unmarshalledBA)
   150  				assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
   151  				if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) {
   152  					assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
   153  				}
   154  			}
   155  		})
   156  	}
   157  }
   158  
   159  func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) {
   160  	testCases := []struct {
   161  		marshalledBA   string
   162  		bAIndex        []int
   163  		trueValueIndex []int
   164  	}{
   165  		{`"_____"`, []int{0, 1, 2, 3, 4}, []int{0, 0, 0, 0, 0}},
   166  		{`"x"`, []int{0}, []int{0}},
   167  		{`"_x"`, []int{1}, []int{0}},
   168  		{`"x___xxxx"`, []int{0, 4, 5, 6, 7}, []int{0, 1, 2, 3, 4}},
   169  		{`"__x_xx_x__x_x___"`, []int{2, 4, 5, 7, 10, 12}, []int{0, 1, 2, 3, 4, 5}},
   170  		{`"______________xx"`, []int{14, 15}, []int{0, 1}},
   171  	}
   172  	for tcIndex, tc := range testCases {
   173  		tc := tc
   174  		tcIndex := tcIndex
   175  		t.Run(tc.marshalledBA, func(t *testing.T) {
   176  			var bA *CompactBitArray
   177  			err := json.Unmarshal([]byte(tc.marshalledBA), &bA)
   178  			require.NoError(t, err)
   179  
   180  			for i := 0; i < len(tc.bAIndex); i++ {
   181  
   182  				require.Equal(t, tc.trueValueIndex[i], bA.NumTrueBitsBefore(tc.bAIndex[i]), "tc %d, i %d", tcIndex, i)
   183  			}
   184  		})
   185  	}
   186  }
   187  
   188  func TestCompactBitArrayGetSetIndex(t *testing.T) {
   189  	r := rand.New(rand.NewSource(100))
   190  	numTests := 10
   191  	numBitsPerArr := 100
   192  	for i := 0; i < numTests; i++ {
   193  		bits := r.Intn(1000)
   194  		bA, _ := randCompactBitArray(bits)
   195  
   196  		for j := 0; j < numBitsPerArr; j++ {
   197  			copy := bA.Copy()
   198  			index := r.Intn(bits)
   199  			val := (r.Int63() % 2) == 0
   200  			bA.SetIndex(index, val)
   201  			require.Equal(t, val, bA.GetIndex(index), "bA.SetIndex(%d, %v) failed on bit array: %s", index, val, copy)
   202  		}
   203  	}
   204  }
   205  
   206  func TestNewCompactBitArrayCrashWithLimits(t *testing.T) {
   207  	if testing.Short() {
   208  		t.Skip("This test can be expensive in memory")
   209  	}
   210  	tests := []struct {
   211  		in       int
   212  		mustPass bool
   213  	}{
   214  		{int(^uint(0) >> 30), false},
   215  		{int(^uint(0) >> 1), false},
   216  		{int(^uint(0) >> 2), false},
   217  		{int(math.MaxInt32), true},
   218  		{int(math.MaxInt32) + 1, true},
   219  		{int(math.MaxInt32) + 2, true},
   220  		{int(math.MaxInt32) - 7, true},
   221  		{int(math.MaxInt32) + 24, true},
   222  		{int(math.MaxInt32) * 9, false}, // results in >=maxint after (bits+7)/8
   223  		{1, true},
   224  		{0, false},
   225  	}
   226  
   227  	for _, tt := range tests {
   228  		tt := tt
   229  		t.Run(fmt.Sprintf("%d", tt.in), func(t *testing.T) {
   230  			got := NewCompactBitArray(tt.in)
   231  			if g := got != nil; g != tt.mustPass {
   232  				t.Fatalf("got!=nil=%t, want=%t", g, tt.mustPass)
   233  			}
   234  		})
   235  	}
   236  }