diff --git a/include/criterion/internal/assert/types.h b/include/criterion/internal/assert/types.h index 55ea54bc..bf798c3d 100644 --- a/include/criterion/internal/assert/types.h +++ b/include/criterion/internal/assert/types.h @@ -44,7 +44,8 @@ struct cri_assert_node { unsigned pass : 1; unsigned dynrepr : 1; - uint32_t nchild : 30; + unsigned negated : 1; + uint32_t nchild : 29; uint32_t maxchild; struct cri_assert_node *children; }; diff --git a/include/criterion/internal/new_asserts.h b/include/criterion/internal/new_asserts.h index f40b51bb..e712d1a5 100644 --- a/include/criterion/internal/new_asserts.h +++ b/include/criterion/internal/new_asserts.h @@ -105,69 +105,78 @@ /* Logical specifiers */ #define CRI_ASSERT_TEST_SPECIFIER_not(...) , -#define CRI_ASSERT_SPECIFIER_not(E) \ - cri_cond_expect = !cri_cond_expect; \ - CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); \ - cri_cond_expect = !cri_cond_expect; \ - cri_cond_un = !cri_cond_un; \ - if (cri_cond_un != cri_cond_expect) \ - cri_assert_node_negate(cri_prevnode) - -#define CRI_ASSERT_SPECIFIER_ALL_INDIRECT(Cond, E); \ - cri_cond_un = CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); \ +#define CRI_ASSERT_SPECIFIER_not(E) \ + cri_cond_def; int *cri_pass_orig = cri_pass; cri_pass = &cri_cond_un; do { \ + cri_assert_node_init(&cri_tmpn); \ + cri_tmpn.repr = "not(" CR_STR(E) ")"; \ + struct cri_assert_node *cri_tmp = cri_assert_node_add(cri_node, &cri_tmpn); \ + struct cri_assert_node *cri_node = cri_tmp; \ + int cri_cond_def = 1, cri_cond_un; \ + int cri_cond = cri_cond_def \ + CRITERION_APPLY(CRI_ASSERT_SPECIFIER_NONE_INDIRECT, cri_cond, E); \ + cri_node->pass = !!cri_cond; \ + *cri_pass = cri_cond; \ + cri_prevnode = cri_node; \ + } while (0); cri_pass = cri_pass_orig + +#define CRI_ASSERT_SPECIFIER_ALL_INDIRECT(Cond, E); \ + { cri_cond_un = CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); } \ Cond = Cond && cri_cond_un #define CRI_ASSERT_TEST_SPECIFIER_all(...) , #define CRI_ASSERT_SPECIFIER_all(...) \ cri_cond_def; int *cri_pass_orig = cri_pass; cri_pass = &cri_cond_un; do { \ cri_assert_node_init(&cri_tmpn); \ + cri_tmpn.repr = "all(" CR_STR(__VA_ARGS__) ")"; \ struct cri_assert_node *cri_tmp = cri_assert_node_add(cri_node, &cri_tmpn); \ struct cri_assert_node *cri_node = cri_tmp; \ int cri_cond_def = 1, cri_cond_un; \ int cri_cond = cri_cond_def \ CRITERION_APPLY(CRI_ASSERT_SPECIFIER_ALL_INDIRECT, cri_cond, __VA_ARGS__); \ cri_node->pass = !!cri_cond; \ - *cri_pass = *cri_pass && cri_cond; \ + *cri_pass = cri_cond; \ cri_prevnode = cri_node; \ } while (0); cri_pass = cri_pass_orig -#define CRI_ASSERT_SPECIFIER_NONE_INDIRECT(Cond, E); \ - cri_cond_expect = !cri_cond_expect; \ - cri_cond_un = CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); \ - if (cri_cond_un != cri_cond_expect) \ - cri_assert_node_negate(cri_prevnode); \ - cri_cond_expect = !cri_cond_expect; \ +#define CRI_ASSERT_SPECIFIER_NONE_INDIRECT(Cond, E); \ + cri_cond_expect = !cri_cond_expect; \ + { cri_cond_un = CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); } \ + if (cri_cond_un != cri_cond_expect) \ + cri_assert_node_negate(cri_prevnode); \ + cri_cond_expect = !cri_cond_expect; \ Cond = Cond && !(cri_cond_un) #define CRI_ASSERT_TEST_SPECIFIER_none(...) , #define CRI_ASSERT_SPECIFIER_none(...) \ cri_cond_def; int *cri_pass_orig = cri_pass; cri_pass = &cri_cond_un; do { \ cri_assert_node_init(&cri_tmpn); \ + cri_tmpn.repr = "none(" CR_STR(__VA_ARGS__) ")"; \ struct cri_assert_node *cri_tmp = cri_assert_node_add(cri_node, &cri_tmpn); \ struct cri_assert_node *cri_node = cri_tmp; \ int cri_cond_def = 1, cri_cond_un; \ int cri_cond = cri_cond_def \ CRITERION_APPLY(CRI_ASSERT_SPECIFIER_NONE_INDIRECT, cri_cond, __VA_ARGS__); \ cri_node->pass = !!cri_cond; \ - *cri_pass = *cri_pass && cri_cond; \ + *cri_pass = cri_cond; \ cri_prevnode = cri_node; \ } while (0); cri_pass = cri_pass_orig -#define CRI_ASSERT_SPECIFIER_ANY_INDIRECT(Cond, E) \ - ; cri_cond_un = CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); \ +#define CRI_ASSERT_SPECIFIER_ANY_INDIRECT(Cond, E) \ + ; { cri_cond_un = CRI_OBSTRUCT_N(CRI_SPECIFIER_INDIRECT)()(E); } \ Cond = Cond || cri_cond_un #define CRI_ASSERT_TEST_SPECIFIER_any(...) , #define CRI_ASSERT_SPECIFIER_any(...) \ cri_cond_def; int *cri_pass_orig = cri_pass; cri_pass = &cri_cond_un; do { \ cri_assert_node_init(&cri_tmpn); \ + cri_tmpn.repr = "any(" CR_STR(__VA_ARGS__) ")"; \ struct cri_assert_node *cri_tmp = cri_assert_node_add(cri_node, &cri_tmpn); \ struct cri_assert_node *cri_node = cri_tmp; \ int cri_cond_def = 0; \ int cri_cond = cri_cond_def \ CRITERION_APPLY(CRI_ASSERT_SPECIFIER_ANY_INDIRECT, cri_cond, __VA_ARGS__); \ cri_node->pass = !!cri_cond; \ - *cri_pass = *cri_pass || cri_cond; \ + *cri_pass = cri_cond; \ cri_prevnode = cri_node; \ } while (0); cri_pass = cri_pass_orig diff --git a/src/core/assert.c b/src/core/assert.c index 6a8bdede..5ac60967 100644 --- a/src/core/assert.c +++ b/src/core/assert.c @@ -59,6 +59,7 @@ CR_API void cri_assert_node_negate(struct cri_assert_node *tree) for (size_t i = 0; i < tree->nchild; ++i) cri_assert_node_negate(&tree->children[i]); tree->pass = !tree->pass; + tree->negated = !tree->negated; } CR_API void cri_assert_node_term(struct cri_assert_node *tree) @@ -117,10 +118,16 @@ static criterion_protocol_result *collect_leaves( if (nbparams > 0) { res->repr = (char *) tree->repr; res->message = (char *) tree->message; + res->has_negated = true; + res->negated = tree->negated; + res->has_combinator = false; + res->combinator = false; const size_t display_threshold = 40; - if (nbparams == 2) { + /* Negated operands are recorded because they matched; diffing + them would come up empty, so always send them verbatim. */ + if (nbparams == 2 && !tree->negated) { if (strcmp(tree->params[0].name, "actual") || strcmp(tree->params[1].name, "expected")) { goto process_params; @@ -176,6 +183,21 @@ static criterion_protocol_result *collect_leaves( return res + 1; } + /* Combinator group nodes announce themselves in a value-less header + result before their failing operands are reported. The root node + has no repr and stays silent. */ + if (tree->repr && (tree->nchild > 0 || tree->negated)) { + *res = (criterion_protocol_result) { + .repr = (char *) tree->repr, + .message = (char *) tree->message, + .has_negated = true, + .negated = tree->negated, + .has_combinator = true, + .combinator = true, + }; + ++res; + } + for (size_t i = 0; i < tree->nchild; ++i) { struct cri_assert_node *node = &tree->children[i]; if (node->pass) diff --git a/src/core/client.c b/src/core/client.c index 5fc346a8..782eb1d0 100644 --- a/src/core/client.c +++ b/src/core/client.c @@ -546,7 +546,18 @@ bool handle_assert(struct server_ctx *sctx, struct client_ctx *ctx, const criter for (size_t i = 0; i < asrt->results_count; ++i) { criterion_protocol_result *res = &asrt->results[i]; - log(assert_sub, &asrt_stats, res->repr, res->message); + bool negated = res->has_negated && res->negated; + + const char *msg = res->message; + if (negated && (!msg || !msg[0])) + msg = "passed, but was expected to fail"; + + log(assert_sub, &asrt_stats, res->repr, msg); + + /* Combinator results are value-less headers; their failing + operands follow as results of their own. */ + if (res->has_combinator && res->combinator) + continue; switch (res->which_value) { case criterion_protocol_result_params_tag: @@ -556,7 +567,7 @@ bool handle_assert(struct server_ctx *sctx, struct client_ctx *ctx, const criter } size_t j = 0; - if (res->value.params->list_count >= 2) { + if (!negated && res->value.params->list_count >= 2) { criterion_protocol_param_entry *actual = &res->value.params->list[0]; criterion_protocol_param_entry *expected = &res->value.params->list[1]; if (!strcmp(actual->name, "actual") && !strcmp(expected->name, "expected")) { @@ -590,6 +601,11 @@ bool handle_assert(struct server_ctx *sctx, struct client_ctx *ctx, const criter break; default: + /* Negated results always carry their operands; only + non-negated ones can lose their value to an empty + diff, which points at a broken user stringifier. */ + if (negated) + break; log(assert_formatted, &asrt_stats, "@@@ "); break; } diff --git a/src/core/theories.c b/src/core/theories.c index de81cc37..4ff5008d 100644 --- a/src/core/theories.c +++ b/src/core/theories.c @@ -100,7 +100,7 @@ void cr_theory_call(struct cri_theory_ctx *ctx, void (*fnptr)(void)) static bool contains_word(const char *str, const char *pattern, size_t sz) { - char *res = strstr(str, pattern); + const char *res = strstr(str, pattern); return res && (res == str || (res > str && res[-1] == ' ')) diff --git a/src/protocol/criterion.pb.h b/src/protocol/criterion.pb.h index dc7a12c6..1c9febe1 100644 --- a/src/protocol/criterion.pb.h +++ b/src/protocol/criterion.pb.h @@ -59,6 +59,10 @@ typedef struct _criterion_protocol_result { struct _criterion_protocol_param_list *params; char *formatted; } value; + bool has_negated; + bool negated; + bool has_combinator; + bool combinator; } criterion_protocol_result; typedef struct _criterion_protocol_ack { @@ -168,7 +172,7 @@ extern "C" { #define criterion_protocol_statistic_init_default {NULL, 0, {0}} #define criterion_protocol_param_entry_init_default {NULL, 0, {NULL}} #define criterion_protocol_param_list_init_default {0, NULL} -#define criterion_protocol_result_init_default {NULL, NULL, 0, {NULL}} +#define criterion_protocol_result_init_default {NULL, NULL, 0, {NULL}, false, false, false, false} #define criterion_protocol_assert_init_default {NULL, 0, NULL, false, 0, false, 0, 0, NULL} #define criterion_protocol_log_init_default {_criterion_protocol_log_level_MIN, NULL, false, 0} #define criterion_protocol_ack_init_default {_criterion_protocol_ack_status_MIN, NULL} @@ -180,7 +184,7 @@ extern "C" { #define criterion_protocol_statistic_init_zero {NULL, 0, {0}} #define criterion_protocol_param_entry_init_zero {NULL, 0, {NULL}} #define criterion_protocol_param_list_init_zero {0, NULL} -#define criterion_protocol_result_init_zero {NULL, NULL, 0, {NULL}} +#define criterion_protocol_result_init_zero {NULL, NULL, 0, {NULL}, false, false, false, false} #define criterion_protocol_assert_init_zero {NULL, 0, NULL, false, 0, false, 0, 0, NULL} #define criterion_protocol_log_init_zero {_criterion_protocol_log_level_MIN, NULL, false, 0} #define criterion_protocol_ack_init_zero {_criterion_protocol_ack_status_MIN, NULL} @@ -196,6 +200,8 @@ extern "C" { #define criterion_protocol_result_message_tag 2 #define criterion_protocol_result_params_tag 3 #define criterion_protocol_result_formatted_tag 4 +#define criterion_protocol_result_negated_tag 5 +#define criterion_protocol_result_combinator_tag 6 #define criterion_protocol_ack_status_code_tag 1 #define criterion_protocol_ack_message_tag 2 #define criterion_protocol_assert_message_tag 1 @@ -276,7 +282,9 @@ X(a, POINTER, REPEATED, MESSAGE, list, 1) X(a, POINTER, REQUIRED, STRING, repr, 1) \ X(a, POINTER, OPTIONAL, STRING, message, 2) \ X(a, POINTER, ONEOF, MESSAGE, (value,params,value.params), 3) \ -X(a, POINTER, ONEOF, STRING, (value,formatted,value.formatted), 4) +X(a, POINTER, ONEOF, STRING, (value,formatted,value.formatted), 4) \ +X(a, STATIC, OPTIONAL, BOOL, negated, 5) \ +X(a, STATIC, OPTIONAL, BOOL, combinator, 6) #define criterion_protocol_result_CALLBACK NULL #define criterion_protocol_result_DEFAULT NULL #define criterion_protocol_result_value_params_MSGTYPE criterion_protocol_param_list diff --git a/src/protocol/criterion.proto b/src/protocol/criterion.proto index 01bb1556..f1634e2f 100644 --- a/src/protocol/criterion.proto +++ b/src/protocol/criterion.proto @@ -67,6 +67,10 @@ message result { param_list params = 3; string formatted = 4; } + + optional bool negated = 5; + + optional bool combinator = 6; } message assert { diff --git a/test/cram/asserts.t b/test/cram/asserts.t index f4354356..fd9eb066 100644 --- a/test/cram/asserts.t +++ b/test/cram/asserts.t @@ -22,9 +22,11 @@ Testing all assert messages $ failmessages.c.bin [----] failmessages.c:216: Assertion Failed + [----] all(eq(i32, 1, 1), eq(i32, 1, 1), eq(i32, 1, 0)): [----] eq(i32, 1, 0): [----] diff: [-1-]{+0+} [----] failmessages.c:217: Assertion Failed + [----] any(eq(i32, 1, 0), eq(i32, 1, 0), eq(i32, 1, 0)): [----] eq(i32, 1, 0): [----] diff: [-1-]{+0+} [----] eq(i32, 1, 0): @@ -32,10 +34,13 @@ Testing all assert messages [----] eq(i32, 1, 0): [----] diff: [-1-]{+0+} [----] failmessages.c:218: Assertion Failed - [----] eq(i32, 1, 1): - [----] @@@ + [----] none(eq(i32, 1, 0), eq(i32, 1, 0), eq(i32, 1, 1)): + [----] eq(i32, 1, 1): passed, but was expected to fail + [----] actual: 1 + [----] expected: 1 [FAIL] message::compo [----] failmessages.c:168: Assertion Failed + [----] all(lt(i8, 1, 0), le(i8, 1, 0), gt(i8, 0, 1), ge(i8, 0, 1)): [----] lt(i8, 1, 0): [----] actual: 1 [----] reference: 0 @@ -49,6 +54,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:169: Assertion Failed + [----] all(lt(i16, 1, 0), le(i16, 1, 0), gt(i16, 0, 1), ge(i16, 0, 1)): [----] lt(i16, 1, 0): [----] actual: 1 [----] reference: 0 @@ -62,6 +68,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:170: Assertion Failed + [----] all(lt(i32, 1, 0), le(i32, 1, 0), gt(i32, 0, 1), ge(i32, 0, 1)): [----] lt(i32, 1, 0): [----] actual: 1 [----] reference: 0 @@ -75,6 +82,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:171: Assertion Failed + [----] all(lt(i64, 1, 0), le(i64, 1, 0), gt(i64, 0, 1), ge(i64, 0, 1)): [----] lt(i64, 1, 0): [----] actual: 1 [----] reference: 0 @@ -88,6 +96,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:172: Assertion Failed + [----] all(lt(u8, 1, 0), le(u8, 1, 0), gt(u8, 0, 1), ge(u8, 0, 1)): [----] lt(u8, 1, 0): [----] actual: 1 [----] reference: 0 @@ -101,6 +110,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:173: Assertion Failed + [----] all(lt(u16, 1, 0), le(u16, 1, 0), gt(u16, 0, 1), ge(u16, 0, 1)): [----] lt(u16, 1, 0): [----] actual: 1 [----] reference: 0 @@ -114,6 +124,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:174: Assertion Failed + [----] all(lt(u32, 1, 0), le(u32, 1, 0), gt(u32, 0, 1), ge(u32, 0, 1)): [----] lt(u32, 1, 0): [----] actual: 1 [----] reference: 0 @@ -127,6 +138,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:175: Assertion Failed + [----] all(lt(u64, 1, 0), le(u64, 1, 0), gt(u64, 0, 1), ge(u64, 0, 1)): [----] lt(u64, 1, 0): [----] actual: 1 [----] reference: 0 @@ -140,6 +152,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 1 [----] failmessages.c:176: Assertion Failed + [----] all(lt(iptr, 1, 0), le(iptr, 1, 0), gt(iptr, 0, 1), ge(iptr, 0, 1)): [----] lt(iptr, 1, 0): [----] actual: 0x1 [----] reference: 0x0 @@ -153,6 +166,7 @@ Testing all assert messages [----] actual: 0x0 [----] reference: 0x1 [----] failmessages.c:177: Assertion Failed + [----] all(lt(uptr, 1, 0), le(uptr, 1, 0), gt(uptr, 0, 1), ge(uptr, 0, 1)): [----] lt(uptr, 1, 0): [----] actual: 0x1 [----] reference: 0x0 @@ -166,6 +180,7 @@ Testing all assert messages [----] actual: 0x0 [----] reference: 0x1 [----] failmessages.c:178: Assertion Failed + [----] all(lt(flt, 1 / 3.f, 0), le(flt, 1 / 3.f, 0), gt(flt, 0, 1 / 3.f), ge(flt, 0, 1 / 3.f)): [----] lt(flt, 1 / 3.f, 0): [----] actual: 0.333333343 [----] reference: 0 @@ -179,6 +194,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 0.333333343 [----] failmessages.c:179: Assertion Failed + [----] all(lt(dbl, 1 / 3., 0), le(dbl, 1 / 3., 0), gt(dbl, 0, 1 / 3.), ge(dbl, 0, 1 / 3.)): [----] lt(dbl, 1 / 3., 0): [----] actual: 0.33333333333333331 [----] reference: 0 @@ -192,6 +208,7 @@ Testing all assert messages [----] actual: 0 [----] reference: 0.33333333333333331 [----] failmessages.c:180: Assertion Failed + [----] all(lt(ldbl, 1 / 3.l, 0), le(ldbl, 1 / 3.l, 0), gt(ldbl, 0, 1 / 3.l), ge(ldbl, 0, 1 / 3.l)): [----] lt(ldbl, 1 / 3.l, 0): \[----\] actual: 0\.3.* (re) [----] reference: 0 @@ -205,6 +222,7 @@ Testing all assert messages [----] actual: 0 \[----\] reference: 0\.3.* (re) [----] failmessages.c:183: Assertion Failed + [----] all(lt(ptr, (void *) 1, (void *) 0), le(ptr, (void *) 1, (void *) 0), gt(ptr, (void *) 0, (void *) 1), ge(ptr, (void *) 0, (void *) 1)): [----] lt(ptr, (void *) 1, (void *) 0): [----] actual: 0x1 [----] reference: 0x0 @@ -218,6 +236,7 @@ Testing all assert messages [----] actual: 0x0 [----] reference: 0x1 [----] failmessages.c:185: Assertion Failed + [----] all(lt(str, "cba", "abc"), le(str, "cba", "abc"), gt(str, "abc", "cba"), ge(str, "abc", "cba")): [----] lt(str, "cba", "abc"): [----] actual: "cba" [----] reference: "abc" @@ -231,6 +250,7 @@ Testing all assert messages [----] actual: "abc" [----] reference: "cba" [----] failmessages.c:186: Assertion Failed + [----] all(lt(str, "cba\ncba", "abc\nabc"), le(str, "cba\ncba", "abc\nabc"), gt(str, "abc\nabc", "cba\ncba"), ge(str, "abc\nabc", "cba\ncba")): [----] lt(str, "cba\ncba", "abc\nabc"): [----] actual: "cba\n" [----] "cba" @@ -252,6 +272,7 @@ Testing all assert messages [----] reference: "cba\n" [----] "cba" [----] failmessages.c:188: Assertion Failed + [----] all(lt(wcs, L"cba", L"abc"), le(wcs, L"cba", L"abc"), gt(wcs, L"abc", L"cba"), ge(wcs, L"abc", L"cba")): [----] lt(wcs, L"cba", L"abc"): [----] actual: L"cba" [----] reference: L"abc" @@ -265,6 +286,7 @@ Testing all assert messages [----] actual: L"abc" [----] reference: L"cba" [----] failmessages.c:189: Assertion Failed + [----] all(lt(wcs, L"cba\ncba", L"abc\nabc"), le(wcs, L"cba\ncba", L"abc\nabc"), gt(wcs, L"abc\nabc", L"cba\ncba"), ge(wcs, L"abc\nabc", L"cba\ncba")): [----] lt(wcs, L"cba\ncba", L"abc\nabc"): [----] actual: L"cba\n" [----] L"cba" @@ -286,6 +308,7 @@ Testing all assert messages [----] reference: L"cba\n" [----] L"cba" [----] failmessages.c:209: Assertion Failed + [----] all(lt(stream, shi, slo), le(stream, shi, slo), gt(stream, slo, shi), ge(stream, slo, shi)): [----] lt(stream, shi, slo): [----] actual: 00: 68656c6c 6f20776f 726c6400 hello world. [----] @@ -452,55 +475,72 @@ Testing all assert messages [----] [FAIL] messages::report_escape [----] failmessages.c:53: Assertion Failed - [----] zero(i8, 0): + [----] not(zero(i8, 0)): + [----] zero(i8, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:54: Assertion Failed - [----] zero(i16, 0): + [----] not(zero(i16, 0)): + [----] zero(i16, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:55: Assertion Failed - [----] zero(i32, 0): + [----] not(zero(i32, 0)): + [----] zero(i32, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:56: Assertion Failed - [----] zero(i64, 0): + [----] not(zero(i64, 0)): + [----] zero(i64, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:57: Assertion Failed - [----] zero(u8, 0): + [----] not(zero(u8, 0)): + [----] zero(u8, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:58: Assertion Failed - [----] zero(u16, 0): + [----] not(zero(u16, 0)): + [----] zero(u16, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:59: Assertion Failed - [----] zero(u32, 0): + [----] not(zero(u32, 0)): + [----] zero(u32, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:60: Assertion Failed - [----] zero(u64, 0): + [----] not(zero(u64, 0)): + [----] zero(u64, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:61: Assertion Failed - [----] zero(iptr, 0): + [----] not(zero(iptr, 0)): + [----] zero(iptr, 0): passed, but was expected to fail [----] value: 0x0 [----] failmessages.c:62: Assertion Failed - [----] zero(uptr, 0): + [----] not(zero(uptr, 0)): + [----] zero(uptr, 0): passed, but was expected to fail [----] value: 0x0 [----] failmessages.c:63: Assertion Failed - [----] zero(flt, 0): + [----] not(zero(flt, 0)): + [----] zero(flt, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:64: Assertion Failed - [----] zero(dbl, 0): + [----] not(zero(dbl, 0)): + [----] zero(dbl, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:65: Assertion Failed - [----] zero(ldbl, 0): + [----] not(zero(ldbl, 0)): + [----] zero(ldbl, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.c:68: Assertion Failed - [----] zero(ptr, 0): + [----] not(zero(ptr, 0)): + [----] zero(ptr, 0): passed, but was expected to fail [----] value: 0x0 [----] failmessages.c:69: Assertion Failed - [----] zero(str, ""): + [----] not(zero(str, "")): + [----] zero(str, ""): passed, but was expected to fail [----] value: "" [----] failmessages.c:70: Assertion Failed - [----] zero(wcs, L""): + [----] not(zero(wcs, L"")): + [----] zero(wcs, L""): passed, but was expected to fail [----] value: L"" [----] failmessages.c:75: Assertion Failed - [----] zero(type(struct dummy_struct), dummy1): + [----] not(zero(type(struct dummy_struct), dummy1)): + [----] zero(type(struct dummy_struct), dummy1): passed, but was expected to fail [----] value: (struct dummy_struct) { [----] \t.a = 0, (esc) [----] \t.b = 0 (esc) @@ -546,9 +586,11 @@ C++ equivalents $ failmessages.cc.bin [----] failmessages.cc:216: Assertion Failed + [----] all(eq(i32, 1, 1), eq(i32, 1, 1), eq(i32, 1, 0)): [----] eq(i32, 1, 0): [----] diff: [-1-]{+0+} [----] failmessages.cc:217: Assertion Failed + [----] any(eq(i32, 1, 0), eq(i32, 1, 0), eq(i32, 1, 0)): [----] eq(i32, 1, 0): [----] diff: [-1-]{+0+} [----] eq(i32, 1, 0): @@ -556,19 +598,23 @@ C++ equivalents [----] eq(i32, 1, 0): [----] diff: [-1-]{+0+} [----] failmessages.cc:218: Assertion Failed - [----] eq(i32, 1, 1): - [----] @@@ + [----] none(eq(i32, 1, 0), eq(i32, 1, 0), eq(i32, 1, 1)): + [----] eq(i32, 1, 1): passed, but was expected to fail + [----] actual: 1 + [----] expected: 1 [FAIL] message::compo [----] failmessages.cc:222: Assertion Failed [----] throw(std::bad_alloc, throw std::invalid_argument("exception message")): [----] message: "exception message" [----] failmessages.cc:223: Assertion Failed + [----] not(throw(std::invalid_argument, throw std::invalid_argument("exception message"))): [----] failmessages.cc:224: Assertion Failed [----] nothrow(throw std::invalid_argument("exception message")): [----] message: "exception message" [----] failmessages.cc:225: Assertion Failed [FAIL] message::exception [----] failmessages.cc:174: Assertion Failed + [----] all(lt(i8, 1, 0), le(i8, 1, 0), gt(i8, 0, 1), ge(i8, 0, 1)): [----] lt(i8, 1, 0): [----] actual: 1 [----] reference: 0 @@ -582,6 +628,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:175: Assertion Failed + [----] all(lt(i16, 1, 0), le(i16, 1, 0), gt(i16, 0, 1), ge(i16, 0, 1)): [----] lt(i16, 1, 0): [----] actual: 1 [----] reference: 0 @@ -595,6 +642,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:176: Assertion Failed + [----] all(lt(i32, 1, 0), le(i32, 1, 0), gt(i32, 0, 1), ge(i32, 0, 1)): [----] lt(i32, 1, 0): [----] actual: 1 [----] reference: 0 @@ -608,6 +656,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:177: Assertion Failed + [----] all(lt(i64, 1, 0), le(i64, 1, 0), gt(i64, 0, 1), ge(i64, 0, 1)): [----] lt(i64, 1, 0): [----] actual: 1 [----] reference: 0 @@ -621,6 +670,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:178: Assertion Failed + [----] all(lt(u8, 1, 0), le(u8, 1, 0), gt(u8, 0, 1), ge(u8, 0, 1)): [----] lt(u8, 1, 0): [----] actual: 1 [----] reference: 0 @@ -634,6 +684,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:179: Assertion Failed + [----] all(lt(u16, 1, 0), le(u16, 1, 0), gt(u16, 0, 1), ge(u16, 0, 1)): [----] lt(u16, 1, 0): [----] actual: 1 [----] reference: 0 @@ -647,6 +698,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:180: Assertion Failed + [----] all(lt(u32, 1, 0), le(u32, 1, 0), gt(u32, 0, 1), ge(u32, 0, 1)): [----] lt(u32, 1, 0): [----] actual: 1 [----] reference: 0 @@ -660,6 +712,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:181: Assertion Failed + [----] all(lt(u64, 1, 0), le(u64, 1, 0), gt(u64, 0, 1), ge(u64, 0, 1)): [----] lt(u64, 1, 0): [----] actual: 1 [----] reference: 0 @@ -673,6 +726,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:182: Assertion Failed + [----] all(lt(iptr, 1, 0), le(iptr, 1, 0), gt(iptr, 0, 1), ge(iptr, 0, 1)): [----] lt(iptr, 1, 0): [----] actual: 1 [----] reference: 0 @@ -686,6 +740,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:183: Assertion Failed + [----] all(lt(uptr, 1, 0), le(uptr, 1, 0), gt(uptr, 0, 1), ge(uptr, 0, 1)): [----] lt(uptr, 1, 0): [----] actual: 1 [----] reference: 0 @@ -699,6 +754,7 @@ C++ equivalents [----] actual: 0 [----] reference: 1 [----] failmessages.cc:184: Assertion Failed + [----] all(lt(flt, 1 / 3.f, 0), le(flt, 1 / 3.f, 0), gt(flt, 0, 1 / 3.f), ge(flt, 0, 1 / 3.f)): [----] lt(flt, 1 / 3.f, 0): [----] actual: 0.333333 [----] reference: 0 @@ -712,6 +768,7 @@ C++ equivalents [----] actual: 0 [----] reference: 0.333333 [----] failmessages.cc:185: Assertion Failed + [----] all(lt(dbl, 1 / 3., 0), le(dbl, 1 / 3., 0), gt(dbl, 0, 1 / 3.), ge(dbl, 0, 1 / 3.)): [----] lt(dbl, 1 / 3., 0): [----] actual: 0.333333 [----] reference: 0 @@ -725,6 +782,7 @@ C++ equivalents [----] actual: 0 [----] reference: 0.333333 [----] failmessages.cc:186: Assertion Failed + [----] all(lt(ldbl, 1 / 3.l, 0), le(ldbl, 1 / 3.l, 0), gt(ldbl, 0, 1 / 3.l), ge(ldbl, 0, 1 / 3.l)): [----] lt(ldbl, 1 / 3.l, 0): [----] actual: 0.333333 [----] reference: 0 @@ -738,6 +796,7 @@ C++ equivalents [----] actual: 0 [----] reference: 0.333333 [----] failmessages.cc:189: Assertion Failed + [----] all(lt(ptr, (void *) 1, (void *) 0), le(ptr, (void *) 1, (void *) 0), gt(ptr, (void *) 0, (void *) 1), ge(ptr, (void *) 0, (void *) 1)): [----] lt(ptr, (void *) 1, (void *) 0): [----] actual: @1 [----] reference: nullptr @@ -751,6 +810,7 @@ C++ equivalents [----] actual: nullptr [----] reference: @1 [----] failmessages.cc:191: Assertion Failed + [----] all(lt(str, "cba", "abc"), le(str, "cba", "abc"), gt(str, "abc", "cba"), ge(str, "abc", "cba")): [----] lt(str, "cba", "abc"): [----] actual: "cba" [----] reference: "abc" @@ -764,6 +824,7 @@ C++ equivalents [----] actual: "abc" [----] reference: "cba" [----] failmessages.cc:192: Assertion Failed + [----] all(lt(str, "cba\ncba", "abc\nabc"), le(str, "cba\ncba", "abc\nabc"), gt(str, "abc\nabc", "cba\ncba"), ge(str, "abc\nabc", "cba\ncba")): [----] lt(str, "cba\ncba", "abc\nabc"): [----] actual: "cba\n" [----] "cba" @@ -785,6 +846,7 @@ C++ equivalents [----] reference: "cba\n" [----] "cba" [----] failmessages.cc:194: Assertion Failed + [----] all(lt(wcs, L"cba", L"abc"), le(wcs, L"cba", L"abc"), gt(wcs, L"abc", L"cba"), ge(wcs, L"abc", L"cba")): [----] lt(wcs, L"cba", L"abc"): [----] actual: L"cba" [----] reference: L"abc" @@ -798,6 +860,7 @@ C++ equivalents [----] actual: L"abc" [----] reference: L"cba" [----] failmessages.cc:195: Assertion Failed + [----] all(lt(wcs, L"cba\ncba", L"abc\nabc"), le(wcs, L"cba\ncba", L"abc\nabc"), gt(wcs, L"abc\nabc", L"cba\ncba"), ge(wcs, L"abc\nabc", L"cba\ncba")): [----] lt(wcs, L"cba\ncba", L"abc\nabc"): [----] actual: L"cba\n" [----] L"cba" @@ -819,6 +882,7 @@ C++ equivalents [----] reference: L"cba\n" [----] L"cba" [----] failmessages.cc:212: Assertion Failed + [----] all(lt(stream, shi, slo), le(stream, shi, slo), gt(stream, slo, shi), ge(stream, slo, shi)): [----] lt(stream, shi, slo): [----] actual: 00: 68656c6c 6f20776f 726c6400 hello world. [----] @@ -1002,64 +1066,83 @@ C++ equivalents [----] [FAIL] messages::report_escape [----] failmessages.cc:50: Assertion Failed - [----] zero(i8, 0): + [----] not(zero(i8, 0)): + [----] zero(i8, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:51: Assertion Failed - [----] zero(i16, 0): + [----] not(zero(i16, 0)): + [----] zero(i16, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:52: Assertion Failed - [----] zero(i32, 0): + [----] not(zero(i32, 0)): + [----] zero(i32, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:53: Assertion Failed - [----] zero(i64, 0): + [----] not(zero(i64, 0)): + [----] zero(i64, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:54: Assertion Failed - [----] zero(u8, 0): + [----] not(zero(u8, 0)): + [----] zero(u8, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:55: Assertion Failed - [----] zero(u16, 0): + [----] not(zero(u16, 0)): + [----] zero(u16, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:56: Assertion Failed - [----] zero(u32, 0): + [----] not(zero(u32, 0)): + [----] zero(u32, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:57: Assertion Failed - [----] zero(u64, 0): + [----] not(zero(u64, 0)): + [----] zero(u64, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:58: Assertion Failed - [----] zero(iptr, 0): + [----] not(zero(iptr, 0)): + [----] zero(iptr, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:59: Assertion Failed - [----] zero(uptr, 0): + [----] not(zero(uptr, 0)): + [----] zero(uptr, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:60: Assertion Failed - [----] zero(flt, 0): + [----] not(zero(flt, 0)): + [----] zero(flt, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:61: Assertion Failed - [----] zero(dbl, 0): + [----] not(zero(dbl, 0)): + [----] zero(dbl, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:62: Assertion Failed - [----] zero(ldbl, 0): + [----] not(zero(ldbl, 0)): + [----] zero(ldbl, 0): passed, but was expected to fail [----] value: 0 [----] failmessages.cc:65: Assertion Failed - [----] zero(ptr, 0): + [----] not(zero(ptr, 0)): + [----] zero(ptr, 0): passed, but was expected to fail [----] value: nullptr [----] failmessages.cc:66: Assertion Failed - [----] zero(str, ""): + [----] not(zero(str, "")): + [----] zero(str, ""): passed, but was expected to fail [----] value: "" [----] failmessages.cc:67: Assertion Failed - [----] zero(wcs, L""): + [----] not(zero(wcs, L"")): + [----] zero(wcs, L""): passed, but was expected to fail [----] value: L"" [----] failmessages.cc:69: Assertion Failed - [----] zero(type(dummy_struct), dummy_struct{}): + [----] not(zero(type(dummy_struct), dummy_struct{})): + [----] zero(type(dummy_struct), dummy_struct{}): passed, but was expected to fail [----] value: (struct dummy_struct) { [----] \t.a = 0, (esc) [----] \t.b = 0 (esc) [----] } [----] failmessages.cc:73: Assertion Failed - [----] zero(type(int_vect), int_vect{}): + [----] not(zero(type(int_vect), int_vect{})): + [----] zero(type(int_vect), int_vect{}): passed, but was expected to fail [----] value: {} [----] failmessages.cc:76: Assertion Failed - [----] zero(type(string_int_map), string_int_map{}): + [----] not(zero(type(string_int_map), string_int_map{})): + [----] zero(type(string_int_map), string_int_map{}): passed, but was expected to fail [----] value: {} [FAIL] messages::zero [====] Synthesis: Tested: 7 | Passing: 0 | Failing: 7 | Crashing: 0 diff --git a/test/cram/bugs.t b/test/cram/bugs.t index 7f42d220..6b444e8e 100644 --- a/test/cram/bugs.t +++ b/test/cram/bugs.t @@ -11,3 +11,73 @@ https://github.com/Snaipe/Criterion/issues/463 [FAIL] bug463::nonl [====] Synthesis: Tested: 2 | Passing: 0 | Failing: 2 | Crashing: 0 +Nested assertion combinators must resolve and compose correctly + + $ combinators.c.bin + [----] combinators.c:26: Assertion Failed + [----] any(eq(i32, 1, 0), all(eq(i32, 1, 0), eq(i32, 1, 1))): + [----] eq(i32, 1, 0): + [----] diff: [-1-]{+0+} + [----] all(eq(i32, 1, 0), eq(i32, 1, 1)): + [----] eq(i32, 1, 0): + [----] diff: [-1-]{+0+} + [FAIL] combinators::nested_any_fails + [----] combinators.c:22: Assertion Failed + [----] not(all(eq(i32, 1, 1), eq(i32, 2, 2))): + [----] all(eq(i32, 1, 1), eq(i32, 2, 2)): passed, but was expected to fail + [----] eq(i32, 1, 1): passed, but was expected to fail + [----] actual: 1 + [----] expected: 1 + [----] eq(i32, 2, 2): passed, but was expected to fail + [----] actual: 2 + [----] expected: 2 + [FAIL] combinators::not_all_fails + [====] Synthesis: Tested: 5 | Passing: 3 | Failing: 2 | Crashing: 0 + +https://github.com/Snaipe/Criterion/issues/463 + + $ bug594.c.bin + [----] bug594.c:19: Assertion Failed + [----] all(eq(int, 1, 1), eq(int, 1, 2)): + [----] eq(int, 1, 2): + [----] diff: [-1-]{+2+} + [FAIL] bug594::all + [----] bug594.c:23: Assertion Failed + [----] any(eq(int, 1, 2), eq(int, 3, 4)): + [----] eq(int, 1, 2): + [----] diff: [-1-]{+2+} + [----] eq(int, 3, 4): + [----] diff: [-3-]{+4+} + [FAIL] bug594::any + [----] bug594.c:27: Assertion Failed + [----] not(all(eq(int, 1, 1))): + [----] all(eq(int, 1, 1)): passed, but was expected to fail + [----] eq(int, 1, 1): passed, but was expected to fail + [----] actual: 1 + [----] expected: 1 + [FAIL] bug594::negated_combinator + [----] bug594.c:5: Assertion Failed + [----] none(eq(int, 1, 1), eq(int, 3, 3), eq(int, 3, 3)): + [----] eq(int, 1, 1): passed, but was expected to fail + [----] actual: 1 + [----] expected: 1 + [----] eq(int, 3, 3): passed, but was expected to fail + [----] actual: 3 + [----] expected: 3 + [----] eq(int, 3, 3): passed, but was expected to fail + [----] actual: 3 + [----] expected: 3 + [FAIL] bug594::none + [----] bug594.c:9: Assertion Failed + [----] not(eq(int, 1, 1)): + [----] eq(int, 1, 1): passed, but was expected to fail + [----] actual: 1 + [----] expected: 1 + [FAIL] bug594::not + [----] bug594.c:15: Assertion Failed + [----] not(eq(str, s, s)): + [----] eq(str, s, s): passed, but was expected to fail + [----] actual: "a string well over the forty character display threshold" + [----] expected: "a string well over the forty character display threshold" + [FAIL] bug594::not_long + [====] Synthesis: Tested: 7 | Passing: 1 | Failing: 6 | Crashing: 0 diff --git a/test/full/bug594.c b/test/full/bug594.c new file mode 100644 index 00000000..2d24be18 --- /dev/null +++ b/test/full/bug594.c @@ -0,0 +1,35 @@ +#include +#include + +Test(bug594, none) { + cr_expect(none(eq(int, 1, 1), eq(int, 3, 3), eq(int, 3, 3))); +} + +Test(bug594, not) { + cr_expect(not(eq(int, 1, 1))); +} + +Test(bug594, not_long) { + char s[] = "a string well over the forty character display threshold"; + + cr_expect(not(eq(str, s, s))); +} + +Test(bug594, all) { + cr_expect(all(eq(int, 1, 1), eq(int, 1, 2))); +} + +Test(bug594, any) { + cr_expect(any(eq(int, 1, 2), eq(int, 3, 4))); +} + +Test(bug594, negated_combinator) { + cr_expect(not(all(eq(int, 1, 1)))); +} + +Test(bug594, passing) { + cr_expect(none(eq(int, 1, 2), eq(int, 3, 4))); + cr_expect(not(eq(int, 1, 2))); + cr_expect(all(eq(int, 1, 1), not(eq(int, 1, 2)))); + cr_expect(any(eq(int, 1, 2), not(not(eq(int, 3, 3))))); +} diff --git a/test/full/combinators.c b/test/full/combinators.c new file mode 100644 index 00000000..ed88fa54 --- /dev/null +++ b/test/full/combinators.c @@ -0,0 +1,27 @@ +#include +#include + +Test(combinators, all_inside_any) { + cr_expect(any(eq(i32, 1, 0), all(eq(i32, 1, 1), eq(i32, 2, 2)))); + cr_expect(any(eq(i32, 1, 0), none(eq(i32, 1, 0)))); + cr_expect(all(any(eq(i32, 1, 0), all(eq(i32, 1, 1), eq(i32, 2, 2))), eq(i32, 3, 3))); +} + +Test(combinators, not_all) { + cr_expect(not(all(eq(i32, 1, 0), eq(i32, 1, 1)))); + cr_expect(not(none(eq(i32, 1, 1)))); +} + +Test(combinators, siblings) { + cr_expect(all(any(eq(i32, 1, 1), eq(i32, 1, 0)), any(eq(i32, 2, 2)))); + cr_expect(any(all(eq(i32, 1, 0)), all(eq(i32, 2, 2)))); + cr_expect(none(any(eq(i32, 1, 0)), any(eq(i32, 0, 1)))); +} + +Test(combinators, not_all_fails) { + cr_expect(not(all(eq(i32, 1, 1), eq(i32, 2, 2)))); +} + +Test(combinators, nested_any_fails) { + cr_expect(any(eq(i32, 1, 0), all(eq(i32, 1, 0), eq(i32, 1, 1)))); +} diff --git a/test/full/meson.build b/test/full/meson.build index 9d30b0aa..43bed466 100644 --- a/test/full/meson.build +++ b/test/full/meson.build @@ -1,4 +1,5 @@ full_tests = [ + 'combinators.c', 'exit.c', 'failmessages.c', 'flood.c', @@ -8,6 +9,7 @@ full_tests = [ # bug-specific programs 'bug463.c', + 'bug594.c', ] if get_option('theories').enabled()