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.

256 lines
5.8 KiB

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