gtestutils: Use test print handler to write subprocess output

When using verbose logging, all the printing and the glib info and debug
logs may end up being written in standard out, making meson TAP parser to be
confused and to fail with TAP parsing errors.

So, in such case write the subprocess output all at once using the the gtest
printer so that we add proper formatting.

Also do not write any gtest result message for subprocesses
This commit is contained in:
Marco Trevisan (Treviño) 2023-01-16 17:51:19 +01:00
parent 8b7b5f5457
commit 03f5d0b060
3 changed files with 186 additions and 3 deletions

View File

@ -1173,7 +1173,7 @@ g_test_log (GTestLogType lbit,
}
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)
{
@ -3696,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
{
@ -3777,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);

View File

@ -20,6 +20,7 @@
#include <glib.h>
#include <locale.h>
#include <stdio.h>
#ifdef G_OS_WIN32
#include <fcntl.h>
#include <io.h>
@ -103,6 +104,45 @@ test_print (void)
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[])
@ -226,9 +266,25 @@ main (int argc,
{
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 ();

View File

@ -2529,6 +2529,112 @@ test_tap_subtest_print (void)
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)
{
@ -2856,6 +2962,8 @@ main (int argc,
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);