github.com/evdatsion/aphelion-dpos-bft@v0.32.1/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  	cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common"
    11  )
    12  
    13  func randCompactBitArray(bits int) (*CompactBitArray, []byte) {
    14  	numBytes := (bits + 7) / 8
    15  	src := cmn.RandBytes((bits + 7) / 8)
    16  	bA := NewCompactBitArray(bits)
    17  
    18  	for i := 0; i < numBytes-1; i++ {
    19  		for j := uint8(0); j < 8; j++ {
    20  			bA.SetIndex(i*8+int(j), src[i]&(uint8(1)<<(8-j)) > 0)
    21  		}
    22  	}
    23  	// Set remaining bits
    24  	for i := uint8(0); i < 8-uint8(bA.ExtraBitsStored); i++ {
    25  		bA.SetIndex(numBytes*8+int(i), src[numBytes-1]&(uint8(1)<<(8-i)) > 0)
    26  	}
    27  	return bA, src
    28  }
    29  
    30  func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) {
    31  	bitList := []int{-127, -128, -1 << 31}
    32  	for _, bits := range bitList {
    33  		bA := NewCompactBitArray(bits)
    34  		require.Nil(t, bA)
    35  	}
    36  }
    37  
    38  func TestJSONMarshalUnmarshal(t *testing.T) {
    39  
    40  	bA1 := NewCompactBitArray(0)
    41  	bA2 := NewCompactBitArray(1)
    42  
    43  	bA3 := NewCompactBitArray(1)
    44  	bA3.SetIndex(0, true)
    45  
    46  	bA4 := NewCompactBitArray(5)
    47  	bA4.SetIndex(0, true)
    48  	bA4.SetIndex(1, true)
    49  
    50  	bA5 := NewCompactBitArray(9)
    51  	bA5.SetIndex(0, true)
    52  	bA5.SetIndex(1, true)
    53  	bA5.SetIndex(8, true)
    54  
    55  	bA6 := NewCompactBitArray(16)
    56  	bA6.SetIndex(0, true)
    57  	bA6.SetIndex(1, true)
    58  	bA6.SetIndex(8, false)
    59  	bA6.SetIndex(15, true)
    60  
    61  	testCases := []struct {
    62  		bA           *CompactBitArray
    63  		marshalledBA string
    64  	}{
    65  		{nil, `null`},
    66  		{bA1, `null`},
    67  		{bA2, `"_"`},
    68  		{bA3, `"x"`},
    69  		{bA4, `"xx___"`},
    70  		{bA5, `"xx______x"`},
    71  		{bA6, `"xx_____________x"`},
    72  	}
    73  
    74  	for _, tc := range testCases {
    75  		t.Run(tc.bA.String(), func(t *testing.T) {
    76  			bz, err := json.Marshal(tc.bA)
    77  			require.NoError(t, err)
    78  
    79  			assert.Equal(t, tc.marshalledBA, string(bz))
    80  
    81  			var unmarshalledBA *CompactBitArray
    82  			err = json.Unmarshal(bz, &unmarshalledBA)
    83  			require.NoError(t, err)
    84  
    85  			if tc.bA == nil {
    86  				require.Nil(t, unmarshalledBA)
    87  			} else {
    88  				require.NotNil(t, unmarshalledBA)
    89  				assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
    90  				if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) {
    91  					assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
    92  				}
    93  			}
    94  		})
    95  	}
    96  }
    97  
    98  func TestCompactMarshalUnmarshal(t *testing.T) {
    99  	bA1 := NewCompactBitArray(0)
   100  	bA2 := NewCompactBitArray(1)
   101  
   102  	bA3 := NewCompactBitArray(1)
   103  	bA3.SetIndex(0, true)
   104  
   105  	bA4 := NewCompactBitArray(5)
   106  	bA4.SetIndex(0, true)
   107  	bA4.SetIndex(1, true)
   108  
   109  	bA5 := NewCompactBitArray(9)
   110  	bA5.SetIndex(0, true)
   111  	bA5.SetIndex(1, true)
   112  	bA5.SetIndex(8, true)
   113  
   114  	bA6 := NewCompactBitArray(16)
   115  	bA6.SetIndex(0, true)
   116  	bA6.SetIndex(1, true)
   117  	bA6.SetIndex(8, false)
   118  	bA6.SetIndex(15, true)
   119  
   120  	testCases := []struct {
   121  		bA           *CompactBitArray
   122  		marshalledBA []byte
   123  	}{
   124  		{nil, []byte("null")},
   125  		{bA1, []byte("null")},
   126  		{bA2, []byte{byte(1), byte(0)}},
   127  		{bA3, []byte{byte(1), byte(128)}},
   128  		{bA4, []byte{byte(5), byte(192)}},
   129  		{bA5, []byte{byte(9), byte(192), byte(128)}},
   130  		{bA6, []byte{byte(16), byte(192), byte(1)}},
   131  	}
   132  
   133  	for _, tc := range testCases {
   134  		t.Run(tc.bA.String(), func(t *testing.T) {
   135  			bz := tc.bA.CompactMarshal()
   136  
   137  			assert.Equal(t, tc.marshalledBA, bz)
   138  
   139  			unmarshalledBA, err := CompactUnmarshal(bz)
   140  			require.NoError(t, err)
   141  			if tc.bA == nil {
   142  				require.Nil(t, unmarshalledBA)
   143  			} else {
   144  				require.NotNil(t, unmarshalledBA)
   145  				assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
   146  				if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) {
   147  					assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
   148  				}
   149  			}
   150  		})
   151  	}
   152  }
   153  
   154  func TestCompactBitArrayNumOfTrueBitsBefore(t *testing.T) {
   155  	testCases := []struct {
   156  		marshalledBA   string
   157  		bAIndex        []int
   158  		trueValueIndex []int
   159  	}{
   160  		{`"_____"`, []int{0, 1, 2, 3, 4}, []int{0, 0, 0, 0, 0}},
   161  		{`"x"`, []int{0}, []int{0}},
   162  		{`"_x"`, []int{1}, []int{0}},
   163  		{`"x___xxxx"`, []int{0, 4, 5, 6, 7}, []int{0, 1, 2, 3, 4}},
   164  		{`"__x_xx_x__x_x___"`, []int{2, 4, 5, 7, 10, 12}, []int{0, 1, 2, 3, 4, 5}},
   165  		{`"______________xx"`, []int{14, 15}, []int{0, 1}},
   166  	}
   167  	for tcIndex, tc := range testCases {
   168  		t.Run(tc.marshalledBA, func(t *testing.T) {
   169  			var bA *CompactBitArray
   170  			err := json.Unmarshal([]byte(tc.marshalledBA), &bA)
   171  			require.NoError(t, err)
   172  
   173  			for i := 0; i < len(tc.bAIndex); i++ {
   174  				require.Equal(t, tc.trueValueIndex[i], bA.NumTrueBitsBefore(tc.bAIndex[i]), "tc %d, i %d", tcIndex, i)
   175  			}
   176  		})
   177  	}
   178  }
   179  
   180  func TestCompactBitArrayGetSetIndex(t *testing.T) {
   181  	r := rand.New(rand.NewSource(100))
   182  	numTests := 10
   183  	numBitsPerArr := 100
   184  	for i := 0; i < numTests; i++ {
   185  		bits := r.Intn(1000)
   186  		bA, _ := randCompactBitArray(bits)
   187  
   188  		for j := 0; j < numBitsPerArr; j++ {
   189  			copy := bA.Copy()
   190  			index := r.Intn(bits)
   191  			val := (r.Int63() % 2) == 0
   192  			bA.SetIndex(index, val)
   193  			require.Equal(t, val, bA.GetIndex(index), "bA.SetIndex(%d, %v) failed on bit array: %s", index, val, copy)
   194  		}
   195  	}
   196  }