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.
 
 
 

423 lines
9.4 KiB

  1. // Copyright 2014 Google LLC
  2. // Modified 2018 by Jonathan Amsterdam (jbamsterdam@gmail.com)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. package btree
  16. import (
  17. "flag"
  18. "fmt"
  19. "math/rand"
  20. "os"
  21. "sort"
  22. "sync"
  23. "testing"
  24. "time"
  25. "github.com/google/go-cmp/cmp"
  26. )
  27. func init() {
  28. seed := time.Now().Unix()
  29. fmt.Println(seed)
  30. rand.Seed(seed)
  31. }
  32. type itemWithIndex struct {
  33. Key Key
  34. Value Value
  35. Index int
  36. }
  37. // perm returns a random permutation of n Int items in the range [0, n).
  38. func perm(n int) []itemWithIndex {
  39. var out []itemWithIndex
  40. for _, v := range rand.Perm(n) {
  41. out = append(out, itemWithIndex{v, v, v})
  42. }
  43. return out
  44. }
  45. // rang returns an ordered list of Int items in the range [0, n).
  46. func rang(n int) []itemWithIndex {
  47. var out []itemWithIndex
  48. for i := 0; i < n; i++ {
  49. out = append(out, itemWithIndex{i, i, i})
  50. }
  51. return out
  52. }
  53. // all extracts all items from an iterator.
  54. func all(it *Iterator) []itemWithIndex {
  55. var out []itemWithIndex
  56. for it.Next() {
  57. out = append(out, itemWithIndex{it.Key, it.Value, it.Index})
  58. }
  59. return out
  60. }
  61. // rangerev returns a reversed ordered list of Int items in the range [0, n).
  62. func rangrev(n int) []itemWithIndex {
  63. var out []itemWithIndex
  64. for i := n - 1; i >= 0; i-- {
  65. out = append(out, itemWithIndex{i, i, i})
  66. }
  67. return out
  68. }
  69. func reverse(s []itemWithIndex) {
  70. for i := 0; i < len(s)/2; i++ {
  71. s[i], s[len(s)-i-1] = s[len(s)-i-1], s[i]
  72. }
  73. }
  74. var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
  75. func TestBTree(t *testing.T) {
  76. tr := New(*btreeDegree, less)
  77. const treeSize = 10000
  78. for i := 0; i < 10; i++ {
  79. if min, _ := tr.Min(); min != nil {
  80. t.Fatalf("empty min, got %+v", min)
  81. }
  82. if max, _ := tr.Max(); max != nil {
  83. t.Fatalf("empty max, got %+v", max)
  84. }
  85. for _, m := range perm(treeSize) {
  86. if _, ok := tr.Set(m.Key, m.Value); ok {
  87. t.Fatal("set found item", m)
  88. }
  89. }
  90. for _, m := range perm(treeSize) {
  91. _, ok, idx := tr.SetWithIndex(m.Key, m.Value)
  92. if !ok {
  93. t.Fatal("set didn't find item", m)
  94. }
  95. if idx != m.Index {
  96. t.Fatalf("got index %d, want %d", idx, m.Index)
  97. }
  98. }
  99. mink, minv := tr.Min()
  100. if want := 0; mink != want || minv != want {
  101. t.Fatalf("min: want %+v, got %+v, %+v", want, mink, minv)
  102. }
  103. maxk, maxv := tr.Max()
  104. if want := treeSize - 1; maxk != want || maxv != want {
  105. t.Fatalf("max: want %+v, got %+v, %+v", want, maxk, maxv)
  106. }
  107. got := all(tr.BeforeIndex(0))
  108. want := rang(treeSize)
  109. if !cmp.Equal(got, want) {
  110. t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
  111. }
  112. for _, m := range perm(treeSize) {
  113. if _, removed := tr.Delete(m.Key); !removed {
  114. t.Fatalf("didn't find %v", m)
  115. }
  116. }
  117. if got = all(tr.BeforeIndex(0)); len(got) > 0 {
  118. t.Fatalf("some left!: %v", got)
  119. }
  120. }
  121. }
  122. func TestAt(t *testing.T) {
  123. tr := New(*btreeDegree, less)
  124. for _, m := range perm(100) {
  125. tr.Set(m.Key, m.Value)
  126. }
  127. for i := 0; i < tr.Len(); i++ {
  128. gotk, gotv := tr.At(i)
  129. if want := i; gotk != want || gotv != want {
  130. t.Fatalf("At(%d) = (%v, %v), want (%v, %v)", i, gotk, gotv, want, want)
  131. }
  132. }
  133. }
  134. func TestGetWithIndex(t *testing.T) {
  135. tr := New(*btreeDegree, less)
  136. for _, m := range perm(100) {
  137. tr.Set(m.Key, m.Value)
  138. }
  139. for i := 0; i < tr.Len(); i++ {
  140. gotv, goti := tr.GetWithIndex(i)
  141. wantv, wanti := i, i
  142. if gotv != wantv || goti != wanti {
  143. t.Errorf("GetWithIndex(%d) = (%v, %v), want (%v, %v)",
  144. i, gotv, goti, wantv, wanti)
  145. }
  146. }
  147. _, got := tr.GetWithIndex(100)
  148. if want := -1; got != want {
  149. t.Errorf("got %d, want %d", got, want)
  150. }
  151. }
  152. func TestSetWithIndex(t *testing.T) {
  153. tr := New(4, less) // use a small degree to cover more cases
  154. var contents []int
  155. for _, m := range perm(100) {
  156. _, _, idx := tr.SetWithIndex(m.Key, m.Value)
  157. contents = append(contents, m.Index)
  158. sort.Ints(contents)
  159. want := -1
  160. for i, c := range contents {
  161. if c == m.Index {
  162. want = i
  163. break
  164. }
  165. }
  166. if idx != want {
  167. t.Fatalf("got %d, want %d", idx, want)
  168. }
  169. }
  170. }
  171. func TestDeleteMin(t *testing.T) {
  172. tr := New(3, less)
  173. for _, m := range perm(100) {
  174. tr.Set(m.Key, m.Value)
  175. }
  176. var got []itemWithIndex
  177. for i := 0; tr.Len() > 0; i++ {
  178. k, v := tr.DeleteMin()
  179. got = append(got, itemWithIndex{k, v, i})
  180. }
  181. if want := rang(100); !cmp.Equal(got, want) {
  182. t.Fatalf("got: %v\nwant: %v", got, want)
  183. }
  184. }
  185. func TestDeleteMax(t *testing.T) {
  186. tr := New(3, less)
  187. for _, m := range perm(100) {
  188. tr.Set(m.Key, m.Value)
  189. }
  190. var got []itemWithIndex
  191. for tr.Len() > 0 {
  192. k, v := tr.DeleteMax()
  193. got = append(got, itemWithIndex{k, v, tr.Len()})
  194. }
  195. reverse(got)
  196. if want := rang(100); !cmp.Equal(got, want) {
  197. t.Fatalf("got: %v\nwant: %v", got, want)
  198. }
  199. }
  200. func TestIterator(t *testing.T) {
  201. const size = 10
  202. tr := New(2, less)
  203. // Empty tree.
  204. for i, it := range []*Iterator{
  205. tr.BeforeIndex(0),
  206. tr.Before(3),
  207. tr.After(3),
  208. } {
  209. if got, want := it.Next(), false; got != want {
  210. t.Errorf("empty, #%d: got %t, want %t", i, got, want)
  211. }
  212. }
  213. // Root with zero children.
  214. tr.Set(1, nil)
  215. tr.Delete(1)
  216. if !(tr.root != nil && len(tr.root.children) == 0 && len(tr.root.items) == 0) {
  217. t.Fatal("wrong shape tree")
  218. }
  219. for i, it := range []*Iterator{
  220. tr.BeforeIndex(0),
  221. tr.Before(3),
  222. tr.After(3),
  223. } {
  224. if got, want := it.Next(), false; got != want {
  225. t.Errorf("zero root, #%d: got %t, want %t", i, got, want)
  226. }
  227. }
  228. // Tree with size elements.
  229. p := perm(size)
  230. for _, v := range p {
  231. tr.Set(v.Key, v.Value)
  232. }
  233. it := tr.BeforeIndex(0)
  234. got := all(it)
  235. want := rang(size)
  236. if !cmp.Equal(got, want) {
  237. t.Fatalf("got %+v\nwant %+v\n", got, want)
  238. }
  239. for i, w := range want {
  240. it := tr.Before(w.Key)
  241. got = all(it)
  242. wn := want[w.Key.(int):]
  243. if !cmp.Equal(got, wn) {
  244. t.Fatalf("got %+v\nwant %+v\n", got, wn)
  245. }
  246. it = tr.BeforeIndex(i)
  247. got = all(it)
  248. if !cmp.Equal(got, wn) {
  249. t.Fatalf("got %+v\nwant %+v\n", got, wn)
  250. }
  251. it = tr.After(w.Key)
  252. got = all(it)
  253. wn = append([]itemWithIndex(nil), want[:w.Key.(int)+1]...)
  254. reverse(wn)
  255. if !cmp.Equal(got, wn) {
  256. t.Fatalf("got %+v\nwant %+v\n", got, wn)
  257. }
  258. it = tr.AfterIndex(i)
  259. got = all(it)
  260. if !cmp.Equal(got, wn) {
  261. t.Fatalf("got %+v\nwant %+v\n", got, wn)
  262. }
  263. }
  264. // Non-existent keys.
  265. tr = New(2, less)
  266. for _, v := range p {
  267. tr.Set(v.Key.(int)*2, v.Value)
  268. }
  269. // tr has only even keys: 0, 2, 4, ... Iterate from odd keys.
  270. for i := -1; i <= size+1; i += 2 {
  271. it := tr.Before(i)
  272. got := all(it)
  273. var want []itemWithIndex
  274. for j := (i + 1) / 2; j < size; j++ {
  275. want = append(want, itemWithIndex{j * 2, j, j})
  276. }
  277. if !cmp.Equal(got, want) {
  278. tr.print(os.Stdout)
  279. t.Fatalf("%d: got %+v\nwant %+v\n", i, got, want)
  280. }
  281. it = tr.After(i)
  282. got = all(it)
  283. want = nil
  284. for j := (i - 1) / 2; j >= 0; j-- {
  285. want = append(want, itemWithIndex{j * 2, j, j})
  286. }
  287. if !cmp.Equal(got, want) {
  288. t.Fatalf("%d: got %+v\nwant %+v\n", i, got, want)
  289. }
  290. }
  291. }
  292. func TestMixed(t *testing.T) {
  293. // Test random, mixed insertions and deletions.
  294. const maxSize = 1000
  295. tr := New(3, less)
  296. has := map[int]bool{}
  297. for i := 0; i < 10000; i++ {
  298. r := rand.Intn(maxSize)
  299. if r >= tr.Len() {
  300. old, ok := tr.Set(r, r)
  301. if has[r] != ok {
  302. t.Fatalf("%d: has=%t, ok=%t", r, has[r], ok)
  303. }
  304. if ok && old.(int) != r {
  305. t.Fatalf("%d: bad old", r)
  306. }
  307. has[r] = true
  308. if got, want := tr.Get(r), r; got != want {
  309. t.Fatalf("Get(%d) = %d, want %d", r, got, want)
  310. }
  311. } else {
  312. // Expoit random map iteration order.
  313. var d int
  314. for d = range has {
  315. break
  316. }
  317. old, removed := tr.Delete(d)
  318. if !removed {
  319. t.Fatalf("%d not found", d)
  320. }
  321. if old.(int) != d {
  322. t.Fatalf("%d: bad old", d)
  323. }
  324. delete(has, d)
  325. }
  326. }
  327. }
  328. const cloneTestSize = 10000
  329. func cloneTest(t *testing.T, b *BTree, start int, p []itemWithIndex, wg *sync.WaitGroup, treec chan<- *BTree) {
  330. treec <- b
  331. for i := start; i < cloneTestSize; i++ {
  332. b.Set(p[i].Key, p[i].Value)
  333. if i%(cloneTestSize/5) == 0 {
  334. wg.Add(1)
  335. go cloneTest(t, b.Clone(), i+1, p, wg, treec)
  336. }
  337. }
  338. wg.Done()
  339. }
  340. func TestCloneConcurrentOperations(t *testing.T) {
  341. b := New(*btreeDegree, less)
  342. treec := make(chan *BTree)
  343. p := perm(cloneTestSize)
  344. var wg sync.WaitGroup
  345. wg.Add(1)
  346. go cloneTest(t, b, 0, p, &wg, treec)
  347. var trees []*BTree
  348. donec := make(chan struct{})
  349. go func() {
  350. for t := range treec {
  351. trees = append(trees, t)
  352. }
  353. close(donec)
  354. }()
  355. wg.Wait()
  356. close(treec)
  357. <-donec
  358. want := rang(cloneTestSize)
  359. for i, tree := range trees {
  360. if !cmp.Equal(want, all(tree.BeforeIndex(0))) {
  361. t.Errorf("tree %v mismatch", i)
  362. }
  363. }
  364. toRemove := rang(cloneTestSize)[cloneTestSize/2:]
  365. for i := 0; i < len(trees)/2; i++ {
  366. tree := trees[i]
  367. wg.Add(1)
  368. go func() {
  369. for _, m := range toRemove {
  370. tree.Delete(m.Key)
  371. }
  372. wg.Done()
  373. }()
  374. }
  375. wg.Wait()
  376. for i, tree := range trees {
  377. var wantpart []itemWithIndex
  378. if i < len(trees)/2 {
  379. wantpart = want[:cloneTestSize/2]
  380. } else {
  381. wantpart = want
  382. }
  383. if got := all(tree.BeforeIndex(0)); !cmp.Equal(wantpart, got) {
  384. t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got))
  385. }
  386. }
  387. }
  388. func less(a, b interface{}) bool { return a.(int) < b.(int) }