Add Expect.notIdentical and Expect.allDistinct to package:expect.

Change-Id: I8d3c92a4723f74b40b8c0c968340d1dd1175d748
Reviewed-on: https://dart-review.googlesource.com/34061
Reviewed-by: Peter von der Ahé <ahe@google.com>
This commit is contained in:
Lasse Reichstein Holst Nielsen 2018-01-11 17:07:10 +01:00 committed by Lasse R.H. Nielsen
parent 68c054d27f
commit ffab960f19
2 changed files with 142 additions and 1 deletions

View file

@ -178,6 +178,55 @@ class Expect {
"fails.");
}
/**
* Checks whether the expected and actual values are *not* identical
* (using `identical`).
*/
static void notIdentical(var unexpected, var actual, [String reason = null]) {
if (!_identical(unexpected, actual)) return;
String msg = _getMessage(reason);
_fail("Expect.notIdentical(expected and actual: <$actual>$msg) fails.");
}
/**
* Checks that no two [objects] are `identical`.
*/
static void allDistinct(List<Object> objects, [String reason = null]) {
String msg = _getMessage(reason);
var equivalences = new List<List<int>>(objects.length);
bool hasEquivalence = false;
for (int i = 0; i < objects.length; i++) {
if (equivalences[i] != null) continue;
var o = objects[i];
for (int j = i + 1; j < objects.length; j++) {
if (equivalences[j] != null) continue;
if (_identical(o, objects[j])) {
equivalences[j] = (equivalences[i] ??= <int>[i])..add(j);
hasEquivalence = true;
}
}
}
if (!hasEquivalence) return;
var buffer = new StringBuffer("Expect.allDistinct([");
var separator = "";
for (int i = 0; i < objects.length; i++) {
buffer.write(separator);
separator = ",";
var equivalence = equivalences[i];
if (equivalence == null) {
buffer.write('_');
} else {
int first = equivalence[0];
buffer..write('#')..write(first);
if (first == i) {
buffer..write('=')..write(objects[i]);
}
}
}
buffer..write("]")..write(msg)..write(")");
_fail(buffer.toString());
}
// Unconditional failure.
static void fail(String msg) {
_fail("Expect.fail('$msg')");
@ -514,15 +563,16 @@ class Expect {
}
}
/// Used in [Expect] because [Expect.identical] shadows the real [identical].
bool _identical(a, b) => identical(a, b);
typedef bool _CheckExceptionFn(exception);
typedef _Nullary(); // Expect.throws argument must be this type.
class ExpectException implements Exception {
final String message;
ExpectException(this.message);
String toString() => message;
String message;
}
/// Annotation class for testing of dart2js. Use this as metadata on method

View file

@ -0,0 +1,91 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
main() {
var o1 = new Object();
var o2 = new Object();
var o3 = new Object();
var c1 = new C(0);
var c2 = new C(0);
// Successful checks.
Expect.notIdentical(o1, o2, "msg");
Expect.equals(c1, c2);
Expect.notIdentical(c1, c2, "msg");
Expect.notIdentical([1], [1], "msg");
Expect.allDistinct([], "msg");
Expect.allDistinct([o1], "msg");
Expect.allDistinct([
o1,
o2,
c1,
c2,
[1]
], "msg");
Expect.allDistinct(new List.generate(100, (_) => new Object()));
fails((msg) {
Expect.notIdentical(o1, o1, msg);
});
fails((msg) {
var list = [1];
Expect.notIdentical(list, list, msg);
});
fails((msg) {
Expect.allDistinct([o1, o1], msg);
});
fails((msg) {
Expect.allDistinct([o1, o1, o1, o1], msg);
});
fails((msg) {
Expect.allDistinct([o1, o1, o2, o3], msg);
});
fails((msg) {
Expect.allDistinct([o1, o2, o1, o3], msg);
});
fails((msg) {
Expect.allDistinct([o1, o2, o3, o1], msg);
});
fails((msg) {
Expect.allDistinct([o1, o2, o2, o3], msg);
});
fails((msg) {
Expect.allDistinct([o1, o2, o3, o2], msg);
});
fails((msg) {
Expect.allDistinct([o1, o2, o3, o3], msg);
});
fails((msg) {
var list = new List.generate(100, (_) => new Object());
list.add(list[0]);
Expect.allDistinct(list, msg);
});
}
class C {
final x;
const C(this.x);
int get hashCode => x.hashCode;
bool operator ==(Object other) => other is C && x == other.x;
}
int _ctr = 0;
fails(test(msg)) {
var msg = "__#${_ctr++}#__"; // "Unique" name.
try {
test(msg);
throw "Did not throw!";
} on ExpectException catch (e) {
if (e.message.indexOf(msg) < 0) {
throw "Failure did not contain message: \"$msg\" not in ${e.message}";
}
}
}