Allow logging to be set for specific parts of QTest. Having a single QTEST_LOG knob creates an output stream that is almost useless due to spamming from some operations.
Add a backward-compatible way of selecting which parts will be made verbose. Reuse the existing QTEST_LOG variable. The new options are: QTEST_LOG= fuzz - fuzz.c qga - unit/test-qga.c qmp - libqmp.c qtest - QTest device, i.e. -qtest-log option test - generic term for usage of all tests E.g.: QTEST_LOG=fuzz,qga,qmp,qtest,test equivalent to QTEST_LOG=1 QTEST_LOG=qmp,qtest enables logging of qmp operations from libqmp.c and logging of the qtest device. QTEST_LOG=test,qmp enable test output and libqmp.c output. QTEST_LOG=-qmp enable all output, except for libqmp.c Acked-by: Peter Xu <[email protected]> Link: https://lore.kernel.org/qemu-devel/[email protected] Signed-off-by: Fabiano Rosas <[email protected]> --- tests/qtest/fuzz/fuzz.c | 7 ++-- tests/qtest/fuzz/generic_fuzz.c | 2 +- tests/qtest/libqmp.c | 7 ++-- tests/qtest/libqtest.c | 56 ++++++++++++++++++++++++++- tests/qtest/libqtest.h | 11 ++++++ tests/qtest/migration/framework.c | 2 +- tests/qtest/migration/framework.h | 5 ++- tests/qtest/migration/precopy-tests.c | 2 +- tests/unit/meson.build | 2 +- tests/unit/test-qga.c | 2 +- 10 files changed, 82 insertions(+), 14 deletions(-) diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index ca248a51a6..d235598961 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -105,7 +105,7 @@ static void usage(char *path) "Set the environment variable FUZZ_SERIALIZE_QTEST=1 to serialize\n" "QTest commands into an ASCII protocol. Useful for building crash\n" "reproducers, but slows down execution.\n\n" - "Set the environment variable QTEST_LOG=1 to log all qtest commands" + "Set the environment variable QTEST_LOG=fuzz to log all qtest commands" "\n"); exit(0); } @@ -168,6 +168,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) GString *cmd_line; gchar *pretty_cmd_line; bool serialize = false; + bool verbose = qtest_verbose("fuzz"); /* Initialize qgraph and modules */ qos_graph_init(); @@ -211,14 +212,14 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) /* Run QEMU's system main with the fuzz-target dependent arguments */ cmd_line = fuzz_target->get_init_cmdline(fuzz_target); g_string_append_printf(cmd_line, " %s -qtest /dev/null ", - getenv("QTEST_LOG") ? "" : "-qtest-log none"); + verbose ? "" : "-qtest-log none"); /* Split the runcmd into an argv and argc */ wordexp_t result; wordexp(cmd_line->str, &result, 0); g_string_free(cmd_line, true); - if (getenv("QTEST_LOG")) { + if (verbose) { pretty_cmd_line = g_strjoinv(" ", result.we_wordv + 1); printf("Starting %s with Arguments: %s\n", result.we_wordv[0], pretty_cmd_line); diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index 440de25034..e48f868775 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -776,7 +776,7 @@ static void generic_pre_fuzz(QTestState *s) if (!getenv("QEMU_FUZZ_OBJECTS")) { usage(); } - if (getenv("QTEST_LOG")) { + if (qtest_verbose("fuzz")) { qtest_log_enabled = 1; } if (getenv("QEMU_AVOID_DOUBLE_FETCH")) { diff --git a/tests/qtest/libqmp.c b/tests/qtest/libqmp.c index 16fe546885..cd12bd2678 100644 --- a/tests/qtest/libqmp.c +++ b/tests/qtest/libqmp.c @@ -17,6 +17,7 @@ #include "qemu/osdep.h" #include "libqmp.h" +#include "libqtest.h" #ifndef _WIN32 #include <sys/socket.h> @@ -62,7 +63,7 @@ static void qmp_response(void *opaque, QObject *obj, Error *err) QDict *qmp_fd_receive(int fd) { QMPResponseParser qmp; - bool log = getenv("QTEST_LOG") != NULL; + bool log = qtest_verbose("qmp"); qmp.response = NULL; json_message_parser_init(&qmp.parser, qmp_response, &qmp, NULL); @@ -149,7 +150,7 @@ _qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num, /* No need to send anything for an empty QObject. */ if (qobj) { - int log = getenv("QTEST_LOG") != NULL; + bool log = qtest_verbose("qmp"); GString *str = qobject_to_json(qobj); /* @@ -220,7 +221,7 @@ void qmp_fd_send(int fd, const char *fmt, ...) void qmp_fd_vsend_raw(int fd, const char *fmt, va_list ap) { - bool log = getenv("QTEST_LOG") != NULL; + bool log = qtest_verbose("qmp"); char *str = g_strdup_vprintf(fmt, ap); if (log) { diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index dc4a665cfa..bf9284b9a1 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -469,7 +469,7 @@ gchar *qtest_qemu_args(const char *extra_args) "-accel qtest", socket_path, - getenv("QTEST_LOG") ? DEV_STDERR : DEV_NULL, + qtest_verbose("qtest") ? DEV_STDERR : DEV_NULL, qmp_socket_path, can_exit_with_parent() ? "-run-with exit-with-parent=on" : "", @@ -2142,3 +2142,57 @@ bool mkimg(const char *file, const char *fmt, unsigned size_mb) return ret && !err; } + +bool qtest_verbose(const char *domain) +{ + const char *log = getenv("QTEST_LOG"); + char *found; + + assert(domain); + + if (log) { + /* + * verbose=true for all domains if: + * QTEST_LOG= + * QTEST_LOG=1 + * other one-character variations + */ + if (log[0] == '\0' || log[1] == '\0') { + return true; + } + + /* + * verbose=true for specified domains if: + * QTEST_LOG=<domain> + * QTEST_LOG=<domain1>,<domain2> + * allows other separators, except - and + + * + * verbose=false for specified domains if: + * QTEST_LOG=-<domain> + * QTEST_LOG=<domain1>,-<domain2> (only false for domain2) + * allows other separators, except - and + + */ + found = strstr(log, domain); + + if (found) { + /* reject options given twice */ + assert(!strstr(found + strlen(domain), domain)); + + if (found > log) { + ptrdiff_t i = found - log - 1; + if (log[i] == '-') { + return false; + } + } + return true; + } else { + /* + * If filtering out a specific domain, all others are + * enabled. + */ + return !!strstr(log, "-"); + } + } + + return false; +} diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index 9c118c89ca..950ea2baaf 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -1178,4 +1178,15 @@ bool have_qemu_img(void); */ bool mkimg(const char *file, const char *fmt, unsigned size_mb); +/** + * qtest_verbose: + * @domain: The logging domain + * + * Read the QTEST_LOG environment variable and return whether the + * specified domain is enabled for verbose logging. Enable specific + * logging domains with QTEST_LOG=<domain> or use QTEST_LOG=-<domain> to + * enable all domains except for the specific one. + */ +bool qtest_verbose(const char *domain); + #endif diff --git a/tests/qtest/migration/framework.c b/tests/qtest/migration/framework.c index 9f71d51f1e..49c7f37e60 100644 --- a/tests/qtest/migration/framework.c +++ b/tests/qtest/migration/framework.c @@ -365,7 +365,7 @@ int migrate_args(char **from, char **to, const char *uri, MigrateStart *args) g_assert_not_reached(); } - if (!getenv("QTEST_LOG") && args->hide_stderr) { + if (!qtest_verbose("test") && args->hide_stderr) { #ifndef _WIN32 ignore_stderr = "2>/dev/null"; #else diff --git a/tests/qtest/migration/framework.h b/tests/qtest/migration/framework.h index 79604c60f5..bb534b8110 100644 --- a/tests/qtest/migration/framework.h +++ b/tests/qtest/migration/framework.h @@ -118,8 +118,9 @@ typedef void (*TestMigrateEndHook)(QTestState *from, */ typedef struct { /* - * QTEST_LOG=1 may override this. When QTEST_LOG=1, we always dump errors - * unconditionally, because it means the user would like to be verbose. + * QTEST_LOG=test may override this in which case we dump errors + * unconditionally, because it means the user would like to be + * verbose. */ bool hide_stderr; MemType mem_type; diff --git a/tests/qtest/migration/precopy-tests.c b/tests/qtest/migration/precopy-tests.c index a0e3ff0547..e65d9e04a5 100644 --- a/tests/qtest/migration/precopy-tests.c +++ b/tests/qtest/migration/precopy-tests.c @@ -130,7 +130,7 @@ static bool mlock_check(void) static int new_rdma_link(char *buffer, bool ipv6) { char cmd[256]; - bool verbose = g_getenv("QTEST_LOG"); + bool verbose = qtest_verbose("test"); snprintf(cmd, sizeof(cmd), "IP_FAMILY=%s %s detect %s", ipv6 ? "ipv6" : "ipv4", RDMA_MIGRATION_HELPER, diff --git a/tests/unit/meson.build b/tests/unit/meson.build index 03d36748c7..de64f9501f 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -161,7 +161,7 @@ if have_system endif if have_ga and host_os == 'linux' - tests += {'test-qga': ['../qtest/libqmp.c']} + tests += {'test-qga': ['../qtest/libqmp.c', '../qtest/libqtest.c']} test_deps += {'test-qga': qga} endif diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index 587e30c7e4..01ccf826e6 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -68,7 +68,7 @@ fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp) cmd = g_strdup_printf("%s%cqga%cqemu-ga -m unix-listen -t %s -p %s %s %s", cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR, fixture->test_dir, path, - getenv("QTEST_LOG") ? "-v" : "", + qtest_verbose("qga") ? "-v" : "", extra_arg ?: ""); g_shell_parse_argv(cmd, NULL, &argv, &error); g_assert_no_error(error); -- 2.51.0
