Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Unified Diff: pkg/unittest/lib/src/iterable_matchers.dart

Issue 112583003: Add an [unorderedMatches] matcher to unittest. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/unittest/pubspec.yaml » ('j') | pkg/unittest/pubspec.yaml » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/unittest/lib/src/iterable_matchers.dart
diff --git a/pkg/unittest/lib/src/iterable_matchers.dart b/pkg/unittest/lib/src/iterable_matchers.dart
index ab7827f115cb3001203840abb9c397c608aa4da4..a81bfed347b341512ff204baae05ff080be9e826 100644
--- a/pkg/unittest/lib/src/iterable_matchers.dart
+++ b/pkg/unittest/lib/src/iterable_matchers.dart
@@ -108,6 +108,7 @@ class _OrderedEquals extends Matcher {
}
}
}
+
/**
* Returns a matcher which matches [Iterable]s that have the same
* length and the same elements as [expected], but not necessarily in
@@ -193,6 +194,73 @@ abstract class _IterableMatcher extends Matcher {
}
/**
+ * Returns a matcher which matches [Iterable]s whose elements match the matchers
+ * in [expected], but not necessarily in the same order.
+ *
+ * Note that this is `O(n^2)` and so should only be used on small objects.
+ */
+Matcher unorderedMatches(Iterable expected) =>
+ new _UnorderedMatches(expected);
+
+class _UnorderedMatches extends Matcher {
Siggi Cherem (dart-lang) 2013/12/17 00:32:03 seems like there is a lot of code in common here a
nweiz 2013/12/17 03:33:47 I intentionally avoided going too deep on modifyin
Siggi Cherem (dart-lang) 2013/12/17 18:48:45 I think it is worth the effort for the matchers li
+ final List<Matcher> _expected;
+
+ _UnorderedMatches(Iterable expected)
+ : _expected = expected.map(wrapMatcher).toList();
+
+ String _test(item) {
+ if (item is !Iterable) return 'not iterable';
+ item = item.toList();
+
+ // Check the lengths are the same.
+ if (_expected.length > item.length) {
+ return 'has too few elements (${item.length} < ${_expected.length})';
+ } else if (_expected.length < item.length) {
+ return 'has too many elements (${item.length} > ${_expected.length})';
+ }
+
+ var matched = new List<bool>.filled(item.length, false);
+ var expectedPosition = 0;
+ for (var expectedMatcher in _expected) {
+ var actualPosition = 0;
+ var gotMatch = false;
+ for (var actualElement in item) {
+ if (!matched[actualPosition]) {
+ if (expectedMatcher.matches(actualElement, {})) {
+ matched[actualPosition] = gotMatch = true;
+ break;
+ }
+ }
+ ++actualPosition;
+ }
+
+ if (!gotMatch) {
+ return new StringDescription()
+ .add('has no match for ')
+ .addDescriptionOf(expectedMatcher)
+ .add(' at index ${expectedPosition}')
+ .toString();
+ }
+
+ ++expectedPosition;
+ }
+ return null;
+ }
+
+ bool matches(item, Map mismatchState) => _test(item) == null;
+
+ Description describe(Description description) =>
+ description
+ .add('matches ')
+ .addAll('[', ', ', ']', _expected)
+ .add(' unordered');
+
+ Description describeMismatch(item, Description mismatchDescription,
+ Map matchState, bool verbose) =>
+ mismatchDescription.add(_test(item));
+}
+
+/**
* A pairwise matcher for iterable. You can pass an arbitrary [comparator]
* function that takes an expected and actual argument which will be applied
* to each pair in order. [description] should be a meaningful name for
« no previous file with comments | « no previous file | pkg/unittest/pubspec.yaml » ('j') | pkg/unittest/pubspec.yaml » ('J')

Powered by Google App Engine
This is Rietveld 408576698