diff --git a/gio/tests/fake-document-portal.c b/gio/tests/fake-document-portal.c index 0ef86b59a..585dee58b 100644 --- a/gio/tests/fake-document-portal.c +++ b/gio/tests/fake-document-portal.c @@ -125,6 +125,8 @@ main (gint argc, gchar *argv[]) GMainLoop *loop; guint id; + g_log_writer_default_set_use_stderr (TRUE); + loop = g_main_loop_new (NULL, FALSE); id = g_bus_own_name (G_BUS_TYPE_SESSION, diff --git a/gio/tests/fake-service-name.c b/gio/tests/fake-service-name.c index 6e317a7cc..0acabd9ec 100644 --- a/gio/tests/fake-service-name.c +++ b/gio/tests/fake-service-name.c @@ -98,6 +98,8 @@ main (gint argc, gchar *argv[]) { guint id; + g_log_writer_default_set_use_stderr (TRUE); + loop = g_main_loop_new (NULL, FALSE); introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (introspection_data != NULL); diff --git a/gio/tests/gapplication.c b/gio/tests/gapplication.c index 4320352d1..a11f2b8bc 100644 --- a/gio/tests/gapplication.c +++ b/gio/tests/gapplication.c @@ -1686,6 +1686,8 @@ main (int argc, char **argv) { g_setenv ("LC_ALL", "C", TRUE); + g_log_writer_default_set_use_stderr (TRUE); + g_test_init (&argc, &argv, NULL); if (!g_test_subprocess ()) diff --git a/gio/tests/gdbus-testserver.c b/gio/tests/gdbus-testserver.c index ae8e47b18..3a16db378 100644 --- a/gio/tests/gdbus-testserver.c +++ b/gio/tests/gdbus-testserver.c @@ -843,6 +843,8 @@ main (int argc, char *argv[]) { guint owner_id; + g_log_writer_default_set_use_stderr (TRUE); + introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); g_hash_table_insert (properties, g_strdup ("y"), g_variant_ref_sink (g_variant_new_byte (1))); diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c index c7de624a2..182e79e0a 100644 --- a/gio/tests/gsettings.c +++ b/gio/tests/gsettings.c @@ -798,7 +798,9 @@ test_l10n (void) str = NULL; } else - g_printerr ("warning: translation is not working... skipping test. "); + { + g_test_skip ("translation is not working"); + } g_setenv ("LC_MESSAGES", locale, TRUE); setlocale (LC_MESSAGES, locale); @@ -843,7 +845,7 @@ test_l10n_context (void) if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\"")) settings_assert_cmpstr (settings, "backspace", ==, "Löschen"); else - g_printerr ("warning: translation is not working... skipping test. "); + g_test_skip ("translation is not working"); g_setenv ("LC_MESSAGES", locale, TRUE); setlocale (LC_MESSAGES, locale); @@ -3017,6 +3019,8 @@ main (int argc, char *argv[]) if (!g_test_subprocess ()) { GError *local_error = NULL; + char *subprocess_stdout = NULL; + /* A GVDB header is 6 guint32s, and requires a magic number in the first * two guint32s. A set of zero bytes of a greater length is considered * corrupt. */ @@ -3056,14 +3060,20 @@ main (int argc, char *argv[]) "--schema-file=org.gtk.test.enums.xml " "--schema-file=org.gtk.test.gschema.xml " "--override-file=org.gtk.test.gschema.override", - NULL, NULL, &result, NULL)); + &subprocess_stdout, NULL, &result, NULL)); + if (subprocess_stdout && *g_strstrip (subprocess_stdout) != '\0') + g_test_message ("%s", subprocess_stdout); + g_clear_pointer (&subprocess_stdout, g_free); g_assert_cmpint (result, ==, 0); g_remove ("schema-source/gschemas.compiled"); g_mkdir ("schema-source", 0777); g_assert_true (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=schema-source " "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml", - NULL, NULL, &result, NULL)); + &subprocess_stdout, NULL, &result, NULL)); + if (subprocess_stdout && *g_strstrip (subprocess_stdout) != '\0') + g_test_message ("%s", subprocess_stdout); + g_clear_pointer (&subprocess_stdout, g_free); g_assert_cmpint (result, ==, 0); g_remove ("schema-source-corrupt/gschemas.compiled"); diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 13a1775ce..de5b80d72 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -144,14 +144,16 @@ gio_tests = { if have_cxx gio_tests += { 'cxx' : { + 'protocol': 'exitcode', 'source' : ['cxx.cpp'], - 'suite': ['C++'], + 'suite': ['cpp'], }, } foreach std, arg: cxx_standards gio_tests += { 'cxx-@0@'.format(std) : { + 'protocol': 'exitcode', 'source' : ['cxx.cpp'], 'suite' : ['cpp'], 'cpp_args' : [arg], @@ -1035,6 +1037,7 @@ foreach test_name, extra_args : gio_tests endif test(test_name, exe, + protocol : extra_args.get('protocol', test_protocol), env : local_test_env, timeout : timeout, suite : suite, @@ -1059,6 +1062,7 @@ foreach test_name, extra_args : python_tests test( test_name, python, + protocol : extra_args.get('protocol', test_protocol), depends: depends, args: ['-B', files(test_name)], env: test_env, diff --git a/glib/gmessages.c b/glib/gmessages.c index 4fd7544ea..aff1316f5 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -501,12 +501,14 @@ struct _GLogHandler GLogHandler *next; }; +static void g_default_print_func (const gchar *string); +static void g_default_printerr_func (const gchar *string); /* --- variables --- */ static GMutex g_messages_lock; static GLogDomain *g_log_domains = NULL; -static GPrintFunc glib_print_func = NULL; -static GPrintFunc glib_printerr_func = NULL; +static GPrintFunc glib_print_func = g_default_print_func; +static GPrintFunc glib_printerr_func = g_default_printerr_func; static GPrivate g_log_depth; static GPrivate g_log_structured_depth; static GLogFunc default_log_func = g_log_default_handler; @@ -525,6 +527,7 @@ static inline const char * format_string (const char *format, va_list args, char **out_allocated_string) G_GNUC_PRINTF (1, 0); +static inline FILE * log_level_to_file (GLogLevelFlags log_level); static void _g_log_abort (gboolean breakpoint) @@ -1206,8 +1209,6 @@ mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE], GLogLevelFlags log_level, gboolean use_color) { - gboolean to_stdout = !gmessages_use_stderr; - /* we may not call _any_ GLib functions here */ strcpy (level_prefix, log_level_to_color (log_level, use_color)); @@ -1216,19 +1217,15 @@ mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE], { case G_LOG_LEVEL_ERROR: strcat (level_prefix, "ERROR"); - to_stdout = FALSE; break; case G_LOG_LEVEL_CRITICAL: strcat (level_prefix, "CRITICAL"); - to_stdout = FALSE; break; case G_LOG_LEVEL_WARNING: strcat (level_prefix, "WARNING"); - to_stdout = FALSE; break; case G_LOG_LEVEL_MESSAGE: strcat (level_prefix, "Message"); - to_stdout = FALSE; break; case G_LOG_LEVEL_INFO: strcat (level_prefix, "INFO"); @@ -1258,7 +1255,7 @@ mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE], if ((log_level & G_LOG_FLAG_FATAL) != 0 && !g_test_initialized ()) win32_keep_fatal_message = TRUE; #endif - return to_stdout ? stdout : stderr; + return log_level_to_file (log_level); } typedef struct { @@ -1487,7 +1484,7 @@ log_level_to_priority (GLogLevelFlags log_level) return "5"; } -static FILE * +static inline FILE * log_level_to_file (GLogLevelFlags log_level) { if (gmessages_use_stderr) @@ -3289,9 +3286,11 @@ g_log_default_handler (const gchar *log_domain, /** * g_set_print_handler: - * @func: the new print handler + * @func: (nullable): the new print handler or %NULL to + * reset to the default * - * Sets the print handler. + * Sets the print handler to @func, or resets it to the + * default GLib handler if %NULL. * * Any messages passed to g_print() will be output via * the new handler. The default handler simply outputs @@ -3299,7 +3298,14 @@ g_log_default_handler (const gchar *log_domain, * you can redirect the output, to a GTK+ widget or a * log file for example. * - * Returns: the old print handler + * Since 2.76 this functions always returns a valid + * #GPrintFunc, and never returns %NULL. If no custom + * print handler was set, it will return the GLib + * default print handler and that can be re-used to + * decorate its output and/or to write to stderr + * in all platforms. Before GLib 2.76, this was %NULL. + * + * Returns: (not nullable): the old print handler */ GPrintFunc g_set_print_handler (GPrintFunc func) @@ -3308,7 +3314,7 @@ g_set_print_handler (GPrintFunc func) g_mutex_lock (&g_messages_lock); old_print_func = glib_print_func; - glib_print_func = func; + glib_print_func = func ? func : g_default_print_func; g_mutex_unlock (&g_messages_lock); return old_print_func; @@ -3365,6 +3371,18 @@ format_string (const char *format, } } +static void +g_default_print_func (const gchar *string) +{ + print_string (stdout, string); +} + +static void +g_default_printerr_func (const gchar *string) +{ + print_string (stderr, string); +} + /** * g_print: * @format: the message format. See the printf() documentation @@ -3400,19 +3418,17 @@ g_print (const gchar *format, local_glib_print_func = glib_print_func; g_mutex_unlock (&g_messages_lock); - if (local_glib_print_func) - local_glib_print_func (string); - else - print_string (stdout, string); - + local_glib_print_func (string); g_free (free_me); } /** * g_set_printerr_handler: - * @func: the new error message handler + * @func: (nullable): he new error message handler or %NULL + * to reset to the default * - * Sets the handler for printing error messages. + * Sets the handler for printing error messages to @func, + * or resets it to the default GLib handler if %NULL. * * Any messages passed to g_printerr() will be output via * the new handler. The default handler simply outputs the @@ -3420,7 +3436,14 @@ g_print (const gchar *format, * redirect the output, to a GTK+ widget or a log file for * example. * - * Returns: the old error message handler + * Since 2.76 this functions always returns a valid + * #GPrintFunc, and never returns %NULL. If no custom error + * print handler was set, it will return the GLib default + * error print handler and that can be re-used to decorate + * its output and/or to write to stderr in all platforms. + * Before GLib 2.76, this was %NULL. + * + * Returns: (not nullable): the old error message handler */ GPrintFunc g_set_printerr_handler (GPrintFunc func) @@ -3429,7 +3452,7 @@ g_set_printerr_handler (GPrintFunc func) g_mutex_lock (&g_messages_lock); old_printerr_func = glib_printerr_func; - glib_printerr_func = func; + glib_printerr_func = func ? func : g_default_printerr_func; g_mutex_unlock (&g_messages_lock); return old_printerr_func; @@ -3468,11 +3491,7 @@ g_printerr (const gchar *format, local_glib_printerr_func = glib_printerr_func; g_mutex_unlock (&g_messages_lock); - if (local_glib_printerr_func) - local_glib_printerr_func (string); - else - print_string (stderr, string); - + local_glib_printerr_func (string); g_free (free_me); } diff --git a/glib/gtestutils.c b/glib/gtestutils.c index 22b48d9ef..a03ff559d 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -58,6 +58,9 @@ #include "glib-private.h" #include "gutilsprivate.h" +/* FIXME: Remove '#' prefix when we'll depend on a meson version supporting TAP 14 + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2885 */ +#define TAP_SUBTEST_PREFIX "# " /* a 4-space indented line */ /** * SECTION:testing @@ -845,7 +848,10 @@ static void gtest_default_log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data); - +static void g_test_tap_print (unsigned subtest_level, + gboolean commented, + const char *format, + ...) G_GNUC_PRINTF (3, 4); static const char * const g_test_result_names[] = { "OK", @@ -901,6 +907,7 @@ static const char *test_built_files_dir; /* points into test_argv0_dirnam static char *test_initial_cwd = NULL; static gboolean test_in_forked_child = FALSE; static gboolean test_in_subprocess = FALSE; +static gboolean test_is_subtest = FALSE; static GTestConfig mutable_test_config_vars = { FALSE, /* test_initialized */ TRUE, /* test_quick */ @@ -911,8 +918,90 @@ static GTestConfig mutable_test_config_vars = { }; const GTestConfig * const g_test_config_vars = &mutable_test_config_vars; static gboolean no_g_set_prgname = FALSE; +static GPrintFunc g_default_print_func = NULL; + /* --- functions --- */ +static inline gboolean +is_subtest (void) +{ + return test_is_subtest || test_in_forked_child || test_in_subprocess; +} + +static void +g_test_print_handler_full (const gchar *string, + gboolean use_tap_format, + gboolean is_tap_comment, + unsigned subtest_level) +{ + g_assert (string != NULL); + + if (G_LIKELY (use_tap_format) && strchr (string, '\n') != NULL) + { + static gboolean last_had_final_newline = TRUE; + GString *output = g_string_new_len (NULL, strlen (string) + 2); + const char *line = string; + + do + { + const char *next = strchr (line, '\n'); + + if (last_had_final_newline && (next || *line != '\0')) + { + for (unsigned l = 0; l < subtest_level; ++l) + g_string_append (output, TAP_SUBTEST_PREFIX); + + if G_LIKELY (is_tap_comment) + g_string_append (output, "# "); + } + + if (next) + { + next += 1; /* Include the newline */ + g_string_append_len (output, line, next - line); + } + else + { + g_string_append (output, line); + last_had_final_newline = (*line == '\0'); + } + + line = next; + } + while (line != NULL); + + g_default_print_func (output->str); + g_string_free (g_steal_pointer (&output), TRUE); + } + else + { + g_default_print_func (string); + } +} + +static void +g_test_print_handler (const gchar *string) +{ + g_test_print_handler_full (string, test_tap_log, TRUE, is_subtest () ? 1 : 0); +} + +static void +g_test_tap_print (unsigned subtest_level, + gboolean commented, + const char *format, + ...) +{ + va_list args; + char *string; + + va_start (args, format); + string = g_strdup_vprintf (format, args); + va_end (args); + + g_test_print_handler_full (string, TRUE, commented, subtest_level); + g_free (string); +} + const char* g_test_log_type_name (GTestLogType log_type) { @@ -949,6 +1038,7 @@ g_test_log_send (guint n_bytes, { GTestLogBuffer *lbuffer = g_test_log_buffer_new (); GTestLogMsg *msg; + GString *output; guint ui; g_test_log_buffer_push (lbuffer, n_bytes, buffer); msg = g_test_log_buffer_pop (lbuffer); @@ -956,22 +1046,25 @@ g_test_log_send (guint n_bytes, g_warn_if_fail (lbuffer->data->len == 0); g_test_log_buffer_free (lbuffer); /* print message */ - g_printerr ("{*LOG(%s)", g_test_log_type_name (msg->log_type)); + output = g_string_new (NULL); + g_string_printf (output, "{*LOG(%s)", g_test_log_type_name (msg->log_type)); for (ui = 0; ui < msg->n_strings; ui++) - g_printerr (":{%s}", msg->strings[ui]); + g_string_append_printf (output, ":{%s}", msg->strings[ui]); if (msg->n_nums) { - g_printerr (":("); + g_string_append (output, ":("); for (ui = 0; ui < msg->n_nums; ui++) { if ((long double) (long) msg->nums[ui] == msg->nums[ui]) - g_printerr ("%s%ld", ui ? ";" : "", (long) msg->nums[ui]); + g_string_append_printf (output, "%s%ld", ui ? ";" : "", (long) msg->nums[ui]); else - g_printerr ("%s%.16g", ui ? ";" : "", (double) msg->nums[ui]); + g_string_append_printf (output, "%s%.16g", ui ? ";" : "", (double) msg->nums[ui]); } - g_printerr (")"); + g_string_append_c (output, ')'); } - g_printerr (":LOG*}\n"); + g_string_append (output, ":LOG*}"); + g_printerr ("%s\n", output->str); + g_string_free (output, TRUE); g_test_log_msg_free (msg); } } @@ -989,14 +1082,38 @@ g_test_log (GTestLogType lbit, gchar *astrings[3] = { NULL, NULL, NULL }; guint8 *dbuffer; guint32 dbufferlen; + unsigned subtest_level; + + if (g_once_init_enter (&g_default_print_func)) + { + g_once_init_leave (&g_default_print_func, + g_set_print_handler (g_test_print_handler)); + g_assert_nonnull (g_default_print_func); + } + + subtest_level = is_subtest () ? 1 : 0; switch (lbit) { case G_TEST_LOG_START_BINARY: if (test_tap_log) - g_print ("# random seed: %s\n", string2); + { + if (!is_subtest ()) + { + g_test_tap_print (0, FALSE, "TAP version 13\n"); + } + else + { + g_test_tap_print (subtest_level > 0 ? subtest_level - 1 : 0, TRUE, + "Subtest: %s\n", test_argv0); + } + + g_print ("random seed: %s\n", string2); + } else if (g_test_verbose ()) - g_print ("GTest: random seed: %s\n", string2); + { + g_print ("GTest: random seed: %s\n", string2); + } break; case G_TEST_LOG_START_SUITE: if (test_tap_log) @@ -1004,9 +1121,9 @@ g_test_log (GTestLogType lbit, /* We only print the TAP "plan" (1..n) ahead of time if we did * not use the -p option to select specific tests to be run. */ if (string1[0] != 0) - g_print ("# Start of %s tests\n", string1); + g_print ("Start of %s tests\n", string1); else if (test_paths == NULL) - g_print ("1..%d\n", test_count); + g_test_tap_print (subtest_level, FALSE, "1..%d\n", test_count); } break; case G_TEST_LOG_STOP_SUITE: @@ -1016,9 +1133,9 @@ g_test_log (GTestLogType lbit, * we were using -p, we need to print how many tests we ran at * the end instead. */ if (string1[0] != 0) - g_print ("# End of %s tests\n", string1); + g_print ("End of %s tests\n", string1); else if (test_paths != NULL) - g_print ("1..%d\n", test_run_count); + g_test_tap_print (subtest_level, FALSE, "1..%d\n", test_run_count); } break; case G_TEST_LOG_STOP_CASE: @@ -1026,7 +1143,7 @@ g_test_log (GTestLogType lbit, fail = result == G_TEST_RUN_FAILURE; if (test_tap_log) { - const gchar *ok; + GString *tap_output; /* The TAP representation for an expected failure starts with * "not ok", even though it does not actually count as failing @@ -1035,28 +1152,33 @@ g_test_log (GTestLogType lbit, * for which GTestResult does not currently have a * representation. */ if (fail || result == G_TEST_RUN_INCOMPLETE) - ok = "not ok"; + tap_output = g_string_new ("not ok"); else - ok = "ok"; + tap_output = g_string_new ("ok"); - g_print ("%s %d %s", ok, test_run_count, string1); + if (is_subtest ()) + g_string_prepend (tap_output, TAP_SUBTEST_PREFIX); + + g_string_append_printf (tap_output, " %d %s", test_run_count, string1); if (result == G_TEST_RUN_INCOMPLETE) - g_print (" # TODO %s\n", string2 ? string2 : ""); + g_string_append_printf (tap_output, " # TODO %s", string2 ? string2 : ""); else if (result == G_TEST_RUN_SKIPPED) - g_print (" # SKIP %s\n", string2 ? string2 : ""); + g_string_append_printf (tap_output, " # SKIP %s", string2 ? string2 : ""); else if (result == G_TEST_RUN_FAILURE && string2 != NULL) - g_print (" - %s\n", string2); - else - g_print ("\n"); + g_string_append_printf (tap_output, " - %s", string2); + + g_string_append_c (tap_output, '\n'); + g_default_print_func (tap_output->str); + g_string_free (g_steal_pointer (&tap_output), TRUE); } else if (g_test_verbose ()) g_print ("GTest: result: %s\n", g_test_result_names[result]); - else if (!g_test_quiet ()) + else if (!g_test_quiet () && !test_in_subprocess) g_print ("%s\n", g_test_result_names[result]); if (fail && test_mode_fatal) { if (test_tap_log) - g_print ("Bail out!\n"); + g_test_tap_print (0, FALSE, "Bail out!\n"); g_abort (); } if (result == G_TEST_RUN_SKIPPED || result == G_TEST_RUN_INCOMPLETE) @@ -1064,44 +1186,54 @@ g_test_log (GTestLogType lbit, break; case G_TEST_LOG_SKIP_CASE: if (test_tap_log) - g_print ("ok %d %s # SKIP\n", test_run_count, string1); + { + g_test_tap_print (subtest_level, FALSE, "ok %d %s # SKIP\n", + test_run_count, string1); + } break; case G_TEST_LOG_MIN_RESULT: if (test_tap_log) - g_print ("# min perf: %s\n", string1); + g_print ("min perf: %s\n", string1); else if (g_test_verbose ()) g_print ("(MINPERF:%s)\n", string1); break; case G_TEST_LOG_MAX_RESULT: if (test_tap_log) - g_print ("# max perf: %s\n", string1); + g_print ("max perf: %s\n", string1); else if (g_test_verbose ()) g_print ("(MAXPERF:%s)\n", string1); break; case G_TEST_LOG_MESSAGE: if (test_tap_log) - { - if (strstr (string1, "\n") == NULL) - g_print ("# %s\n", string1); - else - { - char **lines = g_strsplit (string1, "\n", -1); - gsize i; - - for (i = 0; lines[i] != NULL; i++) - g_print ("# %s\n", lines[i]); - - g_strfreev (lines); - } - } + g_print ("%s\n", string1); else if (g_test_verbose ()) g_print ("(MSG: %s)\n", string1); break; case G_TEST_LOG_ERROR: if (test_tap_log) - g_print ("Bail out! %s\n", string1); + { + char *message = g_strdup (string1); + char *line = message; + + while ((line = strchr (line, '\n'))) + *(line++) = ' '; + + if (is_subtest ()) + { + g_test_tap_print (subtest_level, FALSE, "Bail out! %s\n", message); + g_test_tap_print (0, FALSE, "Bail out!\n"); + } + else + { + g_test_tap_print (0, FALSE, "Bail out! %s\n", message); + } + + g_free (message); + } else if (g_test_verbose ()) - g_print ("(ERROR: %s)\n", string1); + { + g_print ("(ERROR: %s)\n", string1); + } break; default: ; } @@ -1634,16 +1766,31 @@ void } va_end (args); - /* setup random seed string */ - g_snprintf (seedstr, sizeof (seedstr), "R02S%08x%08x%08x%08x", g_random_int(), g_random_int(), g_random_int(), g_random_int()); - test_run_seedstr = seedstr; - /* parse args, sets up mode, changes seed, etc. */ parse_args (argc, argv); + if (test_run_seedstr == NULL) + { + /* setup random seed string */ + g_snprintf (seedstr, sizeof (seedstr), "R02S%08x%08x%08x%08x", + g_random_int(), g_random_int(), g_random_int(), g_random_int()); + test_run_seedstr = seedstr; + } + if (!g_get_prgname() && !no_g_set_prgname) g_set_prgname ((*argv)[0]); + if (g_getenv ("G_TEST_ROOT_PROCESS")) + { + test_is_subtest = TRUE; + } + else if (!g_setenv ("G_TEST_ROOT_PROCESS", test_argv0 ? test_argv0 : "root", TRUE)) + { + g_printerr ("%s: Failed to set environment variable ‘%s’\n", + test_argv0, "G_TEST_ROOT_PROCESS"); + exit (1); + } + /* Set up the temporary directory for isolating the test. We have to do this * early, as we want the return values from g_get_user_data_dir() (and * friends) to return subdirectories of the temporary directory throughout @@ -3003,7 +3150,12 @@ test_should_run (const char *test_path, return TRUE; if (g_test_verbose ()) - g_print ("GTest: skipping: %s\n", test_run_name); + { + if (test_tap_log) + g_print ("skipping: %s\n", test_run_name); + else + g_print ("GTest: skipping: %s\n", test_run_name); + } return FALSE; } @@ -3217,9 +3369,10 @@ gtest_default_log_handler (const gchar *log_domain, msg = g_strjoinv ("", (gchar**) strv); g_test_log (fatal ? G_TEST_LOG_ERROR : G_TEST_LOG_MESSAGE, msg, NULL, 0, NULL); - g_log_default_handler (log_domain, log_level, message, unused_data); - g_free (msg); + + if (!test_tap_log) + g_log_default_handler (log_domain, log_level, message, unused_data); } void @@ -3543,7 +3696,10 @@ child_read (GIOChannel *io, GIOCondition cond, gpointer user_data) { g_string_append_len (data->stdout_str, buf, nread); if (data->echo_stdout) - echo_file = stdout; + { + if G_UNLIKELY (!test_tap_log) + echo_file = stdout; + } } else { @@ -3624,6 +3780,22 @@ wait_for_child (GPid pid, g_main_loop_unref (data.loop); g_main_context_unref (context); + if (echo_stdout && test_tap_log && data.stdout_str->len > 0) + { + gboolean added_newline = FALSE; + + if (data.stdout_str->str[data.stdout_str->len - 1] != '\n') + { + g_string_append_c (data.stdout_str, '\n'); + added_newline = TRUE; + } + + g_test_print_handler_full (data.stdout_str->str, TRUE, TRUE, 1); + + if (added_newline) + g_string_truncate (data.stdout_str, data.stdout_str->len - 1); + } + test_trap_last_pid = pid; test_trap_last_status = data.child_status; test_trap_last_stdout = g_string_free (data.stdout_str, FALSE); @@ -3847,7 +4019,12 @@ g_test_trap_subprocess (const char *test_path, } if (g_test_verbose ()) - g_print ("GTest: subprocess: %s\n", test_path); + { + if (test_tap_log) + g_print ("subprocess: %s\n", test_path); + else + g_print ("GTest: subprocess: %s\n", test_path); + } test_trap_clear (); test_trap_last_subprocess = g_strdup (test_path); @@ -4071,8 +4248,10 @@ g_test_trap_assertions (const char *domain, logged_child_output = logged_child_output || log_child_output (process_id); - msg = g_strdup_printf ("stdout of child process (%s) %s: %s\nstdout was:\n%s", - process_id, match_error, stdout_pattern, test_trap_last_stdout); + g_test_message ("stdout was:\n%s", test_trap_last_stdout); + + msg = g_strdup_printf ("stdout of child process (%s) %s: %s", + process_id, match_error, stdout_pattern); g_assertion_message (domain, file, line, func, msg); g_free (msg); } @@ -4082,8 +4261,10 @@ g_test_trap_assertions (const char *domain, logged_child_output = logged_child_output || log_child_output (process_id); - msg = g_strdup_printf ("stderr of child process (%s) %s: %s\nstderr was:\n%s", - process_id, match_error, stderr_pattern, test_trap_last_stderr); + g_test_message ("stderr was:\n%s", test_trap_last_stderr); + + msg = g_strdup_printf ("stderr of child process (%s) %s: %s", + process_id, match_error, stderr_pattern); g_assertion_message (domain, file, line, func, msg); g_free (msg); } diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c index 7874d258d..49390c900 100644 --- a/glib/tests/gdatetime.c +++ b/glib/tests/gdatetime.c @@ -403,7 +403,7 @@ test_GDateTime_new_from_timeval (void) dt = g_date_time_new_from_timeval_local (&tv); if (g_test_verbose ()) - g_printerr ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n", + g_test_message ("DT%04d-%02d-%02dT%02d:%02d:%02d%s", g_date_time_get_year (dt), g_date_time_get_month (dt), g_date_time_get_day_of_month (dt), @@ -501,7 +501,7 @@ test_GDateTime_new_from_timeval_utc (void) dt = g_date_time_new_from_timeval_utc (&tv); if (g_test_verbose ()) - g_printerr ("\nDT%04d-%02d-%02dT%02d:%02d:%02d%s\n", + g_test_message ("DT%04d-%02d-%02dT%02d:%02d:%02d%s", g_date_time_get_year (dt), g_date_time_get_month (dt), g_date_time_get_day_of_month (dt), @@ -2097,7 +2097,7 @@ test_all_dates (void) dt = g_date_time_new (timezone, year, month, day, 0, 0, 0); #if 0 - g_printerr ("%04d-%02d-%02d = %04d-W%02d-%d = %04d-%03d\n", + g_test_message ("%04d-%02d-%02d = %04d-W%02d-%d = %04d-%03d", year, month, day, week_year, week_num, weekday, year, day_of_year); @@ -2384,7 +2384,7 @@ check_and_set_locale (int category, setlocale (category, name); if (strstr (setlocale (category, NULL), name) == NULL) { - g_print ("Unavailable '%s' locale\n", name); + g_test_message ("Unavailable '%s' locale", name); g_test_skip ("required locale not available, skipping tests"); return FALSE; } diff --git a/glib/tests/gpoll.c b/glib/tests/gpoll.c index de296ca5f..ec3dd6999 100644 --- a/glib/tests/gpoll.c +++ b/glib/tests/gpoll.c @@ -204,11 +204,11 @@ print_buckets (gint buckets[], for (i = 0; i < count; i++) if (i < count - 1) - g_print ("%-4lld-%4lld|", i == 0 ? 0 : bucket_limits[i - 1], bucket_limits[i] - 1); + g_printerr ("%-4lld-%4lld|", i == 0 ? 0 : bucket_limits[i - 1], bucket_limits[i] - 1); else - g_print (" >= %-4lld|", bucket_limits[i - 1]); + g_printerr (" >= %-4lld|", bucket_limits[i - 1]); - g_print ("\n"); + g_printerr ("\n"); for (i = 0; i < count; i++) { @@ -225,17 +225,17 @@ print_buckets (gint buckets[], len = 4; padding = 9 - len; for (j = 0; j < padding / 2; j++) - g_print (" "); + g_printerr (" "); if (buckets[i] != 0) - g_print ("%*d", len, buckets[i]); + g_printerr ("%*d", len, buckets[i]); else - g_print (" "); + g_printerr (" "); for (j = padding / 2; j < padding; j++) - g_print (" "); - g_print (" "); + g_printerr (" "); + g_printerr (" "); } - g_print ("\n\n"); + g_printerr ("\n\n"); } static void @@ -281,7 +281,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("\nempty poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); + g_printerr ("\nempty poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); times_avg = 0; @@ -336,7 +336,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("1-socket + msg poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); + g_printerr ("1-socket + msg poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); times_avg = 0; @@ -384,7 +384,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("1-socket poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); + g_printerr ("1-socket poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); times_avg = 0; @@ -433,7 +433,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("half-socket poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); + g_printerr ("half-socket poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); times_avg = 0; @@ -491,7 +491,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("half-socket + msg poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); + g_printerr ("half-socket + msg poll time:\n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); times_avg = 0; @@ -540,7 +540,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("%d-socket poll time: \n%4lldns - %4lldns, average %4lldns\n", NUM_POLLEES, times_min, times_max, times_avg); + g_printerr ("%d-socket poll time: \n%4lldns - %4lldns, average %4lldns\n", NUM_POLLEES, times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); activatable = 0; @@ -599,7 +599,7 @@ test_gpoll (void) } times_avg /= NUM_POLLEES; - g_print ("variable socket number + msg poll time: \n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); + g_printerr ("variable socket number + msg poll time: \n%4lldns - %4lldns, average %4lldns\n", times_min, times_max, times_avg); print_buckets (buckets, bucket_limits, BUCKET_COUNT); cleanup_sockets (sockets, opp_sockets, NUM_POLLEES); diff --git a/glib/tests/logging.c b/glib/tests/logging.c index e58b405a2..ea9dcb825 100644 --- a/glib/tests/logging.c +++ b/glib/tests/logging.c @@ -3,6 +3,12 @@ #define G_LOG_USE_STRUCTURED 1 #include +#ifdef G_OS_WIN32 +#define LINE_END "\r\n" +#else +#define LINE_END "\n" +#endif + /* Test g_warn macros */ static void test_warnings (void) @@ -61,16 +67,45 @@ test_default_handler_error (void) } static void -test_default_handler_critical (void) +test_default_handler_error_stderr (void) { + g_log_writer_default_set_use_stderr (FALSE); + g_log_set_default_handler (g_log_default_handler, NULL); + g_error ("message1"); + exit (0); +} + +static void +test_default_handler_critical_stderr (void) +{ + g_log_writer_default_set_use_stderr (TRUE); g_log_set_default_handler (g_log_default_handler, NULL); g_critical ("message2"); exit (0); } +static void +test_default_handler_critical (void) +{ + g_log_writer_default_set_use_stderr (FALSE); + g_log_set_default_handler (g_log_default_handler, NULL); + g_critical ("message2"); + exit (0); +} + +static void +test_default_handler_warning_stderr (void) +{ + g_log_writer_default_set_use_stderr (TRUE); + g_log_set_default_handler (g_log_default_handler, NULL); + g_warning ("message3"); + exit (0); +} + static void test_default_handler_warning (void) { + g_log_writer_default_set_use_stderr (FALSE); g_log_set_default_handler (g_log_default_handler, NULL); g_warning ("message3"); exit (0); @@ -79,6 +114,16 @@ test_default_handler_warning (void) static void test_default_handler_message (void) { + g_log_writer_default_set_use_stderr (FALSE); + g_log_set_default_handler (g_log_default_handler, NULL); + g_message ("message4"); + exit (0); +} + +static void +test_default_handler_message_stderr (void) +{ + g_log_writer_default_set_use_stderr (TRUE); g_log_set_default_handler (g_log_default_handler, NULL); g_message ("message4"); exit (0); @@ -87,6 +132,16 @@ test_default_handler_message (void) static void test_default_handler_info (void) { + g_log_writer_default_set_use_stderr (FALSE); + g_log_set_default_handler (g_log_default_handler, NULL); + g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "message5"); + exit (0); +} + +static void +test_default_handler_info_stderr (void) +{ + g_log_writer_default_set_use_stderr (TRUE); g_log_set_default_handler (g_log_default_handler, NULL); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "message5"); exit (0); @@ -95,6 +150,7 @@ test_default_handler_info (void) static void test_default_handler_bar_info (void) { + g_log_writer_default_set_use_stderr (FALSE); g_log_set_default_handler (g_log_default_handler, NULL); g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE); @@ -106,6 +162,7 @@ test_default_handler_bar_info (void) static void test_default_handler_baz_debug (void) { + g_log_writer_default_set_use_stderr (FALSE); g_log_set_default_handler (g_log_default_handler, NULL); g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE); @@ -117,6 +174,7 @@ test_default_handler_baz_debug (void) static void test_default_handler_debug (void) { + g_log_writer_default_set_use_stderr (FALSE); g_log_set_default_handler (g_log_default_handler, NULL); g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); @@ -192,6 +250,7 @@ test_default_handler_would_drop (void) static void test_default_handler_0x400 (void) { + g_log_writer_default_set_use_stderr (FALSE); g_log_set_default_handler (g_log_default_handler, NULL); g_log (G_LOG_DOMAIN, 1<<10, "message7"); exit (0); @@ -205,26 +264,51 @@ test_default_handler (void) g_test_trap_assert_failed (); g_test_trap_assert_stderr ("*ERROR*message1*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/error-stderr", 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*ERROR*message1*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/critical", 0, G_TEST_SUBPROCESS_DEFAULT); g_test_trap_assert_failed (); g_test_trap_assert_stderr ("*CRITICAL*message2*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/critical-stderr", 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*CRITICAL*message2*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/warning", 0, G_TEST_SUBPROCESS_DEFAULT); g_test_trap_assert_failed (); g_test_trap_assert_stderr ("*WARNING*message3*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/warning-stderr", 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*WARNING*message3*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/message", 0, G_TEST_SUBPROCESS_DEFAULT); g_test_trap_assert_passed (); g_test_trap_assert_stderr ("*Message*message4*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/message-stderr", 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_passed (); + g_test_trap_assert_stderr ("*Message*message4*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/info", 0, G_TEST_SUBPROCESS_DEFAULT); g_test_trap_assert_passed (); g_test_trap_assert_stdout_unmatched ("*INFO*message5*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/info-stderr", 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_passed (); + g_test_trap_assert_stderr_unmatched ("*INFO*message5*"); + g_test_trap_subprocess ("/logging/default-handler/subprocess/bar-info", 0, G_TEST_SUBPROCESS_DEFAULT); g_test_trap_assert_passed (); @@ -284,13 +368,27 @@ test_print_handler (void) GPrintFunc old_print_handler; old_print_handler = g_set_print_handler (my_print_handler); - g_assert (old_print_handler == NULL); + g_assert_nonnull (old_print_handler); my_print_count = 0; g_print ("bu ba"); g_assert_cmpint (my_print_count, ==, 1); - g_set_print_handler (NULL); + if (g_test_subprocess ()) + { + g_set_print_handler (NULL); + old_print_handler ("default handler\n"); + g_print ("bu ba\n"); + return; + } + + g_set_print_handler (old_print_handler); + g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_stdout ("*default handler" LINE_END "*"); + g_test_trap_assert_stdout ("*bu ba" LINE_END "*"); + g_test_trap_assert_stdout_unmatched ("*# default handler" LINE_END "*"); + g_test_trap_assert_stdout_unmatched ("*# bu ba" LINE_END "*"); + g_test_trap_has_passed (); } static void @@ -299,13 +397,25 @@ test_printerr_handler (void) GPrintFunc old_printerr_handler; old_printerr_handler = g_set_printerr_handler (my_print_handler); - g_assert (old_printerr_handler == NULL); + g_assert_nonnull (old_printerr_handler); my_print_count = 0; g_printerr ("bu ba"); g_assert_cmpint (my_print_count, ==, 1); - g_set_printerr_handler (NULL); + if (g_test_subprocess ()) + { + g_set_printerr_handler (NULL); + old_printerr_handler ("default handler\n"); + g_printerr ("bu ba\n"); + return; + } + + g_set_printerr_handler (old_printerr_handler); + g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_stderr ("*default handler" LINE_END "*"); + g_test_trap_assert_stderr ("*bu ba" LINE_END "*"); + g_test_trap_has_passed (); } static char *fail_str = "foo"; @@ -746,10 +856,15 @@ main (int argc, char *argv[]) g_test_add_func ("/logging/default-handler", test_default_handler); g_test_add_func ("/logging/default-handler/subprocess/error", test_default_handler_error); + g_test_add_func ("/logging/default-handler/subprocess/error-stderr", test_default_handler_error_stderr); g_test_add_func ("/logging/default-handler/subprocess/critical", test_default_handler_critical); + g_test_add_func ("/logging/default-handler/subprocess/critical-stderr", test_default_handler_critical_stderr); g_test_add_func ("/logging/default-handler/subprocess/warning", test_default_handler_warning); + g_test_add_func ("/logging/default-handler/subprocess/warning-stderr", test_default_handler_warning_stderr); g_test_add_func ("/logging/default-handler/subprocess/message", test_default_handler_message); + g_test_add_func ("/logging/default-handler/subprocess/message-stderr", test_default_handler_message_stderr); g_test_add_func ("/logging/default-handler/subprocess/info", test_default_handler_info); + g_test_add_func ("/logging/default-handler/subprocess/info-stderr", test_default_handler_info_stderr); g_test_add_func ("/logging/default-handler/subprocess/bar-info", test_default_handler_bar_info); g_test_add_func ("/logging/default-handler/subprocess/baz-debug", test_default_handler_baz_debug); g_test_add_func ("/logging/default-handler/subprocess/debug", test_default_handler_debug); diff --git a/glib/tests/meson.build b/glib/tests/meson.build index e1b12e368..cb019b6f7 100644 --- a/glib/tests/meson.build +++ b/glib/tests/meson.build @@ -140,6 +140,7 @@ glib_tests = { 'string' : {}, 'strvbuilder' : {}, 'testing' : { + 'args': [ '--verbose' ], 'extra_programs' : ['testing-helper'], }, 'test-printf' : {}, @@ -386,7 +387,7 @@ foreach test_name, extra_args : glib_tests ) depends = [extra_args.get('depends', [])] - suite = ['glib'] + extra_args.get('suite', []) + suite = ['glib', 'core'] + extra_args.get('suite', []) timeout = suite.contains('slow') ? test_timeout_slow : test_timeout if extra_args.get('can_fail', false) @@ -398,6 +399,8 @@ foreach test_name, extra_args : glib_tests endforeach test(test_name, exe, + args: extra_args.get('args', []), + protocol : extra_args.get('protocol', test_protocol), depends : depends, env : test_env, timeout : timeout, @@ -431,7 +434,7 @@ endif foreach test_name, extra_args : python_tests depends = [extra_args.get('depends', [])] - suite = ['glib', 'no-valgrind'] + suite = ['glib', 'core', 'no-valgrind'] if extra_args.get('can_fail', false) suite += 'failing' @@ -444,6 +447,7 @@ foreach test_name, extra_args : python_tests test( test_name, python, + protocol : extra_args.get('protocol', test_protocol), depends: depends, args: ['-B', files(test_name)], env: test_env, @@ -486,7 +490,7 @@ if not meson.is_cross_build() and host_system != 'windows' test('gtester-xmllint-check', xmllint, args : ['--noout', tmpsample_xml], env : test_env, - suite : ['glib'], + suite : ['glib', 'core'], ) endif endif diff --git a/glib/tests/spawn-test-win32-gui.c b/glib/tests/spawn-test-win32-gui.c index 34945f524..46353c8f3 100644 --- a/glib/tests/spawn-test-win32-gui.c +++ b/glib/tests/spawn-test-win32-gui.c @@ -26,7 +26,7 @@ WinMain (struct HINSTANCE__ *hInstance, } else if (__argc <= 2) { - printf ("This is stdout\n"); + printf ("# This is stdout\n"); fflush (stdout); fprintf (stderr, "This is stderr\n"); @@ -41,36 +41,36 @@ WinMain (struct HINSTANCE__ *hInstance, if (infd < 0 || outfd < 0) { - printf ("spawn-test-win32-gui: illegal fds on command line %s", + fprintf (stderr, "spawn-test-win32-gui: illegal fds on command line %s\n", lpszCmdLine); exit (1); } n = strlen ("Hello there"); if (write (outfd, &n, sizeof (n)) == -1 || - write (outfd, "Hello there", n) == -1) + write (outfd, "Hello there\n", n) == -1) { int errsv = errno; - printf ("spawn-test-win32-gui: Write error: %s", strerror (errsv)); + fprintf (stderr, "spawn-test-win32-gui: Write error: %s\n", strerror (errsv)); exit (1); } if ((k = read (infd, &n, sizeof (n))) != sizeof (n)) { - printf ("spawn-test-win32-gui: Got only %d bytes, wanted %d", + fprintf (stderr, "spawn-test-win32-gui: Got only %d bytes, wanted %d\n", k, (int)sizeof (n)); exit (1); } - printf ("spawn-test-win32-gui: Parent says %d bytes to read", n); + fprintf (stderr, "spawn-test-win32-gui: Parent says %d bytes to read\n", n); if ((k = read (infd, buf, n)) != n) { int errsv = errno; if (k == -1) - printf ("spawn-test-win32-gui: Read error: %s", strerror (errsv)); + fprintf (stderr, "spawn-test-win32-gui: Read error: %s\n", strerror (errsv)); else - printf ("spawn-test-win32-gui: Got only %d bytes", k); + fprintf (stderr, "spawn-test-win32-gui: Got only %d bytes\n", k); exit (1); } @@ -79,7 +79,7 @@ WinMain (struct HINSTANCE__ *hInstance, write (outfd, "See ya", n) == -1) { int errsv = errno; - printf ("spawn-test-win32-gui: Write error: %s", strerror (errsv)); + fprintf (stderr, "spawn-test-win32-gui: Write error: %s\n", strerror (errsv)); exit (1); } } diff --git a/glib/tests/spawn-test.c b/glib/tests/spawn-test.c index c0b6829fe..7da666e3f 100644 --- a/glib/tests/spawn-test.c +++ b/glib/tests/spawn-test.c @@ -149,7 +149,7 @@ test_spawn_basics (void) g_assert_no_error (err); g_assert_true (result); - g_assert_cmpstr (output, ==, "This is stdout\r\n"); + g_assert_cmpstr (output, ==, "# This is stdout\r\n"); g_assert_cmpstr (erroutput, ==, "This is stderr\r\n"); g_free (output); diff --git a/glib/tests/testing-helper.c b/glib/tests/testing-helper.c index 3d435e588..da60f3e44 100644 --- a/glib/tests/testing-helper.c +++ b/glib/tests/testing-helper.c @@ -20,6 +20,7 @@ #include #include +#include #ifdef G_OS_WIN32 #include #include @@ -51,6 +52,12 @@ test_fail (void) g_test_fail (); } +static void +test_error (void) +{ + g_error ("This should error out\nBecause it's just\nwrong!"); +} + static void test_fail_printf (void) { @@ -79,6 +86,63 @@ test_summary (void) "it in the TAP output later."); } +static void +test_message (void) +{ + g_test_message ("Tests that single line message works"); + g_test_message ("Tests that multi\n\nline\nmessage\nworks"); + g_test_message ("\nTests that multi\nline\nmessage\nworks with leading and trailing too\n"); +} + +static void +test_print (void) +{ + g_print ("Tests that single line message works\n"); + g_print ("test that multiple\nlines "); + g_print ("can be "); + g_print ("written "); + g_print ("separately\n"); +} + +static void +test_subprocess_stdout (void) +{ + if (g_test_subprocess ()) + { + printf ("Tests that single line message works\n"); + printf ("test that multiple\nlines "); + printf ("can be "); + printf ("written "); + printf ("separately\n"); + + puts ("And another line has been put"); + + return; + } + + g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDOUT); + g_test_trap_has_passed (); + + g_test_trap_assert_stdout ("/sub-stdout: Tests that single line message works\n*"); + g_test_trap_assert_stdout ("*\ntest that multiple\nlines can be written separately\n*"); + g_test_trap_assert_stdout ("*\nAnd another line has been put\n*"); +} + +static void +test_subprocess_stdout_no_nl (void) +{ + if (g_test_subprocess ()) + { + printf ("A message without trailing new line"); + return; + } + + g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDOUT); + g_test_trap_has_passed (); + + g_test_trap_assert_stdout ("/sub-stdout-no-nl: A message without trailing new line"); +} + int main (int argc, char *argv[]) @@ -149,6 +213,15 @@ main (int argc, { g_test_add_func ("/fail", test_fail); } + else if (g_strcmp0 (argv1, "error") == 0) + { + g_test_add_func ("/error", test_error); + } + else if (g_strcmp0 (argv1, "error-and-pass") == 0) + { + g_test_add_func ("/error", test_error); + g_test_add_func ("/pass", test_pass); + } else if (g_strcmp0 (argv1, "fail-printf") == 0) { g_test_add_func ("/fail-printf", test_fail_printf); @@ -185,9 +258,33 @@ main (int argc, { g_test_add_func ("/summary", test_summary); } + else if (g_strcmp0 (argv1, "message") == 0) + { + g_test_add_func ("/message", test_message); + } + else if (g_strcmp0 (argv1, "print") == 0) + { + g_test_add_func ("/print", test_print); + } + else if (g_strcmp0 (argv1, "subprocess-stdout") == 0) + { + g_test_add_func ("/sub-stdout", test_subprocess_stdout); + } + else if (g_strcmp0 (argv1, "subprocess-stdout-no-nl") == 0) + { + g_test_add_func ("/sub-stdout-no-nl", test_subprocess_stdout_no_nl); + } else { - g_assert_not_reached (); + if (g_test_subprocess ()) + { + g_test_add_func ("/sub-stdout", test_subprocess_stdout); + g_test_add_func ("/sub-stdout-no-nl", test_subprocess_stdout_no_nl); + } + else + { + g_assert_not_reached (); + } } return g_test_run (); diff --git a/glib/tests/testing.c b/glib/tests/testing.c index 24e8d08e4..e0653857d 100644 --- a/glib/tests/testing.c +++ b/glib/tests/testing.c @@ -35,6 +35,9 @@ #include #include +#define TAP_VERSION G_STRINGIFY (13) +#define TAP_SUBTEST_PREFIX "# " + /* test assertion variants */ static void test_assertions_bad_cmpvariant_types (void) @@ -670,6 +673,23 @@ test_expected_messages (void) g_test_trap_assert_stderr ("*GLib:ERROR*Did not see expected message testing-CRITICAL*nope*"); } +static void +test_messages (void) +{ + g_test_trap_subprocess ("/misc/messages/subprocess/use-stderr", 0, + G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_stderr ("*message is in stderr*"); + g_test_trap_assert_stderr ("*warning is in stderr*"); + g_test_trap_has_passed (); +} + +static void +test_messages_use_stderr (void) +{ + g_message ("message is in stderr"); + g_warning ("warning is in stderr"); +} + static void test_expected_messages_debug (void) { @@ -1089,6 +1109,7 @@ test_tap (void) GError *error = NULL; int status; gchar *output; + char **envp; testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); @@ -1099,7 +1120,12 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + /* Remove the G_TEST_ROOT_PROCESS env so it will be considered a standalone test */ + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + envp = g_environ_unsetenv (g_steal_pointer (&envp), "G_TEST_ROOT_PROCESS"); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1107,6 +1133,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nok 1 /pass\n")); g_free (output); g_ptr_array_unref (argv); @@ -1118,7 +1146,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1126,6 +1154,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nok 1 /skip # SKIP not enough tea\n")); g_free (output); g_ptr_array_unref (argv); @@ -1137,7 +1167,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1145,6 +1175,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nok 1 /skip-printf # SKIP not enough coffee\n")); g_free (output); g_ptr_array_unref (argv); @@ -1156,7 +1188,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1164,6 +1196,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nnot ok 1 /incomplete # TODO mind reading not implemented yet\n")); g_free (output); g_ptr_array_unref (argv); @@ -1175,7 +1209,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1183,6 +1217,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nnot ok 1 /incomplete-printf # TODO telekinesis not implemented yet\n")); g_free (output); g_ptr_array_unref (argv); @@ -1194,7 +1230,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1202,6 +1238,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nnot ok 1 /fail\n")); g_free (output); g_clear_error (&error); @@ -1214,7 +1252,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); @@ -1222,6 +1260,8 @@ test_tap (void) g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nnot ok 1 /fail-printf - this test intentionally left failing\n")); g_free (output); g_clear_error (&error); @@ -1234,7 +1274,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL, &status, &error); @@ -1252,7 +1292,7 @@ test_tap (void) g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL, &status, &error); @@ -1272,11 +1312,13 @@ test_tap (void) g_ptr_array_add (argv, "2"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "1..10\n")); g_assert_nonnull (strstr (output, "\nok 1 /a # SKIP\n")); g_assert_nonnull (strstr (output, "\nok 2 /b # SKIP\n")); @@ -1304,11 +1346,13 @@ test_tap (void) g_ptr_array_add (argv, "0"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "1..10\n")); g_assert_nonnull (strstr (output, "\nok 1 /a\n")); g_assert_nonnull (strstr (output, "\nok 2 /b\n")); @@ -1336,11 +1380,13 @@ test_tap (void) g_ptr_array_add (argv, "11"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "1..10\n")); g_assert_nonnull (strstr (output, "\nok 1 /a # SKIP\n")); g_assert_nonnull (strstr (output, "\nok 2 /b # SKIP\n")); @@ -1372,11 +1418,13 @@ test_tap (void) g_ptr_array_add (argv, "/b"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nok 1 /c/a\n")); g_assert_nonnull (strstr (output, "\nok 2 /c/a\n")); g_assert_nonnull (strstr (output, "\nok 3 /b\n")); @@ -1403,11 +1451,13 @@ test_tap (void) g_ptr_array_add (argv, "/b"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nok 1 /c/a\n")); g_assert_nonnull (strstr (output, "\nok 2 /c/a\n")); g_assert_nonnull (strstr (output, "\nok 3 /b\n")); @@ -1433,11 +1483,13 @@ test_tap (void) g_ptr_array_add (argv, "/b/b"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "\nok 1 /b/b\n")); g_assert_nonnull (strstr (output, "\nok 2 /b/b/a\n")); g_assert_nonnull (strstr (output, "\n1..2\n")); @@ -1461,13 +1513,14 @@ test_tap (void) g_ptr_array_add (argv, "/b"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); g_spawn_check_wait_status (status, &error); g_assert_nonnull (error); + g_assert_false (g_str_has_prefix (output, "TAP version " TAP_VERSION)); g_assert_nonnull (strstr (output, "do not mix [-r | --run-prefix] with '-p'\n")); g_clear_error (&error); @@ -1489,11 +1542,13 @@ test_tap (void) g_ptr_array_add (argv, "/c/a"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "1..10\n")); g_assert_nonnull (strstr (output, "\nok 1 /a # SKIP by request")); g_assert_nonnull (strstr (output, "\nok 2 /b # SKIP by request")); @@ -1527,11 +1582,13 @@ test_tap (void) g_ptr_array_add (argv, "/c/a"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); + g_assert_true (g_str_has_prefix (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "# Subtest: ")); g_assert_nonnull (strstr (output, "1..10\n")); g_assert_nonnull (strstr (output, "\nok 1 /a # SKIP by request")); g_assert_nonnull (strstr (output, "\nok 2 /b\n")); @@ -1564,22 +1621,652 @@ test_tap (void) g_ptr_array_add (argv, "/c/a"); g_ptr_array_add (argv, NULL); - g_spawn_sync (NULL, (char **) argv->pdata, NULL, + g_spawn_sync (NULL, (char **) argv->pdata, envp, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); g_spawn_check_wait_status (status, &error); g_assert_nonnull (error); + g_assert_false (g_str_has_prefix (output, "TAP version " TAP_VERSION)); g_assert_nonnull (strstr (output, "do not mix [-x | --skip-prefix] with '-s'\n")); g_clear_error (&error); + g_free (output); + g_ptr_array_unref (argv); + g_strfreev (envp); +} + +/* Test the TAP output when a test suite is run with --tap. */ +static void +test_tap_subtest (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char** envp = NULL; + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + g_test_message ("pass"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "pass"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + g_clear_pointer (&envp, g_strfreev); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /pass\n")); + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("skip"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /skip # SKIP not enough tea\n")); + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("skip with printf format"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-printf"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /skip-printf # SKIP not enough coffee\n")); + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("incomplete"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "incomplete"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null (strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "not ok 1 /incomplete # TODO mind reading not implemented yet\n")); + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("incomplete with printf format"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "incomplete-printf"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "not ok 1 /incomplete-printf # TODO telekinesis not implemented yet\n")); + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("fail"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "fail"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "not ok 1 /fail\n")); + g_free (output); + g_clear_error (&error); + g_ptr_array_unref (argv); + + g_test_message ("fail with message"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "fail-printf"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "not ok 1 /fail-printf - this test intentionally left failing\n")); + g_free (output); + g_clear_error (&error); + g_ptr_array_unref (argv); + + g_test_message ("all"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "all"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); + g_clear_error (&error); + g_ptr_array_unref (argv); + + g_test_message ("all-non-failures"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "all-non-failures"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_ptr_array_unref (argv); + + g_test_message ("--GTestSkipCount"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "--GTestSkipCount"); + g_ptr_array_add (argv, "2"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, TAP_SUBTEST_PREFIX "1..10\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /b # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 6 /prefix/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 7 /prefix/b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 8 /prefix-long/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 9 /c/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 10 /d/a\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--GTestSkipCount=0 is the same as omitting it"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "--GTestSkipCount"); + g_ptr_array_add (argv, "0"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, TAP_SUBTEST_PREFIX "1..10\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 6 /prefix/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 7 /prefix/b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 8 /prefix-long/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 9 /c/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 10 /d/a\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--GTestSkipCount > number of tests skips all"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "--GTestSkipCount"); + g_ptr_array_add (argv, "11"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, TAP_SUBTEST_PREFIX "1..10\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /b # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b/a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/b # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b/a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 6 /prefix/a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 7 /prefix/b/b # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 8 /prefix-long/a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 9 /c/a # SKIP\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 10 /d/a # SKIP\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("-p"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "-p"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, "-p"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, "-p"); + g_ptr_array_add (argv, "/b"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /c/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /c/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "1..5\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--run-prefix"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "-r"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, "-r"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, "--run-prefix"); + g_ptr_array_add (argv, "/b"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /c/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /c/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 6 /b/b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "1..6\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--run-prefix 2"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "-r"); + g_ptr_array_add (argv, "/pre"); + g_ptr_array_add (argv, "--run-prefix"); + g_ptr_array_add (argv, "/b/b"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /b/b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "1..2\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--run-prefix conflict"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "-r"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, "-p"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, "--run-prefix"); + g_ptr_array_add (argv, "/b"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_spawn_check_wait_status (status, &error); + g_assert_nonnull (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, "do not mix [-r | --run-prefix] with '-p'\n")); + g_clear_error (&error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("-s"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "-s"); + g_ptr_array_add (argv, "/a"); + g_ptr_array_add (argv, "-s"); + g_ptr_array_add (argv, "/b"); + g_ptr_array_add (argv, "-s"); + g_ptr_array_add (argv, "/pre"); + g_ptr_array_add (argv, "-s"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_null( strstr (output, "\n# Subtest: ")); + g_assert_nonnull (strstr (output, TAP_SUBTEST_PREFIX "1..10\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /a # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /b # SKIP by request")); + /* "-s /b" would skip a test named exactly /b, but not a test named + * /b/anything */ + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 6 /prefix/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 7 /prefix/b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 8 /prefix-long/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 9 /c/a # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 10 /d/a\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--skip-prefix"); + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "skip-options"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, "-x"); + g_ptr_array_add (argv, "/a"); + g_ptr_array_add (argv, "--skip-prefix"); + g_ptr_array_add (argv, "/pre"); + g_ptr_array_add (argv, "-x"); + g_ptr_array_add (argv, "/c/a"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "TAP version " TAP_VERSION)); + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + g_assert_nonnull (strstr (output, TAP_SUBTEST_PREFIX "1..10\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 1 /a # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 2 /b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 3 /b/a\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 4 /b/b\n")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 5 /b/b/a\n")); + /* "--skip-prefix /pre" will skip all test path which begins with /pre */ + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 6 /prefix/a # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 7 /prefix/b/b # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 8 /prefix-long/a # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 9 /c/a # SKIP by request")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX "ok 10 /d/a\n")); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_free (output); g_ptr_array_unref (argv); } static void test_tap_summary (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **envp; + + g_test_summary ("Test the output of g_test_summary() from the TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "summary"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + /* Remove the G_TEST_ROOT_PROCESS env so it will be considered a standalone test */ + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + envp = g_environ_unsetenv (g_steal_pointer (&envp), "G_TEST_ROOT_PROCESS"); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + g_assert_null (strstr (output, "# Subtest: ")); + + /* Note: The test path in the output is not `/tap/summary` because it’s the + * test path from testing-helper, not from this function. */g_assert_null (strstr (output, "# Subtest: ")); + g_assert_nonnull (strstr (output, "\n# /summary summary: Tests that g_test_summary() " + "works with TAP, by outputting a known " + "summary message in testing-helper, and " + "checking for it in the TAP output later.\n")); + g_free (output); + g_ptr_array_unref (argv); + g_strfreev (envp); +} + +static void +test_tap_subtest_summary (void) { const char *testing_helper; GPtrArray *argv; @@ -1607,14 +2294,535 @@ test_tap_summary (void) g_assert_no_error (error); /* Note: The test path in the output is not `/tap/summary` because it’s the * test path from testing-helper, not from this function. */ - g_assert_nonnull (strstr (output, "\n# /summary summary: Tests that g_test_summary() " - "works with TAP, by outputting a known " - "summary message in testing-helper, and " - "checking for it in the TAP output later.\n")); + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + g_assert_nonnull (strstr (output, + "\n" TAP_SUBTEST_PREFIX + "# /summary summary: Tests that g_test_summary() " + "works with TAP, by outputting a known " + "summary message in testing-helper, and " + "checking for it in the TAP output later.\n")); g_free (output); g_ptr_array_unref (argv); } +static void +test_tap_message (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **output_lines; + char **envp; + + g_test_summary ("Test the output of g_test_message() from the TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "message"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + /* Remove the G_TEST_ROOT_PROCESS env so it will be considered a standalone test */ + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + envp = g_environ_unsetenv (g_steal_pointer (&envp), "G_TEST_ROOT_PROCESS"); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_assert_null (strstr (output, "# Subtest: ")); + + const char *expected_tap_header = "\n1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + output_lines = g_strsplit (interesting_lines, "\n", -1); + g_assert_cmpuint (g_strv_length (output_lines), >=, 12); + + guint i = 0; + g_assert_cmpstr (output_lines[i++], ==, "# Tests that single line message works"); + g_assert_cmpstr (output_lines[i++], ==, "# Tests that multi"); + g_assert_cmpstr (output_lines[i++], ==, "# "); + g_assert_cmpstr (output_lines[i++], ==, "# line"); + g_assert_cmpstr (output_lines[i++], ==, "# message"); + g_assert_cmpstr (output_lines[i++], ==, "# works"); + g_assert_cmpstr (output_lines[i++], ==, "# "); + g_assert_cmpstr (output_lines[i++], ==, "# Tests that multi"); + g_assert_cmpstr (output_lines[i++], ==, "# line"); + g_assert_cmpstr (output_lines[i++], ==, "# message"); + g_assert_cmpstr (output_lines[i++], ==, "# works with leading and trailing too"); + g_assert_cmpstr (output_lines[i++], ==, "# "); + + g_free (output); + g_strfreev (output_lines); + g_strfreev (envp); + g_ptr_array_unref (argv); +} + +static void +test_tap_subtest_message (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **output_lines; + + g_test_summary ("Test the output of g_test_message() from the TAP output of a sub-test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "message"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + + const char *expected_tap_header = "\n" TAP_SUBTEST_PREFIX "1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + output_lines = g_strsplit (interesting_lines, "\n", -1); + g_assert_cmpuint (g_strv_length (output_lines), >=, 12); + + guint i = 0; + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# Tests that single line message works"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# Tests that multi"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# "); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# line"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# message"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# works"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# "); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# Tests that multi"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# line"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# message"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# works with leading and trailing too"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# "); + + g_free (output); + g_strfreev (output_lines); + g_ptr_array_unref (argv); +} + +static void +test_tap_print (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **output_lines; + char **envp; + + g_test_summary ("Test the output of g_print() from the TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "print"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + /* Remove the G_TEST_ROOT_PROCESS env so it will be considered a standalone test */ + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + envp = g_environ_unsetenv (g_steal_pointer (&envp), "G_TEST_ROOT_PROCESS"); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + const char *expected_tap_header = "\n1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + output_lines = g_strsplit (interesting_lines, "\n", -1); + g_assert_cmpuint (g_strv_length (output_lines), >=, 3); + + guint i = 0; + g_assert_cmpstr (output_lines[i++], ==, "# Tests that single line message works"); + g_assert_cmpstr (output_lines[i++], ==, "# test that multiple"); + g_assert_cmpstr (output_lines[i++], ==, "# lines can be written separately"); + + g_free (output); + g_strfreev (envp); + g_strfreev (output_lines); + g_ptr_array_unref (argv); +} + +static void +test_tap_subtest_print (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **output_lines; + + g_test_summary ("Test the output of g_test_print() from the TAP output of a sub-test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "print"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + const char *expected_tap_header = "\n" TAP_SUBTEST_PREFIX "1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + output_lines = g_strsplit (interesting_lines, "\n", -1); + g_assert_cmpuint (g_strv_length (output_lines), >=, 3); + + guint i = 0; + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# Tests that single line message works"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# test that multiple"); + g_assert_cmpstr (output_lines[i++], ==, TAP_SUBTEST_PREFIX "# lines can be written separately"); + + g_free (output); + g_strfreev (output_lines); + g_ptr_array_unref (argv); +} + +static void +test_tap_subtest_stdout (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **output_lines; + + g_test_summary ("Test the stdout from the TAP output of a sub-test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "subprocess-stdout"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + const char *expected_tap_header = "\n" TAP_SUBTEST_PREFIX "1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + + interesting_lines = strstr (interesting_lines, TAP_SUBTEST_PREFIX "# /sub-stdout"); + g_assert_nonnull (interesting_lines); + + output_lines = g_strsplit (interesting_lines, "\n", -1); + g_assert_cmpuint (g_strv_length (output_lines), >=, 5); + + guint i = 0; + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "# /sub-stdout: Tests that single line message works"); + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "# test that multiple"); + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "# lines can be written separately"); + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "# And another line has been put"); + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "ok 1 /sub-stdout"); + + g_free (output); + g_strfreev (output_lines); + g_ptr_array_unref (argv); +} + +static void +test_tap_subtest_stdout_no_new_line (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **output_lines; + + g_test_summary ("Test the stdout from the TAP output of a sub-test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "subprocess-stdout-no-nl"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_no_error (error); + + const char *expected_tap_header = "\n" TAP_SUBTEST_PREFIX "1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + + interesting_lines = strstr (interesting_lines, TAP_SUBTEST_PREFIX "# /sub-stdout-no-nl"); + g_assert_nonnull (interesting_lines); + + output_lines = g_strsplit (interesting_lines, "\n", -1); + g_assert_cmpuint (g_strv_length (output_lines), >=, 2); + + guint i = 0; + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "# /sub-stdout-no-nl: A message without trailing new line"); + g_assert_cmpstr (output_lines[i++], ==, + TAP_SUBTEST_PREFIX "ok 1 /sub-stdout-no-nl"); + + g_free (output); + g_strfreev (output_lines); + g_ptr_array_unref (argv); +} + +static void +test_tap_error (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **envp; + + g_test_summary ("Test that g_error() generates Bail out TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "error"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + /* Remove the G_TEST_ROOT_PROCESS env so it will be considered a standalone test */ + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + envp = g_environ_unsetenv (g_steal_pointer (&envp), "G_TEST_ROOT_PROCESS"); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_nonnull (error); + + g_assert_false (g_str_has_prefix (output, "# Subtest: ")); + + const char *expected_tap_header = "\n1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + g_assert_cmpstr (interesting_lines, ==, "Bail out! GLib-FATAL-ERROR: This should error out " + "Because it's just wrong!\n"); + + g_free (output); + g_strfreev (envp); + g_ptr_array_unref (argv); + g_clear_error (&error); +} + +static void +test_tap_subtest_error (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + + g_test_summary ("Test that g_error() generates Bail out TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "error"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_nonnull (error); + + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + + const char *expected_tap_header = "\n" TAP_SUBTEST_PREFIX "1..1\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + g_assert_cmpstr (interesting_lines, ==, + TAP_SUBTEST_PREFIX "Bail out! GLib-FATAL-ERROR: This should error out " + "Because it's just wrong!\n" + "Bail out!\n"); + + g_free (output); + g_ptr_array_unref (argv); + g_clear_error (&error); +} + +static void +test_tap_error_and_pass (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + char **envp; + + g_test_summary ("Test that g_error() generates Bail out TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + /* Remove the G_TEST_ROOT_PROCESS env so it will be considered a standalone test */ + envp = g_get_environ (); + g_assert_nonnull (g_environ_getenv (envp, "G_TEST_ROOT_PROCESS")); + envp = g_environ_unsetenv (g_steal_pointer (&envp), "G_TEST_ROOT_PROCESS"); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "error-and-pass"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, envp, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_nonnull (error); + + const char *expected_tap_header = "\n1..2\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + g_assert_cmpstr (interesting_lines, ==, "Bail out! GLib-FATAL-ERROR: This should error out " + "Because it's just wrong!\n"); + + g_free (output); + g_strfreev (envp); + g_ptr_array_unref (argv); + g_clear_error (&error); +} + +static void +test_tap_subtest_error_and_pass (void) +{ + const char *testing_helper; + GPtrArray *argv; + GError *error = NULL; + int status; + gchar *output; + + g_test_summary ("Test that g_error() generates Bail out TAP output of a test."); + + testing_helper = g_test_get_filename (G_TEST_BUILT, "testing-helper" EXEEXT, NULL); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, (char *) testing_helper); + g_ptr_array_add (argv, "error-and-pass"); + g_ptr_array_add (argv, "--tap"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char **) argv->pdata, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + + g_spawn_check_wait_status (status, &error); + g_assert_nonnull (error); + + g_assert_true (g_str_has_prefix (output, "# Subtest: ")); + + const char *expected_tap_header = "\n" TAP_SUBTEST_PREFIX "1..2\n"; + const char *interesting_lines = strstr (output, expected_tap_header); + g_assert_nonnull (interesting_lines); + interesting_lines += strlen (expected_tap_header); + + g_assert_cmpstr (interesting_lines, ==, + TAP_SUBTEST_PREFIX "Bail out! GLib-FATAL-ERROR: This should error out " + "Because it's just wrong!\n" + "Bail out!\n"); + + g_free (output); + g_ptr_array_unref (argv); + g_clear_error (&error); +} + static void test_init_no_argv0 (void) { @@ -1718,6 +2926,9 @@ main (int argc, g_test_add_func ("/misc/expected-messages/expect-error", test_expected_messages_expect_error); g_test_add_func ("/misc/expected-messages/skip-debug", test_expected_messages_debug); + g_test_add_func ("/misc/messages", test_messages); + g_test_add_func ("/misc/messages/subprocess/use-stderr", test_messages_use_stderr); + g_test_add_func ("/misc/dash-p", test_dash_p); g_test_add_func ("/misc/dash-p/child", test_dash_p_child); g_test_add_func ("/misc/dash-p/child/sub", test_dash_p_child_sub); @@ -1744,7 +2955,19 @@ main (int argc, g_test_add_func ("/misc/path/second", test_path_second); g_test_add_func ("/tap", test_tap); + g_test_add_func ("/tap/subtest", test_tap_subtest); g_test_add_func ("/tap/summary", test_tap_summary); + g_test_add_func ("/tap/subtest/summary", test_tap_subtest_summary); + g_test_add_func ("/tap/message", test_tap_message); + g_test_add_func ("/tap/subtest/message", test_tap_subtest_message); + g_test_add_func ("/tap/print", test_tap_print); + g_test_add_func ("/tap/subtest/print", test_tap_subtest_print); + g_test_add_func ("/tap/subtest/stdout", test_tap_subtest_stdout); + g_test_add_func ("/tap/subtest/stdout-no-new-line", test_tap_subtest_stdout_no_new_line); + g_test_add_func ("/tap/error", test_tap_error); + g_test_add_func ("/tap/subtest/error", test_tap_subtest_error); + g_test_add_func ("/tap/error-and-pass", test_tap_error_and_pass); + g_test_add_func ("/tap/subtest/error-and-pass", test_tap_subtest_error_and_pass); g_test_add_func ("/init/no_argv0", test_init_no_argv0); diff --git a/gmodule/tests/meson.build b/gmodule/tests/meson.build index a78887529..ec7eb68fd 100644 --- a/gmodule/tests/meson.build +++ b/gmodule/tests/meson.build @@ -5,6 +5,7 @@ gmodule_tests = { if have_cxx gmodule_tests += { 'cxx' : { + 'protocol': 'exitcode', 'source' : ['cxx.cpp'], 'suite' : ['cpp'], } @@ -13,6 +14,7 @@ if have_cxx foreach std, arg: cxx_standards gmodule_tests += { 'cxx-@0@'.format(std) : { + 'protocol': 'exitcode', 'source' : ['cxx.cpp'], 'suite' : ['cpp'], 'cpp_args' : [arg], @@ -115,6 +117,7 @@ foreach test_name, extra_args : gmodule_tests test(test_name, exe, + protocol : extra_args.get('protocol', test_protocol), depends : depends, env : test_env, timeout : timeout, diff --git a/gobject/tests/meson.build b/gobject/tests/meson.build index a880dfb33..9e807463b 100644 --- a/gobject/tests/meson.build +++ b/gobject/tests/meson.build @@ -41,7 +41,7 @@ gobject_tests = { 'defaultiface' : { 'source' : ['defaultiface.c', 'testmodule.c'], }, - 'deftype' : {}, + 'deftype' : { 'protocol': 'exitcode' }, 'deprecated-properties' : {}, 'dynamictype' : { 'source' : ['dynamictype.c', 'testmodule.c'], @@ -109,6 +109,7 @@ gobject_tests = { if have_cxx gobject_tests += { 'cxx' : { + 'protocol': 'exitcode', 'source' : ['cxx.cpp'], 'suite' : ['cpp'], }, @@ -117,6 +118,7 @@ if have_cxx foreach std, arg: cxx_standards gobject_tests += { 'cxx-@0@'.format(std) : { + 'protocol': 'exitcode', 'source' : ['cxx.cpp'], 'suite' : ['cpp'], 'cpp_args' : [arg], @@ -186,7 +188,13 @@ foreach test_name, extra_args : gobject_tests timeout = timeout * 10 endif - test(test_name, exe, env : test_env, timeout : timeout, suite : suite) + test(test_name, + exe, + protocol : extra_args.get('protocol', test_protocol), + env : test_env, + timeout : timeout, + suite : suite, + ) endforeach foreach test_name, extra_args : python_tests @@ -200,6 +208,7 @@ foreach test_name, extra_args : python_tests test( test_name, python, + protocol : extra_args.get('protocol', test_protocol), depends: depends, args: ['-B', files(test_name)], env: test_env, diff --git a/gthread/tests/meson.build b/gthread/tests/meson.build index 86da67413..53fb78e18 100644 --- a/gthread/tests/meson.build +++ b/gthread/tests/meson.build @@ -44,5 +44,11 @@ foreach test_name, extra_args : gthread_tests suite += 'failing' endif - test(test_name, exe, env : test_env, timeout : timeout, suite : suite) + test(test_name, + exe, + protocol : extra_args.get('protocol', test_protocol), + env : test_env, + timeout : timeout, + suite : suite, + ) endforeach diff --git a/meson.build b/meson.build index 8d3500ad7..74173e060 100644 --- a/meson.build +++ b/meson.build @@ -151,6 +151,10 @@ common_test_env = [ 'MALLOC_CHECK_=2', ] +# Note: this may cause the tests output not to be printed when running in +# verbose mode, see https://github.com/mesonbuild/meson/issues/11185 +# Can be changed it to 'exitcode' if required during development. +test_protocol = 'tap' test_timeout = 30 test_timeout_slow = 90