You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
4.7 KiB

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