diff --git a/.travis.yml b/.travis.yml index 6baf06bf..ae59037e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - pub run test test/dart_kollection_test.dart - pub global activate coverage - pub global run coverage:collect_coverage --port=8111 -o coverage.json --resume-isolates --wait-paused & - - dart --observe=8111 test/dart_kollection_test.dart + - dart --observe=8111 --enable-asserts test/dart_kollection_test.dart - pub global run coverage:format_coverage --packages=.packages --report-on lib --in coverage.json --out lcov.info --lcov after_success: - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/lib/src/collection/list.dart b/lib/src/collection/list.dart index 1fe8168a..5f7c05ec 100644 --- a/lib/src/collection/list.dart +++ b/lib/src/collection/list.dart @@ -34,12 +34,19 @@ class DartList @override bool containsAll(KCollection elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); return elements.all((it) => _list.contains(it)); } @override T get(int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); if (index < 0 || index >= size) { throw IndexOutOfBoundsException("index: $index, size: $size"); } @@ -63,7 +70,10 @@ class DartList @override KListIterator listIterator([int index = 0]) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); return InterOpKListIterator(_list, index); } @@ -72,15 +82,17 @@ class DartList @override KList subList(int fromIndex, int toIndex) { - if (fromIndex == null) throw ArgumentError("fromIndex can't be null"); - if (toIndex == null) throw ArgumentError("toIndex can't be null"); + assert(() { + if (fromIndex == null) throw ArgumentError("fromIndex can't be null"); + if (toIndex == null) throw ArgumentError("toIndex can't be null"); + if (fromIndex > toIndex) + throw ArgumentError("fromIndex: $fromIndex > toIndex: $toIndex"); + return true; + }()); if (fromIndex < 0 || toIndex > size) { throw IndexOutOfBoundsException( "fromIndex: $fromIndex, toIndex: $toIndex, size: $size"); } - if (fromIndex > toIndex) { - throw ArgumentError("fromIndex: $fromIndex > toIndex: $toIndex"); - } return DartList(_list.sublist(fromIndex, toIndex)); } diff --git a/lib/src/collection/list_empty.dart b/lib/src/collection/list_empty.dart index c64cf30f..47fa6dd4 100644 --- a/lib/src/collection/list_empty.dart +++ b/lib/src/collection/list_empty.dart @@ -17,18 +17,30 @@ class EmptyList bool contains(T element) => false; @override - bool containsAll(KCollection elements) => elements.isEmpty(); + bool containsAll(KCollection elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); + return elements.isEmpty(); + } @override T get(int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); throw IndexOutOfBoundsException( "Empty list doesn't contain element at index $index."); } @override T operator [](int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); throw IndexOutOfBoundsException( "Empty list doesn't contain element at index $index."); } @@ -47,7 +59,10 @@ class EmptyList @override KListIterator listIterator([int index = 0]) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); return _EmptyIterator(); } @@ -56,8 +71,11 @@ class EmptyList @override KList subList(int fromIndex, int toIndex) { - if (fromIndex == null) throw ArgumentError("fromIndex can't be null"); - if (toIndex == null) throw ArgumentError("toIndex can't be null"); + assert(() { + if (fromIndex == null) throw ArgumentError("fromIndex can't be null"); + if (toIndex == null) throw ArgumentError("toIndex can't be null"); + return true; + }()); if (fromIndex == 0 && toIndex == 0) return this; throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex"); } diff --git a/lib/src/collection/list_mutable.dart b/lib/src/collection/list_mutable.dart index 09a8b992..afb7d2a3 100644 --- a/lib/src/collection/list_mutable.dart +++ b/lib/src/collection/list_mutable.dart @@ -37,12 +37,19 @@ class DartMutableList @override bool containsAll(KCollection elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); return elements.all((it) => _list.contains(it)); } @override T get(int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); if (index < 0 || index >= size) { throw IndexOutOfBoundsException("index: $index, size: $size"); } @@ -81,18 +88,31 @@ class DartMutableList @override bool addAll(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); _list.addAll(elements.iter); return true; } @override bool addAllAt(int index, KCollection elements) { + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); _list.insertAll(index, elements.iter); return true; } @override void addAt(int index, T element) { + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); _list.insert(index, element); } @@ -103,10 +123,20 @@ class DartMutableList bool remove(T element) => _list.remove(element); @override - T removeAt(int index) => _list.removeAt(index); + T removeAt(int index) { + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); + return _list.removeAt(index); + } @override T set(int index, T element) { + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); final old = _list[index]; _list[index] = element; return old; @@ -117,6 +147,10 @@ class DartMutableList @override bool removeAll(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); var changed = false; for (var value in elements.iter) { changed |= _list.remove(value); @@ -126,21 +160,28 @@ class DartMutableList @override bool retainAll(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); _list.removeWhere((it) => !elements.contains(it)); return true; } @override KMutableList subList(int fromIndex, int toIndex) { - if (fromIndex == null) throw ArgumentError("fromIndex can't be null"); - if (toIndex == null) throw ArgumentError("toIndex can't be null"); + assert(() { + if (fromIndex == null) throw ArgumentError("fromIndex can't be null"); + if (toIndex == null) throw ArgumentError("toIndex can't be null"); + if (fromIndex > toIndex) { + throw ArgumentError("fromIndex: $fromIndex > toIndex: $toIndex"); + } + return true; + }()); if (fromIndex < 0 || toIndex > size) { throw IndexOutOfBoundsException( "fromIndex: $fromIndex, toIndex: $toIndex, size: $size"); } - if (fromIndex > toIndex) { - throw ArgumentError("fromIndex: $fromIndex > toIndex: $toIndex"); - } return DartMutableList(_list.sublist(fromIndex, toIndex)); } diff --git a/lib/src/collection/map_mutable.dart b/lib/src/collection/map_mutable.dart index 60527e2e..a3daa904 100644 --- a/lib/src/collection/map_mutable.dart +++ b/lib/src/collection/map_mutable.dart @@ -71,6 +71,10 @@ class DartMutableMap @override void putAll(KMap from) { + assert(() { + if (from == null) throw ArgumentError("from can't be null"); + return true; + }()); for (var entry in from.entries.iter) { _map[entry.key] = entry.value; } diff --git a/lib/src/collection/set.dart b/lib/src/collection/set.dart index e9f19daf..6afa41a2 100644 --- a/lib/src/collection/set.dart +++ b/lib/src/collection/set.dart @@ -24,6 +24,10 @@ class DartSet @override bool containsAll(KCollection elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); return elements.all((it) => _set.contains(it)); } diff --git a/lib/src/collection/set_empty.dart b/lib/src/collection/set_empty.dart index b2f6bcf7..c90a9bab 100644 --- a/lib/src/collection/set_empty.dart +++ b/lib/src/collection/set_empty.dart @@ -13,7 +13,13 @@ class EmptySet bool contains(T element) => false; @override - bool containsAll(KCollection elements) => elements.isEmpty(); + bool containsAll(KCollection elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); + return elements.isEmpty(); + } @override bool isEmpty() => true; diff --git a/lib/src/collection/set_mutable.dart b/lib/src/collection/set_mutable.dart index 5e7680a8..fd1cab44 100644 --- a/lib/src/collection/set_mutable.dart +++ b/lib/src/collection/set_mutable.dart @@ -35,6 +35,10 @@ class DartMutableSet @override bool containsAll(KCollection elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); return elements.all((it) => _set.contains(it)); } @@ -67,6 +71,10 @@ class DartMutableSet @override bool addAll(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); var oldSize = size; _set.addAll(elements.iter); return size != oldSize; @@ -80,6 +88,10 @@ class DartMutableSet @override bool removeAll(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); final oldSize = size; for (var value in elements.iter) { _set.remove(value); @@ -89,6 +101,10 @@ class DartMutableSet @override bool retainAll(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); final oldSize = size; _set.removeWhere((it) => !elements.contains(it)); return oldSize != size; diff --git a/lib/src/extension/iterable_extension_mixin.dart b/lib/src/extension/iterable_extension_mixin.dart index 82b00eb8..b43edb59 100644 --- a/lib/src/extension/iterable_extension_mixin.dart +++ b/lib/src/extension/iterable_extension_mixin.dart @@ -8,7 +8,10 @@ abstract class KIterableExtensionsMixin implements KIterableExtension, KIterable { @override bool all([bool Function(T element) predicate]) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); if (this is KCollection && (this as KCollection).isEmpty()) return true; for (var element in iter) { if (!predicate(element)) { @@ -45,8 +48,8 @@ abstract class KIterableExtensionsMixin } @override - KMap associateByTransform(K Function(T) keySelector, - [V Function(T) valueTransform]) { + KMap associateByTransform( + K Function(T) keySelector, V Function(T) valueTransform) { return associateByTo(linkedMapOf(), keySelector, valueTransform); } @@ -54,6 +57,11 @@ abstract class KIterableExtensionsMixin M associateByTo>( M destination, K Function(T) keySelector, [V Function(T) valueTransform]) { + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (keySelector == null) throw ArgumentError("keySelector can't be null"); + return true; + }()); for (var element in iter) { var key = keySelector(element); var value = valueTransform == null ? element : valueTransform(element); @@ -65,7 +73,10 @@ abstract class KIterableExtensionsMixin @override M associateTo>( M destination, KPair Function(T) transform) { - assert(transform != null); + assert(() { + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); for (var element in iter) { var pair = transform(element); destination.put(pair.first, pair.second); @@ -81,7 +92,11 @@ abstract class KIterableExtensionsMixin @override M associateWithTo>( M destination, V Function(T) valueSelector) { - assert(valueSelector != null); + assert(() { + if (valueSelector == null) + throw ArgumentError("valueSelector can't be null"); + return true; + }()); for (var element in iter) { destination.put(element, valueSelector(element)); } @@ -90,7 +105,10 @@ abstract class KIterableExtensionsMixin @override double averageBy(num Function(T) selector) { - assert(selector != null); + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); num sum = 0.0; var count = 0; for (final element in iter) { @@ -102,11 +120,19 @@ abstract class KIterableExtensionsMixin @override KList> chunked(int size) { + assert(() { + if (size == null) throw ArgumentError("size can't be null"); + return true; + }()); return windowed(size, step: size, partialWindows: true); } @override KList chunkedTransform(int size, R Function(KList) transform) { + assert(() { + if (size == null) throw ArgumentError("size can't be null"); + return true; + }()); return windowedTransform(size, transform, step: size, partialWindows: true); } @@ -138,7 +164,10 @@ abstract class KIterableExtensionsMixin KList distinct() => toMutableSet().toList(); KList distinctBy(K Function(T) selector) { - assert(selector != null); + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); final set = hashSetOf(); final list = mutableListOf(); for (final element in iter) { @@ -152,6 +181,10 @@ abstract class KIterableExtensionsMixin @override KList drop(int n) { + assert(() { + if (n == null) throw ArgumentError("n can't be null"); + return true; + }()); final list = mutableListOf(); var count = 0; for (final item in iter) { @@ -164,7 +197,10 @@ abstract class KIterableExtensionsMixin @override KList dropWhile(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); var yielding = false; var list = mutableListOf(); for (final item in iter) { @@ -182,7 +218,11 @@ abstract class KIterableExtensionsMixin @override T elementAt(int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); + return elementAtOrElse(index, (int index) { throw IndexOutOfBoundsException( "Collection doesn't contain element at index $index."); @@ -191,9 +231,12 @@ abstract class KIterableExtensionsMixin @override T elementAtOrElse(int index, T Function(int) defaultValue) { - if (index == null) throw ArgumentError("index can't be null"); - if (defaultValue == null) - throw ArgumentError("defaultValue function can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + if (defaultValue == null) + throw ArgumentError("defaultValue function can't be null"); + return true; + }()); if (index < 0) { return defaultValue(index); } @@ -210,7 +253,10 @@ abstract class KIterableExtensionsMixin @override T elementAtOrNull(int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); if (index < 0) { return null; } @@ -242,7 +288,10 @@ abstract class KIterableExtensionsMixin @override C filterIndexedTo>( C destination, bool Function(int index, T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); var i = 0; for (final element in iter) { if (predicate(i++, element)) { @@ -292,7 +341,11 @@ abstract class KIterableExtensionsMixin @override C filterNotTo>( C destination, bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + if (destination == null) throw ArgumentError("destination can't be null"); + return true; + }()); for (final element in iter) { if (!predicate(element)) { destination.add(element); @@ -304,7 +357,11 @@ abstract class KIterableExtensionsMixin @override C filterTo>( C destination, bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + if (destination == null) throw ArgumentError("destination can't be null"); + return true; + }()); for (final element in iter) { if (predicate(element)) { destination.add(element); @@ -315,13 +372,19 @@ abstract class KIterableExtensionsMixin @override T find(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); return firstOrNull(predicate); } @override T findLast(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); return lastOrNull(predicate); } @@ -377,7 +440,11 @@ abstract class KIterableExtensionsMixin @override C flatMapTo>( C destination, KIterable Function(T) transform) { - assert(transform != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); for (var element in iter) { final list = transform(element); destination.addAll(list); @@ -387,7 +454,10 @@ abstract class KIterableExtensionsMixin @override R fold(R initial, R Function(R acc, T) operation) { - assert(operation != null); + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); var accumulator = initial; for (final element in iter) { accumulator = operation(accumulator, element); @@ -397,7 +467,10 @@ abstract class KIterableExtensionsMixin @override R foldIndexed(R initial, R Function(int index, R acc, T) operation) { - assert(operation != null); + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); var index = 0; var accumulator = initial; for (final element in iter) { @@ -407,8 +480,11 @@ abstract class KIterableExtensionsMixin } @override - void forEach(void action(T element)) { - assert(action != null); + void forEach(void Function(T element) action) { + assert(() { + if (action == null) throw ArgumentError("action can't be null"); + return true; + }()); var i = iterator(); while (i.hasNext()) { var element = i.next(); @@ -418,7 +494,10 @@ abstract class KIterableExtensionsMixin @override void forEachIndexed(void Function(int index, T element) action) { - assert(action != null); + assert(() { + if (action == null) throw ArgumentError("action can't be null"); + return true; + }()); var index = 0; for (final item in iter) { action(index++, item); @@ -442,8 +521,11 @@ abstract class KIterableExtensionsMixin @override M groupByTo>>( M destination, K Function(T) keySelector) { - assert(destination != null); - assert(keySelector != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (keySelector == null) throw ArgumentError("keySelector can't be null"); + return true; + }()); for (final element in iter) { final key = keySelector(element); final list = destination.getOrPut(key, () => mutableListOf()); @@ -455,9 +537,13 @@ abstract class KIterableExtensionsMixin @override M groupByToTransform>>( M destination, K Function(T) keySelector, V Function(T) valueTransform) { - assert(destination != null); - assert(keySelector != null); - assert(valueTransform != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (keySelector == null) throw ArgumentError("keySelector can't be null"); + if (valueTransform == null) + throw ArgumentError("valueTransform can't be null"); + return true; + }()); for (final element in iter) { final key = keySelector(element); final list = destination.getOrPut(key, () => mutableListOf()); @@ -479,7 +565,10 @@ abstract class KIterableExtensionsMixin @override int indexOfFirst(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); var index = 0; for (var item in iter) { if (predicate(item)) { @@ -491,7 +580,10 @@ abstract class KIterableExtensionsMixin } int indexOfLast(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); var lastIndex = -1; var index = 0; for (var item in iter) { @@ -637,7 +729,11 @@ abstract class KIterableExtensionsMixin @override C mapIndexedNotNullTo>( C destination, R Function(int index, T) transform) { - assert(transform != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); var index = 0; for (final item in iter) { var element = transform(index++, item); @@ -651,7 +747,11 @@ abstract class KIterableExtensionsMixin @override C mapIndexedTo>( C destination, R Function(int index, T) transform) { - assert(transform != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); var index = 0; for (final item in iter) { destination.add(transform(index++, item)); @@ -670,7 +770,11 @@ abstract class KIterableExtensionsMixin @override C mapNotNullTo>( C destination, R Function(T) transform) { - assert(transform != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); for (final item in iter) { var result = transform(item); if (result != null) { @@ -683,7 +787,11 @@ abstract class KIterableExtensionsMixin @override C mapTo>( C destination, R Function(T) transform) { - assert(transform != null); + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); for (var item in iter) { destination.add(transform(item)); } @@ -713,7 +821,10 @@ abstract class KIterableExtensionsMixin @override T maxBy>(R Function(T) selector) { - assert(selector != null); + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); final i = iterator(); if (!iterator().hasNext()) return null; T maxElement = i.next(); @@ -731,6 +842,10 @@ abstract class KIterableExtensionsMixin @override T maxWith(Comparator comparator) { + assert(() { + if (comparator == null) throw ArgumentError("comparator can't be null"); + return true; + }()); final i = iterator(); if (!i.hasNext()) return null; var max = i.next(); @@ -766,6 +881,10 @@ abstract class KIterableExtensionsMixin @override KList minus(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); if (this is KCollection && (this as KCollection).isEmpty()) { return this.toList(); } @@ -791,7 +910,10 @@ abstract class KIterableExtensionsMixin @override T minBy>(R Function(T) selector) { - assert(selector != null); + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); final i = iterator(); if (!iterator().hasNext()) return null; T minElement = i.next(); @@ -809,6 +931,10 @@ abstract class KIterableExtensionsMixin @override T minWith(Comparator comparator) { + assert(() { + if (comparator == null) throw ArgumentError("comparator can't be null"); + return true; + }()); final i = iterator(); if (!i.hasNext()) return null; var min = i.next(); @@ -835,7 +961,10 @@ abstract class KIterableExtensionsMixin @override void onEach(void Function(T) action) { - assert(action != null); + assert(() { + if (action == null) throw ArgumentError("action can't be null"); + return true; + }()); for (final element in iter) { action(element); } @@ -843,7 +972,10 @@ abstract class KIterableExtensionsMixin @override KPair, KList> partition(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); final first = mutableListOf(); final second = mutableListOf(); for (final element in iter) { @@ -858,6 +990,10 @@ abstract class KIterableExtensionsMixin @override KList plus(KIterable elements) { + assert(() { + if (elements == null) throw ArgumentError("elements can't be null"); + return true; + }()); final result = mutableListOf(); result.addAll(this.asIterable()); result.addAll(elements); @@ -876,6 +1012,10 @@ abstract class KIterableExtensionsMixin @override S reduce(S Function(S acc, T) operation) { + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); final i = iterator(); if (!i.hasNext()) throw UnsupportedError("Empty collection can't be reduced."); @@ -888,6 +1028,10 @@ abstract class KIterableExtensionsMixin @override S reduceIndexed(S Function(int index, S acc, T) operation) { + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); final i = iterator(); if (!i.hasNext()) throw UnsupportedError("Empty collection can't be reduced."); @@ -985,19 +1129,32 @@ abstract class KIterableExtensionsMixin KList sorted() => sortedWith(naturalOrder()); @override - KList sortedBy>(R Function(T) selector) => - sortedWith(compareBy(selector)); + KList sortedBy>(R Function(T) selector) { + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); + return sortedWith(compareBy(selector)); + } @override - KList sortedByDescending>( - R Function(T) selector) => - sortedWith(compareByDescending(selector)); + KList sortedByDescending>(R Function(T) selector) { + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); + return sortedWith(compareByDescending(selector)); + } @override KList sortedDescending() => sortedWith(reverseOrder()); @override KList sortedWith(Comparator comparator) { + assert(() { + if (comparator == null) throw ArgumentError("comparator can't be null"); + return true; + }()); final mutableList = toMutableList(); mutableList.list.sort(comparator); return mutableList; @@ -1005,6 +1162,10 @@ abstract class KIterableExtensionsMixin @override KSet subtract(KIterable other) { + assert(() { + if (other == null) throw ArgumentError("other can't be null"); + return true; + }()); final set = toMutableSet(); set.removeAll(other); return set; @@ -1025,6 +1186,10 @@ abstract class KIterableExtensionsMixin } int sumBy(int Function(T) selector) { + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); int sum = 0; for (final element in iter) { sum += selector(element); @@ -1033,6 +1198,10 @@ abstract class KIterableExtensionsMixin } double sumByDouble(double Function(T) selector) { + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); double sum = 0.0; for (final element in iter) { sum += selector(element); @@ -1042,6 +1211,10 @@ abstract class KIterableExtensionsMixin @override KList take(int n) { + assert(() { + if (n == null) throw ArgumentError("n can't be null"); + return true; + }()); if (n < 0) { throw ArgumentError("Requested element count $n is less than zero."); } @@ -1063,6 +1236,10 @@ abstract class KIterableExtensionsMixin } C toCollection>(C destination) { + assert(() { + if (destination == null) throw ArgumentError("destination can't be null"); + return true; + }()); for (final item in iter) { destination.add(item); } @@ -1086,6 +1263,10 @@ abstract class KIterableExtensionsMixin @override KSet union(KIterable other) { + assert(() { + if (other == null) throw ArgumentError("other can't be null"); + return true; + }()); final set = toMutableSet(); set.addAll(other); return set; @@ -1094,6 +1275,13 @@ abstract class KIterableExtensionsMixin @override KList> windowed(int size, {int step = 1, bool partialWindows = false}) { + assert(() { + if (size == null) throw ArgumentError("size can't be null"); + if (step == null) throw ArgumentError("step can't be null"); + if (partialWindows == null) + throw ArgumentError("partialWindows can't be null"); + return true; + }()); final list = this.toList(); final thisSize = list.size; final result = mutableListOf>(); @@ -1111,7 +1299,14 @@ abstract class KIterableExtensionsMixin @override KList windowedTransform(int size, R Function(KList) transform, {int step = 1, bool partialWindows = false}) { - assert(transform != null); + assert(() { + if (size == null) throw ArgumentError("size can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + if (step == null) throw ArgumentError("step can't be null"); + if (partialWindows == null) + throw ArgumentError("partialWindows can't be null"); + return true; + }()); final list = this.toList(); final thisSize = list.size; final result = mutableListOf(); @@ -1133,6 +1328,11 @@ abstract class KIterableExtensionsMixin @override KList zipTransform( KIterable other, V Function(T a, R b) transform) { + assert(() { + if (other == null) throw ArgumentError("other can't be null"); + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); final first = iterator(); final second = other.iterator(); final list = mutableListOf(); @@ -1148,6 +1348,10 @@ abstract class KIterableExtensionsMixin @override KList zipWithNextTransform(R Function(T a, T b) transform) { + assert(() { + if (transform == null) throw ArgumentError("transform can't be null"); + return true; + }()); final i = iterator(); if (!i.hasNext()) { return emptyList(); diff --git a/lib/src/extension/iterable_mutable_extension_mixin.dart b/lib/src/extension/iterable_mutable_extension_mixin.dart index 0649c610..701d684f 100644 --- a/lib/src/extension/iterable_mutable_extension_mixin.dart +++ b/lib/src/extension/iterable_mutable_extension_mixin.dart @@ -12,6 +12,10 @@ abstract class KMutableIterableExtensionsMixin bool _filterInPlace( bool Function(T) predicate, bool predicateResultToRemove) { + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); var result = false; var i = iterator(); while (i.hasNext()) diff --git a/lib/src/extension/list_extension_mixin.dart b/lib/src/extension/list_extension_mixin.dart index 54508322..1363f40e 100644 --- a/lib/src/extension/list_extension_mixin.dart +++ b/lib/src/extension/list_extension_mixin.dart @@ -3,6 +3,10 @@ import 'package:dart_kollection/dart_kollection.dart'; abstract class KListExtensionsMixin implements KListExtension, KList { @override KList dropLast(int n) { + assert(() { + if (n == null) throw ArgumentError("n can't be null"); + return true; + }()); var count = size - n; if (count < 0) { count = 0; @@ -12,7 +16,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override KList dropLastWhile(bool Function(T) predicate) { - assert(predicate != null); + assert(() { + if (predicate == null) throw ArgumentError("predicate can't be null"); + return true; + }()); if (!isEmpty()) { final i = listIterator(size); while (i.hasPrevious()) { @@ -29,9 +36,12 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override T elementAtOrElse(int index, T defaultValue(int index)) { - if (index == null) throw ArgumentError("index can't be null"); - if (defaultValue == null) - throw ArgumentError("defaultValue function can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + if (defaultValue == null) + throw ArgumentError("defaultValue function can't be null"); + return true; + }()); return index >= 0 && index <= lastIndex ? get(index) : defaultValue(index); } @@ -54,6 +64,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override R foldRight(R initial, R Function(T, R acc) operation) { + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); if (isEmpty()) return initial; var accumulator = initial; @@ -66,6 +80,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override R foldRightIndexed(R initial, R Function(int index, T, R acc) operation) { + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); if (isEmpty()) return initial; var accumulator = initial; @@ -78,9 +96,12 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override T getOrElse(int index, T Function(int) defaultValue) { - if (index == null) throw ArgumentError("index can't be null"); - if (defaultValue == null) - throw ArgumentError("default value function can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + if (defaultValue == null) + throw ArgumentError("default value function can't be null"); + return true; + }()); return (index >= 0 && index <= lastIndex) ? get(index) : defaultValue(index); @@ -88,7 +109,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override T getOrNull(int index) { - if (index == null) throw ArgumentError("index can't be null"); + assert(() { + if (index == null) throw ArgumentError("index can't be null"); + return true; + }()); return index >= 0 && index <= lastIndex ? get(index) : null; } @@ -118,6 +142,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override S reduceRight(S Function(T, S acc) operation) { + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); final i = listIterator(size); if (!i.hasPrevious()) { throw UnimplementedError("Empty list can't be reduced."); @@ -131,6 +159,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override S reduceRightIndexed(S Function(int index, T, S acc) operation) { + assert(() { + if (operation == null) throw ArgumentError("operation can't be null"); + return true; + }()); final i = listIterator(size); if (!i.hasPrevious()) { throw UnimplementedError("Empty list can't be reduced."); @@ -144,6 +176,10 @@ abstract class KListExtensionsMixin implements KListExtension, KList { @override KList slice(KIterable indices) { + assert(() { + if (indices == null) throw ArgumentError("indices can't be null"); + return true; + }()); if (indices.count() == 0) { return emptyList(); } diff --git a/lib/src/extension/list_mutable_extension_mixin.dart b/lib/src/extension/list_mutable_extension_mixin.dart index 4851dbe7..9090a816 100644 --- a/lib/src/extension/list_mutable_extension_mixin.dart +++ b/lib/src/extension/list_mutable_extension_mixin.dart @@ -24,6 +24,10 @@ abstract class KMutableListExtensionsMixin @override void sortBy>(R Function(T) selector) { + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); if (size > 1) { sortWith(compareBy(selector)); } @@ -31,6 +35,10 @@ abstract class KMutableListExtensionsMixin @override void sortByDescending>(R Function(T) selector) { + assert(() { + if (selector == null) throw ArgumentError("selector can't be null"); + return true; + }()); if (size > 1) { sortWith(compareByDescending(selector)); } @@ -38,6 +46,10 @@ abstract class KMutableListExtensionsMixin @override void sortWith(Comparator comparator) { + assert(() { + if (comparator == null) throw ArgumentError("comparator can't be null"); + return true; + }()); list.sort(comparator); } diff --git a/lib/src/extension/map_extensions_mixin.dart b/lib/src/extension/map_extensions_mixin.dart index 1eb9e4e6..60474e92 100644 --- a/lib/src/extension/map_extensions_mixin.dart +++ b/lib/src/extension/map_extensions_mixin.dart @@ -5,6 +5,11 @@ abstract class KMapExtensionsMixin implements KMapExtension, KMap { @override V getOrElse(K key, V Function() defaultValue) { + assert(() { + if (defaultValue == null) + throw ArgumentError("defaultValue can't be null"); + return true; + }()); return get(key) ?? defaultValue(); } @@ -56,6 +61,10 @@ abstract class KMapExtensionsMixin @override KMap plus(KMap map) { + assert(() { + if (map == null) throw ArgumentError("map can't be null"); + return true; + }()); return toMutableMap()..putAll(map); } diff --git a/lib/src/extension/map_mutable_extensions_mixin.dart b/lib/src/extension/map_mutable_extensions_mixin.dart index cf909d10..976fdb06 100644 --- a/lib/src/extension/map_mutable_extensions_mixin.dart +++ b/lib/src/extension/map_mutable_extensions_mixin.dart @@ -5,6 +5,11 @@ abstract class KMutableMapExtensionsMixin implements KMutableMapExtension, KMutableMap { @override V getOrPut(K key, V Function() defaultValue) { + assert(() { + if (defaultValue == null) + throw ArgumentError("defaultValue can't be null"); + return true; + }()); final value = get(key); if (value != null) return value; final answer = defaultValue(); @@ -16,6 +21,10 @@ abstract class KMutableMapExtensionsMixin @override void putAllPairs(KIterable> pairs) { + assert(() { + if (pairs == null) throw ArgumentError("pairs can't be null"); + return true; + }()); for (var value in pairs.iter) { put(value.first, value.second); } diff --git a/test/collection/collection_mutable_test.dart b/test/collection/collection_mutable_test.dart new file mode 100644 index 00000000..c8c63402 --- /dev/null +++ b/test/collection/collection_mutable_test.dart @@ -0,0 +1,54 @@ +import 'package:dart_kollection/dart_kollection.dart'; +import 'package:test/test.dart'; + +import '../test/assert_dart.dart'; + +void main() { + group("mutableList", () { + testCollection(() => mutableListOf(), + (Iterable iterable) => mutableListOf(iterable)); + }); + group("hashset", () { + testCollection(() => hashSetOf(), + (Iterable iterable) => hashSetOf(iterable), + ordered: false); + }); + group("linkedSet", () { + testCollection(() => linkedSetOf(), + (Iterable iterable) => linkedSetOf(iterable)); + }); +} + +void testCollection( + KMutableCollection Function() emptyCollection, + KMutableCollection Function(Iterable collection) + mutableCollectionOf, + {bool ordered = true}) { + group("add", () { + test("add a item", () { + final list = mutableCollectionOf(["a"]); + list.add("b"); + expect(list.size, equals(2)); + expect(list, equals(mutableCollectionOf(["a", "b"]))); + }); + test("add null works", () { + final list = mutableCollectionOf(["a"]); + list.add(null); + expect(list.size, equals(2)); + expect(list, equals(mutableCollectionOf(["a", null]))); + }); + }); + group("addAll", () { + test("add all items", () { + final list = mutableCollectionOf(["a"]); + list.addAll(listOf(["b", "c"])); + expect(list.size, equals(3)); + expect(list, equals(mutableCollectionOf(["a", "b", "c"]))); + }); + test("addAll doens't allow null as defaultValue function", () { + final collection = emptyCollection(); + final e = catchException(() => collection.addAll(null)); + expect(e.message, allOf(contains("null"), contains("elements"))); + }); + }); +} diff --git a/test/collection/collection_test.dart b/test/collection/collection_test.dart index ef139553..22e8df5e 100644 --- a/test/collection/collection_test.dart +++ b/test/collection/collection_test.dart @@ -1,6 +1,8 @@ import 'package:dart_kollection/dart_kollection.dart'; import 'package:test/test.dart'; +import '../test/assert_dart.dart'; + void main() { group("list", () { testCollection( @@ -66,5 +68,18 @@ void testCollection(KCollection Function() emptyCollection, expect(list.containsAll(listOf(["x"])), isFalse); expect(list.containsAll(listOf(["c", "x", "d"])), isFalse); }); + + test("containsAll doesn't allow null as argument", () { + final collection = collectionOf(["a", "b", "c", "d", "e"]); + final e = + catchException(() => collection.containsAll(null)); + expect(e.message, allOf(contains("null"), contains("elements"))); + }); + + test("containsAll (empty collection) doesn't allow null as argument", () { + final e = catchException( + () => emptyCollection().containsAll(null)); + expect(e.message, allOf(contains("null"), contains("elements"))); + }); }); } diff --git a/test/collection/iterable_extensions_test.dart b/test/collection/iterable_extensions_test.dart index 54c43f9e..b50e8a5f 100644 --- a/test/collection/iterable_extensions_test.dart +++ b/test/collection/iterable_extensions_test.dart @@ -35,6 +35,26 @@ void main() { void testIterable(KIterable Function() emptyIterable, KIterable Function(Iterable iterable) iterableOf, {bool ordered = true}) { + group('all', () { + test("matches all", () { + final iterable = iterableOf(["abc", "bcd", "cde"]); + expect(iterable.all((e) => e.contains("c")), isTrue); + }); + test("matches none", () { + final iterable = iterableOf(["abc", "bcd", "cde"]); + expect(iterable.all((e) => e.contains("x")), isFalse); + }); + test("matches one", () { + final iterable = iterableOf(["abc", "bcd", "cde"]); + expect(iterable.all((e) => e.contains("a")), isFalse); + }); + test("predicate can't be null", () { + final iterable = iterableOf(["abc", "bcd", "cde"]); + final e = catchException(() => iterable.all(null)); + expect(e.message, allOf(contains("null"))); + }); + }); + group('any', () { test("matches single", () { final iterable = iterableOf(["abc", "bcd", "cde"]); @@ -60,21 +80,26 @@ void testIterable(KIterable Function() emptyIterable, group('associate', () { test("associate", () { - final list = listOf(["a", "b", "c"]); + final list = iterableOf(["a", "b", "c"]); var result = list.associate((it) => KPair(it.toUpperCase(), it)); var expected = mapOf({"A": "a", "B": "b", "C": "c"}); expect(result, equals(expected)); }); test("associate on empty map", () { - final list = emptyList(); - var result = list.associateWith((it) => it.toUpperCase()); + final list = emptyIterable(); + var result = list.associate((it) => KPair(it.toUpperCase(), it)); expect(result, equals(emptyMap())); }); + test("associate doesn't allow null as transform function", () { + final list = emptyIterable(); + var e = catchException(() => list.associate(null)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); }); group('associateBy', () { test("associateBy", () { - final list = listOf(["a", "b", "c"]); + final list = iterableOf(["a", "b", "c"]); var result = list.associateBy((it) => it.toUpperCase()); var expected = mapOf({"A": "a", "B": "b", "C": "c"}); expect(result, equals(expected)); @@ -85,16 +110,31 @@ void testIterable(KIterable Function() emptyIterable, expect(result, equals(emptyMap())); }); test("when conflicting keys, use last ", () { - final list = listOf(["a", "b", "c"]); + final list = iterableOf(["a", "b", "c"]); var result = list.associateBy((it) => it.length); - var expected = mapOf({1: "c"}); - expect(result, equals(expected)); + expect(result.size, equals(1)); + expect(result.containsKey(1), isTrue); + }); + + test("associateBy doesn't allow null as keySelector", () { + final list = emptyIterable(); + var e = catchException(() => list.associateBy(null)); + expect(e.message, allOf(contains("null"), contains("keySelector"))); + }); + }); + + group('associateByTo', () { + test("associateByTo doesn't allow null destination", () { + final list = iterableOf(["a", "b", "c"]); + var e = catchException( + () => list.associateByTo(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); }); }); group('associateByTransform', () { test("associateByTransform", () { - final list = listOf(["a", "bb", "ccc"]); + final list = iterableOf(["a", "bb", "ccc"]); var result = list.associateByTransform( (it) => it.length, (it) => it.toUpperCase()); var expected = mapOf({1: "A", 2: "BB", 3: "CCC"}); @@ -105,6 +145,12 @@ void testIterable(KIterable Function() emptyIterable, var result = list.associateWith((it) => it.toUpperCase()); expect(result, equals(emptyMap())); }); + test("associateByTransform doesn't allow null as keySelector", () { + final list = emptyIterable(); + var e = catchException( + () => list.associateByTransform(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("keySelector"))); + }); }); group('associateWith', () { @@ -119,6 +165,11 @@ void testIterable(KIterable Function() emptyIterable, var result = iterable.associateWith((it) => it.toUpperCase()); expect(result, equals(emptyMap())); }); + test("associateWith doesn't allow null as valueSelector", () { + final list = emptyIterable(); + var e = catchException(() => list.associateWith(null)); + expect(e.message, allOf(contains("null"), contains("valueSelector"))); + }); }); group('average', () { @@ -137,6 +188,11 @@ void testIterable(KIterable Function() emptyIterable, var result = ints.averageBy((it) => it); expect(result, equals(2.5)); }); + test("averageBy doesn't allow null as selector", () { + final list = emptyIterable(); + var e = catchException(() => list.averageBy(null)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); }); group("distinct", () { @@ -167,6 +223,12 @@ void testIterable(KIterable Function() emptyIterable, true); }); } + + test("distinctBy doesn't allow null as selector", () { + final list = emptyIterable(); + var e = catchException(() => list.distinctBy(null)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); }); group("count", () { @@ -180,7 +242,7 @@ void testIterable(KIterable Function() emptyIterable, }); group("chunked", () { - test("chunked", () { + test("chunk", () { final chunks = iterableOf([1, 2, 3, 4, 5]).chunked(3); expect( chunks, @@ -190,11 +252,31 @@ void testIterable(KIterable Function() emptyIterable, ])); }); + test("chunked doesn't allow null as size", () { + final list = emptyIterable(); + var e = catchException(() => list.chunked(null)); + expect(e.message, allOf(contains("null"), contains("size"))); + }); + test("chunkedTransform", () { final chunks = iterableOf([1, 2, 3, 4, 5]).chunkedTransform(3, (it) => it.sum()); expect(chunks, listOf([6, 9])); }); + + test("chunkedTransform doesn't allow null as size", () { + final list = emptyIterable(); + var e = catchException( + () => list.chunkedTransform(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("size"))); + }); + + test("chunkedTransform doesn't allow null as transform function", () { + final list = emptyIterable(); + var e = + catchException(() => list.chunkedTransform(3, null)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); }); group("drop", () { @@ -204,9 +286,9 @@ void testIterable(KIterable Function() emptyIterable, expect(iterable.drop(1), equals(listOf(["b", "c"]))); }); } else { - test("drop first value unordered", () { - final iterable = iterableOf(["a", "b", "c"]); - expect(iterable.drop(1).size, 2); + test("drop on iterable returns a iterable", () { + final iterable = emptyIterable(); + expect(iterable.drop(1), TypeMatcher>()); }); } test("drop empty does nothing", () { @@ -217,40 +299,56 @@ void testIterable(KIterable Function() emptyIterable, final iterable = emptyIterable(); expect(iterable.drop(1), TypeMatcher>()); }); + + test("drop negative, drops nothing", () { + final iterable = iterableOf(["a", "b", "c"]); + expect(iterable.drop(-10).toList(), iterable.toList()); + }); + + test("drop doesn't allow null as size", () { + final list = emptyIterable(); + var e = catchException(() => list.drop(null)); + expect(e.message, allOf(contains("null"), contains("n"))); + }); }); group("dropWhile", () { if (ordered) { - test("drop two", () { + test("dropWhile two", () { final iterable = iterableOf(["a", "b", "c"]); expect(iterable.dropWhile((it) => it != "c"), equals(listOf(["c"]))); }); - test("drop one", () { + test("dropWhile one", () { final iterable = iterableOf(["a", "b", "c"]); expect( iterable.dropWhile((it) => it != "b"), equals(listOf(["b", "c"]))); }); } else { - test("drop first value unordered", () { + test("dropWhile first value unordered", () { final iterable = iterableOf(["a", "b", "c"]); int i = 0; expect(iterable.dropWhile((_) => ++i <= 2).size, 1); }); } - test("drop empty does nothing", () { + test("dropWhile empty does nothing", () { final iterable = emptyIterable(); expect( iterable.dropWhile((_) => false).toList(), equals(emptyList())); }); - test("drop all makes an empty list", () { + test("dropWhile all makes an empty list", () { final iterable = iterableOf(["a", "b", "c"]); expect( iterable.dropWhile((_) => true).toList(), equals(emptyList())); }); - test("drop on iterable returns a iterable", () { + test("dropWhile on iterable returns a iterable", () { final iterable = emptyIterable(); expect(iterable.dropWhile((_) => false), TypeMatcher>()); }); + test("dropWhile doesn't allow null as predicate", () { + final list = emptyIterable(); + var e = catchException(() => list.dropWhile(null)); + expect(e.message, allOf(contains("null"), contains("predicate"))); + }); }); group("elementAt", () { @@ -378,12 +476,38 @@ void testIterable(KIterable Function() emptyIterable, equals(setOf(["paul", "lisa"]))); }); + test("filter doesn't allow null as predicate", () { + final list = emptyIterable(); + var e = catchException(() => list.filter(null)); + expect(e.message, allOf(contains("null"), contains("predicate"))); + }); + + test("filterTo doesn't allow null as destination", () { + final list = emptyIterable(); + var e = + catchException(() => list.filterTo(null, (_) => true)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + test("filterNot", () { final iterable = iterableOf(["paul", "peter", "john", "lisa"]); expect(iterable.filterNot((it) => it.contains("a")).toSet(), equals(setOf(["peter", "john"]))); }); + test("filterNot doesn't allow null as predicate", () { + final list = emptyIterable(); + var e = catchException(() => list.filterNot(null)); + expect(e.message, allOf(contains("null"), contains("predicate"))); + }); + + test("filterNotTo doesn't allow null as destination", () { + final list = emptyIterable(); + var e = catchException( + () => list.filterNotTo(null, (_) => true)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + test("filterNotNull", () { final iterable = iterableOf(["paul", null, "john", "lisa"]); expect(iterable.filterNotNull().toSet(), @@ -448,6 +572,19 @@ void testIterable(KIterable Function() emptyIterable, iterable.flatMap((it) => iterableOf([it, it + 1, it + 2])).toList(), listOf([1, 2, 3, 2, 3, 4, 3, 4, 5])); }); + + test("flatMap doesn't allow null as tranform function", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException(() => iterable.flatMap(null)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); + + test("flatMapTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.flatMapTo(null, (_) => emptyIterable())); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); }); group("groupBy", () { @@ -497,6 +634,47 @@ void testIterable(KIterable Function() emptyIterable, }))); }); } + + test("groupBy doesn't allow null as keySelector", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException(() => iterable.groupBy(null)); + expect(e.message, allOf(contains("null"), contains("keySelector"))); + }); + + test("groupByTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.groupByTo(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + + test("groupByTransform doesn't allow null as keySelector", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.groupByTransform(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("keySelector"))); + }); + + test("groupByTransform doesn't allow null as valueTransform", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.groupByTransform((it) => it, null)); + expect(e.message, allOf(contains("null"), contains("valueTransform"))); + }); + + test("groupByTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.groupByTo(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + + test("groupByToTransform doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.groupByToTransform(null, (it) => it, (it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); }); group("intersect", () { @@ -506,6 +684,12 @@ void testIterable(KIterable Function() emptyIterable, final result = a.intersect(b); expect(result, setOf(["john", "lisa"])); }); + + test("other can't be null", () { + var a = iterableOf(["paul", "john", "max", "lisa"]); + final e = catchException(() => a.intersect(null)); + expect(e.message, allOf(contains("null"))); + }); }); group("last", () { @@ -576,6 +760,31 @@ void testIterable(KIterable Function() emptyIterable, }); }); + group("mapNotNullTo", () { + test("mapNotNullTo int to string", () { + final list = mutableListOf(); + final iterable = iterableOf([1, null, 2, null, 3]); + iterable.mapNotNullTo(list, (it) => it?.toString()); + + expect(list, listOf(["1", "2", "3"])); + }); + + test("mapNotNullTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.mapNotNullTo(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + + test("mapNotNullTo doesn't allow null as transform function", () { + final iterable = iterableOf([1, 2, 3]); + int Function(int) mapper = null; + var e = catchException( + () => iterable.mapNotNullTo(mutableListOf(), mapper)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); + }); + group("mapTo", () { test("mapTo int to string", () { final list = mutableListOf(); @@ -584,6 +793,21 @@ void testIterable(KIterable Function() emptyIterable, expect(list, listOf(["1", "2", "3"])); }); + + test("mapTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = + catchException(() => iterable.mapTo(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + + test("mapTo doesn't allow null as transform function", () { + final iterable = iterableOf([1, 2, 3]); + int Function(int) mapper = null; + var e = catchException( + () => iterable.mapTo(mutableListOf(), mapper)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); }); if (ordered) { @@ -595,6 +819,21 @@ void testIterable(KIterable Function() emptyIterable, expect(list, listOf(["0a", "1b", "2c"])); }); + + test("mapIndexedTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.mapIndexedTo(null, (_, it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + + test("mapIndexedTo doesn't allow null as transform function", () { + final iterable = iterableOf([1, 2, 3]); + int Function(int, int) indexedMapper = null; + var e = catchException( + () => iterable.mapIndexedTo(mutableListOf(), indexedMapper)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); }); } @@ -634,6 +873,21 @@ void testIterable(KIterable Function() emptyIterable, }).toList(); expect(set, setOf(["0a", "2b", "3c"])); }); + + test("mapIndexedNotNullTo doesn't allow null as destination", () { + final iterable = iterableOf([1, 2, 3]); + var e = catchException( + () => iterable.mapIndexedNotNullTo(null, (_, it) => it)); + expect(e.message, allOf(contains("null"), contains("destination"))); + }); + + test("mapIndexedNotNullTo doesn't allow null as transform function", () { + final iterable = iterableOf([1, 2, 3]); + int Function(int, int) indexedMapper = null; + var e = catchException(() => + iterable.mapIndexedNotNullTo(mutableListOf(), indexedMapper)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); }); } @@ -706,6 +960,12 @@ void testIterable(KIterable Function() emptyIterable, expect(result.toSet(), setOf(["paul", "john", "lisa"])); }); } + + test("minus doesn't allow null as elements", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.minus(null)); + expect(e.message, allOf(contains("null"), contains("elements"))); + }); }); group("none", () { @@ -738,6 +998,12 @@ void testIterable(KIterable Function() emptyIterable, final result = iterableOf([1, 2, 3]) + iterableOf([4, 5, 6]); expect(result.toList(), listOf([1, 2, 3, 4, 5, 6])); }); + + test("plus doesn't allow null as elements", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.plus(null)); + expect(e.message, allOf(contains("null"), contains("elements"))); + }); }); group("reduce", () { @@ -750,6 +1016,12 @@ void testIterable(KIterable Function() emptyIterable, expect(() => emptyIterable().reduce((int acc, it) => it + acc), throwsUnsupportedError); }); + + test("reduce doesn't allow null as operation", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.reduce(null)); + expect(e.message, allOf(contains("null"), contains("operation"))); + }); }); group("reversed", () { @@ -794,6 +1066,28 @@ void testIterable(KIterable Function() emptyIterable, .sortedByDescending(lastChar); expect(result, listOf(["max", "john", "paul", "lisa"])); }); + + test("sortedBy doesn't allow null as selector", () { + final iterable = emptyIterable(); + num Function(String) sortFun = null; + var e = catchException(() => iterable.sortedBy(sortFun)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); + + test("sortedByDescending doesn't allow null as selector", () { + final iterable = emptyIterable(); + num Function(String) sortFun = null; + var e = catchException( + () => iterable.sortedByDescending(sortFun)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); + test("sortedWith doesn't allow null as comparator", () { + final iterable = emptyIterable(); + Comparator comparator = null; + var e = + catchException(() => iterable.sortedWith(comparator)); + expect(e.message, allOf(contains("null"), contains("comparator"))); + }); }); group("subtract", () { @@ -802,6 +1096,12 @@ void testIterable(KIterable Function() emptyIterable, .subtract(iterableOf(["max"])); expect(result, setOf(["paul", "john", "lisa"])); }); + + test("subtract doesn't allow null as other", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.subtract(null)); + expect(e.message, allOf(contains("null"), contains("other"))); + }); }); group("sum", () { @@ -827,6 +1127,18 @@ void testIterable(KIterable Function() emptyIterable, test("factor 1.5", () { expect(iterableOf([1, 2, 3]).sumByDouble((i) => i * 1.5), 9.0); }); + + test("sumBy doesn't allow null as selector", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.sumBy(null)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); + + test("sumByDouble doesn't allow null as selector", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.sumByDouble(null)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); }); group("windowed", () { @@ -883,6 +1195,26 @@ void testIterable(KIterable Function() emptyIterable, listOf([1]), ])); }); + + test("window doesn't allow null as size", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.windowed(null)); + expect(e.message, allOf(contains("null"), contains("size"))); + }); + + test("window doesn't allow null as step", () { + final iterable = emptyIterable(); + var e = + catchException(() => iterable.windowed(3, step: null)); + expect(e.message, allOf(contains("null"), contains("step"))); + }); + + test("window doesn't allow null as partialWindows", () { + final iterable = emptyIterable(); + var e = catchException( + () => iterable.windowed(3, partialWindows: null)); + expect(e.message, allOf(contains("null"), contains("partialWindows"))); + }); }); group("windowedTransform", () { @@ -927,6 +1259,34 @@ void testIterable(KIterable Function() emptyIterable, step: 2, partialWindows: true), listOf([1])); }); + + test("windowedTransform doesn't allow null as size", () { + final iterable = emptyIterable(); + var e = catchException( + () => iterable.windowedTransform(null, (it) => it)); + expect(e.message, allOf(contains("null"), contains("size"))); + }); + + test("windowedTransform doesn't allow null as transform function", () { + final iterable = emptyIterable(); + var e = catchException( + () => iterable.windowedTransform(3, null)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); + + test("windowedTransform doesn't allow null as step", () { + final iterable = emptyIterable(); + var e = catchException( + () => iterable.windowedTransform(3, (it) => it, step: null)); + expect(e.message, allOf(contains("null"), contains("step"))); + }); + + test("windowedTransform doesn't allow null as partialWindows", () { + final iterable = emptyIterable(); + var e = catchException(() => + iterable.windowedTransform(3, (it) => it, partialWindows: null)); + expect(e.message, allOf(contains("null"), contains("partialWindows"))); + }); }); group("zip", () { @@ -940,10 +1300,36 @@ void testIterable(KIterable Function() emptyIterable, expect(result, listOf(["1a", "2b"])); }); - test("with next", () { + test("zipWithNextTransform", () { final result = iterableOf([1, 2, 3, 4, 5]).zipWithNextTransform((a, b) => a + b); expect(result, listOf([3, 5, 7, 9])); }); + test("zipWithNextTransform doesn't allow null as transform function", () { + final iterable = emptyIterable(); + int Function(dynamic, dynamic) transform = null; + var e = catchException( + () => iterable.zipWithNextTransform(transform)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); + + test("zip doesn't allow null as other", () { + final iterable = emptyIterable(); + var e = catchException(() => iterable.zip(null)); + expect(e.message, allOf(contains("null"), contains("other"))); + }); + test("zipTransform doesn't allow null as other", () { + final iterable = emptyIterable(); + var e = catchException( + () => iterable.zipTransform(null, (a, b) => a)); + expect(e.message, allOf(contains("null"), contains("other"))); + }); + test("zipTransform doesn't allow null as transform function", () { + final iterable = emptyIterable(); + int Function(dynamic, dynamic) transform = null; + var e = catchException( + () => iterable.zipTransform(emptyIterable(), transform)); + expect(e.message, allOf(contains("null"), contains("transform"))); + }); }); } diff --git a/test/collection/list_empty_test.dart b/test/collection/list_empty_test.dart index 8ec8b320..71f2757f 100644 --- a/test/collection/list_empty_test.dart +++ b/test/collection/list_empty_test.dart @@ -1,6 +1,8 @@ import 'package:dart_kollection/dart_kollection.dart'; import 'package:test/test.dart'; +import '../test/assert_dart.dart'; + void main() { group('empty list', () { test("has no elements", () { @@ -74,6 +76,18 @@ void main() { expect(empty0, equals(empty1)); }); + test("sublist doesn't allow null as fromIndex", () { + final e = + catchException(() => emptyList().subList(null, 10)); + expect(e.message, allOf(contains("null"), contains("fromIndex"))); + }); + + test("sublist doesn't allow null as toIndex", () { + final e = + catchException(() => emptyList().subList(0, null)); + expect(e.message, allOf(contains("null"), contains("toIndex"))); + }); + test("sublist works for index 0 to 0", () { final empty = emptyList(); final subList = empty.subList(0, 0); @@ -98,5 +112,11 @@ void main() { List list = emptyList().list; expect(list.length, 0); }); + + test("listIterator requires index", () { + ArgumentError e = catchException(() => emptyList().listIterator(null)); + expect(e.message, contains("index")); + expect(e.message, contains("null")); + }); }); } diff --git a/test/collection/list_mutable_extensions_test.dart b/test/collection/list_mutable_extensions_test.dart index 056f68ea..a23f3787 100644 --- a/test/collection/list_mutable_extensions_test.dart +++ b/test/collection/list_mutable_extensions_test.dart @@ -1,6 +1,8 @@ import 'package:dart_kollection/dart_kollection.dart'; import 'package:test/test.dart'; +import '../test/assert_dart.dart'; + void main() { group('fill', () { test("replace all elements", () { @@ -28,10 +30,30 @@ void main() { expect(result, listOf(["lisa", "paul", "john", "max"])); }); + test("sortBy doesn't allow null as argument", () { + num Function(dynamic) selector = null; + final e = catchException( + () => mutableListOf()..sortBy(selector)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); + test("sortByDescending", () { final result = mutableListOf(["paul", "john", "max", "lisa"]) ..sortByDescending(lastChar); expect(result, listOf(["max", "john", "paul", "lisa"])); }); + + test("sortByDescending doesn't allow null as argument", () { + num Function(dynamic) selector = null; + final e = catchException( + () => mutableListOf()..sortByDescending(selector)); + expect(e.message, allOf(contains("null"), contains("selector"))); + }); + + test("sortWith doesn't allow null as argument", () { + final e = catchException( + () => mutableListOf()..sortWith(null)); + expect(e.message, allOf(contains("null"), contains("comparator"))); + }); }); } diff --git a/test/collection/list_mutable_test.dart b/test/collection/list_mutable_test.dart index 54e83c1d..377e65a6 100644 --- a/test/collection/list_mutable_test.dart +++ b/test/collection/list_mutable_test.dart @@ -1,6 +1,8 @@ import 'package:dart_kollection/dart_kollection.dart'; import 'package:test/test.dart'; +import '../test/assert_dart.dart'; + void main() { group('basic methods', () { test("has no elements", () { @@ -93,6 +95,12 @@ void main() { expect(list, listOf([4, 2, 10, 4, 1])); }); + test("set doesn't allow null as index", () { + final e = catchException( + () => mutableListOf().set(null, "test")); + expect(e.message, allOf(contains("null"), contains("index"))); + }); + test("set operator", () { final list = mutableListOf([1, 2, 3, 4, 5]); list[2] = 10; @@ -109,6 +117,18 @@ void main() { expect(subList, equals(mutableListOf(["b", "c"]))); }); + test("sublist doesn't allow null as fromIndex", () { + final e = catchException( + () => mutableListOf().subList(null, 10)); + expect(e.message, allOf(contains("null"), contains("fromIndex"))); + }); + + test("sublist doesn't allow null as toIndex", () { + final e = + catchException(() => mutableListOf().subList(0, null)); + expect(e.message, allOf(contains("null"), contains("toIndex"))); + }); + test("sublist throws for illegal ranges", () { final list = mutableListOf(["a", "b", "c"]); @@ -123,18 +143,54 @@ void main() { throwsA(TypeMatcher())); }); - test("add item", () { - final list = mutableListOf(); + test("add item appends item to end", () { + final list = mutableListOf(["World"]); list.add("Hello"); - expect(list.size, equals(1)); - expect(list[0], equals("Hello")); + expect(list, listOf(["World", "Hello"])); + }); + + test("addAt to specific position (first)", () { + final list = mutableListOf(["World"]); + list.addAt(0, "Hello"); + expect(list, listOf(["Hello", "World"])); + }); + + test("addAt to specific position (last)", () { + final list = mutableListOf(["World"]); + list.addAt(1, "Hello"); + expect(list, listOf(["World", "Hello"])); }); - test("addAll add items at the end of the lsit", () { + test("addAt doens't allow null as index", () { + final e = catchException( + () => mutableListOf().addAt(null, listOf(["test"]))); + expect(e.message, allOf(contains("null"), contains("index"))); + }); + + test("addAll add items at the end of the list", () { final list = mutableListOf(["a"]); list.addAll(listOf(["b", "c"])); expect(list.size, equals(3)); expect(list, equals(listOf(["a", "b", "c"]))); }); + + test("addAllAt 0 add items at the beginning of the list", () { + final list = mutableListOf(["a"]); + list.addAllAt(0, listOf(["b", "c"])); + expect(list.size, equals(3)); + expect(list, equals(listOf(["b", "c", "a"]))); + }); + + test("addAllAt doens't allow null as index", () { + final e = catchException( + () => mutableListOf().addAllAt(null, listOf(["test"]))); + expect(e.message, allOf(contains("null"), contains("index"))); + }); + + test("addAllAt doens't allow null as elements", () { + final e = catchException( + () => mutableListOf().addAllAt(0, null)); + expect(e.message, allOf(contains("null"), contains("elements"))); + }); }); } diff --git a/test/collection/list_test.dart b/test/collection/list_test.dart index e56be170..ecf90d32 100644 --- a/test/collection/list_test.dart +++ b/test/collection/list_test.dart @@ -107,6 +107,12 @@ void main() { expect(() => emptyList().reduceRight((it, int acc) => it + acc), throwsUnsupportedError); }); + + test("reduceRight doesn't allow null as operation", () { + final list = emptyList(); + var e = catchException(() => list.reduceRight(null)); + expect(e.message, allOf(contains("null"), contains("operation"))); + }); }); test("sublist works ", () { diff --git a/test/collection/map_extensions_test.dart b/test/collection/map_extensions_test.dart index 64669c45..e117c746 100644 --- a/test/collection/map_extensions_test.dart +++ b/test/collection/map_extensions_test.dart @@ -1,6 +1,8 @@ import 'package:dart_kollection/dart_kollection.dart'; import 'package:test/test.dart'; +import '../test/assert_dart.dart'; + void main() { final pokemon = mapOf({ 1: "Bulbasaur", @@ -31,6 +33,12 @@ void main() { test("getOrElse", () { expect(pokemon.getOrElse(10, () => "None"), "None"); }); + + test("getOrElse doesn't allow null as defaultValue function", () { + final e = + catchException(() => pokemon.getOrElse(10, null)); + expect(e.message, allOf(contains("null"), contains("defaultValue"))); + }); }); group("isEmpty", () { @@ -135,6 +143,15 @@ void main() { expect(map.size, 2); }); + test("plus doesn't allow null as argument", () { + final pokemon = mapOf({ + 1: "Bulbasaur", + 2: "Ivysaur", + }); + final e = catchException(() => pokemon.plus(null)); + expect(e.message, allOf(contains("null"), contains("map"))); + }); + test("+ (plus) operator", () { final map = mapOf({ 1: "Bulbasaur", diff --git a/test/collection/map_mutable_extensions_test.dart b/test/collection/map_mutable_extensions_test.dart index 57cf465b..9810d9e7 100644 --- a/test/collection/map_mutable_extensions_test.dart +++ b/test/collection/map_mutable_extensions_test.dart @@ -1,6 +1,8 @@ import 'package:dart_kollection/dart_kollection.dart'; import 'package:test/test.dart'; +import '../test/assert_dart.dart'; + void main() { group("clear", () { test("clear items", () { @@ -126,6 +128,15 @@ void main() { expect(pokemon.getOrPut(150, () => "Mewtwo"), "Mewtwo"); expect(pokemon.get(150), "Mewtwo"); }); + + test("getOrPut doens't allow null as defaultValue function", () { + final pokemon = mutableMapOf({ + 1: "Bulbasaur", + 2: "Ivysaur", + }); + final e = catchException(() => pokemon.getOrPut(1, null)); + expect(e.message, allOf(contains("null"), contains("defaultValue"))); + }); }); group("put", () { @@ -148,6 +159,28 @@ void main() { }); }); + group("putAll", () { + test("putAll", () { + final pokemon = mutableMapOf({ + 1: "Bulbasaur", + 2: "Ivysaur", + }); + pokemon.putAll(mapOf({1: "Ditto", 3: "Venusaur"})); + expect(pokemon[1], "Ditto"); + expect(pokemon[2], "Ivysaur"); + expect(pokemon[3], "Venusaur"); + }); + + test("can't use null for putAll", () { + final pokemon = mutableMapOf({ + 1: "Bulbasaur", + 2: "Ivysaur", + }); + final e = catchException(() => pokemon.putAll(null)); + expect(e.message, allOf(contains("null"))); + }); + }); + group("putAllPairs", () { test("add new ones", () { final pokemon = mutableMapOf({ @@ -176,6 +209,15 @@ void main() { expect(pokemon.size, 2); expect(pokemon[2], "Dito"); }); + + test("putAllPairs doens't allow null as argument", () { + final pokemon = mutableMapOf({ + 1: "Bulbasaur", + 2: "Ivysaur", + }); + final e = catchException(() => pokemon.putAllPairs(null)); + expect(e.message, allOf(contains("null"), contains("pairs"))); + }); }); group("putIfAbsent", () { diff --git a/test/dart_kollection_test.dart b/test/dart_kollection_test.dart index 73aaafc3..08b2741b 100644 --- a/test/dart_kollection_test.dart +++ b/test/dart_kollection_test.dart @@ -1,3 +1,4 @@ +import 'collection/collection_mutable_test.dart' as collection_mutable_test; import 'collection/collection_test.dart' as collection_test; import 'collection/iterable_extensions_test.dart' as iterable_extensions_test; import 'collection/iterator_test.dart' as iterator_test; @@ -19,6 +20,7 @@ import 'exceptions_test.dart' as exceptions_test; import 'tuples_test.dart' as tuples_test; main() { + collection_mutable_test.main(); collection_test.main(); iterable_extensions_test.main(); iterator_test.main(); diff --git a/tool/run_coverage_locally.sh b/tool/run_coverage_locally.sh index cec09e42..b71b65d5 100755 --- a/tool/run_coverage_locally.sh +++ b/tool/run_coverage_locally.sh @@ -5,7 +5,7 @@ pub global activate coverage } pub global run coverage:collect_coverage --port=8111 -o out/coverage/coverage.json --resume-isolates --wait-paused & -dart --observe=8111 test/dart_kollection_test.dart +dart --observe=8111 --enable-asserts test/dart_kollection_test.dart pub global run coverage:format_coverage --packages=.packages --report-on lib --in out/coverage/coverage.json --out out/coverage/lcov.info --lcov genhtml -o out/coverage/html out/coverage/lcov.info echo "open coverage report $PWD/out/coverage/html/index.html" \ No newline at end of file