mirror of
https://github.com/cesanta/mongoose.git
synced 2025-06-07 09:27:05 +08:00
Make sure test assertions are evaluated once
E.g. if `ASSERT_EQ(myfunc(), 123)` fails, `myfunc()` would be invoked again to print the actual value. This can cause confusion sometimes. To avoid this, we cast arguments to double, which is wide enough for most cases and we provide a variant for 64 bit value types for when it's not. We also perform a check and fail if argument to the check results in loss of precision. CL: none PUBLISHED_FROM=a14551289d92e8a5dead21d16471ebddebe938a8
This commit is contained in:
parent
84a11fe3b1
commit
a3c4a48ef7
@ -77,51 +77,103 @@ void _strfail(const char *a, const char *e, int len);
|
||||
if (msg) return msg; \
|
||||
} while (0)
|
||||
|
||||
/* VC6 doesn't know how to cast an unsigned 64-bit int to double */
|
||||
/* VC6 doesn't have long long. */
|
||||
#if (defined(_MSC_VER) && _MSC_VER <= 1200)
|
||||
#define AS_DOUBLE(d) (double)(int64_t)(d)
|
||||
#define LONG_TYPE int64_t
|
||||
#else
|
||||
#define AS_DOUBLE(d) (double)(d)
|
||||
#define LONG_TYPE long long
|
||||
#endif
|
||||
#define AS_DOUBLE(d) (double)(d)
|
||||
|
||||
#define RANGE_CHECK(x) (fabs(x) > 4503599627370496.0 /* 2 << 51 */)
|
||||
|
||||
/*
|
||||
* Numeric equality assertion. Comparison is made in native types but for
|
||||
* printing both are convetrted to double.
|
||||
* Numeric equality assertion.
|
||||
* Args are cast to double to ensure aruemnts are only evaluated once.
|
||||
* This will work fine for all integer types except large 64-bit values.
|
||||
*/
|
||||
#define ASSERT_EQ(actual, expected) \
|
||||
do { \
|
||||
g_num_checks++; \
|
||||
if (!((actual) == (expected))) { \
|
||||
printf("%f != %f\n", AS_DOUBLE(actual), AS_DOUBLE(expected)); \
|
||||
FAIL(#actual " == " #expected, __LINE__); \
|
||||
} \
|
||||
#define ASSERT_EQ(actual, expected) \
|
||||
do { \
|
||||
const double ad = AS_DOUBLE(actual); \
|
||||
const double ed = AS_DOUBLE(expected); \
|
||||
if (RANGE_CHECK(ad) || RANGE_CHECK(ed)) { \
|
||||
FAIL("loss of precision, use ASSERT_EQ64", __LINE__); \
|
||||
} \
|
||||
g_num_checks++; \
|
||||
if (!(ad == ed)) { \
|
||||
printf("%lf != %lf\n", ad, ed); \
|
||||
FAIL(#actual " != " #expected, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_EQ64(actual, expected) \
|
||||
do { \
|
||||
const LONG_TYPE a64 = (LONG_TYPE)(actual); \
|
||||
const LONG_TYPE e64 = (LONG_TYPE)(expected); \
|
||||
g_num_checks++; \
|
||||
if (!(a64 == e64)) { \
|
||||
printf("%lld != %lld\n", a64, e64); \
|
||||
FAIL(#actual " != " #expected, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_NE(actual, expected) \
|
||||
do { \
|
||||
const double ad = AS_DOUBLE(actual); \
|
||||
const double ed = AS_DOUBLE(expected); \
|
||||
g_num_checks++; \
|
||||
if (RANGE_CHECK(ad) || RANGE_CHECK(ed)) { \
|
||||
FAIL("loss of precision, use ASSERT_NE64", __LINE__); \
|
||||
} \
|
||||
if (!(ad != ed)) { \
|
||||
printf("%lf == %lf\n", ad, ed); \
|
||||
FAIL(#actual " == " #expected, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_NE64(actual, expected) \
|
||||
do { \
|
||||
const LONG_TYPE a64 = (LONG_TYPE)(actual); \
|
||||
const LONG_TYPE e64 = (LONG_TYPE)(expected); \
|
||||
g_num_checks++; \
|
||||
if (!(a64 != e64)) { \
|
||||
printf("%lld == %lld\n", a64, e64); \
|
||||
FAIL(#actual " == " #expected, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* "Less than" assertion. */
|
||||
#define ASSERT_LT(a, b) \
|
||||
do { \
|
||||
g_num_checks++; \
|
||||
if (!((a) < (b))) { \
|
||||
printf("%f >= %f\n", AS_DOUBLE(a), AS_DOUBLE(b)); \
|
||||
FAIL(#a " < " #b, __LINE__); \
|
||||
} \
|
||||
#define ASSERT_LT(a, b) \
|
||||
do { \
|
||||
const double ad = AS_DOUBLE(a); \
|
||||
const double bd = AS_DOUBLE(b); \
|
||||
g_num_checks++; \
|
||||
if (RANGE_CHECK(ad) || RANGE_CHECK(bd)) { \
|
||||
FAIL("loss of precision in comparison", __LINE__); \
|
||||
} \
|
||||
if (!(ad < bd)) { \
|
||||
printf("%lf >= %lf\n", ad, bd); \
|
||||
FAIL(#a " < " #b, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* "Greater than" assertion. */
|
||||
#define ASSERT_GT(a, b) \
|
||||
do { \
|
||||
g_num_checks++; \
|
||||
if (!((a) > (b))) { \
|
||||
printf("%f <= %f\n", AS_DOUBLE(a), AS_DOUBLE(b)); \
|
||||
FAIL(#a " > " #b, __LINE__); \
|
||||
} \
|
||||
#define ASSERT_GT(a, b) \
|
||||
do { \
|
||||
const double ad = AS_DOUBLE(a); \
|
||||
const double bd = AS_DOUBLE(b); \
|
||||
g_num_checks++; \
|
||||
if (!(ad > bd)) { \
|
||||
printf("%lf <= %lf\n", ad, bd); \
|
||||
FAIL(#a " > " #b, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Assert that actual == expected, where both are NUL-terminated. */
|
||||
#define ASSERT_STREQ(actual, expected) \
|
||||
do { \
|
||||
g_num_checks++; \
|
||||
if (!_assert_streq(actual, expected)) { \
|
||||
if (!_assert_streq((actual), (expected))) { \
|
||||
FAIL("ASSERT_STREQ(" #actual ", " #expected ")", __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
@ -129,21 +181,25 @@ void _strfail(const char *a, const char *e, int len);
|
||||
/* Assert that actual == expected, where both are pointers */
|
||||
#define ASSERT_PTREQ(actual, expected) \
|
||||
do { \
|
||||
const void *ap = (const void *) (actual); \
|
||||
const void *ep = (const void *) (expected); \
|
||||
g_num_checks++; \
|
||||
if (actual != expected) { \
|
||||
printf("%p != %p\n", actual, expected); \
|
||||
if (!(ap == ep)) { \
|
||||
printf("%p != %p\n", ap, ep); \
|
||||
FAIL("ASSERT_PTREQ(" #actual ", " #expected ")", __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Assert that actual != expected, where both are pointers */
|
||||
#define ASSERT_PTRNEQ(actual, expected) \
|
||||
do { \
|
||||
g_num_checks++; \
|
||||
if (actual == expected) { \
|
||||
printf("%p == %p\n", actual, expected); \
|
||||
FAIL("ASSERT_PTRNEQ(" #actual ", " #expected ")", __LINE__); \
|
||||
} \
|
||||
#define ASSERT_PTRNE(actual, expected) \
|
||||
do { \
|
||||
const void *ap = (const void *) (actual); \
|
||||
const void *ep = (const void *) (expected); \
|
||||
g_num_checks++; \
|
||||
if (!(ap != ep)) { \
|
||||
printf("%p == %p\n", ap, ep); \
|
||||
FAIL("ASSERT_PTRNE(" #actual ", " #expected ")", __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Same as STREQ, but only expected is NUL-terminated. */
|
||||
|
@ -1533,7 +1533,7 @@ static const char *test_parse_http_message(void) {
|
||||
ASSERT_EQ(mg_vcmp(&req.query_string, "a=b&c=d"), 0);
|
||||
|
||||
ASSERT_EQ(mg_parse_http(f, strlen(f), &req, 1), (int) strlen(f));
|
||||
ASSERT_EQ(req.body.len, (size_t) ~0);
|
||||
ASSERT_EQ64(req.body.len, (size_t) ~0);
|
||||
|
||||
ASSERT_EQ(mg_parse_http(g, strlen(g), &req, 1), (int) strlen(g));
|
||||
ASSERT_EQ(req.body.len, 0);
|
||||
@ -1542,7 +1542,7 @@ static const char *test_parse_http_message(void) {
|
||||
ASSERT_EQ(mg_vcmp(&req.proto, "HTTP/1.0"), 0);
|
||||
ASSERT_EQ(req.resp_code, 200);
|
||||
ASSERT_EQ(mg_vcmp(&req.resp_status_msg, "OK"), 0);
|
||||
ASSERT_EQ(req.body.len, (size_t) ~0);
|
||||
ASSERT_EQ64(req.body.len, (size_t) ~0);
|
||||
|
||||
ASSERT_EQ(mg_parse_http(i, strlen(i), &req, 0), -1);
|
||||
|
||||
@ -3921,7 +3921,7 @@ static const char *test_http_chunk2(void) {
|
||||
strcat(buf, "3\r\n...\r\na\r\n0123456789\r\n0\r");
|
||||
ASSERT_EQ(mg_handle_chunked(&nc, &hm, buf, strlen(buf)), 13);
|
||||
ASSERT_STREQ(buf, "...01234567890\r");
|
||||
ASSERT_EQ(hm.message.len, (size_t) ~0);
|
||||
ASSERT_EQ64(hm.message.len, (size_t) ~0);
|
||||
|
||||
strcat(buf, "\n\r\n");
|
||||
ASSERT_EQ(mg_handle_chunked(&nc, &hm, buf, strlen(buf)), 13);
|
||||
|
Loading…
Reference in New Issue
Block a user