From a076dbcb68df592595ce77e76766dfc534bd529d Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 5 Aug 2021 11:42:22 +0100 Subject: [PATCH] gtestutils: Allow failing a test with a printf-style message This allows a pattern like g_test_message ("cannot reticulate splines: %s", error->message); g_test_fail (); to be replaced by the simpler g_test_fail_printf ("cannot reticulate splines: %s", error->message); with the secondary benefit of making the message available to TAP consumers as part of the "not ok" message. Signed-off-by: Simon McVittie --- docs/reference/glib/glib-sections.txt | 1 + glib/gtestutils.c | 32 +++++++++++++++++++++++++++ glib/gtestutils.h | 3 +++ glib/tests/testing-helper.c | 10 +++++++++ glib/tests/testing.c | 20 +++++++++++++++++ 5 files changed, 66 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 6e4216809..6533764e1 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -3569,6 +3569,7 @@ g_test_get_filename g_test_get_dir g_test_fail +g_test_fail_printf g_test_skip g_test_skip_printf g_test_incomplete diff --git a/glib/gtestutils.c b/glib/gtestutils.c index f27ad2636..578270394 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -1039,6 +1039,8 @@ g_test_log (GTestLogType lbit, g_print (" # TODO %s\n", string2 ? string2 : ""); else if (result == G_TEST_RUN_SKIPPED) g_print (" # SKIP %s\n", string2 ? string2 : ""); + else if (result == G_TEST_RUN_FAILURE && string2 != NULL) + g_print (" - %s\n", string2); else g_print ("\n"); } @@ -2401,12 +2403,42 @@ g_test_add_vtable (const char *testpath, * * If not called from inside a test, this function does nothing. * + * Note that unlike g_test_skip() and g_test_incomplete(), this + * function does not log a message alongside the test failure. + * If details of the test failure are available, either log them with + * g_test_message() before g_test_fail(), or use g_test_fail_printf() + * instead. + * * Since: 2.30 **/ void g_test_fail (void) { test_run_success = G_TEST_RUN_FAILURE; + g_clear_pointer (&test_run_msg, g_free); +} + +/** + * g_test_fail_printf: + * @format: the format string + * @...: printf-like arguments to @format + * + * Equivalent to g_test_fail(), but also record a message like + * g_test_skip_printf(). + * + * Since: 2.70 + **/ +void +g_test_fail_printf (const char *format, + ...) +{ + va_list args; + + test_run_success = G_TEST_RUN_FAILURE; + va_start (args, format); + g_free (test_run_msg); + test_run_msg = g_strdup_vprintf (format, args); + va_end (args); } /** diff --git a/glib/gtestutils.h b/glib/gtestutils.h index 524344b72..f5202ac44 100644 --- a/glib/gtestutils.h +++ b/glib/gtestutils.h @@ -345,6 +345,9 @@ const char * g_test_get_path (void); /* tell about failure */ GLIB_AVAILABLE_IN_2_30 void g_test_fail (void); +GLIB_AVAILABLE_IN_2_70 +void g_test_fail_printf (const char *format, + ...) G_GNUC_PRINTF (1, 2); GLIB_AVAILABLE_IN_2_38 void g_test_incomplete (const gchar *msg); GLIB_AVAILABLE_IN_2_70 diff --git a/glib/tests/testing-helper.c b/glib/tests/testing-helper.c index 9c30b01b8..7b61e8337 100644 --- a/glib/tests/testing-helper.c +++ b/glib/tests/testing-helper.c @@ -49,6 +49,12 @@ test_fail (void) g_test_fail (); } +static void +test_fail_printf (void) +{ + g_test_fail_printf ("this test intentionally left failing"); +} + static void test_incomplete (void) { @@ -123,6 +129,10 @@ main (int argc, { g_test_add_func ("/fail", test_fail); } + else if (g_strcmp0 (argv1, "fail-printf") == 0) + { + g_test_add_func ("/fail-printf", test_fail_printf); + } else if (g_strcmp0 (argv1, "all-non-failures") == 0) { g_test_add_func ("/pass", test_pass); diff --git a/glib/tests/testing.c b/glib/tests/testing.c index a646f7c71..03cfe03e1 100644 --- a/glib/tests/testing.c +++ b/glib/tests/testing.c @@ -1177,6 +1177,26 @@ test_tap (void) 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, 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_error (error, G_SPAWN_EXIT_ERROR, 1); + g_assert_nonnull (strstr (output, "\nnot 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);