vector_test.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. package vector
  2. import (
  3. "errors"
  4. "math/rand"
  5. "strconv"
  6. "testing"
  7. "time"
  8. )
  9. // Nx is the minimum number of elements for the internal tree of the vector to
  10. // be x levels deep.
  11. const (
  12. N1 = tailMaxLen + 1 // 33
  13. N2 = nodeSize + tailMaxLen + 1 // 65
  14. N3 = nodeSize*nodeSize + tailMaxLen + 1 // 1057
  15. N4 = nodeSize*nodeSize*nodeSize + tailMaxLen + 1 // 32801
  16. )
  17. func init() {
  18. rand.Seed(time.Now().UTC().UnixNano())
  19. }
  20. func TestVector(t *testing.T) {
  21. run := func(n int) {
  22. t.Run(strconv.Itoa(n), func(t *testing.T) {
  23. v := testCons(t, n)
  24. testIndex(t, v, 0, n)
  25. testAssoc(t, v, "233")
  26. testIterator(t, v.Iterator(), 0, n)
  27. testPop(t, v)
  28. })
  29. }
  30. for i := 0; i <= N3; i++ {
  31. run(i)
  32. }
  33. run(N4)
  34. }
  35. // Regression test against #4.
  36. func TestIterator_VectorWithNil(t *testing.T) {
  37. run := func(n int) {
  38. t.Run(strconv.Itoa(n), func(t *testing.T) {
  39. v := Empty
  40. for i := 0; i < n; i++ {
  41. v = v.Cons(nil)
  42. }
  43. iterated := 0
  44. for it := v.Iterator(); it.HasElem(); it.Next() {
  45. iterated++
  46. if it.Elem() != nil {
  47. t.Errorf("element not nil")
  48. }
  49. }
  50. if iterated != n {
  51. t.Errorf("did not iterate %d items", n)
  52. }
  53. })
  54. }
  55. for i := 0; i <= N3; i++ {
  56. run(i)
  57. }
  58. run(N4)
  59. }
  60. // testCons creates a vector containing 0...n-1 with Cons, and ensures that the
  61. // length of the old and new vectors are expected after each Cons. It returns
  62. // the created vector.
  63. func testCons(t *testing.T, n int) Vector {
  64. v := Empty
  65. for i := 0; i < n; i++ {
  66. oldv := v
  67. v = v.Cons(i)
  68. if count := oldv.Len(); count != i {
  69. t.Errorf("oldv.Count() == %v, want %v", count, i)
  70. }
  71. if count := v.Len(); count != i+1 {
  72. t.Errorf("v.Count() == %v, want %v", count, i+1)
  73. }
  74. }
  75. return v
  76. }
  77. // testIndex tests Index, assuming that the vector contains begin...int-1.
  78. func testIndex(t *testing.T, v Vector, begin, end int) {
  79. n := v.Len()
  80. for i := 0; i < n; i++ {
  81. elem, _ := v.Index(i)
  82. if elem != i {
  83. t.Errorf("v.Index(%v) == %v, want %v", i, elem, i)
  84. }
  85. }
  86. for _, i := range []int{-2, -1, n, n + 1, n * 2} {
  87. if elem, _ := v.Index(i); elem != nil {
  88. t.Errorf("v.Index(%d) == %v, want nil", i, elem)
  89. }
  90. }
  91. }
  92. // testIterator tests the iterator, assuming that the result is begin...end-1.
  93. func testIterator(t *testing.T, it Iterator, begin, end int) {
  94. i := begin
  95. for ; it.HasElem(); it.Next() {
  96. elem := it.Elem()
  97. if elem != i {
  98. t.Errorf("iterator produce %v, want %v", elem, i)
  99. }
  100. i++
  101. }
  102. if i != end {
  103. t.Errorf("iterator produces up to %v, want %v", i, end)
  104. }
  105. }
  106. // testAssoc tests Assoc by replacing each element.
  107. func testAssoc(t *testing.T, v Vector, subst interface{}) {
  108. n := v.Len()
  109. for i := 0; i <= n; i++ {
  110. oldv := v
  111. v = v.Assoc(i, subst)
  112. if i < n {
  113. elem, _ := oldv.Index(i)
  114. if elem != i {
  115. t.Errorf("oldv.Index(%v) == %v, want %v", i, elem, i)
  116. }
  117. }
  118. elem, _ := v.Index(i)
  119. if elem != subst {
  120. t.Errorf("v.Index(%v) == %v, want %v", i, elem, subst)
  121. }
  122. }
  123. n++
  124. for _, i := range []int{-1, n + 1, n + 2, n * 2} {
  125. newv := v.Assoc(i, subst)
  126. if newv != nil {
  127. t.Errorf("v.Assoc(%d) = %v, want nil", i, newv)
  128. }
  129. }
  130. }
  131. // testPop tests Pop by removing each element.
  132. func testPop(t *testing.T, v Vector) {
  133. n := v.Len()
  134. for i := 0; i < n; i++ {
  135. oldv := v
  136. v = v.Pop()
  137. if count := oldv.Len(); count != n-i {
  138. t.Errorf("oldv.Count() == %v, want %v", count, n-i)
  139. }
  140. if count := v.Len(); count != n-i-1 {
  141. t.Errorf("oldv.Count() == %v, want %v", count, n-i-1)
  142. }
  143. }
  144. newv := v.Pop()
  145. if newv != nil {
  146. t.Errorf("v.Pop() = %v, want nil", newv)
  147. }
  148. }
  149. func TestSubVector(t *testing.T) {
  150. v := Empty
  151. for i := 0; i < 10; i++ {
  152. v = v.Cons(i)
  153. }
  154. sv := v.SubVector(0, 4)
  155. testIndex(t, sv, 0, 4)
  156. testAssoc(t, sv, "233")
  157. testIterator(t, sv.Iterator(), 0, 4)
  158. testPop(t, sv)
  159. sv = v.SubVector(1, 4)
  160. if !checkVector(sv, 1, 2, 3) {
  161. t.Errorf("v[0:4] is not expected")
  162. }
  163. if !checkVector(sv.Assoc(1, "233"), 1, "233", 3) {
  164. t.Errorf("v[0:4].Assoc is not expected")
  165. }
  166. if !checkVector(sv.Cons("233"), 1, 2, 3, "233") {
  167. t.Errorf("v[0:4].Cons is not expected")
  168. }
  169. if !checkVector(sv.Pop(), 1, 2) {
  170. t.Errorf("v[0:4].Pop is not expected")
  171. }
  172. if !checkVector(sv.SubVector(1, 2), 2) {
  173. t.Errorf("v[0:4][1:2] is not expected")
  174. }
  175. testIterator(t, sv.Iterator(), 1, 4)
  176. if !checkVector(v.SubVector(1, 1)) {
  177. t.Errorf("v[1:1] is not expected")
  178. }
  179. // Begin is allowed to be equal to n if end is also n
  180. if !checkVector(v.SubVector(10, 10)) {
  181. t.Errorf("v[10:10] is not expected")
  182. }
  183. bad := v.SubVector(-1, 0)
  184. if bad != nil {
  185. t.Errorf("v.SubVector(-1, 0) = %v, want nil", bad)
  186. }
  187. bad = v.SubVector(5, 100)
  188. if bad != nil {
  189. t.Errorf("v.SubVector(5, 100) = %v, want nil", bad)
  190. }
  191. bad = v.SubVector(-1, 100)
  192. if bad != nil {
  193. t.Errorf("v.SubVector(-1, 100) = %v, want nil", bad)
  194. }
  195. bad = v.SubVector(4, 2)
  196. if bad != nil {
  197. t.Errorf("v.SubVector(4, 2) = %v, want nil", bad)
  198. }
  199. }
  200. // Regression test for https://b.elv.sh/1287: crash when tree has a height >= 1
  201. // and start of subvector is in the tail.
  202. func TestSubVector_BeginFromTail(t *testing.T) {
  203. v := Empty
  204. for i := 0; i < 65; i++ {
  205. v = v.Cons(i)
  206. }
  207. sv := v.SubVector(64, 65)
  208. testIterator(t, sv.Iterator(), 64, 65)
  209. }
  210. func checkVector(v Vector, values ...interface{}) bool {
  211. if v.Len() != len(values) {
  212. return false
  213. }
  214. for i, a := range values {
  215. if x, _ := v.Index(i); x != a {
  216. return false
  217. }
  218. }
  219. return true
  220. }
  221. func TestVectorEqual(t *testing.T) {
  222. v1, v2 := Empty, Empty
  223. for i := 0; i < N3; i++ {
  224. elem := rand.Int63()
  225. v1 = v1.Cons(elem)
  226. v2 = v2.Cons(elem)
  227. if !eqVector(v1, v2) {
  228. t.Errorf("Not equal after Cons'ing %d elements", i+1)
  229. }
  230. }
  231. }
  232. func eqVector(v1, v2 Vector) bool {
  233. if v1.Len() != v2.Len() {
  234. return false
  235. }
  236. for i := 0; i < v1.Len(); i++ {
  237. a1, _ := v1.Index(i)
  238. a2, _ := v2.Index(i)
  239. if a1 != a2 {
  240. return false
  241. }
  242. }
  243. return true
  244. }
  245. var marshalJSONTests = []struct {
  246. in Vector
  247. wantOut string
  248. wantErr error
  249. }{
  250. {makeVector("1", 2, nil), `["1",2,null]`, nil},
  251. {makeVector("1", makeVector(2)), `["1",[2]]`, nil},
  252. {makeVector(0, 1, 2, 3, 4, 5).SubVector(1, 5), `[1,2,3,4]`, nil},
  253. {makeVector(0, func() {}), "", errors.New("element 1: json: unsupported type: func()")},
  254. }
  255. func TestMarshalJSON(t *testing.T) {
  256. for i, test := range marshalJSONTests {
  257. out, err := test.in.MarshalJSON()
  258. if string(out) != test.wantOut {
  259. t.Errorf("v%d.MarshalJSON -> out %q, want %q", i, out, test.wantOut)
  260. }
  261. if err == nil || test.wantErr == nil {
  262. if err != test.wantErr {
  263. t.Errorf("v%d.MarshalJSON -> err %v, want %v", i, err, test.wantErr)
  264. }
  265. } else {
  266. if err.Error() != test.wantErr.Error() {
  267. t.Errorf("v%d.MarshalJSON -> err %v, want %v", i, err, test.wantErr)
  268. }
  269. }
  270. }
  271. }
  272. func makeVector(elements ...interface{}) Vector {
  273. v := Empty
  274. for _, element := range elements {
  275. v = v.Cons(element)
  276. }
  277. return v
  278. }
  279. func BenchmarkConsNativeN1(b *testing.B) { benchmarkNativeAppend(b, N1) }
  280. func BenchmarkConsNativeN2(b *testing.B) { benchmarkNativeAppend(b, N2) }
  281. func BenchmarkConsNativeN3(b *testing.B) { benchmarkNativeAppend(b, N3) }
  282. func BenchmarkConsNativeN4(b *testing.B) { benchmarkNativeAppend(b, N4) }
  283. func benchmarkNativeAppend(b *testing.B, n int) {
  284. for r := 0; r < b.N; r++ {
  285. var s []interface{}
  286. for i := 0; i < n; i++ {
  287. s = append(s, i)
  288. }
  289. }
  290. }
  291. func BenchmarkConsPersistentN1(b *testing.B) { benchmarkCons(b, N1) }
  292. func BenchmarkConsPersistentN2(b *testing.B) { benchmarkCons(b, N2) }
  293. func BenchmarkConsPersistentN3(b *testing.B) { benchmarkCons(b, N3) }
  294. func BenchmarkConsPersistentN4(b *testing.B) { benchmarkCons(b, N4) }
  295. func benchmarkCons(b *testing.B, n int) {
  296. for r := 0; r < b.N; r++ {
  297. v := Empty
  298. for i := 0; i < n; i++ {
  299. v = v.Cons(i)
  300. }
  301. }
  302. }
  303. var (
  304. sliceN4 = make([]interface{}, N4)
  305. vectorN4 = Empty
  306. )
  307. func init() {
  308. for i := 0; i < N4; i++ {
  309. vectorN4 = vectorN4.Cons(i)
  310. }
  311. }
  312. var x interface{}
  313. func BenchmarkIndexSeqNativeN4(b *testing.B) { benchmarkIndexSeqNative(b, N4) }
  314. func benchmarkIndexSeqNative(b *testing.B, n int) {
  315. for r := 0; r < b.N; r++ {
  316. for i := 0; i < n; i++ {
  317. x = sliceN4[i]
  318. }
  319. }
  320. }
  321. func BenchmarkIndexSeqPersistentN4(b *testing.B) { benchmarkIndexSeqPersistent(b, N4) }
  322. func benchmarkIndexSeqPersistent(b *testing.B, n int) {
  323. for r := 0; r < b.N; r++ {
  324. for i := 0; i < n; i++ {
  325. x, _ = vectorN4.Index(i)
  326. }
  327. }
  328. }
  329. var randIndicies []int
  330. func init() {
  331. randIndicies = make([]int, N4)
  332. for i := 0; i < N4; i++ {
  333. randIndicies[i] = rand.Intn(N4)
  334. }
  335. }
  336. func BenchmarkIndexRandNative(b *testing.B) {
  337. for r := 0; r < b.N; r++ {
  338. for _, i := range randIndicies {
  339. x = sliceN4[i]
  340. }
  341. }
  342. }
  343. func BenchmarkIndexRandPersistent(b *testing.B) {
  344. for r := 0; r < b.N; r++ {
  345. for _, i := range randIndicies {
  346. x, _ = vectorN4.Index(i)
  347. }
  348. }
  349. }
  350. func nativeEqual(s1, s2 []int) bool {
  351. if len(s1) != len(s2) {
  352. return false
  353. }
  354. for i, v1 := range s1 {
  355. if v1 != s2[i] {
  356. return false
  357. }
  358. }
  359. return true
  360. }
  361. func BenchmarkEqualNative(b *testing.B) {
  362. b.StopTimer()
  363. var s1, s2 []int
  364. for i := 0; i < N4; i++ {
  365. s1 = append(s1, i)
  366. s2 = append(s2, i)
  367. }
  368. b.StartTimer()
  369. for r := 0; r < b.N; r++ {
  370. eq := nativeEqual(s1, s2)
  371. if !eq {
  372. panic("not equal")
  373. }
  374. }
  375. }
  376. func BenchmarkEqualPersistent(b *testing.B) {
  377. b.StopTimer()
  378. v1, v2 := Empty, Empty
  379. for i := 0; i < N4; i++ {
  380. v1 = v1.Cons(i)
  381. v2 = v2.Cons(i)
  382. }
  383. b.StartTimer()
  384. for r := 0; r < b.N; r++ {
  385. eq := eqVector(v1, v2)
  386. if !eq {
  387. panic("not equal")
  388. }
  389. }
  390. }