Skip to content

Commit 0cceec6

Browse files
committed
Add float comparison operators
1 parent 69b815b commit 0cceec6

File tree

6 files changed

+106
-18
lines changed

6 files changed

+106
-18
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
- Environment variable to run a custom initialization script during CI testing: `CUSTOM_INIT_SCRIPT`
1111
- Environment variable to run from a subdirectory during CI testing: `USE_SUBDIR`
1212
- `assertComparativeEqual()` and `assertComparativeNotEqual()` to evaluate equality on an `a - b == 0` basis (and/or `!(a > b) && !(a < b)`)
13+
- `assertEqualFloat()` and `assertNotEqualFloat()` for comparing floats with epsilon
14+
- `assertInfinity()` and `assertNotInfinity()` for comparing floats to infinity
15+
- `assertNAN()` and `assertNotNAN()` for comparing floats to `NaN`
16+
- `assertion()`, `ReporterTAP.onAssert()`, and `testBehaviorExp` macro to handle simple expression evaluation (is true, is false, etc)
1317

1418
### Changed
1519
- Rubocop expected syntax downgraded from ruby 2.6 to 2.5
1620
- `assertEqual()` and `assertNotEqual()` use actual `==` and `!=` -- they no longer require a type to be totally ordered just to do equality tests
21+
- Evaluative assertions (is true/false/null/etc) now produce simpler error messages instead of masquerading as an operation (e.g. "== true")
1722

1823
### Deprecated
1924

REFERENCE.md

