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