From: Manu Bretelle <chantr4@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: bpf@vger.kernel.org, andrii@kernel.org, mykolal@fb.com,
ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev,
yhs@fb.com
Subject: Re: [PATCH bpf-next] selftests/bpf: add --json-summary option to test_progs
Date: Thu, 16 Mar 2023 17:40:03 -0700 [thread overview]
Message-ID: <ZBO24yyuynZCMqGO@worktop> (raw)
In-Reply-To: <CAEf4BzYiFYdqToBpnnYMCxi+eihMu1VJ1Njz9_3vHES9y3yYcw@mail.gmail.com>
On Thu, Mar 16, 2023 at 04:21:52PM -0700, Andrii Nakryiko wrote:
> On Wed, Mar 15, 2023 at 11:39 PM Manu Bretelle <chantr4@gmail.com> wrote:
> >
> > Currently, test_progs outputs all stdout/stderr as it runs, and when it
> > is done, prints a summary.
> >
> > It is non-trivial for tooling to parse that output and extract meaningful
> > information from it.
> >
> > This change adds a new option, `--json-summary`/`-J` that let the caller
> > specify a file where `test_progs{,-no_alu32}` can write a summary of the
> > run in a json format that can later be parsed by tooling.
> >
> > Currently, it creates a summary section with successes/skipped/failures
> > followed by a list of failed tests/subtests.
> >
> > A test contains the following fields:
> > - test_name: the name of the test
> > - test_number: the number of the test
> > - message: the log message that was printed by the test.
> > - failed: A boolean indicating whether the test failed or not. Currently
> > we only output failed tests, but in the future, successful tests could
> > be added.
> >
> > A subtest contains the following fields:
> > - test_name: same as above
> > - test_number: sanme as above
> > - subtest_name: the name of the subtest
> > - subtest_number: the number of the subtest.
> > - message: the log message that was printed by the subtest.
> > - is_subtest: a boolean indicating that the entry is a subtest.
>
> "is_" prefix stands out compared to other bool field ("failed"),
> should we call this just "subtest" for consistency?
>
yes, I will give a try to the nested representation and play a bit more
with jq. In any case, this will become `subtest[s]`.
> > - failed: same as above but for the subtest
> >
> > ```
> > $ sudo ./test_progs -a $(grep -v '^#' ./DENYLIST.aarch64 | awk '{print
> > $1","}' | tr -d '\n') -j -J /tmp/test_progs.json
> > $ jq . < /tmp/test_progs.json | head -n 30
> > $ head -n 30 /tmp/test_progs.json
> > {
> > "success": 29,
> > "success_subtest": 23,
> > "skipped": 3,
> > "failed": 27,
> > "results": [{
> > "test_name": "bpf_cookie",
> > "test_number": 10,
> > "message": "test_bpf_cookie:PASS:skel_open 0 nsec\n",
> > "failed": true
> > },{
> > "test_name": "bpf_cookie",
> > "subtest_name": "multi_kprobe_link_api",
> > "test_number": 10,
> > "subtest_number": 2,
> > "message": "kprobe_multi_link_api_subtest:PASS:load_kallsyms
> > 0 nsec\nlibbpf: extern 'bpf_testmod_fentry_test1' (strong): not
> > resolved\nlibbpf: failed to load object 'kprobe_multi'\nlibbpf: failed
> > to load BPF skeleton 'kprobe_multi':
> > -3\nkprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected
> > error: -3\n",
> > "is_subtest": true,
> > "failed": true
> > },{
> > "test_name": "bpf_cookie",
> > "subtest_name": "multi_kprobe_attach_api",
> > "test_number": 10,
> > "subtest_number": 3,
> > "message": "libbpf: extern 'bpf_testmod_fentry_test1'
> > (strong): not resolved\nlibbpf: failed to load object
> > 'kprobe_multi'\nlibbpf: failed to load BPF skeleton 'kprobe_multi':
> > -3\nkprobe_multi_attach_api_subtest:FAIL:fentry_raw_skel_load unexpected
> > error: -3\n",
> > "is_subtest": true,
> > "failed": true
> > },{
> > "test_name": "bpf_cookie",
> > "subtest_name": "lsm",
> > "test_number": 10,
> > ```
> >
> > The file can then be used to print a summary of the test run and list of
> > failing tests/subtests:
> >
> > ```
> > $ jq -r < /tmp/test_progs.json '"Success:
> > \(.success)/\(.success_subtest), Skipped: \(.skipped), Failed:
> > \(.failed)"'
> >
> > Success: 29/23, Skipped: 3, Failed: 27
> > $ jq -r <
> > /tmp/test_progs.json '.results[] | if .is_subtest then
> > "#\(.test_number)/\(.subtest_number) \(.test_name)/\(.subtest_name)"
> > else "#\(.test_number) \(.test_name)" end'
> > ```
> >
> > Signed-off-by: Manu Bretelle <chantr4@gmail.com>
> > ---
>
> Looks great, some nits below.
>
> > tools/testing/selftests/bpf/Makefile | 4 +-
> > tools/testing/selftests/bpf/json_writer.c | 1 +
> > tools/testing/selftests/bpf/json_writer.h | 1 +
> > tools/testing/selftests/bpf/test_progs.c | 83 +++++++++++++++++++++--
> > tools/testing/selftests/bpf/test_progs.h | 1 +
> > 5 files changed, 84 insertions(+), 6 deletions(-)
> > create mode 120000 tools/testing/selftests/bpf/json_writer.c
> > create mode 120000 tools/testing/selftests/bpf/json_writer.h
> >
>
> [...]
>
> > @@ -269,10 +270,22 @@ static void print_subtest_name(int test_num, int subtest_num,
> > fprintf(env.stdout, "\n");
> > }
> >
> > +static void jsonw_write_log_message(json_writer_t *w, char *log_buf, size_t log_cnt)
> > +{
> > + // open_memstream (from stdio_hijack_init) ensures that log_bug is terminated by a
> > + // null byte. Yet in parralel mode, log_buf will be NULL if there is no message.
>
> please don't use C++-style comments, let's use /* */ consistently
>
> also typo: parallel
>
ack
> > + if (log_cnt) {
> > + jsonw_string_field(w, "message", log_buf);
> > + } else {
> > + jsonw_string_field(w, "message", "");
> > + }
> > +}
> > +
>
> [...]
>
> > @@ -1283,7 +1327,7 @@ static void *dispatch_thread(void *ctx)
> > } while (false);
> >
> > pthread_mutex_lock(&stdout_output_lock);
> > - dump_test_log(test, state, false, true);
> > + dump_test_log(test, state, false, true, NULL);
> > pthread_mutex_unlock(&stdout_output_lock);
> > } /* while (true) */
> > error:
> > @@ -1322,8 +1366,28 @@ static void calculate_summary_and_print_errors(struct test_env *env)
> > fail_cnt++;
> > else
> > succ_cnt++;
> > +
> > + }
> > +
> > + json_writer_t *w = NULL;
>
> please declare variable at the top to follow C89 style
>
ack
> > +
> > + if (env->json) {
> > + w = jsonw_new(env->json);
> > + if (!w)
> > + fprintf(env->stderr, "Failed to create new JSON stream.");
> > }
> >
> > + if (w) {
> > + jsonw_pretty(w, 1);
>
> true, it's bool
>
actually, given that this is not printed to stdout, and jq is widely available...
probably no need to pretty the output.
> > + jsonw_start_object(w);
> > + jsonw_uint_field(w, "success", succ_cnt);
> > + jsonw_uint_field(w, "success_subtest", sub_succ_cnt);
> > + jsonw_uint_field(w, "skipped", skip_cnt);
> > + jsonw_uint_field(w, "failed", fail_cnt);
> > + jsonw_name(w, "results");
> > + jsonw_start_array(w);
> > +
> > + }
>
> [...]
prev parent reply other threads:[~2023-03-17 0:40 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-16 6:39 [PATCH bpf-next] selftests/bpf: add --json-summary option to test_progs Manu Bretelle
2023-03-16 15:03 ` Eduard Zingerman
2023-03-16 16:38 ` Manu Bretelle
2023-03-16 19:18 ` Eduard Zingerman
2023-03-16 23:23 ` Andrii Nakryiko
2023-03-16 23:33 ` Eduard Zingerman
2023-03-17 0:07 ` Andrii Nakryiko
2023-03-17 0:24 ` Manu Bretelle
2023-03-16 23:21 ` Andrii Nakryiko
2023-03-17 0:40 ` Manu Bretelle [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZBO24yyuynZCMqGO@worktop \
--to=chantr4@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=martin.lau@linux.dev \
--cc=mykolal@fb.com \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.