OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, 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 /// Tests priority queue implementations utilities. |
| 6 |
| 7 import "package:collection/priority_queue.dart"; |
| 8 import "package:test/test.dart"; |
| 9 |
| 10 void main() { |
| 11 testInt(() => new HeapPriorityQueue<int>()); |
| 12 testCustom((comparator) => new HeapPriorityQueue<C>(comparator)); |
| 13 } |
| 14 |
| 15 void testInt(PriorityQueue<int> create()) { |
| 16 for (int count in [1, 5, 127, 128]) { |
| 17 testQueue("int:$count", |
| 18 create, |
| 19 new List<int>.generate(count, (x) => x), |
| 20 count); |
| 21 } |
| 22 } |
| 23 |
| 24 void testCustom(PriorityQueue<C> create(comparator)) { |
| 25 for (int count in [1, 5, 127, 128]) { |
| 26 testQueue("Custom:$count/null", |
| 27 () => create(null), |
| 28 new List<C>.generate(count, (x) => new C(x)), |
| 29 new C(count)); |
| 30 testQueue("Custom:$count/compare", |
| 31 () => create(compare), |
| 32 new List<C>.generate(count, (x) => new C(x)), |
| 33 new C(count)); |
| 34 testQueue("Custom:$count/compareNeg", |
| 35 () => create(compareNeg), |
| 36 new List<C>.generate(count, (x) => new C(count - x)), |
| 37 new C(0)); |
| 38 } |
| 39 } |
| 40 |
| 41 /** |
| 42 * Test that a queue behaves correctly. |
| 43 * |
| 44 * The elements must be in priority order, from highest to lowest. |
| 45 */ |
| 46 void testQueue(String name, PriorityQueue create(), List elements, notElement) { |
| 47 test(name, () => testQueueBody(create, elements, notElement)); |
| 48 } |
| 49 |
| 50 void testQueueBody(PriorityQueue create(), List elements, notElement) { |
| 51 PriorityQueue q = create(); |
| 52 expect(q.isEmpty, isTrue); |
| 53 expect(q, hasLength(0)); |
| 54 expect(() { q.first; }, throwsStateError); |
| 55 expect(() { q.removeFirst(); }, throwsStateError); |
| 56 |
| 57 // Tests removeFirst, first, contains, toList and toSet. |
| 58 void testElements() { |
| 59 expect(q.isNotEmpty, isTrue); |
| 60 expect(q, hasLength(elements.length)); |
| 61 |
| 62 expect(q.toList(), equals(elements)); |
| 63 expect(q.toSet().toList(), equals(elements)); |
| 64 |
| 65 for (int i = 0; i < elements.length; i++) { |
| 66 expect(q.contains(elements[i]), isTrue); |
| 67 } |
| 68 expect(q.contains(notElement), isFalse); |
| 69 |
| 70 List all = []; |
| 71 while (!q.isEmpty) { |
| 72 var expected = q.first; |
| 73 var actual = q.removeFirst(); |
| 74 expect(actual, same(expected)); |
| 75 all.add(actual); |
| 76 } |
| 77 |
| 78 expect(all.length, elements.length); |
| 79 for (int i = 0; i < all.length; i++) { |
| 80 expect(all[i], same(elements[i])); |
| 81 } |
| 82 |
| 83 expect(q.isEmpty, isTrue); |
| 84 } |
| 85 |
| 86 q.addAll(elements); |
| 87 testElements(); |
| 88 |
| 89 q.addAll(elements.reversed); |
| 90 testElements(); |
| 91 |
| 92 // Add elements in a non-linear order (gray order). |
| 93 for (int i = 0, j = 0; i < elements.length; i++) { |
| 94 int gray; |
| 95 do { |
| 96 gray = j ^ (j >> 1); |
| 97 j++; |
| 98 } while (gray >= elements.length); |
| 99 q.add(elements[gray]); |
| 100 } |
| 101 testElements(); |
| 102 |
| 103 // Add elements by picking the middle element first, and then recursing |
| 104 // on each side. |
| 105 void addRec(int min, int max) { |
| 106 int mid = min + ((max - min) >> 1); |
| 107 q.add(elements[mid]); |
| 108 if (mid + 1 < max) addRec(mid + 1, max); |
| 109 if (mid > min) addRec(min, mid); |
| 110 } |
| 111 addRec(0, elements.length); |
| 112 testElements(); |
| 113 |
| 114 // Test removeAll. |
| 115 q.addAll(elements); |
| 116 expect(q, hasLength(elements.length)); |
| 117 Iterable all = q.removeAll(); |
| 118 expect(q.isEmpty, isTrue); |
| 119 expect(all, hasLength(elements.length)); |
| 120 for (int i = 0; i < elements.length; i++) { |
| 121 expect(all, contains(elements[i])); |
| 122 } |
| 123 |
| 124 // Test the same element more than once in queue. |
| 125 q.addAll(elements); |
| 126 q.addAll(elements.reversed); |
| 127 expect(q, hasLength(elements.length * 2)); |
| 128 for (int i = 0; i < elements.length; i++) { |
| 129 var element = elements[i]; |
| 130 expect(q.contains(element), isTrue); |
| 131 expect(q.removeFirst(), element); |
| 132 expect(q.removeFirst(), element); |
| 133 } |
| 134 |
| 135 // Test queue with all same element. |
| 136 var a = elements[0]; |
| 137 for (int i = 0; i < elements.length; i++) { |
| 138 q.add(a); |
| 139 } |
| 140 expect(q, hasLength(elements.length)); |
| 141 expect(q.contains(a), isTrue); |
| 142 expect(q.contains(notElement), isFalse); |
| 143 q.removeAll().forEach((x) => expect(x, same(a))); |
| 144 |
| 145 // Test remove. |
| 146 q.addAll(elements); |
| 147 for (var element in elements.reversed) { |
| 148 expect(q.remove(element), isTrue); |
| 149 } |
| 150 expect(q.isEmpty, isTrue); |
| 151 } |
| 152 |
| 153 |
| 154 // Custom class. |
| 155 // Class is comparable, comparators match normal and inverse order. |
| 156 int compare(C c1, C c2) => c1.value - c2.value; |
| 157 int compareNeg(C c1, C c2) => c2.value - c1.value; |
| 158 |
| 159 class C implements Comparable { |
| 160 final int value; |
| 161 const C(this.value); |
| 162 int get hashCode => value; |
| 163 bool operator==(Object other) => other is C && value == other.value; |
| 164 int compareTo(C other) => value - other.value; |
| 165 String toString() => "C($value)"; |
| 166 } |
OLD | NEW |