blob: e2e99fd7fc69b31f6afa10ee7885da38766548cd [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. 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:math' show Random;
import 'package:sledge/src/document/leaf_value.dart'; // ignore: implementation_imports
import 'package:test/test.dart';
import '../dummies/dummy_value_observer.dart';
// methods: removeWhere, retainWhere, sort, shuffle are not tested.
/// Generic class, to test if [TestingList] correctly implements List API.
class ListApiTester<TestingList extends List, E> {
List<E> Function() _newList;
E Function(int id) _newElement;
ListApiTester(this._newList, this._newElement);
/// Tests List API implementation.
void testApi() {
test('length', () {
final list = _newList();
expect(list.length, equals(0));
list.add(_newElement(0));
expect(list.length, equals(1));
list.insert(0, _newElement(1));
expect(list.length, equals(2));
list.removeAt(0);
expect(list.length, equals(1));
});
test('reversed', () {
final list = _newList();
expect(list.toList(), equals([]));
list
..add(_newElement(0))
..add(_newElement(2))
..add(_newElement(1))
..add(_newElement(3));
expect(
list.toList(),
equals([
_newElement(0),
_newElement(2),
_newElement(1),
_newElement(3)
]));
expect(
list.reversed.toList(),
equals([
_newElement(3),
_newElement(1),
_newElement(2),
_newElement(0)
]));
});
test('first', () {
final list = _newList();
expect(() => list.first, throwsStateError);
list.add(_newElement(2));
expect(list.first, equals(_newElement(2)));
list.insert(0, _newElement(4));
expect(list.first, equals(_newElement(4)));
list.add(_newElement(3));
expect(list.first, equals(_newElement(4)));
});
test('hashCode', () {
_newList().hashCode;
});
test('isEmpty', () {
final list = _newList();
expect(list.isEmpty, isTrue);
list.insert(0, _newElement(1));
expect(list.isEmpty, isFalse);
list.removeAt(0);
expect(list.isEmpty, isTrue);
});
test('isNotEmpty', () {
final list = _newList();
expect(list.isNotEmpty, isFalse);
list.insert(0, _newElement(1));
expect(list.isNotEmpty, isTrue);
});
test('last', () {
final list = _newList();
expect(() => list.last, throwsStateError);
list.add(_newElement(2));
expect(list.last, equals(_newElement(2)));
list.insert(0, _newElement(4));
expect(list.last, equals(_newElement(2)));
list.add(_newElement(3));
expect(list.last, equals(_newElement(3)));
});
test('single', () {
final list = _newList();
expect(() => list.single, throwsStateError);
list.add(_newElement(2));
expect(list.single, equals(_newElement(2)));
list.add(_newElement(3));
expect(() => list.single, throwsStateError);
list.removeAt(0);
expect(list.single, equals(_newElement(3)));
});
test('operator []', () {
final list = _newList();
expect(() => list[0], throwsRangeError);
list.add(_newElement(1));
expect(list[0], equals(_newElement(1)));
expect(() => list[1], throwsRangeError);
expect(() => list[-1], throwsRangeError);
list.add(_newElement(2));
expect(list[0], equals(_newElement(1)));
expect(list[1], equals(_newElement(2)));
});
test('operator []=', () {
final list = _newList();
expect(() => list[0] = _newElement(1), throwsRangeError);
list.add(_newElement(2));
list[0] = _newElement(3);
expect(list[0], equals(_newElement(3)));
expect(() => list[1] = _newElement(2), throwsRangeError);
expect(() => list[2] = _newElement(2), throwsRangeError);
expect(() => list[-1] = _newElement(2), throwsRangeError);
list.add(_newElement(4));
list[0] = _newElement(1);
list[1] = _newElement(-1);
expect(list, equals([_newElement(1), _newElement(-1)]));
});
test('add()', () {
final list = _newList()
..add(_newElement(2))
..add(_newElement(1))
..add(_newElement(4));
expect(list, equals([_newElement(2), _newElement(1), _newElement(4)]));
});
test('addAll()', () {
final list = _newList()
..addAll([_newElement(1), _newElement(2), _newElement(3)])
..addAll([_newElement(4)])
..addAll([_newElement(5), _newElement(6), _newElement(7)]);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(5),
_newElement(6),
_newElement(7)
]));
});
test('asMap()', () {
final list = _newList()
..addAll(
[_newElement(1), _newElement(2), _newElement(4), _newElement(3)]);
final map = list.asMap();
expect(map[0], equals(_newElement(1)));
expect(map[1], equals(_newElement(2)));
expect(map[2], equals(_newElement(4)));
expect(map[3], equals(_newElement(3)));
expect(map.length, equals(4));
});
test('clear()', () {
final list = _newList()
..addAll(
[_newElement(1), _newElement(2), _newElement(3), _newElement(4)])
..clear();
expect(list, equals([]));
list.addAll([_newElement(1), _newElement(2)]);
expect(list, equals([_newElement(1), _newElement(2)]));
});
test('fillRange()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(5),
_newElement(6)
])
..fillRange(2, 4, _newElement(-1));
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(-1),
_newElement(-1),
_newElement(5),
_newElement(6)
]));
expect(() => list.fillRange(-1, 2, _newElement(2)), throwsRangeError);
expect(() => list.fillRange(3, 7, _newElement(2)), throwsRangeError);
list.fillRange(3, 6, _newElement(5));
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(-1),
_newElement(5),
_newElement(5),
_newElement(5)
]));
list.fillRange(0, 6, _newElement(3));
expect(
list,
equals([
_newElement(3),
_newElement(3),
_newElement(3),
_newElement(3),
_newElement(3),
_newElement(3)
]));
});
test('getRange()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(5),
_newElement(6)
]);
expect(() => list.getRange(4, 7), throwsRangeError);
expect(list.getRange(2, 4).toList(),
equals([_newElement(3), _newElement(4)]));
expect(
list.getRange(0, 6).toList(),
equals([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(5),
_newElement(6)
]));
});
test('indexOf()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]);
expect(list.indexOf(_newElement(2)), 1);
expect(list.indexOf(_newElement(4)), 3);
expect(list.indexOf(_newElement(2), 3), 5);
expect(list.indexOf(_newElement(4), 4), -1);
expect(list.indexOf(_newElement(5)), -1);
});
test('insert()', () {
final list = _newList();
expect(() => list.insert(-1, _newElement(0)), throwsRangeError);
expect(() => list.insert(1, _newElement(0)), throwsRangeError);
list
..insert(0, _newElement(5))
..insert(1, _newElement(4))
..insert(0, _newElement(3));
expect(list, equals([_newElement(3), _newElement(5), _newElement(4)]));
expect(() => list.insert(4, _newElement(1)), throwsRangeError);
});
test('insertAll()', () {
final list = _newList();
expect(() => list.insertAll(-1, []), throwsRangeError);
expect(() => list.insertAll(1, []), throwsRangeError);
list.insertAll(
0, [_newElement(1), _newElement(3), _newElement(4), _newElement(2)]);
expect(
list,
equals(<E>[]..insertAll(0, [
_newElement(1),
_newElement(3),
_newElement(4),
_newElement(2)
])));
list.insertAll(1, [_newElement(1), _newElement(2)]);
expect(
list,
equals([
_newElement(1),
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(2)
]));
});
test('lastIndexOf()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]);
expect(list.lastIndexOf(_newElement(2)), 5);
expect(list.lastIndexOf(_newElement(4)), 3);
expect(list.lastIndexOf(_newElement(2), 3), 1);
expect(list.lastIndexOf(_newElement(4), 4), 3);
expect(list.lastIndexOf(_newElement(5)), -1);
});
test('remove()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]);
expect(list.remove(_newElement(2)), true);
expect(list.remove(_newElement(5)), false);
expect(
list,
equals([
_newElement(1),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]));
expect(list.remove(_newElement(2)), true);
expect(
list,
equals([
_newElement(1),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(3)
]));
expect(list.remove(_newElement(2)), false);
expect(list.remove(_newElement(4)), true);
expect(
list,
equals([
_newElement(1),
_newElement(3),
_newElement(1),
_newElement(3)
]));
});
test('removeAt()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]);
expect(list.removeAt(2), equals(_newElement(3)));
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]));
expect(list.removeAt(2), equals(_newElement(4)));
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(1),
_newElement(2),
_newElement(3)
]));
expect(list.removeAt(4), equals(_newElement(3)));
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(1),
_newElement(2)
]));
expect(() => list.removeAt(-1), throwsRangeError);
expect(() => list.removeAt(4), throwsRangeError);
});
test('removeLast()', () {
final list = _newList()
..addAll([_newElement(1), _newElement(2), _newElement(3)]);
expect(list.removeLast(), equals(_newElement(3)));
expect(list.removeLast(), equals(_newElement(2)));
expect(list.removeLast(), equals(_newElement(1)));
expect(list.removeLast, throwsRangeError);
expect(list, equals([]));
});
test('removeRange()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]);
expect(() => list.removeRange(4, 8), throwsRangeError);
expect(() => list.removeRange(-1, 2), throwsRangeError);
expect(() => list.removeRange(4, 2), throwsRangeError);
list.removeRange(2, 4);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(1),
_newElement(2),
_newElement(3)
]));
list.removeRange(3, 4);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(1),
_newElement(3)
]));
list.removeRange(0, 4);
expect(list, equals([]));
});
test('replaceRange()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
])
..replaceRange(6, 7, [_newElement(8), _newElement(9), _newElement(10)]);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(8),
_newElement(9),
_newElement(10)
]));
expect(() => list.replaceRange(3, 2, [_newElement(1), _newElement(2)]),
throwsRangeError);
list.replaceRange(0, 9, [_newElement(1), _newElement(2)]);
expect(list, equals([_newElement(1), _newElement(2)]));
});
test('setAll()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
])
..setAll(3, [_newElement(1), _newElement(2), _newElement(3)]);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(3)
]));
list.setAll(6, [_newElement(1)]);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(1)
]));
expect(
() => list.setAll(6,
[_newElement(1), _newElement(1), _newElement(1), _newElement(1)]),
throwsRangeError);
expect(() => list.setAll(10, [_newElement(1)]), throwsRangeError);
});
test('setRange()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
])
..setRange(3, 5, [_newElement(5), _newElement(6), _newElement(7)]);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(5),
_newElement(6),
_newElement(2),
_newElement(3)
]));
expect(() => list.setRange(2, 6, [_newElement(8)], 2), throwsStateError);
list.setRange(
2,
6,
[
_newElement(9),
_newElement(9),
_newElement(9),
_newElement(9),
_newElement(9)
],
1);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(9),
_newElement(9),
_newElement(9),
_newElement(9),
_newElement(3)
]));
list.setRange(2, 3,
[_newElement(7), _newElement(7), _newElement(7), _newElement(7)]);
expect(
list,
equals([
_newElement(1),
_newElement(2),
_newElement(7),
_newElement(9),
_newElement(9),
_newElement(9),
_newElement(3)
]));
expect(() => list.setRange(5, 3, [_newElement(1), _newElement(2)]),
throwsRangeError);
});
test('sublist()', () {
final list = _newList()
..addAll([
_newElement(1),
_newElement(2),
_newElement(3),
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]);
expect(
list.sublist(3),
equals([
_newElement(4),
_newElement(1),
_newElement(2),
_newElement(3)
]));
expect(list.sublist(3, 5), equals([_newElement(4), _newElement(1)]));
expect(() => list.sublist(4, 2), throwsRangeError);
});
// TODO: add tests for inherited methods.
test('toString()', () {
final list = _newList()..add(_newElement(2))..add(_newElement(0));
expect(list.toString(), equals('[${_newElement(2)}, ${_newElement(0)}]'));
});
}
void testObserver() {
test('Observer calls.', () {
final list = _newList();
final observer = DummyValueObserver();
expect(list, const TypeMatcher<LeafValue>());
dynamic leafValue = list;
leafValue.observer = observer; // ignore: cascade_invocations
expect(list.length, equals(0));
observer.expectNotChanged();
// Check that each modification method calls observer.valueWasChanged():
list.add(_newElement(1));
observer
..expectChanged()
..reset();
list.addAll([
_newElement(3),
_newElement(2),
_newElement(1),
_newElement(5),
_newElement(5),
_newElement(5),
_newElement(5),
_newElement(5)
]);
observer
..expectChanged()
..reset();
list.insert(2, _newElement(5));
observer
..expectChanged()
..reset();
list.insertAll(1, [_newElement(6), _newElement(7)]);
observer
..expectChanged()
..reset();
list.shuffle(Random(1));
observer
..expectChanged()
..reset();
list.remove(_newElement(1));
observer
..expectChanged()
..reset();
list.removeAt(2);
observer
..expectChanged()
..reset();
list.removeLast();
observer
..expectChanged()
..reset();
list.removeRange(1, 2);
observer
..expectChanged()
..reset();
list.replaceRange(0, 2, [_newElement(1), _newElement(2)]);
observer
..expectChanged()
..reset();
list.setAll(0, [_newElement(1), _newElement(2)]);
observer
..expectChanged()
..reset();
list.setRange(0, 2, [_newElement(1), _newElement(2)]);
observer
..expectChanged()
..reset();
list.clear();
observer
..expectChanged()
..reset();
});
}
}