mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-29 02:50:04 +01:00
gtestutils: Define a custom g_print handler for TAP
When using TAP output in gtest, all the printed strings should be commented not to break the spec, so enforce this at GTest level, by ensuring that all the lines written via g_print() will be in the commented form and will respect the subtest indentation. As per this we can remove some custom code in g_test_log() as now there are very few cases in which we need to use the default print handler which is now private when testing.
This commit is contained in:
parent
3d1736c828
commit
8b7b5f5457
@ -848,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",
|
||||
@ -915,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)
|
||||
{
|
||||
@ -997,23 +1082,33 @@ g_test_log (GTestLogType lbit,
|
||||
gchar *astrings[3] = { NULL, NULL, NULL };
|
||||
guint8 *dbuffer;
|
||||
guint32 dbufferlen;
|
||||
gboolean is_subtest;
|
||||
const char *tap_prefix;
|
||||
unsigned subtest_level;
|
||||
|
||||
is_subtest = test_is_subtest || test_in_forked_child || test_in_subprocess;
|
||||
tap_prefix = test_tap_log && is_subtest ? TAP_SUBTEST_PREFIX : "";
|
||||
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)
|
||||
{
|
||||
if (!is_subtest)
|
||||
g_print ("TAP version 13\n");
|
||||
if (!is_subtest ())
|
||||
{
|
||||
g_test_tap_print (0, FALSE, "TAP version 13\n");
|
||||
}
|
||||
else
|
||||
g_print ("# Subtest: %s\n", test_argv0);
|
||||
{
|
||||
g_test_tap_print (subtest_level > 0 ? subtest_level - 1 : 0, TRUE,
|
||||
"Subtest: %s\n", test_argv0);
|
||||
}
|
||||
|
||||
g_print ("%s# random seed: %s\n", tap_prefix, string2);
|
||||
g_print ("random seed: %s\n", string2);
|
||||
}
|
||||
else if (g_test_verbose ())
|
||||
{
|
||||
@ -1026,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 ("%s# Start of %s tests\n", tap_prefix, string1);
|
||||
g_print ("Start of %s tests\n", string1);
|
||||
else if (test_paths == NULL)
|
||||
g_print ("%s1..%d\n", tap_prefix, test_count);
|
||||
g_test_tap_print (subtest_level, FALSE, "1..%d\n", test_count);
|
||||
}
|
||||
break;
|
||||
case G_TEST_LOG_STOP_SUITE:
|
||||
@ -1038,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 ("%s# End of %s tests\n", tap_prefix, string1);
|
||||
g_print ("End of %s tests\n", string1);
|
||||
else if (test_paths != NULL)
|
||||
g_print ("%s1..%d\n", tap_prefix, test_run_count);
|
||||
g_test_tap_print (subtest_level, FALSE, "1..%d\n", test_run_count);
|
||||
}
|
||||
break;
|
||||
case G_TEST_LOG_STOP_CASE:
|
||||
@ -1061,7 +1156,7 @@ g_test_log (GTestLogType lbit,
|
||||
else
|
||||
tap_output = g_string_new ("ok");
|
||||
|
||||
if (is_subtest)
|
||||
if (is_subtest ())
|
||||
g_string_prepend (tap_output, TAP_SUBTEST_PREFIX);
|
||||
|
||||
g_string_append_printf (tap_output, " %d %s", test_run_count, string1);
|
||||
@ -1072,7 +1167,8 @@ g_test_log (GTestLogType lbit,
|
||||
else if (result == G_TEST_RUN_FAILURE && string2 != NULL)
|
||||
g_string_append_printf (tap_output, " - %s", string2);
|
||||
|
||||
g_print ("%s\n", tap_output->str);
|
||||
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 ())
|
||||
@ -1082,7 +1178,7 @@ g_test_log (GTestLogType lbit,
|
||||
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)
|
||||
@ -1091,56 +1187,25 @@ g_test_log (GTestLogType lbit,
|
||||
case G_TEST_LOG_SKIP_CASE:
|
||||
if (test_tap_log)
|
||||
{
|
||||
g_print ("%sok %d %s # SKIP\n", tap_prefix,
|
||||
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 ("%s# min perf: %s\n", tap_prefix, 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 ("%s# max perf: %s\n", tap_prefix, 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 (strchr (string1, '\n') == NULL)
|
||||
g_print ("%s# %s\n", tap_prefix, string1);
|
||||
else
|
||||
{
|
||||
GString *output = g_string_new (NULL);
|
||||
const char *line = string1;
|
||||
|
||||
do
|
||||
{
|
||||
const char *next = strchr (line, '\n');
|
||||
g_string_append (output, tap_prefix);
|
||||
g_string_append (output, "# ");
|
||||
|
||||
if (next)
|
||||
{
|
||||
g_string_append_len (output, line, next - line + 1);
|
||||
line = next + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append (output, line);
|
||||
g_string_append_c (output, '\n');
|
||||
line = next;
|
||||
}
|
||||
}
|
||||
while (line != NULL);
|
||||
|
||||
g_print ("%s", output->str);
|
||||
g_string_free (g_steal_pointer (&output), TRUE);
|
||||
}
|
||||
}
|
||||
g_print ("%s\n", string1);
|
||||
else if (g_test_verbose ())
|
||||
g_print ("(MSG: %s)\n", string1);
|
||||
break;
|
||||
@ -1153,10 +1218,15 @@ g_test_log (GTestLogType lbit,
|
||||
while ((line = strchr (line, '\n')))
|
||||
*(line++) = ' ';
|
||||
|
||||
if (is_subtest)
|
||||
g_print ("%sBail out! %s\nBail out!\n", tap_prefix, message);
|
||||
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_print ("Bail out! %s\n", message);
|
||||
{
|
||||
g_test_tap_print (0, FALSE, "Bail out! %s\n", message);
|
||||
}
|
||||
|
||||
g_free (message);
|
||||
}
|
||||
@ -3082,7 +3152,7 @@ test_should_run (const char *test_path,
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
if (test_tap_log)
|
||||
g_print ("# skipping: %s\n", test_run_name);
|
||||
g_print ("skipping: %s\n", test_run_name);
|
||||
else
|
||||
g_print ("GTest: skipping: %s\n", test_run_name);
|
||||
}
|
||||
@ -3932,7 +4002,7 @@ g_test_trap_subprocess (const char *test_path,
|
||||
if (g_test_verbose ())
|
||||
{
|
||||
if (test_tap_log)
|
||||
g_print ("# subprocess: %s\n", test_path);
|
||||
g_print ("subprocess: %s\n", test_path);
|
||||
else
|
||||
g_print ("GTest: subprocess: %s\n", test_path);
|
||||
}
|
||||
|
@ -374,18 +374,20 @@ test_print_handler (void)
|
||||
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 ();
|
||||
}
|
||||
|
||||
@ -401,15 +403,15 @@ test_printerr_handler (void)
|
||||
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 "*");
|
||||
|
@ -93,6 +93,16 @@ test_message (void)
|
||||
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");
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -212,6 +222,10 @@ main (int argc,
|
||||
{
|
||||
g_test_add_func ("/message", test_message);
|
||||
}
|
||||
else if (g_strcmp0 (argv1, "print") == 0)
|
||||
{
|
||||
g_test_add_func ("/print", test_print);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
|
@ -2428,6 +2428,107 @@ test_tap_subtest_message (void)
|
||||
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_error (void)
|
||||
{
|
||||
@ -2753,6 +2854,8 @@ main (int argc,
|
||||
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/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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user