| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2013 Google Inc. All Rights Reserved. | 
|  | 2 // | 
|  | 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 // you may not use this file except in compliance with the License. | 
|  | 5 // You may obtain a copy of the License at | 
|  | 6 // | 
|  | 7 //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 // | 
|  | 9 // Unless required by applicable law or agreed to in writing, software | 
|  | 10 // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 // See the License for the specific language governing permissions and | 
|  | 13 // limitations under the License. | 
|  | 14 | 
|  | 15 library quiver.collection.treeset_test; | 
|  | 16 | 
|  | 17 import 'package:quiver/collection.dart'; | 
|  | 18 import 'package:test/test.dart'; | 
|  | 19 | 
|  | 20 main() { | 
|  | 21   group("TreeSet", () { | 
|  | 22     group("when empty", () { | 
|  | 23       TreeSet<num> tree; | 
|  | 24       setUp(() { | 
|  | 25         tree = new TreeSet<num>(); | 
|  | 26       }); | 
|  | 27       test("should actually be empty", () => expect(tree, isEmpty)); | 
|  | 28       test("should not contain an element", | 
|  | 29           () => expect(tree.lookup(0), isNull)); | 
|  | 30       test("has no element when iterating forward", () { | 
|  | 31         var i = tree.iterator; | 
|  | 32         expect(i.moveNext(), isFalse, reason: "moveNext reports an element"); | 
|  | 33         expect(i.current, isNull, reason: "current returns an element"); | 
|  | 34       }); | 
|  | 35       test("has no element when iterating backward", () { | 
|  | 36         var i = tree.iterator; | 
|  | 37         expect(i.movePrevious(), isFalse, | 
|  | 38             reason: "movePrevious reports an element"); | 
|  | 39         expect(i.current, isNull, reason: "current returns an element"); | 
|  | 40       }); | 
|  | 41     }); | 
|  | 42 | 
|  | 43     group("with [10, 20, 15]", () { | 
|  | 44       AvlTreeSet<num> tree; | 
|  | 45       setUp(() { | 
|  | 46         tree = new TreeSet<num>()..addAll([10, 20, 15]); | 
|  | 47       }); | 
|  | 48       test("lookup succeeds for inserted elements", () { | 
|  | 49         expect(tree.lookup(10), equals(10), reason: "missing 10"); | 
|  | 50         expect(tree.lookup(15), equals(15), reason: "missing 15"); | 
|  | 51         expect(tree.lookup(20), equals(20), reason: "missing 20"); | 
|  | 52       }); | 
|  | 53       test("order is correct", () { | 
|  | 54         AvlNode ten = tree.getNode(10); | 
|  | 55         AvlNode twenty = tree.getNode(20); | 
|  | 56         AvlNode fifteen = tree.getNode(15); | 
|  | 57         expect(ten.predecessor, isNull, reason: "10 is the smalled element"); | 
|  | 58         expect(ten.successor, equals(fifteen), reason: "15 should follow 10"); | 
|  | 59         expect(ten.successor.successor, equals(twenty), | 
|  | 60             reason: "20 should follow 10"); | 
|  | 61 | 
|  | 62         expect(twenty.successor, isNull, reason: "20 is the largest element"); | 
|  | 63         expect(twenty.predecessor, equals(fifteen), reason: "15 is before 20"); | 
|  | 64         expect(twenty.predecessor.predecessor, equals(ten), | 
|  | 65             reason: "10 is before 15"); | 
|  | 66       }); | 
|  | 67     }); | 
|  | 68 | 
|  | 69     group("with repeated elements", () { | 
|  | 70       TreeSet<num> tree; | 
|  | 71       setUp(() { | 
|  | 72         tree = new TreeSet<num>()..addAll([10, 20, 15, 21, 30, 20]); | 
|  | 73       }); | 
|  | 74 | 
|  | 75       test("only contains subset", () { | 
|  | 76         var it = tree.iterator; | 
|  | 77         var testList = new List.from([10, 15, 20, 21, 30]); | 
|  | 78         while (it.moveNext()) { | 
|  | 79           expect(it.current, equals(testList.removeAt(0))); | 
|  | 80         } | 
|  | 81         expect(testList.length, equals(0), reason: "valid subset seen in tree"); | 
|  | 82       }); | 
|  | 83     }); | 
|  | 84 | 
|  | 85     group("iteration", () { | 
|  | 86       TreeSet<num> tree; | 
|  | 87       setUp(() { | 
|  | 88         tree = new TreeSet<num>()..addAll([10, 20, 15, 21, 30]); | 
|  | 89       }); | 
|  | 90 | 
|  | 91       test("works bidirectionally", () { | 
|  | 92         var it = tree.iterator; | 
|  | 93         while (it.moveNext()); | 
|  | 94         expect(it.movePrevious(), isTrue, | 
|  | 95             reason: "we can backup after walking the entire list"); | 
|  | 96         expect(it.current, equals(30), | 
|  | 97             reason: "the last element is what we expect"); | 
|  | 98         while (it.movePrevious()); | 
|  | 99         expect(it.moveNext(), isTrue, | 
|  | 100             reason: "we can move next after walking to the front of the set"); | 
|  | 101         expect(it.current, equals(10), | 
|  | 102             reason: "the first element is what we expect"); | 
|  | 103       }); | 
|  | 104 | 
|  | 105       group("from", () { | 
|  | 106         test("non-inserted midpoint works forward", () { | 
|  | 107           var it = tree.fromIterator(19); | 
|  | 108           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 109           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 110           expect(it.current, equals(20)); | 
|  | 111         }); | 
|  | 112 | 
|  | 113         test("non-inserted midpoint works for movePrevious()", () { | 
|  | 114           var it = tree.fromIterator(19); | 
|  | 115           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 116           expect(it.movePrevious(), isTrue, | 
|  | 117               reason: "movePrevious() from spot works"); | 
|  | 118           expect(it.current, equals(15)); | 
|  | 119         }); | 
|  | 120 | 
|  | 121         test("non-inserted midpoint works reversed", () { | 
|  | 122           var it = tree.fromIterator(19, reversed: true); | 
|  | 123           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 124           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 125           expect(it.current, equals(15)); | 
|  | 126         }); | 
|  | 127 | 
|  | 128         test("non-inserted midpoint works reversed, movePrevious()", () { | 
|  | 129           var it = tree.fromIterator(19, reversed: true); | 
|  | 130           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 131           expect(it.movePrevious(), isTrue, | 
|  | 132               reason: "movePrevious() from spot works"); | 
|  | 133           expect(it.current, equals(20)); | 
|  | 134         }); | 
|  | 135 | 
|  | 136         test("inserted midpoint works forward", () { | 
|  | 137           var it = tree.fromIterator(20); | 
|  | 138           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 139           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 140           expect(it.current, equals(20)); | 
|  | 141         }); | 
|  | 142 | 
|  | 143         test("inserted midpoint works reversed", () { | 
|  | 144           var it = tree.fromIterator(20, reversed: true); | 
|  | 145           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 146           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 147           expect(it.current, equals(20)); | 
|  | 148         }); | 
|  | 149 | 
|  | 150         test("after the set", () { | 
|  | 151           var it = tree.fromIterator(100); | 
|  | 152           expect(it.current, isNull); | 
|  | 153           expect(it.moveNext(), isFalse, reason: "not following items"); | 
|  | 154           expect(it.movePrevious(), isTrue, reason: "backwards movement valid"); | 
|  | 155           expect(it.current, equals(30)); | 
|  | 156         }); | 
|  | 157 | 
|  | 158         test("before the set", () { | 
|  | 159           var it = tree.fromIterator(0); | 
|  | 160           expect(it.current, isNull); | 
|  | 161           expect(it.movePrevious(), isFalse, reason: "not previous items"); | 
|  | 162           expect(it.moveNext(), isTrue, reason: "forwards movement valid"); | 
|  | 163           expect(it.current, equals(10)); | 
|  | 164         }); | 
|  | 165 | 
|  | 166         test("inserted midpoint, non-inclusive, works forward", () { | 
|  | 167           var it = tree.fromIterator(20, inclusive: false); | 
|  | 168           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 169           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 170           expect(it.current, equals(21)); | 
|  | 171         }); | 
|  | 172 | 
|  | 173         test("inserted endpoint, non-inclusive, works forward", () { | 
|  | 174           var it = tree.fromIterator(30, inclusive: false); | 
|  | 175           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 176           expect(it.moveNext(), isFalse, reason: "moveNext() from spot works"); | 
|  | 177 | 
|  | 178           it = tree.fromIterator(10, inclusive: false); | 
|  | 179           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 180           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 181           expect(it.current, equals(15), | 
|  | 182               reason: "non-inclusive start should be 15"); | 
|  | 183         }); | 
|  | 184 | 
|  | 185         test("inserted endpoint, non-inclusive, works backward", () { | 
|  | 186           var it = tree.fromIterator(10, inclusive: false); | 
|  | 187           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 188           expect(it.movePrevious(), isFalse, | 
|  | 189               reason: "movePrevious() from spot is null"); | 
|  | 190 | 
|  | 191           it = tree.fromIterator(30, inclusive: false); | 
|  | 192           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 193           expect( | 
|  | 194               it.movePrevious(), isTrue, reason: "moveNext() from spot works"); | 
|  | 195           expect(it.current, equals(21)); | 
|  | 196         }); | 
|  | 197 | 
|  | 198         test("inserted midpoint, non-inclusive, reversed, works forward", () { | 
|  | 199           var it = tree.fromIterator(20, inclusive: false, reversed: true); | 
|  | 200           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 201           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 202           expect(it.current, equals(15)); | 
|  | 203         }); | 
|  | 204 | 
|  | 205         test("inserted endpoint, non-inclusive, reversed, works forward", () { | 
|  | 206           var it = tree.fromIterator(30, inclusive: false, reversed: true); | 
|  | 207           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 208           expect(it.moveNext(), isTrue, reason: "moveNext() from spot works"); | 
|  | 209           expect(it.current, equals(21)); | 
|  | 210 | 
|  | 211           it = tree.fromIterator(10, inclusive: false, reversed: true); | 
|  | 212           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 213           expect(it.moveNext(), isFalse, reason: "moveNext() works"); | 
|  | 214         }); | 
|  | 215 | 
|  | 216         test("inserted endpoint, non-inclusive, reversed, works backward", () { | 
|  | 217           var it = tree.fromIterator(10, inclusive: false, reversed: true); | 
|  | 218           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 219           expect( | 
|  | 220               it.movePrevious(), isTrue, reason: "moveNext() from spot works"); | 
|  | 221           expect(it.current, equals(15)); | 
|  | 222 | 
|  | 223           it = tree.fromIterator(30, inclusive: false, reversed: true); | 
|  | 224           expect(it.current, isNull, reason: "iteration starts with null"); | 
|  | 225           expect( | 
|  | 226               it.movePrevious(), isFalse, reason: "moveNext() from spot works"); | 
|  | 227         }); | 
|  | 228       }); | 
|  | 229 | 
|  | 230       group("fails", () { | 
|  | 231         var it; | 
|  | 232         setUp(() => it = tree.iterator); | 
|  | 233 | 
|  | 234         test("after tree is cleared", () { | 
|  | 235           tree.clear(); | 
|  | 236           var error; | 
|  | 237           try { | 
|  | 238             it.moveNext(); | 
|  | 239           } catch (e) { | 
|  | 240             error = e; | 
|  | 241           } | 
|  | 242           expect(error, isConcurrentModificationError); | 
|  | 243         }); | 
|  | 244 | 
|  | 245         test("after inserting an element", () { | 
|  | 246           tree.add(101); | 
|  | 247           var error; | 
|  | 248           try { | 
|  | 249             it.moveNext(); | 
|  | 250           } catch (e) { | 
|  | 251             error = e; | 
|  | 252           } | 
|  | 253           expect(error, isConcurrentModificationError); | 
|  | 254         }); | 
|  | 255 | 
|  | 256         test("after removing an element", () { | 
|  | 257           tree.remove(10); | 
|  | 258           var error; | 
|  | 259           try { | 
|  | 260             it.moveNext(); | 
|  | 261           } catch (e) { | 
|  | 262             error = e; | 
|  | 263           } | 
|  | 264           expect(error, isConcurrentModificationError); | 
|  | 265         }); | 
|  | 266       }); | 
|  | 267 | 
|  | 268       group("still works", () { | 
|  | 269         var it; | 
|  | 270         setUp(() => it = tree.iterator); | 
|  | 271 | 
|  | 272         test("when removing non-existing element", () { | 
|  | 273           tree.remove(42); | 
|  | 274           var error; | 
|  | 275           try { | 
|  | 276             it.moveNext(); | 
|  | 277           } catch (e) { | 
|  | 278             error = e; | 
|  | 279           } | 
|  | 280           expect(error, isNull, reason: "set was not modified"); | 
|  | 281         }); | 
|  | 282         test("when adding an already existing element", () { | 
|  | 283           tree.add(10); | 
|  | 284           var error; | 
|  | 285           try { | 
|  | 286             it.moveNext(); | 
|  | 287           } catch (e) { | 
|  | 288             error = e; | 
|  | 289           } | 
|  | 290           expect(error, isNull, reason: "set was not modified"); | 
|  | 291         }); | 
|  | 292       }); | 
|  | 293     }); | 
|  | 294 | 
|  | 295     group("set math", () { | 
|  | 296       /// NOTE: set math with sorted sets should have a performance benifit, | 
|  | 297       /// we do not check the performance, only that the resulting math | 
|  | 298       /// is equivilant to non-sorted sets. | 
|  | 299 | 
|  | 300       TreeSet<num> tree; | 
|  | 301       List<num> expectedUnion; | 
|  | 302       List<num> expectedIntersection; | 
|  | 303       List<num> expectedDifference; | 
|  | 304       Set<num> nonSortedTestSet; | 
|  | 305       TreeSet<num> sortedTestSet; | 
|  | 306 | 
|  | 307       setUp(() { | 
|  | 308         tree = new TreeSet()..addAll([10, 20, 15, 21, 30, 20]); | 
|  | 309         expectedUnion = [10, 15, 18, 20, 21, 22, 30]; | 
|  | 310         expectedIntersection = [10, 15]; | 
|  | 311         expectedDifference = [20, 21, 30]; | 
|  | 312         nonSortedTestSet = new Set.from([10, 18, 22, 15]); | 
|  | 313         sortedTestSet = new TreeSet()..addAll(nonSortedTestSet); | 
|  | 314       }); | 
|  | 315 | 
|  | 316       test("union with non sorted set", () => | 
|  | 317           expect(tree.union(nonSortedTestSet).toList(), equals(expectedUnion))); | 
|  | 318       test("union with sorted set", () => | 
|  | 319           expect(tree.union(sortedTestSet).toList(), equals(expectedUnion))); | 
|  | 320       test("intersection with non sorted set", () => expect( | 
|  | 321           tree.intersection(nonSortedTestSet).toList(), | 
|  | 322           equals(expectedIntersection))); | 
|  | 323       test("intersection with sorted set", () => expect( | 
|  | 324           tree.intersection(sortedTestSet).toList(), | 
|  | 325           equals(expectedIntersection))); | 
|  | 326       test("difference with non sorted set", () => expect( | 
|  | 327           tree.difference(nonSortedTestSet).toList(), | 
|  | 328           equals(expectedDifference))); | 
|  | 329       test("difference with sorted set", () => expect( | 
|  | 330           tree.difference(sortedTestSet).toList(), equals(expectedDifference))); | 
|  | 331     }); | 
|  | 332 | 
|  | 333     group("AVL implementaiton", () { | 
|  | 334       /// NOTE: This is implementation specific testing for coverage. | 
|  | 335       /// Users do not have access to [AvlNode] or [AvlTreeSet] | 
|  | 336       test("RightLeftRotation", () { | 
|  | 337         AvlTreeSet<num> tree = new TreeSet<num>(); | 
|  | 338         tree.add(10); | 
|  | 339         tree.add(20); | 
|  | 340         tree.add(15); | 
|  | 341 | 
|  | 342         AvlNode ten = tree.getNode(10); | 
|  | 343         AvlNode twenty = tree.getNode(20); | 
|  | 344         AvlNode fifteen = tree.getNode(15); | 
|  | 345 | 
|  | 346         expect(ten.parent, equals(fifteen)); | 
|  | 347         expect(ten.left, equals(null)); | 
|  | 348         expect(ten.right, equals(null)); | 
|  | 349         expect(ten.balance, equals(0)); | 
|  | 350 | 
|  | 351         expect(twenty.parent, equals(fifteen)); | 
|  | 352         expect(twenty.left, equals(null)); | 
|  | 353         expect(twenty.right, equals(null)); | 
|  | 354         expect(twenty.balance, equals(0)); | 
|  | 355 | 
|  | 356         expect(fifteen.parent, equals(null)); | 
|  | 357         expect(fifteen.left, equals(ten)); | 
|  | 358         expect(fifteen.right, equals(twenty)); | 
|  | 359         expect(fifteen.balance, equals(0)); | 
|  | 360       }); | 
|  | 361       test("LeftRightRotation", () { | 
|  | 362         AvlTreeSet<num> tree = new TreeSet<num>(); | 
|  | 363         tree.add(30); | 
|  | 364         tree.add(10); | 
|  | 365         tree.add(20); | 
|  | 366 | 
|  | 367         AvlNode thirty = tree.getNode(30); | 
|  | 368         AvlNode ten = tree.getNode(10); | 
|  | 369         AvlNode twenty = tree.getNode(20); | 
|  | 370 | 
|  | 371         expect(thirty.parent, equals(twenty)); | 
|  | 372         expect(thirty.left, equals(null)); | 
|  | 373         expect(thirty.right, equals(null)); | 
|  | 374         expect(thirty.balance, equals(0)); | 
|  | 375 | 
|  | 376         expect(ten.parent, equals(twenty)); | 
|  | 377         expect(ten.left, equals(null)); | 
|  | 378         expect(ten.right, equals(null)); | 
|  | 379         expect(ten.balance, equals(0)); | 
|  | 380 | 
|  | 381         expect(twenty.parent, equals(null)); | 
|  | 382         expect(twenty.left, equals(ten)); | 
|  | 383         expect(twenty.right, equals(thirty)); | 
|  | 384         expect(twenty.balance, equals(0)); | 
|  | 385       }); | 
|  | 386 | 
|  | 387       test("AVL-LeftRotation", () { | 
|  | 388         AvlTreeSet<num> tree = new TreeSet<num>(); | 
|  | 389         tree.add(1); | 
|  | 390         tree.add(2); | 
|  | 391         tree.add(3); | 
|  | 392 | 
|  | 393         AvlNode one = tree.getNode(1); | 
|  | 394         AvlNode two = tree.getNode(2); | 
|  | 395         AvlNode three = tree.getNode(3); | 
|  | 396 | 
|  | 397         expect(one.parent, equals(two)); | 
|  | 398         expect(one.left, equals(null)); | 
|  | 399         expect(one.right, equals(null)); | 
|  | 400         expect(one.balance, equals(0)); | 
|  | 401 | 
|  | 402         expect(three.parent, equals(two)); | 
|  | 403         expect(three.left, equals(null)); | 
|  | 404         expect(three.right, equals(null)); | 
|  | 405         expect(three.balance, equals(0)); | 
|  | 406 | 
|  | 407         expect(two.parent, equals(null)); | 
|  | 408         expect(two.left, equals(one)); | 
|  | 409         expect(two.right, equals(three)); | 
|  | 410         expect(two.balance, equals(0)); | 
|  | 411       }); | 
|  | 412 | 
|  | 413       test("AVL-RightRotation", () { | 
|  | 414         AvlTreeSet<num> tree = new TreeSet<num>(); | 
|  | 415         tree.add(3); | 
|  | 416         tree.add(2); | 
|  | 417         tree.add(1); | 
|  | 418 | 
|  | 419         AvlNode one = tree.getNode(1); | 
|  | 420         AvlNode two = tree.getNode(2); | 
|  | 421         AvlNode three = tree.getNode(3); | 
|  | 422 | 
|  | 423         expect(one.parent, equals(two)); | 
|  | 424         expect(one.left, equals(null)); | 
|  | 425         expect(one.right, equals(null)); | 
|  | 426         expect(one.balance, equals(0)); | 
|  | 427 | 
|  | 428         expect(three.parent, equals(two)); | 
|  | 429         expect(three.left, equals(null)); | 
|  | 430         expect(three.right, equals(null)); | 
|  | 431         expect(three.balance, equals(0)); | 
|  | 432 | 
|  | 433         expect(two.parent, equals(null)); | 
|  | 434         expect(two.left, equals(one)); | 
|  | 435         expect(two.right, equals(three)); | 
|  | 436         expect(two.balance, equals(0)); | 
|  | 437       }); | 
|  | 438     }); | 
|  | 439 | 
|  | 440     group("nearest search", () { | 
|  | 441       TreeSet<num> tree; | 
|  | 442       setUp(() { | 
|  | 443         tree = new TreeSet<num>(comparator: (num left, num right) { | 
|  | 444           return left - right; | 
|  | 445         })..addAll([300, 200, 100]); | 
|  | 446       }); | 
|  | 447 | 
|  | 448       test("NEAREST is sane", () { | 
|  | 449         var val = tree.nearest(199); | 
|  | 450         expect(val, equals(200), reason: "199 is closer to 200"); | 
|  | 451         val = tree.nearest(201); | 
|  | 452         expect(val, equals(200), reason: "201 is 200"); | 
|  | 453         val = tree.nearest(150); | 
|  | 454         expect(val, equals(100), reason: "150 defaults to lower 100"); | 
|  | 455       }); | 
|  | 456 | 
|  | 457       test("LESS_THAN is sane", () { | 
|  | 458         var val = tree.nearest(199, nearestOption: TreeSearch.LESS_THAN); | 
|  | 459         expect(val, equals(100), reason: "199 rounds down to 100"); | 
|  | 460       }); | 
|  | 461 | 
|  | 462       test("GREATER_THAN is sane", () { | 
|  | 463         var val = tree.nearest(101, nearestOption: TreeSearch.GREATER_THAN); | 
|  | 464         expect(val, equals(200), reason: "101 rounds up to 200"); | 
|  | 465       }); | 
|  | 466     }); | 
|  | 467   }); | 
|  | 468 } | 
| OLD | NEW | 
|---|