// 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"); } var hasNext = it.moveNext(); Expect.isFalse(hasNext, "$name: extra element at ${expects.length}: ${hasNext ? it.current : ''}"); } on Error { print("Failed during: $name"); rethrow; } } // Tests various operations on the a followedBy iterable. tests(List expects, Iterable 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 first, List second, String name) { var conversions = Function(List)>{ "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 toConst(List elements) => elements; List toList(List elements) => elements.toList(); List toUnmodifiable(List elements) => new List.unmodifiable(elements); Set toSet(List elements) => elements.toSet(); Queue toQueue(List elements) => new Queue.from(elements); // Creates an efficient-length iterable. Iterable toELIter(List elements) => elements.map((x) => x); // Creates a non-efficient-length iterable. Iterable toNEIter(List elements) => elements.where((x) => true); List toTyped(List elements) => new Int32List.fromList(elements); Iterable toKeys(List elements) => new Map.fromIterables(elements, elements).keys; Iterable toValues(List elements) => new Map.fromIterables(elements, elements).values; main() { types([], const [], const [], "0+0"); types([1, 2, 3, 4], const [], const [1, 2, 3, 4], "0+4"); types([1, 2, 3, 4], const [1, 2], const [3, 4], "2+2"); types([1, 2, 3, 4], const [1, 2, 3, 4], const [], "4+0"); }