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 |