[Intel-gfx] [PATCH i-g-t] Add support for subtest-specific documentation
Leo
sunpeng.li at amd.com
Thu Jun 29 16:08:28 UTC 2017
On 2017-06-22 07:30 AM, Petri Latvala wrote:
> The current documentation for tests is limited to a single string per
> test binary. This patch adds support for documenting individual
> subtests.
>
> The syntax for subtest documentation is:
>
> igt_subtest_documentation("Frob knobs to see if one of the "
> "crossbeams will go out of skew on the "
> "treadle.");
> igt_subtest("knob-frobbing-askew")
> test_frob();
>
> or with a format string:
>
> for_example_loop(e) {
> igt_subtest_documentation_f("Frob %s to see if one of the "
> "crossbeams will go out of skew on the "
> "treadle.", e->readable_name);
> igt_subtest_f("%s-frob-askew", e->name)
> test_frob(e);
> }
>
> The documentation cannot be extracted from just comments, because
> associating them with the correct subtest name will then require doing
> pattern matching in the documentation generator, for subtests where
> the name is generated at runtime using igt_subtest_f.
>
> This patch does not hook the subtest documentation to the doc
> building. It adds command line parameters for --document-all-subtests
> and --document-subtest <namepattern>, but using them blindly without
> parallelizing will cause the docs build time to rise too much.
>
> Signed-off-by: Petri Latvala <petri.latvala at intel.com>
Acked-by: Leo Li <sunpeng.li at amd.com>
> ---
> lib/igt_aux.c | 8 ++--
> lib/igt_core.c | 147 +++++++++++++++++++++++++++++++++++++++++++++------------
> lib/igt_core.h | 6 ++-
> 3 files changed, 126 insertions(+), 35 deletions(-)
>
> diff --git a/lib/igt_aux.c b/lib/igt_aux.c
> index eb563f7..4796b01 100644
> --- a/lib/igt_aux.c
> +++ b/lib/igt_aux.c
> @@ -311,7 +311,7 @@ static void sig_handler(int i)
> */
> void igt_fork_signal_helper(void)
> {
> - if (igt_only_list_subtests())
> + if (igt_only_collect_data())
> return;
>
> /* We pick SIGCONT as it is a "safe" signal - if we send SIGCONT to
> @@ -344,7 +344,7 @@ void igt_fork_signal_helper(void)
> */
> void igt_stop_signal_helper(void)
> {
> - if (igt_only_list_subtests())
> + if (igt_only_collect_data())
> return;
>
> igt_stop_helper(&signal_helper);
> @@ -375,7 +375,7 @@ static void __attribute__((noreturn)) shrink_helper_process(int fd, pid_t pid)
> */
> void igt_fork_shrink_helper(int drm_fd)
> {
> - assert(!igt_only_list_subtests());
> + assert(!igt_only_collect_data());
> igt_require(igt_drop_caches_has(drm_fd, DROP_SHRINK_ALL));
> igt_fork_helper(&shrink_helper)
> shrink_helper_process(drm_fd, getppid());
> @@ -473,7 +473,7 @@ void igt_stop_hang_detector(void)
> #else
> void igt_fork_hang_detector(int fd)
> {
> - if (igt_only_list_subtests())
> + if (igt_only_collect_data())
> return;
> }
>
> diff --git a/lib/igt_core.c b/lib/igt_core.c
> index 9a5ed40..0324382 100644
> --- a/lib/igt_core.c
> +++ b/lib/igt_core.c
> @@ -98,7 +98,7 @@
> *
> * To allow this i-g-t provides #igt_fixture code blocks for setup code outside
> * of subtests and automatically skips the subtest code blocks themselves. For
> - * special cases igt_only_list_subtests() is also provided. For setup code only
> + * special cases igt_only_collect_data() is also provided. For setup code only
> * shared by a group of subtest encapsulate the #igt_fixture block and all the
> * subtestest in a #igt_subtest_group block.
> *
> @@ -231,9 +231,9 @@ static unsigned int exit_handler_count;
> const char *igt_interactive_debug;
>
> /* subtests helpers */
> -static bool list_subtests = false;
> -static char *run_single_subtest = NULL;
> -static bool run_single_subtest_found = false;
> +static char *single_subtest = NULL;
> +static bool single_subtest_found = false;
> +static char *current_subtest_documentation = NULL;
> static const char *in_subtest = NULL;
> static struct timespec subtest_time;
> static clockid_t igt_clock = (clockid_t)-1;
> @@ -243,6 +243,13 @@ static bool in_atexit_handler = false;
> static enum {
> CONT = 0, SKIP, FAIL
> } skip_subtests_henceforth = CONT;
> +static enum {
> + EXECUTE_ALL,
> + EXECUTE_SINGLE,
> + LIST_SUBTESTS,
> + DOCUMENT,
> + DOCUMENT_SINGLE
> +} runmode = EXECUTE_ALL;
>
> bool __igt_plain_output = false;
>
> @@ -255,6 +262,8 @@ bool test_child;
> enum {
> OPT_LIST_SUBTESTS,
> OPT_RUN_SUBTEST,
> + OPT_DOC_SUBTESTS,
> + OPT_DOC_SINGLE_SUBTEST,
> OPT_DESCRIPTION,
> OPT_DEBUG,
> OPT_INTERACTIVE_DEBUG,
> @@ -441,7 +450,7 @@ bool __igt_fixture(void)
> {
> assert(!in_fixture);
>
> - if (igt_only_list_subtests())
> + if (igt_only_collect_data())
> return false;
>
> if (skip_subtests_henceforth)
> @@ -535,7 +544,7 @@ static void low_mem_killer_disable(bool disable)
> bool igt_exit_called;
> static void common_exit_handler(int sig)
> {
> - if (!igt_only_list_subtests()) {
> + if (!igt_only_collect_data()) {
> low_mem_killer_disable(false);
> kick_fbcon(true);
> }
> @@ -555,7 +564,7 @@ static void print_version(void)
> {
> struct utsname uts;
>
> - if (list_subtests)
> + if (igt_only_collect_data())
> return;
>
> uname(&uts);
> @@ -571,6 +580,8 @@ static void print_usage(const char *help_str, bool output_on_stderr)
>
> fprintf(f, "Usage: %s [OPTIONS]\n", command_str);
> fprintf(f, " --list-subtests\n"
> + " --document-all-subtests\n"
> + " --document-subtest <pattern>\n"
> " --run-subtest <pattern>\n"
> " --debug[=log-domain]\n"
> " --interactive-debug[=domain]\n"
> @@ -604,6 +615,8 @@ static int common_init(int *argc, char **argv,
> static struct option long_options[] = {
> {"list-subtests", 0, 0, OPT_LIST_SUBTESTS},
> {"run-subtest", 1, 0, OPT_RUN_SUBTEST},
> + {"document-all-subtests", 0, 0, OPT_DOC_SUBTESTS},
> + {"document-subtest", 1, 0, OPT_DOC_SINGLE_SUBTEST},
> {"help-description", 0, 0, OPT_DESCRIPTION},
> {"debug", optional_argument, 0, OPT_DEBUG},
> {"interactive-debug", optional_argument, 0, OPT_INTERACTIVE_DEBUG},
> @@ -711,12 +724,24 @@ static int common_init(int *argc, char **argv,
> igt_log_domain_filter = strdup(optarg);
> break;
> case OPT_LIST_SUBTESTS:
> - if (!run_single_subtest)
> - list_subtests = true;
> + if (runmode == EXECUTE_ALL)
> + runmode = LIST_SUBTESTS;
> break;
> case OPT_RUN_SUBTEST:
> - if (!list_subtests)
> - run_single_subtest = strdup(optarg);
> + if (runmode == EXECUTE_ALL) {
> + runmode = EXECUTE_SINGLE;
> + single_subtest = strdup(optarg);
> + }
> + break;
> + case OPT_DOC_SUBTESTS:
> + if (runmode == EXECUTE_ALL)
> + runmode = DOCUMENT;
> + break;
> + case OPT_DOC_SINGLE_SUBTEST:
> + if (runmode == EXECUTE_ALL) {
> + runmode = DOCUMENT_SINGLE;
> + single_subtest = strdup(optarg);
> + }
> break;
> case OPT_DESCRIPTION:
> print_test_description();
> @@ -744,11 +769,11 @@ out:
> /* exit immediately if this test has no subtests and a subtest or the
> * list of subtests has been requested */
> if (!test_with_subtests) {
> - if (run_single_subtest) {
> - igt_warn("Unknown subtest: %s\n", run_single_subtest);
> + if (runmode == EXECUTE_SINGLE || runmode == DOCUMENT_SINGLE) {
> + igt_warn("Unknown subtest: %s\n", single_subtest);
> exit(IGT_EXIT_INVALID);
> }
> - if (list_subtests)
> + if (runmode == LIST_SUBTESTS || runmode == DOCUMENT)
> exit(IGT_EXIT_INVALID);
> }
>
> @@ -756,7 +781,7 @@ out:
> /* exit with no error for -h/--help */
> exit(ret == -1 ? 0 : IGT_EXIT_INVALID);
>
> - if (!list_subtests) {
> + if (!igt_only_collect_data()) {
> kick_fbcon(false);
> kmsg(KERN_INFO "[IGT] %s: executing\n", command_str);
> print_version();
> @@ -864,16 +889,37 @@ bool __igt_run_subtest(const char *subtest_name)
> igt_exit();
> }
>
> - if (list_subtests) {
> + if (runmode == LIST_SUBTESTS) {
> printf("%s\n", subtest_name);
> return false;
> }
>
> - if (run_single_subtest) {
> - if (uwildmat(subtest_name, run_single_subtest) == 0)
> + if (runmode == DOCUMENT) {
> + if (current_subtest_documentation) {
> + printf("%s:\n\n", subtest_name);
> + printf("%s", current_subtest_documentation);
> + free(current_subtest_documentation);
> + current_subtest_documentation = NULL;
> + }
> + return false;
> + }
> +
> + if (runmode == EXECUTE_SINGLE || runmode == DOCUMENT_SINGLE) {
> + if (uwildmat(subtest_name, single_subtest) == 0)
> return false;
> - else
> - run_single_subtest_found = true;
> + else {
> + single_subtest_found = true;
> +
> + if (runmode == DOCUMENT_SINGLE) {
> + if (current_subtest_documentation) {
> + printf("%s", current_subtest_documentation);
> + free(current_subtest_documentation);
> + current_subtest_documentation = NULL;
> + }
> +
> + return false;
> + }
> + }
> }
>
> if (skip_subtests_henceforth) {
> @@ -890,10 +936,51 @@ bool __igt_run_subtest(const char *subtest_name)
> _igt_log_buffer_reset();
>
> gettime(&subtest_time);
> +
> return (in_subtest = subtest_name);
> }
>
> /**
> + * igt_document_subtest:
> + * @documentation: documentation for the next subtest
> + *
> + * This function sets the documentation string for the next occurring subtest.
> + */
> +void igt_document_subtest(const char *documentation)
> +{
> + if (runmode == DOCUMENT || runmode == DOCUMENT_SINGLE) {
> + free(current_subtest_documentation);
> + current_subtest_documentation = strdup(documentation);
> + }
> +}
> +
> +/**
> + * igt_document_subtest_f:
> + * @documentation: Documentation for the next subtest
> + * @...: format string and optional arguments
> + *
> + * This function sets the documentation string for the next occurring subtest.
> + *
> + * Like igt_document_subtest(), but also accepts a printf format
> + * string instead of a static string.
> + */
> +__attribute__((format(printf, 1, 2)))
> +void igt_document_subtest_f(const char *documentation, ...)
> +{
> + int err;
> + va_list args;
> +
> + if (runmode == DOCUMENT || runmode == DOCUMENT_SINGLE) {
> + free(current_subtest_documentation);
> + va_start(args, documentation);
> + err = vasprintf(¤t_subtest_documentation, documentation, args);
> + if (err < 0)
> + current_subtest_documentation = NULL;
> + }
> +}
> +
> +
> +/**
> * igt_subtest_name:
> *
> * Returns: The name of the currently executed subtest or NULL if called from
> @@ -905,14 +992,14 @@ const char *igt_subtest_name(void)
> }
>
> /**
> - * igt_only_list_subtests:
> + * igt_only_collect_data:
> *
> - * Returns: Returns true if only subtest should be listed and any setup code
> + * Returns: Returns true if the running mode is only collecting data and any setup code
> * must be skipped, false otherwise.
> */
> -bool igt_only_list_subtests(void)
> +bool igt_only_collect_data(void)
> {
> - return list_subtests;
> + return runmode != EXECUTE_ALL && runmode != EXECUTE_SINGLE;
> }
>
> void __igt_subtest_group_save(int *save)
> @@ -966,7 +1053,7 @@ void igt_skip(const char *f, ...)
>
> assert(!test_child);
>
> - if (!igt_only_list_subtests()) {
> + if (!igt_only_collect_data()) {
> va_start(args, f);
> vprintf(f, args);
> va_end(args);
> @@ -1345,12 +1432,12 @@ void igt_exit(void)
> {
> igt_exit_called = true;
>
> - if (run_single_subtest && !run_single_subtest_found) {
> - igt_warn("Unknown subtest: %s\n", run_single_subtest);
> + if (single_subtest && !single_subtest_found) {
> + igt_warn("Unknown subtest: %s\n", single_subtest);
> exit(IGT_EXIT_INVALID);
> }
>
> - if (igt_only_list_subtests())
> + if (igt_only_collect_data())
> exit(IGT_EXIT_SUCCESS);
>
> /* Calling this without calling one of the above is a failure */
> @@ -1914,7 +2001,7 @@ bool igt_run_in_simulation(void)
> */
> void igt_skip_on_simulation(void)
> {
> - if (igt_only_list_subtests())
> + if (igt_only_collect_data())
> return;
>
> if (!in_fixture && !in_subtest) {
> @@ -1989,7 +2076,7 @@ void igt_vlog(const char *domain, enum igt_log_level level, const char *format,
> program_name = command_str;
> #endif
>
> - if (list_subtests && level <= IGT_LOG_WARN)
> + if (igt_only_collect_data() && level <= IGT_LOG_WARN)
> return;
>
> if (vasprintf(&line, format, args) == -1)
> diff --git a/lib/igt_core.h b/lib/igt_core.h
> index a2ed972..423e5e7 100644
> --- a/lib/igt_core.h
> +++ b/lib/igt_core.h
> @@ -195,8 +195,12 @@ bool __igt_run_subtest(const char *subtest_name);
> #define igt_subtest_f(f...) \
> __igt_subtest_f(igt_tokencat(__tmpchar, __LINE__), f)
>
> +void igt_document_subtest(const char *documentation);
> +__attribute__((format(printf, 1, 2)))
> +void igt_document_subtest_f(const char *documentation, ...);
> +
> const char *igt_subtest_name(void);
> -bool igt_only_list_subtests(void);
> +bool igt_only_collect_data(void);
>
> void __igt_subtest_group_save(int *);
> void __igt_subtest_group_restore(int);
>
More information about the Intel-gfx
mailing list