| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, 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 // Sanity check on the growing behavior of a growable list. | |
| 6 | |
| 7 import "package:expect/expect.dart"; | |
| 8 | |
| 9 void main() { | |
| 10 testConstructor(); | |
| 11 | |
| 12 bool checked = false; | |
| 13 assert((checked = true)); | |
| 14 // Concurrent modification checks are only guaranteed in checked mode. | |
| 15 if (checked) testConcurrentModification(); | |
| 16 } | |
| 17 | |
| 18 // Iterable generating numbers in range [0..count). | |
| 19 // May perform callback at some point underways. | |
| 20 class TestIterableBase extends Iterable<int> { | |
| 21 final int length; | |
| 22 final int count; | |
| 23 // call [callback] if generating callbackIndex. | |
| 24 final int callbackIndex; | |
| 25 final Function callback; | |
| 26 TestIterableBase(this.length, this.count, this.callbackIndex, this.callback); | |
| 27 Iterator<int> get iterator => new CallbackIterator(this); | |
| 28 } | |
| 29 | |
| 30 class TestIterable extends TestIterableBase { | |
| 31 TestIterable(count, [callbackIndex = -1, callback]) | |
| 32 : super(-1, count, callbackIndex, callback); | |
| 33 int get length => throw "SHOULD NOT BE CALLED"; | |
| 34 } | |
| 35 | |
| 36 // Implement Set for private EfficientLengthIterable interface. | |
| 37 class EfficientTestIterable extends TestIterableBase implements Set<int> { | |
| 38 EfficientTestIterable(length, count, [callbackIndex = -1, callback]) | |
| 39 : super(length, count, callbackIndex, callback); | |
| 40 // Avoid warnings because we don't actually implement Set. | |
| 41 noSuchMethod(i) => super.noSuchMethod(i); | |
| 42 } | |
| 43 | |
| 44 class CallbackIterator implements Iterator<int> { | |
| 45 TestIterableBase _iterable; | |
| 46 int _current = null; | |
| 47 int _nextIndex = 0; | |
| 48 CallbackIterator(this._iterable); | |
| 49 bool moveNext() { | |
| 50 if (_nextIndex >= _iterable.count) { | |
| 51 _current = null; | |
| 52 return false; | |
| 53 } | |
| 54 _current = _nextIndex; | |
| 55 _nextIndex++; | |
| 56 if (_current == _iterable.callbackIndex) { | |
| 57 _iterable.callback(); | |
| 58 } | |
| 59 return true; | |
| 60 } | |
| 61 | |
| 62 int get current => _current; | |
| 63 } | |
| 64 | |
| 65 void testConstructor() { | |
| 66 // Constructor can make both growable and fixed-length lists. | |
| 67 testGrowable(list) { | |
| 68 Expect.isTrue(list is List<int>); | |
| 69 Expect.isFalse(list is List<String>); | |
| 70 int length = list.length; | |
| 71 list.add(42); | |
| 72 Expect.equals(list.length, length + 1); | |
| 73 } | |
| 74 | |
| 75 testFixedLength(list) { | |
| 76 Expect.isTrue(list is List<int>); | |
| 77 int length = list.length; | |
| 78 Expect.throws(() { | |
| 79 list.add(42); | |
| 80 }, null, "adding to fixed-length list"); | |
| 81 Expect.equals(length, list.length); | |
| 82 } | |
| 83 | |
| 84 bool checked = false; | |
| 85 assert((checked = true)); | |
| 86 testThrowsOrTypeError(fn, test, [name]) { | |
| 87 Expect.throws( | |
| 88 fn, checked ? null : test, checked ? name : "$name w/ TypeError"); | |
| 89 } | |
| 90 | |
| 91 testFixedLength(new List<int>(0)); | |
| 92 testFixedLength(new List<int>(5)); | |
| 93 testFixedLength(new List<int>.filled(5, null)); // default growable: false. | |
| 94 testGrowable(new List<int>()); | |
| 95 testGrowable(new List<int>()..length = 5); | |
| 96 testGrowable(new List<int>.filled(5, null, growable: true)); | |
| 97 Expect.throws(() => new List<int>(-1), (e) => e is ArgumentError, "-1"); | |
| 98 // There must be limits. Fix this test if we ever allow 10^30 elements. | |
| 99 Expect.throws(() => new List<int>(0x7fffffffffffffff), | |
| 100 (e) => e is ArgumentError, "bignum"); | |
| 101 Expect.throws(() => new List<int>(null), (e) => e is ArgumentError, "null"); | |
| 102 testThrowsOrTypeError( | |
| 103 () => new List([] as Object), // Cast to avoid warning. | |
| 104 (e) => e is ArgumentError, | |
| 105 'list'); | |
| 106 testThrowsOrTypeError( | |
| 107 () => new List([42] as Object), (e) => e is ArgumentError, "list2"); | |
| 108 } | |
| 109 | |
| 110 void testConcurrentModification() { | |
| 111 // Without EfficientLengthIterable interface | |
| 112 { | |
| 113 // Change length of list after 200 additions. | |
| 114 var l = []; | |
| 115 var ci = new TestIterable(257, 200, () { | |
| 116 l.add("X"); | |
| 117 }); | |
| 118 Expect.throws(() { | |
| 119 l.addAll(ci); | |
| 120 }, (e) => e is ConcurrentModificationError, "cm1"); | |
| 121 } | |
| 122 | |
| 123 { | |
| 124 // Change length of list after 200 additions. | |
| 125 var l = []; | |
| 126 var ci = new TestIterable(257, 200, () { | |
| 127 l.length = 0; | |
| 128 }); | |
| 129 Expect.throws(() { | |
| 130 l.addAll(ci); | |
| 131 }, (e) => e is ConcurrentModificationError, "cm2"); | |
| 132 } | |
| 133 | |
| 134 // With EfficientLengthIterable interface (uses length). | |
| 135 { | |
| 136 // Change length of list after 20 additions. | |
| 137 var l = []; | |
| 138 var ci = new EfficientTestIterable(257, 257, 20, () { | |
| 139 l.add("X"); | |
| 140 }); | |
| 141 Expect.throws(() { | |
| 142 l.addAll(ci); | |
| 143 }, (e) => e is ConcurrentModificationError, "cm3"); | |
| 144 } | |
| 145 | |
| 146 { | |
| 147 var l = []; | |
| 148 var ci = new EfficientTestIterable(257, 257, 20, () { | |
| 149 l.length = 0; | |
| 150 }); | |
| 151 Expect.throws(() { | |
| 152 l.addAll(ci); | |
| 153 }, (e) => e is ConcurrentModificationError, "cm4"); | |
| 154 } | |
| 155 | |
| 156 { | |
| 157 // Length 500, only 250 elements. | |
| 158 var l = []; | |
| 159 var ci = new EfficientTestIterable(500, 250); | |
| 160 l.addAll(ci); | |
| 161 Expect.listEquals(new List.generate(250, (x) => x), l, "cm5"); | |
| 162 } | |
| 163 | |
| 164 { | |
| 165 // Length 250, but 500 elements. | |
| 166 var l = []; | |
| 167 var ci = new EfficientTestIterable(250, 500); | |
| 168 l.addAll(ci); | |
| 169 Expect.listEquals(new List.generate(500, (x) => x), l, "cm6"); | |
| 170 } | |
| 171 | |
| 172 { | |
| 173 // Adding to yourself. | |
| 174 var l = [1]; | |
| 175 Expect.throws(() { | |
| 176 l.addAll(l); | |
| 177 }, (e) => e is ConcurrentModificationError, "cm7"); | |
| 178 } | |
| 179 | |
| 180 { | |
| 181 // Adding to yourself. | |
| 182 var l = [1, 2, 3]; | |
| 183 Expect.throws(() { | |
| 184 l.addAll(l); | |
| 185 }, (e) => e is ConcurrentModificationError, "cm8"); | |
| 186 } | |
| 187 } | |
| OLD | NEW |