mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
8a5e2a688b
Bug: https://github.com/dart-lang/sdk/issues/38575 Change-Id: I3f93488511519ac1dca04f91465efad3d2a0c66d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118886 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Aart Bik <ajcbik@google.com>
165 lines
4.7 KiB
Dart
165 lines
4.7 KiB
Dart
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// Sanity check on the growing behavior of a growable list.
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
void main() {
|
|
testConstructor();
|
|
// Concurrent modification checks are only guaranteed in checked mode.
|
|
testConcurrentModification();
|
|
}
|
|
|
|
// Iterable generating numbers in range [0..count).
|
|
// May perform callback at some point underways.
|
|
class TestIterableBase extends Iterable<int> {
|
|
final int length;
|
|
final int count;
|
|
// call [callback] if generating callbackIndex.
|
|
final int callbackIndex;
|
|
final Function callback;
|
|
TestIterableBase(this.length, this.count, this.callbackIndex, this.callback);
|
|
Iterator<int> get iterator => new CallbackIterator(this);
|
|
}
|
|
|
|
class TestIterable extends TestIterableBase {
|
|
TestIterable(count, [callbackIndex = -1, callback])
|
|
: super(-1, count, callbackIndex, callback);
|
|
int get length => throw "SHOULD NOT BE CALLED";
|
|
}
|
|
|
|
// Implement Set for private EfficientLengthIterable interface.
|
|
class EfficientTestIterable extends TestIterableBase implements Set<int> {
|
|
EfficientTestIterable(length, count, [callbackIndex = -1, callback])
|
|
: super(length, count, callbackIndex, callback);
|
|
// Avoid warnings because we don't actually implement Set.
|
|
noSuchMethod(i) => super.noSuchMethod(i);
|
|
Set<R> cast<R>() => throw "not used by test";
|
|
}
|
|
|
|
class CallbackIterator implements Iterator<int> {
|
|
TestIterableBase _iterable;
|
|
int _current = null;
|
|
int _nextIndex = 0;
|
|
CallbackIterator(this._iterable);
|
|
bool moveNext() {
|
|
if (_nextIndex >= _iterable.count) {
|
|
_current = null;
|
|
return false;
|
|
}
|
|
_current = _nextIndex;
|
|
_nextIndex++;
|
|
if (_current == _iterable.callbackIndex) {
|
|
_iterable.callback();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int get current => _current;
|
|
}
|
|
|
|
void testConstructor() {
|
|
// Constructor can make both growable and fixed-length lists.
|
|
testGrowable(list) {
|
|
Expect.isTrue(list is List<int>);
|
|
Expect.isFalse(list is List<String>);
|
|
int length = list.length;
|
|
list.add(42);
|
|
Expect.equals(list.length, length + 1);
|
|
}
|
|
|
|
testFixedLength(list) {
|
|
Expect.isTrue(list is List<int>);
|
|
int length = list.length;
|
|
Expect.throws(() {
|
|
list.add(42);
|
|
}, null, "adding to fixed-length list");
|
|
Expect.equals(length, list.length);
|
|
}
|
|
|
|
testThrowsOrTypeError(fn, [name]) {
|
|
Expect.throws(fn, null, name);
|
|
}
|
|
|
|
testFixedLength(new List<int>(0));
|
|
testFixedLength(new List<int>(5));
|
|
testFixedLength(new List<int>.filled(5, null)); // default growable: false.
|
|
testGrowable(new List<int>());
|
|
testGrowable(new List<int>()..length = 5);
|
|
testGrowable(new List<int>.filled(5, null, growable: true));
|
|
Expect.throwsArgumentError(() => new List<int>(-1), "-1");
|
|
// There must be limits. Fix this test if we ever allow 2^63 elements.
|
|
Expect.throws(() => new List<int>(0x7ffffffffffff000),
|
|
(e) => e is OutOfMemoryError || e is ArgumentError, "bignum");
|
|
Expect.throwsArgumentError(() => new List<int>(null), "null");
|
|
testThrowsOrTypeError(
|
|
() => new List([] as Object), // Cast to avoid warning.
|
|
'list');
|
|
testThrowsOrTypeError(() => new List([42] as Object), "list2");
|
|
}
|
|
|
|
void testConcurrentModification() {
|
|
// Without EfficientLengthIterable interface
|
|
{
|
|
// Change length of list after 200 additions.
|
|
var l = [];
|
|
var ci = new TestIterable(257, 200, () {
|
|
l.add("X");
|
|
});
|
|
Expect.throws(() {
|
|
l.addAll(ci);
|
|
}, (e) => e is ConcurrentModificationError, "cm1");
|
|
}
|
|
|
|
{
|
|
// Change length of list after 200 additions.
|
|
var l = [];
|
|
var ci = new TestIterable(257, 200, () {
|
|
l.length = 0;
|
|
});
|
|
Expect.throws(() {
|
|
l.addAll(ci);
|
|
}, (e) => e is ConcurrentModificationError, "cm2");
|
|
}
|
|
|
|
// With EfficientLengthIterable interface (uses length).
|
|
{
|
|
// Change length of list after 20 additions.
|
|
var l = [];
|
|
var ci = new EfficientTestIterable(257, 257, 20, () {
|
|
l.add("X");
|
|
});
|
|
Expect.throws(() {
|
|
l.addAll(ci);
|
|
}, (e) => e is ConcurrentModificationError, "cm3");
|
|
}
|
|
|
|
{
|
|
var l = [];
|
|
var ci = new EfficientTestIterable(257, 257, 20, () {
|
|
l.length = 0;
|
|
});
|
|
Expect.throws(() {
|
|
l.addAll(ci);
|
|
}, (e) => e is ConcurrentModificationError, "cm4");
|
|
}
|
|
|
|
{
|
|
// Length 500, only 250 elements.
|
|
var l = [];
|
|
var ci = new EfficientTestIterable(500, 250);
|
|
l.addAll(ci);
|
|
Expect.listEquals(new List.generate(250, (x) => x), l, "cm5");
|
|
}
|
|
|
|
{
|
|
// Length 250, but 500 elements.
|
|
var l = [];
|
|
var ci = new EfficientTestIterable(250, 500);
|
|
l.addAll(ci);
|
|
Expect.listEquals(new List.generate(500, (x) => x), l, "cm6");
|
|
}
|
|
}
|