Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: pkg/analysis_server/test/index/btree_test.dart

Issue 314413004: A simple B+Tree implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Better redistribution, random stress test, renames. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library test.index.btree;
6
7 import 'dart:math';
8
9 import 'package:analysis_server/src/index/btree.dart';
10 import 'package:unittest/unittest.dart';
11
12 import '../reflective_tests.dart';
13
14
15 main() {
16 groupSep = ' | ';
17 group('BTree', () {
18 runReflectiveTests(BTreeTest);
19 });
20 }
21
22
23 void _assertDebugString(BTree tree, String expected) {
24 String dump = _getDebugString(tree);
25 // print(dump);
Brian Wilkerson 2014/06/07 16:34:02 Remove?
scheglov 2014/06/07 21:26:23 Done.
26 expect(dump, expected);
27 }
28
29
30 String _getDebugString(BTree tree) {
31 StringBuffer buffer = new StringBuffer();
32 (tree as dynamic).debugPrint(buffer);
33 return buffer.toString();
34 }
35
36
37 int _intComparator(int a, int b) => a - b;
38
39
40 @ReflectiveTestCase()
41 class BTreeTest {
42 BTree<int, String> tree = new BTree<int, String>(4, 4, _intComparator);
43
44 test_NoSuchMethodError() {
45 expect(() {
46 (tree as dynamic).thereIsNoSuchMethod();
47 }, throwsA(new isInstanceOf<NoSuchMethodError>()));
48 }
49
50 void test_find() {
51 _insertValues(12);
52 expect(tree.find(-1), isNull);
53 expect(tree.find(1000), isNull);
54 for (int key = 0; key < 12; key++) {
55 expect(tree.find(key), 'V$key');
56 }
57 }
58
59 void test_insert_01() {
60 _insert(0, 'A');
61 _assertDebugString(tree, 'LNode {0: A}\n');
62 }
63
64 void test_insert_02() {
65 _insert(1, 'B');
66 _insert(0, 'A');
67 _assertDebugString(tree, 'LNode {0: A, 1: B}\n');
68 }
69
70 void test_insert_03() {
71 _insert(2, 'C');
72 _insert(0, 'A');
73 _insert(1, 'B');
74 _assertDebugString(tree, 'LNode {0: A, 1: B, 2: C}\n');
75 }
76
77 void test_insert_05() {
78 _insertValues(5);
79 _assertDebugString(tree, '''
80 INode {
81 LNode {0: V0, 1: V1}
82 2
83 LNode {2: V2, 3: V3, 4: V4}
84 }
85 ''');
86 }
87
88 void test_insert_09() {
89 _insertValues(9);
90 _assertDebugString(tree, '''
91 INode {
92 LNode {0: V0, 1: V1}
93 2
94 LNode {2: V2, 3: V3}
95 4
96 LNode {4: V4, 5: V5}
97 6
98 LNode {6: V6, 7: V7, 8: V8}
99 }
100 ''');
101 }
102
103 void test_insert_innerSplitLeft() {
104 // Prepare a tree with '0' key missing.
105 for (int i = 1; i < 12; i++) {
106 _insert(i, "V$i");
107 }
108 _assertDebugString(tree, '''
109 INode {
110 LNode {1: V1, 2: V2}
111 3
112 LNode {3: V3, 4: V4}
113 5
114 LNode {5: V5, 6: V6}
115 7
116 LNode {7: V7, 8: V8}
117 9
118 LNode {9: V9, 10: V10, 11: V11}
119 }
120 ''');
121 // Split and insert into the 'left' child.
122 _insert(0, 'V0');
123 _assertDebugString(tree, '''
124 INode {
125 INode {
126 LNode {0: V0, 1: V1, 2: V2}
127 3
128 LNode {3: V3, 4: V4}
129 5
130 LNode {5: V5, 6: V6}
131 }
132 7
133 INode {
134 LNode {7: V7, 8: V8}
135 9
136 LNode {9: V9, 10: V10, 11: V11}
137 }
138 }
139 ''');
140 }
141
142 void test_insert_innerSplitRight() {
143 _insertValues(12);
144 _assertDebugString(tree, '''
145 INode {
146 INode {
147 LNode {0: V0, 1: V1}
148 2
149 LNode {2: V2, 3: V3}
150 4
151 LNode {4: V4, 5: V5}
152 }
153 6
154 INode {
155 LNode {6: V6, 7: V7}
156 8
157 LNode {8: V8, 9: V9, 10: V10, 11: V11}
158 }
159 }
160 ''');
161 }
162
163 void test_insert_replace() {
164 _insert(0, 'A');
165 _insert(1, 'B');
166 _insert(2, 'C');
167 _assertDebugString(tree, 'LNode {0: A, 1: B, 2: C}\n');
168 _insert(2, 'C2');
169 _insert(1, 'B2');
170 _insert(0, 'A2');
171 _assertDebugString(tree, 'LNode {0: A2, 1: B2, 2: C2}\n');
172 }
173
174 void test_remove_inner_borrowLeft() {
175 tree = new BTree<int, String>(10, 4, _intComparator);
176 for (int i = 100; i < 125; i++) {
177 _insert(i, 'V$i');
178 }
179 for (int i = 0; i < 10; i++) {
180 _insert(i, 'V$i');
181 }
182 _assertDebugString(tree, '''
183 INode {
184 INode {
185 LNode {0: V0, 1: V1}
186 2
187 LNode {2: V2, 3: V3}
188 4
189 LNode {4: V4, 5: V5}
190 6
191 LNode {6: V6, 7: V7}
192 8
193 LNode {8: V8, 9: V9, 100: V100, 101: V101}
194 102
195 LNode {102: V102, 103: V103}
196 104
197 LNode {104: V104, 105: V105}
198 106
199 LNode {106: V106, 107: V107}
200 108
201 LNode {108: V108, 109: V109}
202 110
203 LNode {110: V110, 111: V111}
204 }
205 112
206 INode {
207 LNode {112: V112, 113: V113}
208 114
209 LNode {114: V114, 115: V115}
210 116
211 LNode {116: V116, 117: V117}
212 118
213 LNode {118: V118, 119: V119}
214 120
215 LNode {120: V120, 121: V121}
216 122
217 LNode {122: V122, 123: V123, 124: V124}
218 }
219 }
220 ''');
221 expect(tree.remove(112), 'V112');
222 _assertDebugString(tree, '''
223 INode {
224 INode {
225 LNode {0: V0, 1: V1}
226 2
227 LNode {2: V2, 3: V3}
228 4
229 LNode {4: V4, 5: V5}
230 6
231 LNode {6: V6, 7: V7}
232 8
233 LNode {8: V8, 9: V9, 100: V100, 101: V101}
234 102
235 LNode {102: V102, 103: V103}
236 104
237 LNode {104: V104, 105: V105}
238 }
239 106
240 INode {
241 LNode {106: V106, 107: V107}
242 108
243 LNode {108: V108, 109: V109}
244 110
245 LNode {110: V110, 111: V111}
246 112
247 LNode {113: V113, 114: V114, 115: V115}
248 116
249 LNode {116: V116, 117: V117}
250 118
251 LNode {118: V118, 119: V119}
252 120
253 LNode {120: V120, 121: V121}
254 122
255 LNode {122: V122, 123: V123, 124: V124}
256 }
257 }
258 ''');
259 }
260
261 void test_remove_inner_borrowRight() {
262 tree = new BTree<int, String>(10, 4, _intComparator);
263 for (int i = 100; i < 135; i++) {
264 _insert(i, 'V$i');
265 }
266 _assertDebugString(tree, '''
267 INode {
268 INode {
269 LNode {100: V100, 101: V101}
270 102
271 LNode {102: V102, 103: V103}
272 104
273 LNode {104: V104, 105: V105}
274 106
275 LNode {106: V106, 107: V107}
276 108
277 LNode {108: V108, 109: V109}
278 110
279 LNode {110: V110, 111: V111}
280 }
281 112
282 INode {
283 LNode {112: V112, 113: V113}
284 114
285 LNode {114: V114, 115: V115}
286 116
287 LNode {116: V116, 117: V117}
288 118
289 LNode {118: V118, 119: V119}
290 120
291 LNode {120: V120, 121: V121}
292 122
293 LNode {122: V122, 123: V123}
294 124
295 LNode {124: V124, 125: V125}
296 126
297 LNode {126: V126, 127: V127}
298 128
299 LNode {128: V128, 129: V129}
300 130
301 LNode {130: V130, 131: V131}
302 132
303 LNode {132: V132, 133: V133, 134: V134}
304 }
305 }
306 ''');
307 expect(tree.remove(100), 'V100');
308 _assertDebugString(tree, '''
309 INode {
310 INode {
311 LNode {101: V101, 102: V102, 103: V103}
312 104
313 LNode {104: V104, 105: V105}
314 106
315 LNode {106: V106, 107: V107}
316 108
317 LNode {108: V108, 109: V109}
318 110
319 LNode {110: V110, 111: V111}
320 112
321 LNode {112: V112, 113: V113}
322 114
323 LNode {114: V114, 115: V115}
324 116
325 LNode {116: V116, 117: V117}
326 }
327 118
328 INode {
329 LNode {118: V118, 119: V119}
330 120
331 LNode {120: V120, 121: V121}
332 122
333 LNode {122: V122, 123: V123}
334 124
335 LNode {124: V124, 125: V125}
336 126
337 LNode {126: V126, 127: V127}
338 128
339 LNode {128: V128, 129: V129}
340 130
341 LNode {130: V130, 131: V131}
342 132
343 LNode {132: V132, 133: V133, 134: V134}
344 }
345 }
346 ''');
347 }
348
349 void test_remove_inner_mergeLeft() {
350 _insertValues(15);
351 _assertDebugString(tree, '''
352 INode {
353 INode {
354 LNode {0: V0, 1: V1}
355 2
356 LNode {2: V2, 3: V3}
357 4
358 LNode {4: V4, 5: V5}
359 }
360 6
361 INode {
362 LNode {6: V6, 7: V7}
363 8
364 LNode {8: V8, 9: V9}
365 10
366 LNode {10: V10, 11: V11}
367 12
368 LNode {12: V12, 13: V13, 14: V14}
369 }
370 }
371 ''');
372 expect(tree.remove(12), 'V12');
373 expect(tree.remove(13), 'V13');
374 expect(tree.remove(14), 'V14');
375 _assertDebugString(tree, '''
376 INode {
377 INode {
378 LNode {0: V0, 1: V1}
379 2
380 LNode {2: V2, 3: V3}
381 4
382 LNode {4: V4, 5: V5}
383 }
384 6
385 INode {
386 LNode {6: V6, 7: V7}
387 8
388 LNode {8: V8, 9: V9}
389 10
390 LNode {10: V10, 11: V11}
391 }
392 }
393 ''');
394 expect(tree.remove(8), 'V8');
395 _assertDebugString(tree, '''
396 INode {
397 LNode {0: V0, 1: V1}
398 2
399 LNode {2: V2, 3: V3}
400 4
401 LNode {4: V4, 5: V5}
402 6
403 LNode {6: V6, 7: V7, 9: V9}
404 10
405 LNode {10: V10, 11: V11}
406 }
407 ''');
408 }
409
410 void test_remove_inner_mergeRight() {
411 _insertValues(12);
412 _assertDebugString(tree, '''
413 INode {
414 INode {
415 LNode {0: V0, 1: V1}
416 2
417 LNode {2: V2, 3: V3}
418 4
419 LNode {4: V4, 5: V5}
420 }
421 6
422 INode {
423 LNode {6: V6, 7: V7}
424 8
425 LNode {8: V8, 9: V9, 10: V10, 11: V11}
426 }
427 }
428 ''');
429 expect(tree.remove(0), 'V0');
430 _assertDebugString(tree, '''
431 INode {
432 LNode {1: V1, 2: V2, 3: V3}
433 4
434 LNode {4: V4, 5: V5}
435 6
436 LNode {6: V6, 7: V7}
437 8
438 LNode {8: V8, 9: V9, 10: V10, 11: V11}
439 }
440 ''');
441 }
442
443 void test_remove_inner_notFound() {
444 _insertValues(20);
445 expect(tree.remove(100), isNull);
446 }
447
448 void test_remove_leafRoot_becomesEmpty() {
449 _insertValues(1);
450 _assertDebugString(tree, 'LNode {0: V0}\n');
451 expect(tree.remove(0), 'V0');
452 _assertDebugString(tree, 'LNode {}\n');
453 }
454
455 void test_remove_leafRoot_first() {
456 _insertValues(3);
457 _assertDebugString(tree, 'LNode {0: V0, 1: V1, 2: V2}\n');
458 expect(tree.remove(0), 'V0');
459 _assertDebugString(tree, 'LNode {1: V1, 2: V2}\n');
460 }
461
462 void test_remove_leafRoot_last() {
463 _insertValues(3);
464 _assertDebugString(tree, 'LNode {0: V0, 1: V1, 2: V2}\n');
465 expect(tree.remove(2), 'V2');
466 _assertDebugString(tree, 'LNode {0: V0, 1: V1}\n');
467 }
468
469 void test_remove_leafRoot_middle() {
470 _insertValues(3);
471 _assertDebugString(tree, 'LNode {0: V0, 1: V1, 2: V2}\n');
472 expect(tree.remove(1), 'V1');
473 _assertDebugString(tree, 'LNode {0: V0, 2: V2}\n');
474 }
475
476 void test_remove_leafRoot_notFound() {
477 _insertValues(1);
478 _assertDebugString(tree, 'LNode {0: V0}\n');
479 expect(tree.remove(10), null);
480 _assertDebugString(tree, 'LNode {0: V0}\n');
481 }
482
483 void test_remove_leaf_borrowLeft() {
484 tree = new BTree<int, String>(10, 10, _intComparator);
485 for (int i = 20; i < 40; i++) {
486 _insert(i, 'V$i');
487 }
488 for (int i = 0; i < 5; i++) {
489 _insert(i, 'V$i');
490 }
491 _assertDebugString(tree, '''
492 INode {
493 LNode {0: V0, 1: V1, 2: V2, 3: V3, 4: V4, 20: V20, 21: V21, 22: V22, 23: V23 , 24: V24}
494 25
495 LNode {25: V25, 26: V26, 27: V27, 28: V28, 29: V29}
496 30
497 LNode {30: V30, 31: V31, 32: V32, 33: V33, 34: V34, 35: V35, 36: V36, 37: V3 7, 38: V38, 39: V39}
498 }
499 ''');
500 expect(tree.remove(25), 'V25');
501 _assertDebugString(tree, '''
502 INode {
503 LNode {0: V0, 1: V1, 2: V2, 3: V3, 4: V4, 20: V20, 21: V21}
504 22
505 LNode {22: V22, 23: V23, 24: V24, 26: V26, 27: V27, 28: V28, 29: V29}
506 30
507 LNode {30: V30, 31: V31, 32: V32, 33: V33, 34: V34, 35: V35, 36: V36, 37: V3 7, 38: V38, 39: V39}
508 }
509 ''');
510 }
511
512 void test_remove_leaf_borrowRight() {
513 tree = new BTree<int, String>(10, 10, _intComparator);
514 _insertValues(15);
515 _assertDebugString(tree, '''
516 INode {
517 LNode {0: V0, 1: V1, 2: V2, 3: V3, 4: V4}
518 5
519 LNode {5: V5, 6: V6, 7: V7, 8: V8, 9: V9, 10: V10, 11: V11, 12: V12, 13: V13 , 14: V14}
520 }
521 ''');
522 expect(tree.remove(0), 'V0');
523 _assertDebugString(tree, '''
524 INode {
525 LNode {1: V1, 2: V2, 3: V3, 4: V4, 5: V5, 6: V6, 7: V7}
526 8
527 LNode {8: V8, 9: V9, 10: V10, 11: V11, 12: V12, 13: V13, 14: V14}
528 }
529 ''');
530 }
531
532 void test_remove_leaf_mergeLeft() {
533 _insertValues(9);
534 _assertDebugString(tree, '''
535 INode {
536 LNode {0: V0, 1: V1}
537 2
538 LNode {2: V2, 3: V3}
539 4
540 LNode {4: V4, 5: V5}
541 6
542 LNode {6: V6, 7: V7, 8: V8}
543 }
544 ''');
545 expect(tree.remove(2), 'V2');
546 _assertDebugString(tree, '''
547 INode {
548 LNode {0: V0, 1: V1, 3: V3}
549 4
550 LNode {4: V4, 5: V5}
551 6
552 LNode {6: V6, 7: V7, 8: V8}
553 }
554 ''');
555 }
556
557 void test_remove_leaf_mergeRight() {
558 _insertValues(9);
559 _assertDebugString(tree, '''
560 INode {
561 LNode {0: V0, 1: V1}
562 2
563 LNode {2: V2, 3: V3}
564 4
565 LNode {4: V4, 5: V5}
566 6
567 LNode {6: V6, 7: V7, 8: V8}
568 }
569 ''');
570 expect(tree.remove(1), 'V1');
571 _assertDebugString(tree, '''
572 INode {
573 LNode {0: V0, 2: V2, 3: V3}
574 4
575 LNode {4: V4, 5: V5}
576 6
577 LNode {6: V6, 7: V7, 8: V8}
578 }
579 ''');
580 }
581
582 void test_remove_leaf_noReorder() {
583 _insertValues(5);
584 _assertDebugString(tree, '''
585 INode {
586 LNode {0: V0, 1: V1}
587 2
588 LNode {2: V2, 3: V3, 4: V4}
589 }
590 ''');
591 expect(tree.remove(3), 'V3');
592 _assertDebugString(tree, '''
593 INode {
594 LNode {0: V0, 1: V1}
595 2
596 LNode {2: V2, 4: V4}
597 }
598 ''');
599 }
600
601 void test_stress_evenOdd() {
602 int count = 1000;
603 // insert odd, forward
604 for (int i = 1; i < count; i += 2) {
605 _insert(i, 'V$i');
606 }
607 // insert even, backward
608 for (int i = count - 2; i >= 0; i -= 2) {
609 _insert(i, 'V$i');
610 }
611 // find every
612 for (int i = 0; i < count; i++) {
613 expect(tree.find(i), 'V$i');
614 }
615 // remove odd, backward
616 for (int i = count - 1; i >= 1; i -= 2) {
617 expect(tree.remove(i), 'V$i');
618 }
619 for (int i = 0; i < count; i++) {
620 if (i.isEven) {
621 expect(tree.find(i), 'V$i');
622 } else {
623 expect(tree.find(i), isNull);
624 }
625 }
626 // remove even, forward
627 for (int i = 0; i < count; i += 2) {
628 tree.remove(i);
629 }
630 for (int i = 0; i < count; i++) {
631 expect(tree.find(i), isNull);
632 }
633 }
634
635 void test_stress_random() {
636 tree = new BTree<int, String>(10, 10, _intComparator);
637 int maxKey = 1000000;
638 int tryCount = 1000;
639 Set<int> keys = new Set<int>();
640 {
641 Random random = new Random();
642 for (int i = 0; i < tryCount; i++) {
643 int key = random.nextInt(maxKey);
644 keys.add(key);
645 _insert(key, 'V$key');
646 }
647 }
648 // find every
649 for (int key in keys) {
650 expect(tree.find(key), 'V$key');
651 }
652 // remove random keys
653 {
654 Random random = new Random();
655 for (int key in new Set<int>.from(keys)) {
656 if (random.nextBool()) {
657 keys.remove(key);
658 expect(tree.remove(key), 'V$key');
659 }
660 }
661 }
662 // find every remaining key
663 for (int key in keys) {
664 expect(tree.find(key), 'V$key');
665 }
666 }
667
668 void _insert(int key, String value) {
669 tree.insert(key, value);
670 }
671
672 void _insertValues(int count) {
673 for (int i = 0; i < count; i++) {
674 _insert(i, 'V$i');
675 // print('----------------------');
676 // print(_getDump(tree));
677 }
678 }
679 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698