blob: 55d2a125776acb850374f8f8dea44da10f4d7b8a [file]
// Copyright (c) 2025, 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:collection/collection.dart';
import 'package:test/test.dart';
void main() {
group('Iterable.separated', () {
group('empty', () {
test('', () {
expectIterable(iterable(<int>[]).separated(42), <int>[]);
});
test('before', () {
expectIterable(iterable(<int>[]).separated(42, before: true), <int>[]);
});
test('after', () {
expectIterable(iterable(<int>[]).separated(42, after: true), <int>[]);
});
test('before and after', () {
expectIterable(
iterable(<int>[]).separated(42, before: true, after: true),
<int>[]);
});
test('List', () {
var separatedList = iterable(<int>[]).separated(42);
expect(separatedList, isNot(isA<List>()));
expectIterable(separatedList, <int>[]);
});
});
group('Singleton', () {
test('', () {
expectIterable(iterable(<int>[1]).separated(42), [1]);
});
test('before', () {
expectIterable(iterable(<int>[1]).separated(42, before: true), [42, 1]);
});
test('after', () {
expectIterable(iterable(<int>[1]).separated(42, after: true), [1, 42]);
});
test('before and after', () {
expectIterable(
iterable(<int>[1]).separated(42, before: true, after: true),
[42, 1, 42]);
});
test('List', () {
var separatedList = iterable(<int>[1]).separated(42);
expect(separatedList, isNot(isA<List>()));
expectIterable(separatedList, [1]);
});
});
group('Multiple', () {
test('', () {
expectIterable(
iterable(<int>[1, 2, 3]).separated(42), [1, 42, 2, 42, 3]);
});
test('before', () {
expectIterable(iterable(<int>[1, 2, 3]).separated(42, before: true),
[42, 1, 42, 2, 42, 3]);
});
test('after', () {
expectIterable(iterable(<int>[1, 2, 3]).separated(42, after: true),
[1, 42, 2, 42, 3, 42]);
});
test('before and after', () {
expectIterable(
iterable(<int>[1, 2, 3]).separated(42, before: true, after: true),
[42, 1, 42, 2, 42, 3, 42]);
});
});
test('nulls', () {
expectIterable(iterable<int?>([null, 2, null]).separated(null),
[null, null, 2, null, null]);
});
test('upcast receiver', () {
var source = <int>[1, 2, 3];
expectIterable(
iterable<num>(source).separated(3.14), [1, 3.14, 2, 3.14, 3]);
});
});
// ------------------------------------------------------------------
group('List.separated', () {
group('empty', () {
test('', () {
expectUnmodifiableList(<int>[].separated(42), <int>[], 0);
});
test('before', () {
expectUnmodifiableList(<int>[].separated(42, before: true), <int>[], 0);
});
test('after', () {
expectUnmodifiableList(<int>[].separated(42, after: true), <int>[], 0);
});
test('before and after', () {
expectUnmodifiableList(
<int>[].separated(42, before: true, after: true), <int>[], 0);
});
test('List', () {
var separatedList = <int>[].separated(42);
expect(separatedList, isA<List>());
expectUnmodifiableList(separatedList, <int>[], 0);
});
});
group('Singleton', () {
test('', () {
expectUnmodifiableList(<int>[1].separated(42), [1], 0);
});
test('before', () {
expectUnmodifiableList(
<int>[1].separated(42, before: true), [42, 1], 0);
});
test('after', () {
expectUnmodifiableList(<int>[1].separated(42, after: true), [1, 42], 0);
});
test('before and after', () {
expectUnmodifiableList(
<int>[1].separated(42, before: true, after: true), [42, 1, 42], 0);
});
test('List', () {
var separatedList = <int>[1].separated(42);
expect(separatedList, isA<List>());
expectUnmodifiableList(separatedList, [1], 0);
});
});
group('Multiple', () {
test('', () {
expectUnmodifiableList(
<int>[1, 2, 3].separated(42), [1, 42, 2, 42, 3], 0);
});
test('before', () {
expectUnmodifiableList(<int>[1, 2, 3].separated(42, before: true),
[42, 1, 42, 2, 42, 3], 0);
});
test('after', () {
expectUnmodifiableList(<int>[1, 2, 3].separated(42, after: true),
[1, 42, 2, 42, 3, 42], 0);
});
test('before and after', () {
expectUnmodifiableList(
<int>[1, 2, 3].separated(42, before: true, after: true),
[42, 1, 42, 2, 42, 3, 42],
0);
});
test('List', () {
var separatedList = <int>[1, 2, 3].separated(42);
expect(separatedList, isA<List>());
expectUnmodifiableList(separatedList, [1, 42, 2, 42, 3], 0);
});
});
test('nulls', () {
expectUnmodifiableList(
[null, 2, null].separated(null), [null, null, 2, null, null], 0);
});
test('upcast receiver', () {
var source = <int>[1, 2, 3];
expectUnmodifiableList(
(source as List<num>).separated(3.14), [1, 3.14, 2, 3.14, 3], 0);
});
});
// ------------------------------------------------------------------
group('Iterable.separatedList', () {
group('empty', () {
test('', () {
expect(iterable(<int>[]).separatedList(42), <int>[]);
});
test('before', () {
expect(iterable(<int>[]).separatedList(42, before: true), <int>[]);
});
test('after', () {
expect(iterable(<int>[]).separatedList(42, after: true), <int>[]);
});
test('before and after', () {
expect(iterable(<int>[]).separatedList(42, before: true, after: true),
<int>[]);
});
});
group('Singleton', () {
test('', () {
expect(iterable(<int>[1]).separatedList(42), [1]);
});
test('before', () {
expect(iterable(<int>[1]).separatedList(42, before: true), [42, 1]);
});
test('after', () {
expect(iterable(<int>[1]).separatedList(42, after: true), [1, 42]);
});
test('before and after', () {
expect(iterable(<int>[1]).separatedList(42, before: true, after: true),
[42, 1, 42]);
});
});
group('Multiple', () {
test('', () {
expect(iterable(<int>[1, 2, 3]).separatedList(42), [1, 42, 2, 42, 3]);
});
test('before', () {
expect(iterable(<int>[1, 2, 3]).separatedList(42, before: true),
[42, 1, 42, 2, 42, 3]);
});
test('after', () {
expect(iterable(<int>[1, 2, 3]).separatedList(42, after: true),
[1, 42, 2, 42, 3, 42]);
});
test('before and after', () {
expect(
iterable(<int>[1, 2, 3])
.separatedList(42, before: true, after: true),
[42, 1, 42, 2, 42, 3, 42]);
});
});
test('nulls', () {
expect(iterable<int?>([null, 2, null]).separatedList(null),
[null, null, 2, null, null]);
});
test('upcast receiver', () {
var source = <int>[1, 2, 3];
expect(iterable<num>(source).separatedList(3.14), [1, 3.14, 2, 3.14, 3]);
});
});
// ------------------------------------------------------------------
group('List.separatedList', () {
group('empty', () {
test('', () {
expect(<int>[].separatedList(42), <int>[]);
});
test('before', () {
expect(<int>[].separatedList(42, before: true), <int>[]);
});
test('after', () {
expect(<int>[].separatedList(42, after: true), <int>[]);
});
test('before and after', () {
expect(<int>[].separatedList(42, before: true, after: true), <int>[]);
});
});
group('Singleton', () {
test('', () {
expect(<int>[1].separatedList(42), [1]);
});
test('before', () {
expect(<int>[1].separatedList(42, before: true), [42, 1]);
});
test('after', () {
expect(<int>[1].separatedList(42, after: true), [1, 42]);
});
test('before and after', () {
expect(
<int>[1].separatedList(42, before: true, after: true), [42, 1, 42]);
});
});
group('Multiple', () {
test('', () {
expect(<int>[1, 2, 3].separatedList(42), [1, 42, 2, 42, 3]);
});
test('before', () {
expect(<int>[1, 2, 3].separatedList(42, before: true),
[42, 1, 42, 2, 42, 3]);
});
test('after', () {
expect(<int>[1, 2, 3].separatedList(42, after: true),
[1, 42, 2, 42, 3, 42]);
});
test('before and after', () {
expect(<int>[1, 2, 3].separatedList(42, before: true, after: true),
[42, 1, 42, 2, 42, 3, 42]);
});
});
test('nulls', () {
expect([null, 2, null].separatedList(null), [null, null, 2, null, null]);
});
test('upcast receiver', () {
var source = <int>[1, 2, 3];
expect((source as List<num>).separatedList(3.14), [1, 3.14, 2, 3.14, 3]);
});
});
// ------------------------------------------------------------------
group('List.separate', () {
group('empty', () {
test('', () {
expectList(<int>[]..separate(42), <int>[]);
});
test('before', () {
expectList(<int>[]..separate(42, before: true), <int>[]);
});
test('after', () {
expectList(<int>[]..separate(42, after: true), <int>[]);
});
test('before and after', () {
expectList(<int>[]..separate(42, before: true, after: true), <int>[]);
});
});
group('Singleton', () {
test('', () {
expectList(<int>[1]..separate(42), [1]);
});
test('before', () {
expectList(<int>[1]..separate(42, before: true), [42, 1]);
});
test('after', () {
expectList(<int>[1]..separate(42, after: true), [1, 42]);
});
test('before and after', () {
expectList(
<int>[1]..separate(42, before: true, after: true), [42, 1, 42]);
});
});
group('Multiple', () {
group('odd length', () {
test('', () {
expectList(<int>[1, 2, 3]..separate(42), [1, 42, 2, 42, 3]);
});
test('before', () {
expectList(<int>[1, 2, 3]..separate(42, before: true),
[42, 1, 42, 2, 42, 3]);
});
test('after', () {
expectList(
<int>[1, 2, 3]..separate(42, after: true), [1, 42, 2, 42, 3, 42]);
});
test('before and after', () {
expectList(<int>[1, 2, 3]..separate(42, before: true, after: true),
[42, 1, 42, 2, 42, 3, 42]);
});
});
group('even length', () {
test('', () {
expectList(<int>[1, 2, 3, 4]..separate(42), [1, 42, 2, 42, 3, 42, 4]);
});
test('before', () {
expectList(<int>[1, 2, 3, 4]..separate(42, before: true),
[42, 1, 42, 2, 42, 3, 42, 4]);
});
test('after', () {
expectList(<int>[1, 2, 3, 4]..separate(42, after: true),
[1, 42, 2, 42, 3, 42, 4, 42]);
});
test('before and after', () {
expectList(<int>[1, 2, 3, 4]..separate(42, before: true, after: true),
[42, 1, 42, 2, 42, 3, 42, 4, 42]);
});
});
});
test('nulls', () {
expectList([null, 2, null]..separate(null), [null, null, 2, null, null]);
});
test('upcast receiver throws', () {
// Modifying the list is a contravariant operation,
// throws if separator is not valid.
var source = <int>[1, 2, 3];
expect(() => (source as List<num>).separate(3.14),
throwsA(isA<TypeError>()));
});
test('upcast receiver succeeds if separator valid', () {
// Modifying the list is a contravariant operation,
// succeeds if the separator is a valid value.
// (All operations are read/write with existing elements
// or the separator, which works when upcast if values are valid.)
var source = <int>[1, 2, 3];
expectList((source as List<num>)..separate(42), [1, 42, 2, 42, 3]);
});
});
}
/// Creates a plain iterable not implementing any other class.
Iterable<T> iterable<T>(Iterable<T> values) sync* {
yield* values;
}
void expectIterable<T>(Iterable<T> actual, List<T> expected) {
expect(actual, expected); // Elements are correct, uses `iterator`.
// Specialized members should work.
expect(actual.length, expected.length);
for (var i = 0; i < expected.length; i++) {
expect(actual.isEmpty, expected.isEmpty);
expect(actual.isNotEmpty, expected.isNotEmpty);
expect(actual.elementAt(i), expected[i]);
expect(actual.skip(i), expected.sublist(i));
expect(actual.take(i), expected.sublist(0, i));
}
expect(() => actual.elementAt(actual.length), throwsRangeError);
expect(() => actual.elementAt(-1), throwsRangeError);
if (expected.isNotEmpty) {
expect(actual.first, expected.first, reason: 'first');
expect(actual.last, expected.last, reason: 'last');
} else {
expect(() => actual.first, throwsStateError, reason: 'first');
expect(() => actual.last, throwsStateError, reason: 'last');
}
}
void expectList<T>(List<T> actual, List<T> expected) {
expectIterable(actual, expected);
for (var i = 0; i < expected.length; i++) {
expect(actual[i], expected[i]);
}
expect(() => actual[actual.length], throwsRangeError);
expect(() => actual[-1], throwsRangeError);
}
void expectUnmodifiableList<T>(List<T> actual, List<T> expected, T value) {
expectList(actual, expected);
expect(() => actual.length = 0, throwsUnsupportedError);
expect(() => actual.add(value), throwsUnsupportedError);
expect(() => actual.addAll([]), throwsUnsupportedError);
expect(() => actual.clear(), throwsUnsupportedError);
expect(() => actual.fillRange(0, 0, value), throwsUnsupportedError);
expect(() => actual.remove(0), throwsUnsupportedError);
expect(() => actual.removeAt(0), throwsUnsupportedError);
expect(() => actual.removeLast(), throwsUnsupportedError);
expect(() => actual.removeRange(0, 0), throwsUnsupportedError);
expect(() => actual.removeWhere((_) => false), throwsUnsupportedError);
expect(() => actual.replaceRange(0, 0, []), throwsUnsupportedError);
expect(() => actual.retainWhere((_) => true), throwsUnsupportedError);
expect(() => actual.setAll(0, []), throwsUnsupportedError);
expect(() => actual.setRange(0, 0, []), throwsUnsupportedError);
expect(() => actual.sort((a, b) => 0), throwsUnsupportedError);
}