+8
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ assertMoreOrEqual(lowerBound, actual); // a >= b
220220
assertTrue(actual);
221221
assertFalse(actual);
222222
assertNull(actual);
223+
224+
// special cases for floats
225+
assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon
226+
assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon
227+
assertInfinity(actual); // isinf(a)
228+
assertNotInfinity(actual); // !isinf(a)
229+
assertNAN(arg); // isnan(a)
230+
assertNotNAN(arg); // !isnan(a)
223231
```
224232

225233
These functions will report the result of the test to the console, and the testing will continue if they fail.

SampleProjects/DoSomething/test/bad-errormessages.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
unittest(check_that_assertion_error_messages_are_comprehensible)
99
{
10-
assertEqual(1 ,2);
10+
assertEqual(1, 2);
1111
assertNotEqual(2, 2);
1212
assertComparativeEqual(1, 2);
1313
assertComparativeNotEqual(2, 2);
@@ -19,6 +19,13 @@ unittest(check_that_assertion_error_messages_are_comprehensible)
1919
assertFalse(true);
2020
assertNull(3);
2121
assertNotNull(NULL);
22+
23+
assertEqualFloat(1.2, 1.0, 0.01);
24+
assertNotEqualFloat(1.0, 1.02, 0.1);
25+
assertInfinity(42);
26+
assertNotInfinity(INFINITY);
27+
assertNAN(42);
28+
assertNotNAN(0.0/0.0);
2229
}
2330

2431
unittest_main()

SampleProjects/DoSomething/test/good-assert.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,15 @@ unittest(assert_equal_without_total_ordering)
3232

3333
}
3434

35+
unittest(float_assertions)
36+
{
37+
assertInfinity(exp(800));
38+
assertInfinity(0.0/0.0);
39+
assertNotInfinity(42);
40+
41+
assertNAN(INFINITY - INFINITY);
42+
assertNAN(0.0/0.0);
43+
assertNotNAN(42);
44+
}
45+
3546
unittest_main()

cpp/unittest/ArduinoUnitTests.h

+32
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ class Test
6969
}
7070
}
7171

72+
// non-comparative assert
73+
void onAssert(
74+
const char* file,
75+
int line,
76+
const char* description,
77+
bool pass
78+
) {
79+
cerr << " " << (pass ? "" : "not ") << "ok " << ++mAssertCounter << " - " << description << endl;
80+
if (!pass) {
81+
cerr << " ---" << endl;
82+
cerr << " at:" << endl;
83+
cerr << " file: " << file << endl;
84+
cerr << " line: " << line << endl;
85+
cerr << " ..." << endl;
86+
}
87+
}
88+
7289
template <typename A, typename B> void onAssert(
7390
const char* file,
7491
int line,
@@ -194,6 +211,21 @@ class Test
194211
excise();
195212
}
196213

214+
bool assertion(
215+
const char *file,
216+
int line,
217+
const char *description,
218+
bool ok)
219+
{
220+
if (mReporter) {
221+
mReporter->onAssert(file, line, description, ok);
222+
}
223+
224+
if (!ok)
225+
fail();
226+
return ok;
227+
}
228+
197229
template <typename A, typename B>
198230
bool assertion(
199231
const char *file,

cpp/unittest/Assertion.h

+42-17
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,19 @@
66

77
#include "Compare.h"
88

9+
#define testBehaviorExp(die, desc, pass) \
10+
do \
11+
{ \
12+
if (!assertion(__FILE__, __LINE__, \
13+
desc, pass)) \
14+
{ \
15+
if (die) return; \
16+
} \
17+
} while (0)
18+
919
#define testBehaviorOp(die, desc, rel1, arg1, op, op_name, rel2, arg2) \
1020
do \
11-
{ \
21+
{ \
1222
if (!assertion<typeof(arg1), typeof(arg2)>(__FILE__, __LINE__, \
1323
desc, \
1424
rel1, #arg1, (arg1), \
@@ -30,29 +40,44 @@
3040

3141

3242
/** macro generates optional output and calls fail() but does not return if false. */
43+
#define assertTrue(arg) testBehaviorExp(false, "assertTrue " #arg, (arg))
44+
#define assertFalse(arg) testBehaviorExp(false, "assertFalse " #arg, !(arg))
45+
#define assertNull(arg) testBehaviorExp(false, "assertNull " #arg, ((void*)NULL == (void*)(arg)))
46+
#define assertNotNull(arg) testBehaviorExp(false, "assertNotNull " #arg, ((void*)NULL != (void*)(arg)))
3347
#define assertEqual(arg1,arg2) assertOp("assertEqual","expected",arg1,evaluateDoubleEqual,"==","actual",arg2)
3448
#define assertNotEqual(arg1,arg2) assertOp("assertNotEqual","unwanted",arg1,evaluateNotEqual,"!=","actual",arg2)
3549
#define assertComparativeEqual(arg1,arg2) assertOp("assertEqual","expected",arg1,compareEqual,"!<>","actual",arg2)
3650
#define assertComparativeNotEqual(arg1,arg2) assertOp("assertEqual","unwanted",arg1,compareNotEqual,"<>","actual",arg2)
37-
#define assertLess(arg1,arg2) assertOp("assertLess","lowerBound",arg1,compareLess,"<","upperBound",arg2)
38-
#define assertMore(arg1,arg2) assertOp("assertMore","upperBound",arg1,compareMore,">","lowerBound",arg2)
39-
#define assertLessOrEqual(arg1,arg2) assertOp("assertLessOrEqual","lowerBound",arg1,compareLessOrEqual,"<=","upperBound",arg2)
40-
#define assertMoreOrEqual(arg1,arg2) assertOp("assertMoreOrEqual","upperBound",arg1,compareMoreOrEqual,">=","lowerBound",arg2)
41-
#define assertTrue(arg) assertEqual(true, arg)
42-
#define assertFalse(arg) assertEqual(false, arg)
43-
#define assertNull(arg) assertEqual((void*)NULL, (void*)arg)
44-
#define assertNotNull(arg) assertNotEqual((void*)NULL, (void*)arg)
51+
#define assertLess(arg1,arg2) assertOp("assertLess","lowerBound",arg1,compareLess,"<","actual",arg2)
52+
#define assertMore(arg1,arg2) assertOp("assertMore","upperBound",arg1,compareMore,">","actual",arg2)
53+
#define assertLessOrEqual(arg1,arg2) assertOp("assertLessOrEqual","lowerBound",arg1,compareLessOrEqual,"<=","actual",arg2)
54+
#define assertMoreOrEqual(arg1,arg2) assertOp("assertMoreOrEqual","upperBound",arg1,compareMoreOrEqual,">=","actual",arg2)
55+
56+
#define assertEqualFloat(arg1, arg2, arg3) assertOp("assertEqualFloat", "epsilon", arg3, compareMoreOrEqual, ">=", "actualDifference", fabs(arg1 - arg2))
57+
#define assertNotEqualFloat(arg1, arg2, arg3) assertOp("assertNotEqualFloat", "epsilon", arg3, compareLessOrEqual, "<=", "insufficientDifference", fabs(arg1 - arg2))
58+
#define assertInfinity(arg) testBehaviorExp(false, "assertInfinity " #arg, isinf(arg))
59+
#define assertNotInfinity(arg) testBehaviorExp(false, "assertNotInfinity " #arg, !isinf(arg))
60+
#define assertNAN(arg) testBehaviorExp(false, "assertNAN " #arg, isnan(arg))
61+
#define assertNotNAN(arg) testBehaviorExp(false, "assertNotNAN " #arg, !isnan(arg))
62+
4563

4664
/** macro generates optional output and calls fail() followed by a return if false. */
65+
#define assureTrue(arg) testBehaviorExp(true, "assertTrue " #arg, (arg))
66+
#define assureFalse(arg) testBehaviorExp(true, "assertFalse " #arg, !(arg))
67+
#define assureNull(arg) testBehaviorExp(true, "assertNull " #arg, ((void*)NULL == (void*)(arg)))
68+
#define assureNotNull(arg) testBehaviorExp(true, "assertNotNull " #arg, ((void*)NULL != (void*)(arg)))
4769
#define assureEqual(arg1,arg2) assureOp("assureEqual","expected",arg1,evaluateDoubleEqual,"==","actual",arg2)
4870
#define assureNotEqual(arg1,arg2) assureOp("assureNotEqual","unwanted",arg1,evaluateNotEqual,"!=","actual",arg2)
4971
#define assureComparativeEqual(arg1,arg2) assertOp("assureEqual","expected",arg1,compareEqual,"!<>","actual",arg2)
5072
#define assureComparativeNotEqual(arg1,arg2) assertOp("assertEqual","unwanted",arg1,compareNotEqual,"<>","actual",arg2)
51-
#define assureLess(arg1,arg2) assureOp("assureLess","lowerBound",arg1,compareLess,"<","upperBound",arg2)
52-
#define assureMore(arg1,arg2) assureOp("assureMore","upperBound",arg1,compareMore,">","lowerBound",arg2)
53-
#define assureLessOrEqual(arg1,arg2) assureOp("assureLessOrEqual","lowerBound",arg1,compareLessOrEqual,"<=","upperBound",arg2)
54-
#define assureMoreOrEqual(arg1,arg2) assureOp("assureMoreOrEqual","upperBound",arg1,compareMoreOrEqual,">=","lowerBound",arg2)
55-
#define assureTrue(arg) assureEqual(true, arg)
56-
#define assureFalse(arg) assureEqual(false, arg)
57-
#define assureNull(arg) assureEqual((void*)NULL, (void*)arg)
58-
#define assureNotNull(arg) assureNotEqual((void*)NULL, (void*)arg)
73+
#define assureLess(arg1,arg2) assureOp("assureLess","lowerBound",arg1,compareLess,"<","actual",arg2)
74+
#define assureMore(arg1,arg2) assureOp("assureMore","upperBound",arg1,compareMore,">","actual",arg2)
75+
#define assureLessOrEqual(arg1,arg2) assureOp("assureLessOrEqual","lowerBound",arg1,compareLessOrEqual,"<=","actual",arg2)
76+
#define assureMoreOrEqual(arg1,arg2) assureOp("assureMoreOrEqual","upperBound",arg1,compareMoreOrEqual,">=","actual",arg2)
77+
78+
#define assureEqualFloat(arg1, arg2, arg3) assureOp("assureEqualFloat", "epsilon", arg3, compareMoreOrEqual, ">=", "actualDifference", fabs(arg1 - arg2))
79+
#define assureNotEqualFloat(arg1, arg2, arg3) assureOp("assureNotEqualFloat", "epsilon", arg3, compareLessOrEqual, "<=", "insufficientDifference", fabs(arg1 - arg2))
80+
#define assureInfinity(arg) testBehaviorExp(true, "assertInfinity " #arg, isinf(arg))
81+
#define assureNotInfinity(arg) testBehaviorExp(true, "assertNotInfinity " #arg, !isinf(arg))
82+
#define assureNAN(arg) testBehaviorExp(true, "assertNAN " #arg, isnan(arg))
83+
#define assureNotNAN(arg) testBehaviorExp(true, "assertNotNAN " #arg, !isnan(arg))

0 commit comments

Comments
 (0)