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.

290 lines
6.4 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package bits
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "testing"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. tmrand "github.com/tendermint/tendermint/libs/rand"
  10. )
  11. func randBitArray(bits int) (*BitArray, []byte) {
  12. src := tmrand.Bytes((bits + 7) / 8)
  13. bA := NewBitArray(bits)
  14. for i := 0; i < len(src); i++ {
  15. for j := 0; j < 8; j++ {
  16. if i*8+j >= bits {
  17. return bA, src
  18. }
  19. setBit := src[i]&(1<<uint(j)) > 0
  20. bA.SetIndex(i*8+j, setBit)
  21. }
  22. }
  23. return bA, src
  24. }
  25. func TestAnd(t *testing.T) {
  26. bA1, _ := randBitArray(51)
  27. bA2, _ := randBitArray(31)
  28. bA3 := bA1.And(bA2)
  29. var bNil *BitArray
  30. require.Equal(t, bNil.And(bA1), (*BitArray)(nil))
  31. require.Equal(t, bA1.And(nil), (*BitArray)(nil))
  32. require.Equal(t, bNil.And(nil), (*BitArray)(nil))
  33. if bA3.Bits != 31 {
  34. t.Error("Expected min bits", bA3.Bits)
  35. }
  36. if len(bA3.Elems) != len(bA2.Elems) {
  37. t.Error("Expected min elems length")
  38. }
  39. for i := 0; i < bA3.Bits; i++ {
  40. expected := bA1.GetIndex(i) && bA2.GetIndex(i)
  41. if bA3.GetIndex(i) != expected {
  42. t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
  43. }
  44. }
  45. }
  46. func TestOr(t *testing.T) {
  47. bA1, _ := randBitArray(51)
  48. bA2, _ := randBitArray(31)
  49. bA3 := bA1.Or(bA2)
  50. bNil := (*BitArray)(nil)
  51. require.Equal(t, bNil.Or(bA1), bA1)
  52. require.Equal(t, bA1.Or(nil), bA1)
  53. require.Equal(t, bNil.Or(nil), (*BitArray)(nil))
  54. if bA3.Bits != 51 {
  55. t.Error("Expected max bits")
  56. }
  57. if len(bA3.Elems) != len(bA1.Elems) {
  58. t.Error("Expected max elems length")
  59. }
  60. for i := 0; i < bA3.Bits; i++ {
  61. expected := bA1.GetIndex(i) || bA2.GetIndex(i)
  62. if bA3.GetIndex(i) != expected {
  63. t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
  64. }
  65. }
  66. }
  67. func TestSub(t *testing.T) {
  68. testCases := []struct {
  69. initBA string
  70. subtractingBA string
  71. expectedBA string
  72. }{
  73. {`null`, `null`, `null`},
  74. {`"x"`, `null`, `null`},
  75. {`null`, `"x"`, `null`},
  76. {`"x"`, `"x"`, `"_"`},
  77. {`"xxxxxx"`, `"x_x_x_"`, `"_x_x_x"`},
  78. {`"x_x_x_"`, `"xxxxxx"`, `"______"`},
  79. {`"xxxxxx"`, `"x_x_x_xxxx"`, `"_x_x_x"`},
  80. {`"x_x_x_xxxx"`, `"xxxxxx"`, `"______xxxx"`},
  81. {`"xxxxxxxxxx"`, `"x_x_x_"`, `"_x_x_xxxxx"`},
  82. {`"x_x_x_"`, `"xxxxxxxxxx"`, `"______"`},
  83. }
  84. for _, tc := range testCases {
  85. var bA *BitArray
  86. err := json.Unmarshal([]byte(tc.initBA), &bA)
  87. require.Nil(t, err)
  88. var o *BitArray
  89. err = json.Unmarshal([]byte(tc.subtractingBA), &o)
  90. require.Nil(t, err)
  91. got, _ := json.Marshal(bA.Sub(o))
  92. require.Equal(
  93. t,
  94. tc.expectedBA,
  95. string(got),
  96. "%s minus %s doesn't equal %s",
  97. tc.initBA,
  98. tc.subtractingBA,
  99. tc.expectedBA,
  100. )
  101. }
  102. }
  103. func TestPickRandom(t *testing.T) {
  104. empty16Bits := "________________"
  105. empty64Bits := empty16Bits + empty16Bits + empty16Bits + empty16Bits
  106. testCases := []struct {
  107. bA string
  108. ok bool
  109. }{
  110. {`null`, false},
  111. {`"x"`, true},
  112. {`"` + empty16Bits + `"`, false},
  113. {`"x` + empty16Bits + `"`, true},
  114. {`"` + empty16Bits + `x"`, true},
  115. {`"x` + empty16Bits + `x"`, true},
  116. {`"` + empty64Bits + `"`, false},
  117. {`"x` + empty64Bits + `"`, true},
  118. {`"` + empty64Bits + `x"`, true},
  119. {`"x` + empty64Bits + `x"`, true},
  120. }
  121. for _, tc := range testCases {
  122. var bitArr *BitArray
  123. err := json.Unmarshal([]byte(tc.bA), &bitArr)
  124. require.NoError(t, err)
  125. _, ok := bitArr.PickRandom()
  126. require.Equal(t, tc.ok, ok, "PickRandom got an unexpected result on input %s", tc.bA)
  127. }
  128. }
  129. func TestBytes(t *testing.T) {
  130. bA := NewBitArray(4)
  131. bA.SetIndex(0, true)
  132. check := func(bA *BitArray, bz []byte) {
  133. if !bytes.Equal(bA.Bytes(), bz) {
  134. panic(fmt.Sprintf("Expected %X but got %X", bz, bA.Bytes()))
  135. }
  136. }
  137. check(bA, []byte{0x01})
  138. bA.SetIndex(3, true)
  139. check(bA, []byte{0x09})
  140. bA = NewBitArray(9)
  141. check(bA, []byte{0x00, 0x00})
  142. bA.SetIndex(7, true)
  143. check(bA, []byte{0x80, 0x00})
  144. bA.SetIndex(8, true)
  145. check(bA, []byte{0x80, 0x01})
  146. bA = NewBitArray(16)
  147. check(bA, []byte{0x00, 0x00})
  148. bA.SetIndex(7, true)
  149. check(bA, []byte{0x80, 0x00})
  150. bA.SetIndex(8, true)
  151. check(bA, []byte{0x80, 0x01})
  152. bA.SetIndex(9, true)
  153. check(bA, []byte{0x80, 0x03})
  154. }
  155. func TestEmptyFull(t *testing.T) {
  156. ns := []int{47, 123}
  157. for _, n := range ns {
  158. bA := NewBitArray(n)
  159. if !bA.IsEmpty() {
  160. t.Fatal("Expected bit array to be empty")
  161. }
  162. for i := 0; i < n; i++ {
  163. bA.SetIndex(i, true)
  164. }
  165. if !bA.IsFull() {
  166. t.Fatal("Expected bit array to be full")
  167. }
  168. }
  169. }
  170. func TestUpdateNeverPanics(t *testing.T) {
  171. newRandBitArray := func(n int) *BitArray {
  172. ba, _ := randBitArray(n)
  173. return ba
  174. }
  175. pairs := []struct {
  176. a, b *BitArray
  177. }{
  178. {nil, nil},
  179. {newRandBitArray(10), newRandBitArray(12)},
  180. {newRandBitArray(23), newRandBitArray(23)},
  181. {newRandBitArray(37), nil},
  182. {nil, NewBitArray(10)},
  183. }
  184. for _, pair := range pairs {
  185. a, b := pair.a, pair.b
  186. a.Update(b)
  187. b.Update(a)
  188. }
  189. }
  190. func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) {
  191. bitList := []int{-127, -128, -1 << 31}
  192. for _, bits := range bitList {
  193. _ = NewBitArray(bits)
  194. }
  195. }
  196. func TestJSONMarshalUnmarshal(t *testing.T) {
  197. bA1 := NewBitArray(0)
  198. bA2 := NewBitArray(1)
  199. bA3 := NewBitArray(1)
  200. bA3.SetIndex(0, true)
  201. bA4 := NewBitArray(5)
  202. bA4.SetIndex(0, true)
  203. bA4.SetIndex(1, true)
  204. testCases := []struct {
  205. bA *BitArray
  206. marshalledBA string
  207. }{
  208. {nil, `null`},
  209. {bA1, `null`},
  210. {bA2, `"_"`},
  211. {bA3, `"x"`},
  212. {bA4, `"xx___"`},
  213. }
  214. for _, tc := range testCases {
  215. tc := tc
  216. t.Run(tc.bA.String(), func(t *testing.T) {
  217. bz, err := json.Marshal(tc.bA)
  218. require.NoError(t, err)
  219. assert.Equal(t, tc.marshalledBA, string(bz))
  220. var unmarshalledBA *BitArray
  221. err = json.Unmarshal(bz, &unmarshalledBA)
  222. require.NoError(t, err)
  223. if tc.bA == nil {
  224. require.Nil(t, unmarshalledBA)
  225. } else {
  226. require.NotNil(t, unmarshalledBA)
  227. assert.EqualValues(t, tc.bA.Bits, unmarshalledBA.Bits)
  228. if assert.EqualValues(t, tc.bA.String(), unmarshalledBA.String()) {
  229. assert.EqualValues(t, tc.bA.Elems, unmarshalledBA.Elems)
  230. }
  231. }
  232. })
  233. }
  234. }
  235. func TestBitArrayProtoBuf(t *testing.T) {
  236. testCases := []struct {
  237. msg string
  238. bA1 *BitArray
  239. expPass bool
  240. }{
  241. {"success empty", &BitArray{}, true},
  242. {"success", NewBitArray(1), true},
  243. {"success", NewBitArray(2), true},
  244. {"negative", NewBitArray(-1), false},
  245. }
  246. for _, tc := range testCases {
  247. protoBA := tc.bA1.ToProto()
  248. ba := new(BitArray)
  249. ba.FromProto(protoBA)
  250. if tc.expPass {
  251. require.Equal(t, tc.bA1, ba, tc.msg)
  252. } else {
  253. require.NotEqual(t, tc.bA1, ba, tc.msg)
  254. }
  255. }
  256. }