| 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 import "dart:collection"; | |
| 6 import "dart:typed_data"; | |
| 7 import "package:expect/expect.dart"; | |
| 8 | |
| 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 testTypedList(new Uint8List(4).toList(growable: false)); | |
| 18 testTypedList(new Int8List(4).toList(growable: false)); | |
| 19 testTypedList(new Uint16List(4).toList(growable: false)); | |
| 20 testTypedList(new Int16List(4).toList(growable: false)); | |
| 21 testTypedList(new Uint32List(4).toList(growable: false)); | |
| 22 testTypedList(new Int32List(4).toList(growable: false)); | |
| 23 | |
| 24 // Fixed length lists, length 4. | |
| 25 testFixedLengthList(new List(4)); | |
| 26 testFixedLengthList(new List(4).toList(growable: false)); | |
| 27 testFixedLengthList((new List()..length = 4).toList(growable: false)); | |
| 28 // ListBase implementation of List. | |
| 29 testFixedLengthList(new MyFixedList(new List(4))); | |
| 30 testFixedLengthList(new MyFixedList(new List(4)).toList(growable: false)); | |
| 31 | |
| 32 // Growable lists. Initial length 0. | |
| 33 testGrowableList(new List()); | |
| 34 testGrowableList(new List().toList()); | |
| 35 testGrowableList(new List(0).toList()); | |
| 36 testGrowableList(new List.filled(0, null, growable: true)); | |
| 37 testGrowableList([]); | |
| 38 testGrowableList((const []).toList()); | |
| 39 testGrowableList(new MyList([])); | |
| 40 testGrowableList(new MyList([]).toList()); | |
| 41 | |
| 42 testTypedGrowableList(new Uint8List(0).toList()); | |
| 43 testTypedGrowableList(new Int8List(0).toList()); | |
| 44 testTypedGrowableList(new Uint16List(0).toList()); | |
| 45 testTypedGrowableList(new Int16List(0).toList()); | |
| 46 testTypedGrowableList(new Uint32List(0).toList()); | |
| 47 testTypedGrowableList(new Int32List(0).toList()); | |
| 48 | |
| 49 testListConstructor(); | |
| 50 | |
| 51 testErrors(); | |
| 52 } | |
| 53 | |
| 54 void testErrors() { | |
| 55 // Regression for issue http://dartbug.com/24295 | |
| 56 testIndexError(list, index, name) { | |
| 57 try { | |
| 58 list[list.length]; | |
| 59 } catch (err, s) { | |
| 60 Expect.isTrue(err is RangeError, "$name[$index]"); | |
| 61 Expect.equals(list.length, err.invalidValue, "$name[$index] value"); | |
| 62 Expect.equals(list.length - 1, err.end, "$name[$index] end"); | |
| 63 Expect.equals(0, err.start, "$name[$index] start"); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 testIndex(list, name) { | |
| 68 testIndexError(list, list.length, name); // Just too big. | |
| 69 testIndexError(list, -1, name); // Negative. | |
| 70 testIndexError(list, 0x123456789, name); // > 2^32. | |
| 71 testIndexError(list, -0x123456789, name); // < -2^32. | |
| 72 } | |
| 73 | |
| 74 // Slices. | |
| 75 testSliceError(list, start, end, name) { | |
| 76 name = "$name[$start:$end]"; | |
| 77 var realError; | |
| 78 try { | |
| 79 RangeError.checkValidRange(start, end, list.length); | |
| 80 } catch (e) { | |
| 81 realError = e; | |
| 82 } | |
| 83 var result; | |
| 84 try { | |
| 85 result = list.sublist(start, end); | |
| 86 } catch (actualError) { | |
| 87 Expect.isNotNull(realError, "$name should not fail"); | |
| 88 Expect.isTrue(actualError is RangeError, "$name is-error: $actualError"); | |
| 89 Expect.equals(realError.name, actualError.name, "$name name"); | |
| 90 Expect.equals(realError.invalidValue, actualError.invalidValue, | |
| 91 "$name[0:l+1] value"); | |
| 92 Expect.equals(realError.start, actualError.start, "$name[0:l+1] start"); | |
| 93 Expect.equals(realError.end, actualError.end, "$name[0:l+1] end"); | |
| 94 return; | |
| 95 } | |
| 96 // Didn't throw. | |
| 97 Expect.isNull(realError, "$name should fail"); | |
| 98 Expect.equals(end - start, result.length, "$name result length"); | |
| 99 } | |
| 100 | |
| 101 testSlice(list, name) { | |
| 102 testSliceError(list, 0, list.length, name); // Should not fail. | |
| 103 testSliceError(list, 0, list.length + 1, name); | |
| 104 testSliceError(list, 0, 0x123456789, name); | |
| 105 testSliceError(list, -1, list.length, name); | |
| 106 testSliceError(list, -0x123456789, list.length, name); | |
| 107 testSliceError(list, list.length + 1, list.length + 1, name); | |
| 108 testSliceError(list, -1, null, name); | |
| 109 if (list.length > 0) { | |
| 110 testSliceError(list, list.length, list.length - 1, name); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 testRangeErrors(list, name) { | |
| 115 testIndex(list, "$name#${list.length} index"); | |
| 116 testSlice(list, "$name#${list.length} slice"); | |
| 117 } | |
| 118 | |
| 119 // Empty lists. | |
| 120 testRangeErrors([], "list"); | |
| 121 testRangeErrors(new List(0), "fixed-list"); | |
| 122 testRangeErrors(const [], "const-list"); | |
| 123 testRangeErrors(new List.unmodifiable([]), "unmodifiable"); | |
| 124 testRangeErrors(new Uint8List(0), "typed-list"); | |
| 125 testRangeErrors(new Uint8List.view(new Uint8List(0).buffer), "typed-list"); | |
| 126 testRangeErrors([1, 2, 3].sublist(1, 1), "sub-list"); | |
| 127 // Non-empty lists. | |
| 128 testRangeErrors([1, 2, 3], "list"); | |
| 129 testRangeErrors(new List(3), "fixed-list"); | |
| 130 testRangeErrors(const [1, 2, 3], "const-list"); | |
| 131 testRangeErrors(new List.unmodifiable([1, 2, 3]), "unmodifiable"); | |
| 132 testRangeErrors(new Uint8List(3), "typed-list"); | |
| 133 testRangeErrors(new Uint8List.view(new Uint8List(3).buffer), "typed-list"); | |
| 134 testRangeErrors([1, 2, 3, 4, 5].sublist(1, 3), "sub-list"); | |
| 135 } | |
| 136 | |
| 137 void testLength(int length, List list) { | |
| 138 Expect.equals(length, list.length); | |
| 139 (length == 0 ? Expect.isTrue : Expect.isFalse)(list.isEmpty); | |
| 140 (length != 0 ? Expect.isTrue : Expect.isFalse)(list.isNotEmpty); | |
| 141 } | |
| 142 | |
| 143 void testTypedLengthInvariantOperations(List list) { | |
| 144 // length | |
| 145 Expect.equals(list.length, 4); | |
| 146 // operators [], []=. | |
| 147 for (int i = 0; i < 4; i++) list[i] = 0; | |
| 148 list[0] = 4; | |
| 149 Expect.listEquals([4, 0, 0, 0], list); | |
| 150 list[1] = 7; | |
| 151 Expect.listEquals([4, 7, 0, 0], list); | |
| 152 list[3] = 2; | |
| 153 Expect.listEquals([4, 7, 0, 2], list); | |
| 154 | |
| 155 for (int i = 0; i < list.length; i++) { | |
| 156 list[i] = i; | |
| 157 } | |
| 158 | |
| 159 // indexOf, lastIndexOf | |
| 160 for (int i = 0; i < 4; i++) { | |
| 161 Expect.equals(i, list[i]); | |
| 162 Expect.equals(i, list.indexOf(i)); | |
| 163 Expect.equals(i, list.lastIndexOf(i)); | |
| 164 } | |
| 165 | |
| 166 // setRange. | |
| 167 list.setRange(0, 4, [3, 2, 1, 0]); | |
| 168 Expect.listEquals([3, 2, 1, 0], list); | |
| 169 | |
| 170 list.setRange(1, 4, list); | |
| 171 Expect.listEquals([3, 3, 2, 1], list); | |
| 172 | |
| 173 list.setRange(0, 3, list, 1); | |
| 174 Expect.listEquals([3, 2, 1, 1], list); | |
| 175 list.setRange(0, 3, list, 1); | |
| 176 Expect.listEquals([2, 1, 1, 1], list); | |
| 177 | |
| 178 list.setRange(2, 4, list, 0); | |
| 179 Expect.listEquals([2, 1, 2, 1], list); | |
| 180 | |
| 181 // setAll. | |
| 182 list.setAll(0, [3, 2, 0, 1]); | |
| 183 Expect.listEquals([3, 2, 0, 1], list); | |
| 184 list.setAll(1, [0, 1]); | |
| 185 Expect.listEquals([3, 0, 1, 1], list); | |
| 186 | |
| 187 // fillRange. | |
| 188 list.fillRange(1, 3, 7); | |
| 189 Expect.listEquals([3, 7, 7, 1], list); | |
| 190 list.fillRange(0, 0, 9); | |
| 191 Expect.listEquals([3, 7, 7, 1], list); | |
| 192 list.fillRange(4, 4, 9); | |
| 193 Expect.listEquals([3, 7, 7, 1], list); | |
| 194 list.fillRange(0, 4, 9); | |
| 195 Expect.listEquals([9, 9, 9, 9], list); | |
| 196 | |
| 197 // sort. | |
| 198 list.setRange(0, 4, [3, 2, 1, 0]); | |
| 199 list.sort(); | |
| 200 Expect.listEquals([0, 1, 2, 3], list); | |
| 201 list.setRange(0, 4, [1, 2, 3, 0]); | |
| 202 list.sort(); | |
| 203 Expect.listEquals([0, 1, 2, 3], list); | |
| 204 list.setRange(0, 4, [1, 3, 0, 2]); | |
| 205 list.sort((a, b) => b - a); // reverse compare. | |
| 206 Expect.listEquals([3, 2, 1, 0], list); | |
| 207 list.setRange(0, 4, [1, 2, 3, 0]); | |
| 208 list.sort((a, b) => b - a); | |
| 209 Expect.listEquals([3, 2, 1, 0], list); | |
| 210 | |
| 211 // Some Iterable methods. | |
| 212 | |
| 213 list.setRange(0, 4, [0, 1, 2, 3]); | |
| 214 // map. | |
| 215 testMap(val) { | |
| 216 return val * 2 + 10; | |
| 217 } | |
| 218 | |
| 219 List mapped = list.map(testMap).toList(); | |
| 220 Expect.equals(mapped.length, list.length); | |
| 221 for (var i = 0; i < list.length; i++) { | |
| 222 Expect.equals(mapped[i], list[i] * 2 + 10); | |
| 223 } | |
| 224 | |
| 225 matchAll(val) => true; | |
| 226 matchSome(val) { | |
| 227 return (val == 1 || val == 2); | |
| 228 } | |
| 229 | |
| 230 matchSomeFirst(val) { | |
| 231 return val == 0; | |
| 232 } | |
| 233 | |
| 234 matchSomeLast(val) { | |
| 235 return val == 3; | |
| 236 } | |
| 237 | |
| 238 matchNone(val) => false; | |
| 239 | |
| 240 // where. | |
| 241 Iterable filtered = list.where(matchSome); | |
| 242 Expect.equals(filtered.length, 2); | |
| 243 | |
| 244 // every | |
| 245 Expect.isTrue(list.every(matchAll)); | |
| 246 Expect.isFalse(list.every(matchSome)); | |
| 247 Expect.isFalse(list.every(matchNone)); | |
| 248 | |
| 249 // any | |
| 250 Expect.isTrue(list.any(matchAll)); | |
| 251 Expect.isTrue(list.any(matchSome)); | |
| 252 Expect.isTrue(list.any(matchSomeFirst)); | |
| 253 Expect.isTrue(list.any(matchSomeLast)); | |
| 254 Expect.isFalse(list.any(matchNone)); | |
| 255 | |
| 256 // Argument checking isn't implemented for typed arrays in browsers, | |
| 257 // so it's moved to the method below for now. | |
| 258 } | |
| 259 | |
| 260 void testLengthInvariantOperations(List list) { | |
| 261 testTypedLengthInvariantOperations(list); | |
| 262 // Tests that need untyped lists. | |
| 263 list.setAll(0, [0, 1, 2, 3]); | |
| 264 Expect.equals(-1, list.indexOf(100)); | |
| 265 Expect.equals(-1, list.lastIndexOf(100)); | |
| 266 list[2] = new Yes(); | |
| 267 Expect.equals(2, list.indexOf(100)); | |
| 268 Expect.equals(2, list.lastIndexOf(100)); | |
| 269 list[3] = new Yes(); | |
| 270 Expect.equals(2, list.indexOf(100)); | |
| 271 Expect.equals(3, list.lastIndexOf(100)); | |
| 272 list[2] = 2; | |
| 273 Expect.equals(3, list.indexOf(100)); | |
| 274 Expect.equals(3, list.lastIndexOf(100)); | |
| 275 list[3] = 3; | |
| 276 Expect.equals(-1, list.indexOf(100)); | |
| 277 Expect.equals(-1, list.lastIndexOf(100)); | |
| 278 | |
| 279 // Argument errors on bad indices. List is still [0, 1, 2, 3]. | |
| 280 testArgumentError(action()) { | |
| 281 Expect.throws(action, (e) => e is ArgumentError); | |
| 282 } | |
| 283 | |
| 284 // Direct indices (0 <= index < length). | |
| 285 testArgumentError(() => list[-1]); | |
| 286 testArgumentError(() => list[4]); | |
| 287 testArgumentError(() => list[-1] = 99); | |
| 288 testArgumentError(() => list[4] = 99); | |
| 289 testArgumentError(() => list.elementAt(-1)); | |
| 290 testArgumentError(() => list.elementAt(4)); | |
| 291 // Ranges (0 <= start <= end <= length). | |
| 292 testArgumentError(() => list.sublist(-1, 2)); | |
| 293 testArgumentError(() => list.sublist(-1, 5)); | |
| 294 testArgumentError(() => list.sublist(2, 5)); | |
| 295 testArgumentError(() => list.sublist(4, 2)); | |
| 296 testArgumentError(() => list.getRange(-1, 2)); | |
| 297 testArgumentError(() => list.getRange(-1, 5)); | |
| 298 testArgumentError(() => list.getRange(2, 5)); | |
| 299 testArgumentError(() => list.getRange(4, 2)); | |
| 300 testArgumentError(() => list.setRange(-1, 2, [1, 2, 3])); | |
| 301 testArgumentError(() => list.setRange(-1, 5, [1, 2, 3, 4, 5, 6])); | |
| 302 testArgumentError(() => list.setRange(2, 5, [1, 2, 3])); | |
| 303 testArgumentError(() => list.setRange(4, 2, [1, 2])); | |
| 304 // for setAll, end is implicitly start + values.length. | |
| 305 testArgumentError(() => list.setAll(-1, [])); | |
| 306 testArgumentError(() => list.setAll(5, [])); | |
| 307 testArgumentError(() => list.setAll(2, [1, 2, 3])); | |
| 308 testArgumentError(() => list.fillRange(-1, 2)); | |
| 309 testArgumentError(() => list.fillRange(-1, 5)); | |
| 310 testArgumentError(() => list.fillRange(2, 5)); | |
| 311 testArgumentError(() => list.fillRange(4, 2)); | |
| 312 } | |
| 313 | |
| 314 void testTypedList(List list) { | |
| 315 testTypedLengthInvariantOperations(list); | |
| 316 testCannotChangeLength(list); | |
| 317 } | |
| 318 | |
| 319 void testFixedLengthList(List list) { | |
| 320 testLengthInvariantOperations(list); | |
| 321 testCannotChangeLength(list); | |
| 322 } | |
| 323 | |
| 324 void testCannotChangeLength(List list) { | |
| 325 isUnsupported(action()) { | |
| 326 Expect.throws(action, (e) => e is UnsupportedError); | |
| 327 } | |
| 328 | |
| 329 isUnsupported(() => list.add(0)); | |
| 330 isUnsupported(() => list.addAll([0])); | |
| 331 isUnsupported(() => list.removeLast()); | |
| 332 isUnsupported(() => list.insert(0, 1)); | |
| 333 isUnsupported(() => list.insertAll(0, [1])); | |
| 334 isUnsupported(() => list.clear()); | |
| 335 isUnsupported(() => list.remove(1)); | |
| 336 isUnsupported(() => list.removeAt(1)); | |
| 337 isUnsupported(() => list.removeRange(0, 1)); | |
| 338 isUnsupported(() => list.replaceRange(0, 1, [])); | |
| 339 } | |
| 340 | |
| 341 void testTypedGrowableList(List list) { | |
| 342 testLength(0, list); | |
| 343 // set length. | |
| 344 list.length = 4; | |
| 345 testLength(4, list); | |
| 346 | |
| 347 testTypedLengthInvariantOperations(list); | |
| 348 | |
| 349 testGrowableListOperations(list); | |
| 350 } | |
| 351 | |
| 352 void testGrowableList(List list) { | |
| 353 testLength(0, list); | |
| 354 // set length. | |
| 355 list.length = 4; | |
| 356 testLength(4, list); | |
| 357 | |
| 358 testLengthInvariantOperations(list); | |
| 359 | |
| 360 testGrowableListOperations(list); | |
| 361 } | |
| 362 | |
| 363 void testGrowableListOperations(List list) { | |
| 364 // add, removeLast. | |
| 365 list.clear(); | |
| 366 testLength(0, list); | |
| 367 list.add(4); | |
| 368 testLength(1, list); | |
| 369 Expect.equals(4, list.removeLast()); | |
| 370 testLength(0, list); | |
| 371 | |
| 372 for (int i = 0; i < 100; i++) { | |
| 373 list.add(i); | |
| 374 } | |
| 375 | |
| 376 Expect.equals(list.length, 100); | |
| 377 for (int i = 0; i < 100; i++) { | |
| 378 Expect.equals(i, list[i]); | |
| 379 } | |
| 380 | |
| 381 Expect.equals(17, list.indexOf(17)); | |
| 382 Expect.equals(17, list.lastIndexOf(17)); | |
| 383 Expect.equals(-1, list.indexOf(999)); | |
| 384 Expect.equals(-1, list.lastIndexOf(999)); | |
| 385 | |
| 386 Expect.equals(99, list.removeLast()); | |
| 387 testLength(99, list); | |
| 388 | |
| 389 // remove. | |
| 390 Expect.isTrue(list.remove(4)); | |
| 391 testLength(98, list); | |
| 392 Expect.isFalse(list.remove(4)); | |
| 393 testLength(98, list); | |
| 394 list.clear(); | |
| 395 testLength(0, list); | |
| 396 | |
| 397 list.add(4); | |
| 398 list.add(4); | |
| 399 testLength(2, list); | |
| 400 Expect.isTrue(list.remove(4)); | |
| 401 testLength(1, list); | |
| 402 Expect.isTrue(list.remove(4)); | |
| 403 testLength(0, list); | |
| 404 Expect.isFalse(list.remove(4)); | |
| 405 testLength(0, list); | |
| 406 | |
| 407 // removeWhere, retainWhere | |
| 408 for (int i = 0; i < 100; i++) { | |
| 409 list.add(i); | |
| 410 } | |
| 411 testLength(100, list); | |
| 412 list.removeWhere((int x) => x.isOdd); | |
| 413 testLength(50, list); | |
| 414 for (int i = 0; i < list.length; i++) { | |
| 415 Expect.isTrue(list[i].isEven); | |
| 416 } | |
| 417 list.retainWhere((int x) => (x % 3) == 0); | |
| 418 testLength(17, list); | |
| 419 for (int i = 0; i < list.length; i++) { | |
| 420 Expect.isTrue((list[i] % 6) == 0); | |
| 421 } | |
| 422 | |
| 423 // insert, remove, removeAt | |
| 424 list.clear(); | |
| 425 testLength(0, list); | |
| 426 | |
| 427 list.insert(0, 0); | |
| 428 Expect.listEquals([0], list); | |
| 429 | |
| 430 list.insert(0, 1); | |
| 431 Expect.listEquals([1, 0], list); | |
| 432 | |
| 433 list.insert(0, 2); | |
| 434 Expect.listEquals([2, 1, 0], list); | |
| 435 | |
| 436 Expect.isTrue(list.remove(1)); | |
| 437 Expect.listEquals([2, 0], list); | |
| 438 | |
| 439 list.insert(1, 1); | |
| 440 Expect.listEquals([2, 1, 0], list); | |
| 441 | |
| 442 list.removeAt(1); | |
| 443 Expect.listEquals([2, 0], list); | |
| 444 | |
| 445 list.removeAt(1); | |
| 446 Expect.listEquals([2], list); | |
| 447 | |
| 448 // insertAll | |
| 449 list.insertAll(0, [1, 2, 3]); | |
| 450 Expect.listEquals([1, 2, 3, 2], list); | |
| 451 | |
| 452 list.insertAll(2, []); | |
| 453 Expect.listEquals([1, 2, 3, 2], list); | |
| 454 | |
| 455 list.insertAll(4, [7, 9]); | |
| 456 Expect.listEquals([1, 2, 3, 2, 7, 9], list); | |
| 457 | |
| 458 // addAll | |
| 459 list.addAll(list.reversed.toList()); | |
| 460 Expect.listEquals([1, 2, 3, 2, 7, 9, 9, 7, 2, 3, 2, 1], list); | |
| 461 | |
| 462 list.addAll([]); | |
| 463 Expect.listEquals([1, 2, 3, 2, 7, 9, 9, 7, 2, 3, 2, 1], list); | |
| 464 | |
| 465 // replaceRange | |
| 466 list.replaceRange(3, 7, [0, 0]); | |
| 467 Expect.listEquals([1, 2, 3, 0, 0, 7, 2, 3, 2, 1], list); | |
| 468 | |
| 469 list.replaceRange(2, 3, [5, 5, 5]); | |
| 470 Expect.listEquals([1, 2, 5, 5, 5, 0, 0, 7, 2, 3, 2, 1], list); | |
| 471 | |
| 472 list.replaceRange(2, 4, [6, 6]); | |
| 473 Expect.listEquals([1, 2, 6, 6, 5, 0, 0, 7, 2, 3, 2, 1], list); | |
| 474 | |
| 475 list.replaceRange(6, 8, []); | |
| 476 Expect.listEquals([1, 2, 6, 6, 5, 0, 2, 3, 2, 1], list); | |
| 477 | |
| 478 // Operations that change the length cause ConcurrentModificationError. | |
| 479 void testConcurrentModification(action()) { | |
| 480 testIterator(int when) { | |
| 481 list.length = 4; | |
| 482 list.setAll(0, [0, 1, 2, 3]); | |
| 483 Expect.throws(() { | |
| 484 for (var element in list) { | |
| 485 if (element == when) action(); | |
| 486 } | |
| 487 }, (e) => e is ConcurrentModificationError); | |
| 488 } | |
| 489 | |
| 490 testForEach(int when) { | |
| 491 list.length = 4; | |
| 492 list.setAll(0, [0, 1, 2, 3]); | |
| 493 Expect.throws(() { | |
| 494 list.forEach((var element) { | |
| 495 if (element == when) action(); | |
| 496 }); | |
| 497 }, (e) => e is ConcurrentModificationError); | |
| 498 } | |
| 499 | |
| 500 // Test the change at different points of the iteration. | |
| 501 testIterator(0); | |
| 502 testIterator(1); | |
| 503 testIterator(3); | |
| 504 testForEach(0); | |
| 505 testForEach(1); | |
| 506 testForEach(3); | |
| 507 } | |
| 508 | |
| 509 testConcurrentModification(() => list.add(5)); | |
| 510 testConcurrentModification(() => list.addAll([5, 6])); | |
| 511 testConcurrentModification(() => list.removeLast()); | |
| 512 for (int i = 0; i < 4; i++) { | |
| 513 testConcurrentModification(() => list.remove(i)); | |
| 514 testConcurrentModification(() => list.removeAt(i)); | |
| 515 testConcurrentModification(() => list.removeWhere((x) => x == i)); | |
| 516 testConcurrentModification(() => list.retainWhere((x) => x != i)); | |
| 517 testConcurrentModification(() => list.insert(i, 5)); | |
| 518 testConcurrentModification(() => list.insertAll(i, [5, 6])); | |
| 519 testConcurrentModification(() => list.removeRange(i, i + 1)); | |
| 520 testConcurrentModification(() => list.replaceRange(i, i + 1, [5, 6])); | |
| 521 } | |
| 522 | |
| 523 // Any operation that doesn't change the length should be safe for iteration. | |
| 524 testSafeConcurrentModification(action()) { | |
| 525 list.length = 4; | |
| 526 list.setAll(0, [0, 1, 2, 3]); | |
| 527 for (var i in list) { | |
| 528 action(); | |
| 529 } | |
| 530 list.forEach((e) => action()); | |
| 531 } | |
| 532 | |
| 533 testSafeConcurrentModification(() { | |
| 534 list.add(5); | |
| 535 list.removeLast(); | |
| 536 }); | |
| 537 testSafeConcurrentModification(() { | |
| 538 list.add(list[0]); | |
| 539 list.removeAt(0); | |
| 540 }); | |
| 541 testSafeConcurrentModification(() { | |
| 542 list.insert(0, list.removeLast()); | |
| 543 }); | |
| 544 testSafeConcurrentModification(() { | |
| 545 list.replaceRange(1, 3, list.sublist(1, 3).reversed); | |
| 546 }); | |
| 547 | |
| 548 // Argument errors on bad indices for methods that are only allowed | |
| 549 // on growable lists. | |
| 550 list.length = 4; | |
| 551 list.setAll(0, [0, 1, 2, 3]); | |
| 552 testArgumentError(action()) { | |
| 553 Expect.throws(action, (e) => e is ArgumentError); | |
| 554 } | |
| 555 | |
| 556 // Direct indices (0 <= index < length). | |
| 557 testArgumentError(() => list.removeAt(-1)); | |
| 558 testArgumentError(() => list.removeAt(4)); | |
| 559 // Direct indices including end (0 <= index <= length). | |
| 560 testArgumentError(() => list.insert(-1, 0)); | |
| 561 testArgumentError(() => list.insert(5, 0)); | |
| 562 testArgumentError(() => list.insertAll(-1, [0])); | |
| 563 testArgumentError(() => list.insertAll(5, [0])); | |
| 564 testArgumentError(() => list.insertAll(-1, [0])); | |
| 565 testArgumentError(() => list.insertAll(5, [0])); | |
| 566 // Ranges (0 <= start <= end <= length). | |
| 567 testArgumentError(() => list.removeRange(-1, 2)); | |
| 568 testArgumentError(() => list.removeRange(2, 5)); | |
| 569 testArgumentError(() => list.removeRange(-1, 5)); | |
| 570 testArgumentError(() => list.removeRange(4, 2)); | |
| 571 testArgumentError(() => list.replaceRange(-1, 2, [9])); | |
| 572 testArgumentError(() => list.replaceRange(2, 5, [9])); | |
| 573 testArgumentError(() => list.replaceRange(-1, 5, [9])); | |
| 574 testArgumentError(() => list.replaceRange(4, 2, [9])); | |
| 575 } | |
| 576 | |
| 577 class Yes { | |
| 578 operator ==(var other) => true; | |
| 579 int get hashCode => 0; | |
| 580 } | |
| 581 | |
| 582 class MyList<E> extends ListBase<E> { | |
| 583 List<E> _source; | |
| 584 MyList(this._source); | |
| 585 int get length => _source.length; | |
| 586 void set length(int length) { | |
| 587 _source.length = length; | |
| 588 } | |
| 589 | |
| 590 E operator [](int index) => _source[index]; | |
| 591 void operator []=(int index, E value) { | |
| 592 _source[index] = value; | |
| 593 } | |
| 594 } | |
| 595 | |
| 596 class MyFixedList<E> extends ListBase<E> { | |
| 597 List<E> _source; | |
| 598 MyFixedList(this._source); | |
| 599 int get length => _source.length; | |
| 600 void set length(int length) { | |
| 601 throw new UnsupportedError("Fixed length!"); | |
| 602 } | |
| 603 | |
| 604 E operator [](int index) => _source[index]; | |
| 605 void operator []=(int index, E value) { | |
| 606 _source[index] = value; | |
| 607 } | |
| 608 } | |
| 609 | |
| 610 void testListConstructor() { | |
| 611 // Is fixed-length. | |
| 612 Expect.throws(() { | |
| 613 new List(0).add(4); | |
| 614 }); | |
| 615 Expect.throws(() { new List(-2); }); // Not negative. //# 01: ok | |
| 616 // Not null. | |
| 617 Expect.throws(() { | |
| 618 new List(null); | |
| 619 }); | |
| 620 Expect.listEquals([4], new List()..add(4)); | |
| 621 // Is fixed-length. | |
| 622 Expect.throws(() { | |
| 623 new List.filled(0, 42).add(4); | |
| 624 }); | |
| 625 // Not negative. | |
| 626 Expect.throws(() { | |
| 627 new List.filled(-2, 42); | |
| 628 }); | |
| 629 // Not null. | |
| 630 Expect.throws(() { | |
| 631 new List.filled(null, 42); | |
| 632 }); | |
| 633 } | |
| OLD | NEW |