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.

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