Skip to content

Commit 6aeb1e4

Browse files
authored
Consider NaN a match for itself (#2524)
Closes #2520 A `double.nan` is not equal to itself with the `==` operator, but for the purposes of testing it's easier to consider a `NaN` correct where a `NaN` was expected. This matches behavior in several other testing frameworks in other languages. This is unlikely to cause existing tests to fail or change semantics since a test is unlikely to use non-equality as a positive indication of a `NaN` result.
1 parent 65a3769 commit 6aeb1e4

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

pkgs/matcher/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
## 0.12.18-wip
22

3+
* Add `isSorted` and related matchers for iterables.
4+
* Consider `NaN` to be equal to itself in `equals`.
35
* Remove some dynamic invocations.
46
* Add explicit casts from `dynamic` values.
57
* Require Dart 3.7
6-
* Add `isSorted` and related matchers for iterables.
78

89
## 0.12.17
910

pkgs/matcher/lib/src/equals_matcher.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,15 @@ class _DeepMatcher extends Matcher {
209209
}
210210
});
211211
} else {
212-
// Otherwise, test for equality.
212+
// Otherwise, test for equality, or both values NaN
213213
try {
214-
if (expected == actual) return null;
214+
if (expected == actual ||
215+
(expected is num &&
216+
expected.isNaN &&
217+
actual is num &&
218+
actual.isNaN)) {
219+
return null;
220+
}
215221
} catch (e) {
216222
// TODO(gram): Add a test for this case.
217223
return _Mismatch(

pkgs/matcher/test/core_matchers_test.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@ void main() {
9595
);
9696
});
9797

98+
test('equals with NaN', () {
99+
final a = double.nan;
100+
final b = 0;
101+
shouldPass(a, equals(a));
102+
shouldFail(a, equals(b), 'Expected: <0> Actual: <NaN>');
103+
shouldFail(b, equals(a), 'Expected: <NaN> Actual: <0>');
104+
});
105+
106+
test('equals with NaN in a collection', () {
107+
final a = {double.nan};
108+
final b = {0};
109+
shouldPass(a, equals(a));
110+
shouldFail(
111+
a,
112+
equals(b),
113+
'Expected: Set:[0] Actual: Set:[NaN] '
114+
'Which: does not contain <0>',
115+
);
116+
shouldFail(
117+
b,
118+
equals(a),
119+
'Expected: Set:[NaN] Actual: Set:[0] '
120+
'Which: does not contain <NaN>',
121+
);
122+
});
123+
98124
test('anything', () {
99125
var a = <Object?, Object?>{};
100126
shouldPass(0, anything);

0 commit comments

Comments
 (0)