blob: 5edf0e3e2232369614969c19b97e8873265ee531 [file] [log] [blame]
// Copyright (c) 2018, 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.
import "dart:collection" show Queue;
import "dart:typed_data" show Int32List;
import "package:expect/expect.dart";
// Tests behavior of result of an operation on a followedBy iterable.
test(List expects, Iterable iterable, [String name]) {
try {
Expect.isFalse(iterable is List, "$name is! List");
Expect.isFalse(iterable is Set, "$name is! Set");
Expect.isFalse(iterable is Queue, "$name is! Queue");
if (expects.isNotEmpty) {
Expect.equals(expects.first, iterable.first, "$name: first");
Expect.equals(expects.last, iterable.last, "$name: last");
} else {
Expect.throwsStateError(() => iterable.first, "$name: first");
Expect.throwsStateError(() => iterable.last, "$name: last");
}
var it = iterable.iterator;
for (int index = 0; index < expects.length; index++) {
Expect.isTrue(it.moveNext(), "$name: has element $index");
var expect = expects[index];
Expect.equals(expect, it.current, "$name at $index");
Expect.equals(
expect, iterable.elementAt(index), "$name: elementAt($index)");
Expect.isTrue(iterable.contains(expect), "$name:contains $index");
}
Expect.isFalse(it.moveNext(),
"$name: extra element at ${expects.length}: ${it.current}");
} on Error {
print("Failed during: $name");
rethrow;
}
}
// Tests various operations on the a followedBy iterable.
tests(List<int> expects, Iterable<int> follow, [String name]) {
int length = expects.length;
test(expects, follow, name);
for (int i = 0; i <= length; i++) {
test(expects.sublist(i), follow.skip(i), "$name.skip($i)");
}
for (int i = 0; i <= length; i++) {
test(expects.sublist(0, i), follow.take(i), "$name.take($i)");
}
for (int i = 0; i <= length; i++) {
for (int j = 0; j <= length - i; j++) {
test(expects.sublist(i, i + j), follow.skip(i).take(j),
"$name.skiptake($i,${i+j})");
test(expects.sublist(i, i + j), follow.take(i + j).skip(i),
"$name.takeskip($i,${i+j})");
}
}
}
// Tests various different types of iterables as first and second operand.
types(List expects, List<int> first, List<int> second, [String name]) {
var conversions = <String, Iterable<int> Function(List<int>)>{
"const": toConst,
"list": toList,
"unmod": toUnmodifiable,
"set": toSet,
"queue": toQueue,
"eff-len-iter": toELIter,
"non-eff-iter": toNEIter,
"typed": toTyped,
"keys": toKeys,
"values": toValues,
};
conversions.forEach((n1, c1) {
conversions.forEach((n2, c2) {
tests(expects, c1(first).followedBy(c2(second)), "$name:$n1/$n2");
});
});
}
List<int> toConst(List<int> elements) => elements;
List<int> toList(List<int> elements) => elements.toList();
List<int> toUnmodifiable(List<int> elements) =>
new List<int>.unmodifiable(elements);
Set<int> toSet(List<int> elements) => elements.toSet();
Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
// Creates an efficient-length iterable.
Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
// Creates a non-efficient-length iterable.
Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
Iterable<int> toKeys(List<int> elements) =>
new Map<int, int>.fromIterables(elements, elements).keys;
Iterable<int> toValues(List<int> elements) =>
new Map<int, int>.fromIterables(elements, elements).values;
main() {
types(<int>[], const <int>[], const <int>[], "0+0");
types(<int>[1, 2, 3, 4], const <int>[], const <int>[1, 2, 3, 4], "0+4");
types(<int>[1, 2, 3, 4], const <int>[1, 2], const <int>[3, 4], "2+2");
types(<int>[1, 2, 3, 4], const <int>[1, 2, 3, 4], const <int>[], "4+0");
}