// Copyright (c) 2014, 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 "package:expect/expect.dart"; import 'dart:collection'; import 'dart:typed_data'; class MyList extends ListBase { List list; MyList(this.list); get length => list.length; set length(val) { list.length = val; } operator [](index) => list[index]; operator []=(index, val) => list[index] = val; } Iterable id(Iterable x) => x; main() { // Test functionality. for (dynamic iterable in [ const [1, 2, 3], [1, 2, 3], new List(3) ..[0] = 1 ..[1] = 2 ..[2] = 3, {1: 1, 2: 2, 3: 3}.keys, {1: 1, 2: 2, 3: 3}.values, new Iterable.generate(3, (x) => x + 1), new List.generate(3, (x) => x + 1), [0, 1, 2, 3].where((x) => x > 0), [0, 1, 2].map((x) => x + 1), [ [1, 2], [3] ].expand(id), [3, 2, 1].reversed, [0, 1, 2, 3].skip(1), [1, 2, 3, 4].take(3), new Uint8List(3) ..[0] = 1 ..[1] = 2 ..[2] = 3, (new HashMap() ..[1] = 1 ..[2] = 2 ..[3] = 3) .keys, (new HashMap() ..[1] = 1 ..[2] = 2 ..[3] = 3) .values, (new SplayTreeMap() ..[1] = 0 ..[2] = 0 ..[3] = 0) .keys, (new SplayTreeMap() ..[0] = 1 ..[1] = 2 ..[2] = 3) .values, new HashSet()..add(1)..add(2)..add(3), new LinkedHashSet()..add(1)..add(2)..add(3), new SplayTreeSet()..add(1)..add(2)..add(3), "\x01\x02\x03".codeUnits, "\x01\x02\x03".runes, new MyList([1, 2, 3]), ]) { int callCount = 0; var result = iterable.reduce((x, y) { callCount++; // Return type of reduce() callback should match element type. return (x + y) as int; }); Expect.equals(6, result, "${iterable.runtimeType}"); Expect.equals(2, callCount); } // Empty iterables not allowed. for (var iterable in [ const [], [], new List(0), {}.keys, {}.values, new Iterable.generate(0, (x) => x + 1), new List.generate(0, (x) => x + 1), [0, 1, 2, 3].where((x) => false), [].map((x) => x + 1), [[], []].expand(id), [].reversed, [0, 1, 2, 3].skip(4), [1, 2, 3, 4].take(0), new Uint8List(0), (new HashMap()).keys, (new HashMap()).values, (new SplayTreeMap()).keys, (new SplayTreeMap()).values, new HashSet(), new LinkedHashSet(), new SplayTreeSet(), "".codeUnits, "".runes, new MyList([]), ]) { Expect .throwsStateError(() => iterable.reduce((x, y) => throw "Unreachable")); } // Singleton iterables not calling reduce function. for (dynamic iterable in [ const [1], [1], new List(1)..[0] = 1, {1: 1}.keys, {1: 1}.values, new Iterable.generate(1, (x) => x + 1), new List.generate(1, (x) => x + 1), [0, 1, 2, 3].where((x) => x == 1), [0].map((x) => x + 1), [ [], [1] ].expand(id), [1].reversed, [0, 1].skip(1), [1, 2, 3, 4].take(1), new Uint8List(1)..[0] = 1, (new HashMap()..[1] = 0).keys, (new HashMap()..[0] = 1).values, (new SplayTreeMap()..[1] = 0).keys, (new SplayTreeMap()..[0] = 1).values, new HashSet()..add(1), new LinkedHashSet()..add(1), new SplayTreeSet()..add(1), "\x01".codeUnits, "\x01".runes, new MyList([1]), ]) { Expect.equals(1, iterable.reduce((x, y) => throw "Unreachable")); } // Concurrent modifications not allowed. testModification(base, modify, transform) { var iterable = transform(base); Expect.throws(() { iterable.reduce((x, y) { modify(base); // Return type of reduce() callback should match element type. return (x + y) as int; }); }, (e) => e is ConcurrentModificationError); } void add4(collection) { collection.add(4); } void addListOf4(collection) { collection.add([4]); } void put4(map) { map[4] = 4; } testModification([1, 2, 3], add4, id); testModification(new HashSet()..add(1)..add(2)..add(3), add4, id); testModification(new LinkedHashSet()..add(1)..add(2)..add(3), add4, id); testModification(new SplayTreeSet()..add(1)..add(2)..add(3), add4, id); testModification(new MyList([1, 2, 3]), add4, id); testModification([0, 1, 2, 3], add4, (x) => x.where((int x) => x > 0)); testModification([0, 1, 2], add4, (x) => x.map((x) => x + 1)); testModification([ [1, 2], [3] ], addListOf4, (x) => x.expand((List x) => x)); testModification([3, 2, 1], add4, (x) => x.reversed); testModification({1: 1, 2: 2, 3: 3}, put4, (x) => x.keys); testModification({1: 1, 2: 2, 3: 3}, put4, (x) => x.values); var hashMap = new HashMap() ..[1] = 1 ..[2] = 2 ..[3] = 3; testModification(hashMap, put4, (x) => x.keys); hashMap = new HashMap() ..[1] = 1 ..[2] = 2 ..[3] = 3; testModification(hashMap, put4, (x) => x.values); var splayMap = new SplayTreeMap() ..[1] = 1 ..[2] = 2 ..[3] = 3; testModification(splayMap, put4, (x) => x.keys); splayMap = new SplayTreeMap() ..[1] = 1 ..[2] = 2 ..[3] = 3; testModification(splayMap, put4, (x) => x.values); }