On Wed, Aug 14, 2019 at 1:07 PM Stanislav Fomichev <sdf@xxxxxxxxxxx> wrote: > > On 08/14, Andrii Nakryiko wrote: > > On Wed, Aug 14, 2019 at 9:48 AM Stanislav Fomichev <sdf@xxxxxxxxxx> wrote: > > > > > > Now that we have a global per-test/per-environment state, there > > > is no longer the need to have global fail/success counters > > > (and there is no need to save/get the diff before/after the > > > test). > > > > > > Cc: Andrii Nakryiko <andriin@xxxxxx> > > > Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxx> > > > --- [...] > > > +void __test__fail(const char *file, int line) > > > +{ > > > + if (env.test->subtest_name) > > > + fprintf(stderr, "%s:%s failed at %s:%d, errno=%d\n", > > > > Nit: let's keep <test>/<subtest> convention here as well? > > > > Failure doesn't always set errno, this will be quite confusing > > sometimes. Especially for higher-level libbpf APIs, which don't set > > errno at all. > > If test wants to log additional information, let it do it explicitly. > SG. Maybe we can adapt log_err from cgroup_helpers.h for error reporting > once I move sockopt tests into test_progs. > > > Also, _CHECK already logs error message, so this is going to be > > double-verbose for typical case. I'd say let's drop these error > > messages and instead slightly extend _CHECK one with line number (it > > already logs func name). > Not everything goes through the _CHECK macro unfortunately, see Well, it should (at least eventually). If existing macro doesn't cover typical use case, we can add one that does cover. > all the cases where I did s/error_cnt++/test__fail/. How about I > remove the error message from _CHECK and leave it in __test_fail? I'd keep test__fail() and test__success() as a low-level building block. And move all the logging into corresponding high-level macro. This still gives flexibility to do one-off crazy tests, if necessary, while having consistent approach for everything else. > > > > + env.test->test_name, env.test->subtest_name, > > > + file, line, errno); > > > + else > > > + fprintf(stderr, "%s failed at %s:%d, errno=%d\n", > > > + env.test->test_name, file, line, errno); > > > + > > > + env.test->fail_cnt++; > > > +} > > > + > > > struct ipv4_packet pkt_v4 = { > > > .eth.h_proto = __bpf_constant_htons(ETH_P_IP), > > > .iph.ihl = 5, > > > @@ -150,7 +145,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name) > > > map = bpf_object__find_map_by_name(obj, name); > > > if (!map) { > > > printf("%s:FAIL:map '%s' not found\n", test, name); > > > - error_cnt++; > > > + test__fail(); > > > return -1; > > > } > > > return bpf_map__fd(map); > > > @@ -509,8 +504,6 @@ int main(int argc, char **argv) > > > stdio_hijack(); > > > for (i = 0; i < prog_test_cnt; i++) { > > > struct prog_test_def *test = &prog_test_defs[i]; > > > - int old_pass_cnt = pass_cnt; > > > - int old_error_cnt = error_cnt; > > > > > > env.test = test; > > > test->test_num = i + 1; > > > @@ -525,14 +518,12 @@ int main(int argc, char **argv) > > > test__end_subtest(); > > > > > > test->tested = true; > > > - test->pass_cnt = pass_cnt - old_pass_cnt; > > > - test->error_cnt = error_cnt - old_error_cnt; > > > - if (test->error_cnt) > > > + if (test->fail_cnt) > > > env.fail_cnt++; > > > else > > > env.succ_cnt++; > > > > > > - dump_test_log(test, test->error_cnt); > > > + dump_test_log(test, test->fail_cnt); > > > > > > fprintf(env.stdout, "#%3d %4s %s\n", > > > test->test_num, > > > @@ -546,5 +537,5 @@ int main(int argc, char **argv) > > > free(env.test_selector.num_set); > > > free(env.subtest_selector.num_set); > > > > > > - return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; > > > + return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS; > > > } > > > diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h > > > index 9defd35cb6c0..7b05921784a4 100644 > > > --- a/tools/testing/selftests/bpf/test_progs.h > > > +++ b/tools/testing/selftests/bpf/test_progs.h > > > @@ -38,7 +38,23 @@ typedef __u16 __sum16; > > > #include "trace_helpers.h" > > > #include "flow_dissector_load.h" > > > > > > -struct prog_test_def; > > > +struct prog_test_def { > > > + const char *test_name; > > > + int test_num; > > > + void (*run_test)(void); > > > + bool force_log; > > > + bool tested; > > > + > > > + const char *subtest_name; > > > + int subtest_num; > > > + > > > + int succ_cnt; > > > + int fail_cnt; > > > > So I'm neutral on this rename, I even considered it myself initially. > > But keep in mind, that succ/fail in env means number of tests, while > > test->succ/fail means number of assertions. We don't report total > > number of failed checks anymore, so it doesn't matter, but if we ever > > want to keep track of that at env level, it will be very confusing and > > inconvenient. > Point taken, I didn't think about it, let me undo the rename. I'll > try to add a comment instead to highlight the difference. > > > > + > > > + /* store counts before subtest started */ > > > + int old_succ_cnt; > > > + int old_fail_cnt; > > > +}; > > > > Did you move it here just to access env.test->succ_cnt in _CHECK()? > > Maybe add test__success() counterpart to test__fail() instead? > Yeah, good point, will do. > > > > > > > struct test_selector { > > > const char *name; > > > @@ -67,13 +83,13 @@ struct test_env { > > > int skip_cnt; /* skipped tests */ > > > }; > > > > > > -extern int error_cnt; > > > -extern int pass_cnt; > > > extern struct test_env env; > > > > > > extern void test__force_log(); > > > extern bool test__start_subtest(const char *name); > > > extern void test__skip(void); > > > +#define test__fail() __test__fail(__FILE__, __LINE__) > > > +extern void __test__fail(const char *file, int line); > > > > Given my comment above about too verbose logging, I'd say let's keep > > this simple and have just > > > > extern void test__fail() > > > > And let _CHECK log file:line. > See above about test__fail without _CHECK. Maybe we should do QCHECK > as you suggested in the other email. > > So those lonely: > > if (err) { > error_cnt++; > return; > } > > checks can instead be converted to: > > if (QCHECK(err)) > return; > > Let me play with it a bit and see how it goes. Yeah, give it a go. Try keeping file:line logging in macro, where it's more natural, IMO. > > > > > > > #define MAGIC_BYTES 123 > > > > > > @@ -96,11 +112,11 @@ extern struct ipv6_packet pkt_v6; > > > #define _CHECK(condition, tag, duration, format...) ({ \ > > > int __ret = !!(condition); \ > > > if (__ret) { \ > > > - error_cnt++; \ > > > + test__fail(); \ > > > printf("%s:FAIL:%s ", __func__, tag); \ > > > printf(format); \ > > > } else { \ > > > - pass_cnt++; \ > > > + env.test->succ_cnt++; \ > > > printf("%s:PASS:%s %d nsec\n", \ > > > __func__, tag, duration); \ > > > } \ > > > -- > > > 2.23.0.rc1.153.gdeed80330f-goog > > >