Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

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