// 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. import "dart:collection"; import "dart:typed_data"; import "package:expect/expect.dart"; void main() { testIterable(); testList(); } final elements = [c, d, e, f, null]; void testIterable() { var iterable = new Iterable.generate(elements.length, (n) => elements[n]); // Down-cast { // An iterable that (likely) can do direct access. var dIterable = Iterable.castFrom(iterable); Expect.throws(() => dIterable.first, null, "1.first"); Expect.equals(d, dIterable.elementAt(1)); Expect.throws(() => dIterable.elementAt(2), null, "1.2"); // E is not D. Expect.equals(f, dIterable.skip(3).first); // Skip does not access element. Expect.equals(null, dIterable.skip(3).elementAt(1)); Expect.throws(() => dIterable.toList(), null, "1.toList"); } { // An iterable that cannot do direct access. var dIterable2 = Iterable.castFrom(iterable.where((_) => true)); Expect.throws(() => dIterable2.first, null, "2.first"); Expect.equals(d, dIterable2.elementAt(1)); Expect.throws(() => dIterable2.elementAt(2), null, "2.2"); // E is not D. Expect.equals(f, dIterable2.skip(3).first); // Skip does not access element. Expect.equals(null, dIterable2.skip(3).elementAt(1)); Expect.throws(() => dIterable2.toList(), null, "2.toList"); } { // Iterable that definitely won't survive accessing element 2. var iterable3 = new Iterable.generate( elements.length, (n) => n == 3 ? throw "untouchable" : elements[n]); var dIterable3 = Iterable.castFrom(iterable3); Expect.throws(() => dIterable3.first, null, "3.first"); Expect.equals(d, dIterable3.elementAt(1)); Expect.throws(() => dIterable3.elementAt(3), null, "3.3"); // Skip does not access element. Expect.equals(null, dIterable3.skip(4).first); Expect.equals(null, dIterable3.skip(3).elementAt(1)); Expect.throws(() => dIterable3.toList(), null, "3.toList"); } // Up-cast. { var oIterable4 = Iterable.castFrom(iterable); Expect.listEquals(elements, oIterable4.toList()); } } void testList() { // Down-cast. var list = new List.from(elements); var dList = List.castFrom(list); Expect.throws(() => dList.first); // C is not D. Expect.equals(d, dList[1]); Expect.throws(() => dList[2]); // E is not D. Expect.equals(f, dList[3]); Expect.equals(null, dList.last); Expect.throws(() => dList.toList()); dList[2] = d; Expect.equals(d, dList[2]); // Setting works. // Up-cast. var list2 = new List.from(elements); var dList2 = List.castFrom(list2); Expect.listEquals(elements, dList2); Expect.throws(() => dList2[2] = new Object()); // Cannot set non-C. Expect.listEquals(elements, dList2); // Regression test. var list3 = [4, 3, 2, 1]; var dList3 = list3.cast(); dList3.sort(null); Expect.listEquals([1, 2, 3, 4], list3); } void testSet() { var set = new Set.from(elements); // Linked HashSet. Expect.listEquals(elements, set.toList()); // Preserves order. var dSet = Set.castFrom(set); // Preserves order. Expect.throws(() => dSet.first); // C is not D. Expect.equals(d, dSet.elementAt(1)); Expect.throws(() => dSet.elementAt(2)); // E is not D. Expect.throws(() => dSet.toList()); // Contains is not typed. var newC = new C(); Expect.isFalse(dSet.contains(newC)); dSet.add(newC); Expect.isTrue(dSet.contains(newC)); Expect.equals(5, dSet.length); dSet.remove(newC); Expect.equals(5, dSet.length); dSet.remove(c); // Success, no type checks. Expect.equals(4, dSet.length); // Up-cast var set2 = new Set.from(elements); var dSet2 = Set.castFrom(set2); var newObject = new Object(); Expect.throws(() => dSet2.add(newObject)); Expect.isFalse(dSet.contains(newObject)); var toSet2 = dSet2.toSet(); Expect.isTrue(toSet2 is LinkedHashSet); Expect.isTrue(toSet2 is! LinkedHashSet); // Custom emptySet. var set3 = new Set.from(elements); var dSet3 = Set.castFrom(set3, newSet: () => new HashSet()); var toSet3 = dSet3.toSet(); Expect.isTrue(toSet3 is HashSet); Expect.isTrue(toSet3 is HashSet); Expect.isTrue(toSet3 is! LinkedHashSet); } void testMap() { var map = new Map.fromIterables(elements, elements); var dMap = Map.castFrom(map); Expect.isTrue(dMap is Map); Expect.equals(null, dMap[new C()]); Expect.throws(() => dMap[c]); Expect.isTrue(dMap.containsKey(c)); Expect.equals(d, dMap[d]); Expect.throws(() => dMap[e]); Expect.equals(null, dMap[null]); Expect.equals(5, dMap.length); dMap.remove(c); // Success, no type checks along the way. Expect.equals(4, dMap.length); Expect.equals(null, dMap[c]); Expect.throws(() => dMap[c] = d); Expect.throws(() => dMap[d] = c); Expect.equals(4, dMap.length); Expect.isTrue(dMap.keys is Iterable); Expect.isTrue(dMap.values is Iterable); Expect.throws(() => dMap.keys.toList()); Expect.throws(() => dMap.values.toList()); } class C {} class D extends C {} class E extends C {} class F implements D, E {} final c = new C(); final d = new D(); final e = new E(); final f = new F();