Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: tests/corelib/list_test.dart

Issue 14468004: Fix missing concurrency check in [].forEach. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added comment about iteration order of lists. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« sdk/lib/core/list.dart ('K') | « sdk/lib/core/list.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import "dart:collection"; 5 import "dart:collection";
6 import "dart:typeddata"; 6 import "dart:typeddata";
7 import "package:expect/expect.dart"; 7 import "package:expect/expect.dart";
8 8
9 void main() { 9 void main() {
10 // Typed lists - fixed length and can only contain integers.
11 testTypedList(new Uint8List(4));
12 testTypedList(new Int8List(4));
13 testTypedList(new Uint16List(4));
14 testTypedList(new Int16List(4));
15 testTypedList(new Uint32List(4));
16 testTypedList(new Int32List(4));
17
10 // Fixed length lists, length 4. 18 // Fixed length lists, length 4.
11 testFixedLengthList(new List(4)); 19 testFixedLengthList(new List(4));
12 testFixedLengthList(new List(4).toList(growable: false)); 20 testFixedLengthList(new List(4).toList(growable: false));
13 testFixedLengthList((new List()..length = 4).toList(growable: false)); 21 testFixedLengthList((new List()..length = 4).toList(growable: false));
14 // ListBase implementation of List. 22 // ListBase implementation of List.
15 testFixedLengthList(new MyFixedList(new List(4))); 23 testFixedLengthList(new MyFixedList(new List(4)));
16 testFixedLengthList(new MyFixedList(new List(4)).toList(growable: false)); 24 testFixedLengthList(new MyFixedList(new List(4)).toList(growable: false));
17 25
18 26 testFixedLengthList(new Uint8List(4).toList(growable: false));
19 testTypedList(new Uint8List(4)); 27 testFixedLengthList(new Int8List(4).toList(growable: false));
20 testTypedList(new Int8List(4)); 28 testFixedLengthList(new Uint16List(4).toList(growable: false));
21 testTypedList(new Uint16List(4)); 29 testFixedLengthList(new Int16List(4).toList(growable: false));
22 testTypedList(new Int16List(4)); 30 testFixedLengthList(new Uint32List(4).toList(growable: false));
23 testTypedList(new Uint32List(4)); 31 testFixedLengthList(new Int32List(4).toList(growable: false));
24 testTypedList(new Int32List(4));
25 32
26 // Growable lists. Initial length 0. 33 // Growable lists. Initial length 0.
27 testGrowableList(new List()); 34 testGrowableList(new List());
28 testGrowableList(new List().toList()); 35 testGrowableList(new List().toList());
29 testGrowableList(new List(0).toList()); 36 testGrowableList(new List(0).toList());
30 testGrowableList([]); 37 testGrowableList([]);
31 testGrowableList((const []).toList()); 38 testGrowableList((const []).toList());
32 testGrowableList(new MyList([])); 39 testGrowableList(new MyList([]));
33 testGrowableList(new MyList([]).toList()); 40 testGrowableList(new MyList([]).toList());
41 testGrowableList(new Uint8List(0).toList());
42 testGrowableList(new Int8List(0).toList());
43 testGrowableList(new Uint16List(0).toList());
44 testGrowableList(new Int16List(0).toList());
45 testGrowableList(new Uint32List(0).toList());
46 testGrowableList(new Int32List(0).toList());
34 } 47 }
35 48
36 void testLength(int length, List list) { 49 void testLength(int length, List list) {
37 Expect.equals(length, list.length); 50 Expect.equals(length, list.length);
38 (length == 0 ? Expect.isTrue : Expect.isFalse)(list.isEmpty); 51 (length == 0 ? Expect.isTrue : Expect.isFalse)(list.isEmpty);
39 } 52 }
40 53
41 void testTypedLengthInvariantOperations(List list) { 54 void testTypedLengthInvariantOperations(List list) {
42 // length 55 // length
43 Expect.equals(list.length, 4); 56 Expect.equals(list.length, 4);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 88
76 list.setRange(2, 4, list, 0); 89 list.setRange(2, 4, list, 0);
77 Expect.listEquals([2, 1, 2, 1], list); 90 Expect.listEquals([2, 1, 2, 1], list);
78 91
79 // setAll. 92 // setAll.
80 list.setAll(0, [3, 2, 0, 1]); 93 list.setAll(0, [3, 2, 0, 1]);
81 Expect.listEquals([3, 2, 0, 1], list); 94 Expect.listEquals([3, 2, 0, 1], list);
82 list.setAll(1, [0, 1]); 95 list.setAll(1, [0, 1]);
83 Expect.listEquals([3, 0, 1, 1], list); 96 Expect.listEquals([3, 0, 1, 1], list);
84 97
98 // fillRange.
99 list.fillRange(1, 3, 7);
100 Expect.listEquals([3, 7, 7, 1], list);
101 list.fillRange(0, 0, 9);
102 Expect.listEquals([3, 7, 7, 1], list);
103 list.fillRange(4, 4, 9);
104 Expect.listEquals([3, 7, 7, 1], list);
105 list.fillRange(0, 4, 9);
106 Expect.listEquals([9, 9, 9, 9], list);
107
85 // sort. 108 // sort.
86 list.setRange(0, 4, [3, 2, 1, 0]); 109 list.setRange(0, 4, [3, 2, 1, 0]);
87 list.sort(); 110 list.sort();
88 Expect.listEquals([0, 1, 2, 3], list); 111 Expect.listEquals([0, 1, 2, 3], list);
89 list.setRange(0, 4, [1, 2, 3, 0]); 112 list.setRange(0, 4, [1, 2, 3, 0]);
90 list.sort(); 113 list.sort();
91 Expect.listEquals([0, 1, 2, 3], list); 114 Expect.listEquals([0, 1, 2, 3], list);
92 list.setRange(0, 4, [1, 3, 0, 2]); 115 list.setRange(0, 4, [1, 3, 0, 2]);
93 list.sort((a, b) => b - a); // reverse compare. 116 list.sort((a, b) => b - a); // reverse compare.
94 Expect.listEquals([3, 2, 1, 0], list); 117 Expect.listEquals([3, 2, 1, 0], list);
(...skipping 26 matching lines...) Expand all
121 Expect.isTrue(list.every(matchAll)); 144 Expect.isTrue(list.every(matchAll));
122 Expect.isFalse(list.every(matchSome)); 145 Expect.isFalse(list.every(matchSome));
123 Expect.isFalse(list.every(matchNone)); 146 Expect.isFalse(list.every(matchNone));
124 147
125 // any 148 // any
126 Expect.isTrue(list.any(matchAll)); 149 Expect.isTrue(list.any(matchAll));
127 Expect.isTrue(list.any(matchSome)); 150 Expect.isTrue(list.any(matchSome));
128 Expect.isTrue(list.any(matchSomeFirst)); 151 Expect.isTrue(list.any(matchSomeFirst));
129 Expect.isTrue(list.any(matchSomeLast)); 152 Expect.isTrue(list.any(matchSomeLast));
130 Expect.isFalse(list.any(matchNone)); 153 Expect.isFalse(list.any(matchNone));
154
155 // Argument errors on bad indices. List is still [0, 1, 2, 3].
156 testArgumentError(action()) {
157 Expect.throws(action, (e) => e is ArgumentError);
158 }
159
160 // Direct indices (0 <= index < length).
161 testArgumentError(() => list[-1]);
162 testArgumentError(() => list[4]);
163 testArgumentError(() => list[-1] = 99);
164 testArgumentError(() => list[4] = 99);
165 testArgumentError(() => list.elementAt(-1));
166 testArgumentError(() => list.elementAt(4));
167 // Ranges (0 <= start <= end <= length).
168 testArgumentError(() => list.sublist(-1, 2));
169 testArgumentError(() => list.sublist(-1, 5));
170 testArgumentError(() => list.sublist(2, 5));
171 testArgumentError(() => list.sublist(4, 2));
172 testArgumentError(() => list.getRange(-1, 2));
173 testArgumentError(() => list.getRange(-1, 5));
174 testArgumentError(() => list.getRange(2, 5));
175 testArgumentError(() => list.getRange(4, 2));
176 testArgumentError(() => list.setRange(-1, 2, [1, 2, 3]));
177 testArgumentError(() => list.setRange(-1, 5, [1, 2, 3, 4, 5, 6]));
178 testArgumentError(() => list.setRange(2, 5, [1, 2, 3]));
179 testArgumentError(() => list.setRange(4, 2, [1, 2]));
180 // for setAll, end is implictly start + values.length.
181 testArgumentError(() => list.setAll(-1, []));
182 testArgumentError(() => list.setAll(5, []));
183 testArgumentError(() => list.setAll(2, [1, 2, 3]));
184 testArgumentError(() => list.fillRange(-1, 2));
185 testArgumentError(() => list.fillRange(-1, 5));
186 testArgumentError(() => list.fillRange(2, 5));
187 testArgumentError(() => list.fillRange(4, 2));
131 } 188 }
132 189
133 void testLengthInvariantOperations(List list) { 190 void testLengthInvariantOperations(List list) {
134 testTypedLengthInvariantOperations(list); 191 testTypedLengthInvariantOperations(list);
135 // Tests that need untyped lists. 192 // Tests that need untyped lists.
136 list.setAll(0, [0, 1, 2, 3]); 193 list.setAll(0, [0, 1, 2, 3]);
137 Expect.equals(-1, list.indexOf(100)); 194 Expect.equals(-1, list.indexOf(100));
138 Expect.equals(-1, list.lastIndexOf(100)); 195 Expect.equals(-1, list.lastIndexOf(100));
139 list[2] = new Yes(); 196 list[2] = new Yes();
140 Expect.equals(2, list.indexOf(100)); 197 Expect.equals(2, list.indexOf(100));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 Expect.listEquals([1, 2, 3, 0, 0, 7, 2, 3, 2, 1], list); 348 Expect.listEquals([1, 2, 3, 0, 0, 7, 2, 3, 2, 1], list);
292 349
293 list.replaceRange(2, 3, [5, 5, 5]); 350 list.replaceRange(2, 3, [5, 5, 5]);
294 Expect.listEquals([1, 2, 5, 5, 5, 0, 0, 7, 2, 3, 2, 1], list); 351 Expect.listEquals([1, 2, 5, 5, 5, 0, 0, 7, 2, 3, 2, 1], list);
295 352
296 list.replaceRange(2, 4, [6, 6]); 353 list.replaceRange(2, 4, [6, 6]);
297 Expect.listEquals([1, 2, 6, 6, 5, 0, 0, 7, 2, 3, 2, 1], list); 354 Expect.listEquals([1, 2, 6, 6, 5, 0, 0, 7, 2, 3, 2, 1], list);
298 355
299 list.replaceRange(6, 8, []); 356 list.replaceRange(6, 8, []);
300 Expect.listEquals([1, 2, 6, 6, 5, 0, 2, 3, 2, 1], list); 357 Expect.listEquals([1, 2, 6, 6, 5, 0, 2, 3, 2, 1], list);
301 } 358
359 // Operations that change the length cause ConcurrentModificationError.
360 void testConcurrentModification(action()) {
361 testIterator(int when) {
362 list.length = 4;
363 list.setAll(0, [0, 1, 2, 3]);
364 Expect.throws(() {
365 for (var element in list) {
366 if (element == when) action();
367 }
368 }, (e) => e is ConcurrentModificationError);
369 }
370 testForEach(int when) {
371 list.length = 4;
372 list.setAll(0, [0, 1, 2, 3]);
373 Expect.throws(() {
374 list.forEach((var element) {
375 if (element == when) action();
376 });
377 }, (e) => e is ConcurrentModificationError);
378 }
379 // Test the change at different points of the iteration.
380 testIterator(0);
381 testIterator(1);
382 testIterator(3);
383 testForEach(0);
384 testForEach(1);
385 testForEach(3);
386 }
387
388 testConcurrentModification(() => list.add(5));
389 testConcurrentModification(() => list.addAll([5, 6]));
390 testConcurrentModification(() => list.removeLast());
391 for (int i = 0; i < 4; i++) {
392 testConcurrentModification(() => list.remove(i));
393 testConcurrentModification(() => list.removeAt(i));
394 testConcurrentModification(() => list.removeWhere((x) => x == i));
395 testConcurrentModification(() => list.retainWhere((x) => x != i));
396 testConcurrentModification(() => list.insert(i, 5));
397 testConcurrentModification(() => list.insertAll(i, [5, 6]));
398 testConcurrentModification(() => list.removeRange(i, i + 1));
399 testConcurrentModification(() => list.replaceRange(i, i + 1, [5, 6]));
400 }
401
402 // Any operation that doesn't change the length should be safe for iteration.
403 testSafeConcurrentModification(action()) {
404 list.length = 4;
405 list.setAll(0, [0, 1, 2, 3]);
406 for (var i in list) {
407 action();
408 }
409 list.forEach((e) => action());
410 }
411
412 testSafeConcurrentModification(() {
413 list.add(5);
414 list.removeLast();
415 });
416 testSafeConcurrentModification(() {
417 list.add(list[0]);
418 list.removeAt(0);
419 });
420 testSafeConcurrentModification(() {
421 list.insert(0, list.removeLast());
422 });
423 testSafeConcurrentModification(() {
424 list.replaceRange(1, 3, list.sublist(1, 3).reversed);
425 });
426
427 // Argument errors on bad indices for methods that are only allowed
428 // on growable lists.
429 list.length = 4;
430 list.setAll(0, [0, 1, 2, 3]);
431 testArgumentError(action()) {
432 Expect.throws(action, (e) => e is ArgumentError);
433 }
434
435 // Direct indices (0 <= index < length).
436 testArgumentError(() => list.removeAt(-1));
437 testArgumentError(() => list.removeAt(4));
438 // Direct indices including end (0 <= index <= length).
439 testArgumentError(() => list.insert(-1, 0));
440 testArgumentError(() => list.insert(5, 0));
441 testArgumentError(() => list.insertAll(-1, [0]));
442 testArgumentError(() => list.insertAll(5, [0]));
443 testArgumentError(() => list.insertAll(-1, [0]));
444 testArgumentError(() => list.insertAll(5, [0]));
445 // Ranges (0 <= start <= end <= length).
446 testArgumentError(() => list.removeRange(-1, 2));
447 testArgumentError(() => list.removeRange(2, 5));
448 testArgumentError(() => list.removeRange(-1, 5));
449 testArgumentError(() => list.removeRange(4, 2));
450 testArgumentError(() => list.replaceRange(-1, 2, [9]));
451 testArgumentError(() => list.replaceRange(2, 5, [9]));
452 testArgumentError(() => list.replaceRange(-1, 5, [9]));
453 testArgumentError(() => list.replaceRange(4, 2, [9]));
454 }
302 455
303 class Yes { 456 class Yes {
304 operator ==(var other) => true; 457 operator ==(var other) => true;
305 } 458 }
306 459
307 class MyList<E> extends ListBase<E> { 460 class MyList<E> extends ListBase<E> {
308 List<E> _source; 461 List<E> _source;
309 MyList(this._source); 462 MyList(this._source);
310 int get length => _source.length; 463 int get length => _source.length;
311 void set length(int length) { _source.length = length; } 464 void set length(int length) { _source.length = length; }
312 E operator[](int index) => _source[index]; 465 E operator[](int index) => _source[index];
313 void operator[]=(int index, E value) { _source[index] = value; } 466 void operator[]=(int index, E value) { _source[index] = value; }
314 } 467 }
315 468
316 class MyFixedList<E> extends ListBase<E> { 469 class MyFixedList<E> extends ListBase<E> {
317 List<E> _source; 470 List<E> _source;
318 MyFixedList(this._source); 471 MyFixedList(this._source);
319 int get length => _source.length; 472 int get length => _source.length;
320 void set length(int length) { throw new UnsupportedError("Fixed length!"); } 473 void set length(int length) { throw new UnsupportedError("Fixed length!"); }
321 E operator[](int index) => _source[index]; 474 E operator[](int index) => _source[index];
322 void operator[]=(int index, E value) { _source[index] = value; } 475 void operator[]=(int index, E value) { _source[index] = value; }
323 } 476 }
OLDNEW
« sdk/lib/core/list.dart ('K') | « sdk/lib/core/list.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698