Chromium Code Reviews| 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 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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(() { | |
|
Søren Gjesse
2013/04/24 09:00:49
This doesn't change length, but the result of forE
Lasse Reichstein Nielsen
2013/04/24 09:30:57
It is intentional, but I can't find any places whe
| |
| 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 } |
| OLD | NEW |