diff --git a/glib/gtestutils.c b/glib/gtestutils.c index d48368830..be6b68e56 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -868,7 +868,11 @@ static guint test_startup_skip_count = 0; static GTimer *test_user_timer = NULL; static double test_user_stamp = 0; static GSList *test_paths = NULL; +static gboolean test_prefix = FALSE; +static gboolean test_prefix_extended = FALSE; static GSList *test_paths_skipped = NULL; +static gboolean test_prefix_skipped = FALSE; +static gboolean test_prefix_extended_skipped = FALSE; static GTestSuite *test_suite_root = NULL; static int test_trap_last_status = 0; /* unmodified platform-specific status */ static GPid test_trap_last_pid = 0; @@ -1199,6 +1203,31 @@ parse_args (gint *argc_p, test_paths = g_slist_prepend (test_paths, argv[i]); } argv[i] = NULL; + if (test_prefix_extended) { + printf ("do not mix [-r | --run-prefix] with '-p'\n"); + exit (1); + } + test_prefix = TRUE; + } + else if (strcmp ("-r", argv[i]) == 0 || + strncmp ("-r=", argv[i], 3) == 0 || + strcmp ("--run-prefix", argv[i]) == 0 || + strncmp ("--run-prefix=", argv[i], 13) == 0) + { + gchar *equal = argv[i] + 2; + if (*equal == '=') + test_paths = g_slist_prepend (test_paths, equal + 1); + else if (i + 1 < argc) + { + argv[i++] = NULL; + test_paths = g_slist_prepend (test_paths, argv[i]); + } + argv[i] = NULL; + if (test_prefix) { + printf ("do not mix [-r | --run-prefix] with '-p'\n"); + exit (1); + } + test_prefix_extended = TRUE; } else if (strcmp ("-s", argv[i]) == 0 || strncmp ("-s=", argv[i], 3) == 0) { @@ -1211,6 +1240,31 @@ parse_args (gint *argc_p, test_paths_skipped = g_slist_prepend (test_paths_skipped, argv[i]); } argv[i] = NULL; + if (test_prefix_extended_skipped) { + printf ("do not mix [-x | --skip-prefix] with '-s'\n"); + exit (1); + } + test_prefix_skipped = TRUE; + } + else if (strcmp ("-x", argv[i]) == 0 || + strncmp ("-x=", argv[i], 3) == 0 || + strcmp ("--skip-prefix", argv[i]) == 0 || + strncmp ("--skip-prefix=", argv[i], 14) == 0) + { + gchar *equal = argv[i] + 2; + if (*equal == '=') + test_paths_skipped = g_slist_prepend (test_paths_skipped, equal + 1); + else if (i + 1 < argc) + { + argv[i++] = NULL; + test_paths_skipped = g_slist_prepend (test_paths_skipped, argv[i]); + } + argv[i] = NULL; + if (test_prefix_skipped) { + printf ("do not mix [-x | --skip-prefix] with '-s'\n"); + exit (1); + } + test_prefix_extended_skipped = TRUE; } else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0) { @@ -1286,6 +1340,13 @@ parse_args (gint *argc_p, " -m {undefined|no-undefined} Execute tests according to mode\n" " -p TESTPATH Only start test cases matching TESTPATH\n" " -s TESTPATH Skip all tests matching TESTPATH\n" + " [-r | --run-prefix] PREFIX Only start test cases (or suites) matching PREFIX (incompatible with -p).\n" + " Unlike the -p option (which only goes one level deep), this option would \n" + " run all tests path that have PREFIX at the beginning of their name.\n" + " Note that the prefix used should be a valid test path (and not a simple prefix).\n" + " [-x | --skip-prefix] PREFIX Skip all tests matching PREFIX (incompatible with -s)\n" + " Unlike the -s option (which only skips the exact TESTPATH), this option will \n" + " skip all the tests that begins with PREFIX).\n" " --seed=SEEDSTRING Start tests with random seed SEEDSTRING\n" " --debug-log debug test logging output\n" " -q, --quiet Run tests quietly\n" @@ -2630,6 +2691,22 @@ g_test_queue_destroy (GDestroyNotify destroy_func, test_destroy_queue = dentry; } +static gint +test_has_prefix (gconstpointer a, + gconstpointer b) +{ + const gchar *test_path_skipped_local = (const gchar *)a; + const gchar* test_run_name_local = (const gchar*)b; + if (test_prefix_extended_skipped) + { + /* If both are null, we consider that it doesn't match */ + if (!test_path_skipped_local || !test_run_name_local) + return FALSE; + return strncmp (test_run_name_local, test_path_skipped_local, strlen (test_path_skipped_local)); + } + return g_strcmp0 (test_run_name_local, test_path_skipped_local); +} + static gboolean test_case_run (GTestCase *tc) { @@ -2657,7 +2734,7 @@ test_case_run (GTestCase *tc) test_run_success = G_TEST_RUN_SUCCESS; g_clear_pointer (&test_run_msg, g_free); g_test_log_set_fatal_handler (NULL, NULL); - if (test_paths_skipped && g_slist_find_custom (test_paths_skipped, test_run_name, (GCompareFunc)g_strcmp0)) + if (test_paths_skipped && g_slist_find_custom (test_paths_skipped, test_run_name, (GCompareFunc)test_has_prefix)) g_test_skip ("by request (-s option)"); else { @@ -2775,8 +2852,15 @@ g_test_run_suite_internal (GTestSuite *suite, GTestSuite *ts = iter->data; test_run_name = g_build_path ("/", old_name, ts->name, NULL); - if (!path || path_has_prefix (path, test_run_name)) + if (test_prefix_extended) { + if (!path || path_has_prefix (test_run_name, path)) + n_bad += g_test_run_suite_internal (ts, test_run_name); + else if (!path || path_has_prefix (path, test_run_name)) + n_bad += g_test_run_suite_internal (ts, path); + } else if (!path || path_has_prefix (path, test_run_name)) { n_bad += g_test_run_suite_internal (ts, path); + } + g_free (test_run_name); } diff --git a/glib/tests/testing-helper.c b/glib/tests/testing-helper.c index 07820f6e7..cc6afe589 100644 --- a/glib/tests/testing-helper.c +++ b/glib/tests/testing-helper.c @@ -115,10 +115,15 @@ main (int argc, else if (g_strcmp0 (argv1, "skip-options") == 0) { /* The caller is expected to skip some of these with - * -p, -s and/or --GTestSkipCount */ + * -p/-r, -s/-x and/or --GTestSkipCount */ g_test_add_func ("/a", test_pass); + g_test_add_func ("/b", test_pass); g_test_add_func ("/b/a", test_pass); g_test_add_func ("/b/b", test_pass); + g_test_add_func ("/b/b/a", test_pass); + g_test_add_func ("/prefix/a", test_pass); + g_test_add_func ("/prefix/b/b", test_pass); + g_test_add_func ("/prefix-long/a", test_pass); g_test_add_func ("/c/a", test_pass); g_test_add_func ("/d/a", test_pass); } diff --git a/glib/tests/testing.c b/glib/tests/testing.c index 1e6a33742..29551b9d2 100644 --- a/glib/tests/testing.c +++ b/glib/tests/testing.c @@ -1173,12 +1173,17 @@ test_tap (void) NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); - g_assert_nonnull (strstr (output, "1..5\n")); + 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/a # SKIP\n")); - g_assert_nonnull (strstr (output, "\nok 3 /b/b\n")); - g_assert_nonnull (strstr (output, "\nok 4 /c/a\n")); - g_assert_nonnull (strstr (output, "\nok 5 /d/a\n")); + g_assert_nonnull (strstr (output, "\nok 2 /b # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 3 /b/a\n")); + g_assert_nonnull (strstr (output, "\nok 4 /b/b\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b/a\n")); + g_assert_nonnull (strstr (output, "\nok 6 /prefix/a\n")); + g_assert_nonnull (strstr (output, "\nok 7 /prefix/b/b\n")); + g_assert_nonnull (strstr (output, "\nok 8 /prefix-long/a\n")); + g_assert_nonnull (strstr (output, "\nok 9 /c/a\n")); + g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); g_spawn_check_exit_status (status, &error); g_assert_no_error (error); @@ -1200,12 +1205,17 @@ test_tap (void) NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); - g_assert_nonnull (strstr (output, "1..5\n")); + 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/a\n")); - g_assert_nonnull (strstr (output, "\nok 3 /b/b\n")); - g_assert_nonnull (strstr (output, "\nok 4 /c/a\n")); - g_assert_nonnull (strstr (output, "\nok 5 /d/a\n")); + g_assert_nonnull (strstr (output, "\nok 2 /b\n")); + g_assert_nonnull (strstr (output, "\nok 3 /b/a\n")); + g_assert_nonnull (strstr (output, "\nok 4 /b/b\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b/a\n")); + g_assert_nonnull (strstr (output, "\nok 6 /prefix/a\n")); + g_assert_nonnull (strstr (output, "\nok 7 /prefix/b/b\n")); + g_assert_nonnull (strstr (output, "\nok 8 /prefix-long/a\n")); + g_assert_nonnull (strstr (output, "\nok 9 /c/a\n")); + g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); g_spawn_check_exit_status (status, &error); g_assert_no_error (error); @@ -1219,7 +1229,7 @@ test_tap (void) g_ptr_array_add (argv, "skip-options"); g_ptr_array_add (argv, "--tap"); g_ptr_array_add (argv, "--GTestSkipCount"); - g_ptr_array_add (argv, "6"); + g_ptr_array_add (argv, "11"); g_ptr_array_add (argv, NULL); g_spawn_sync (NULL, (char **) argv->pdata, NULL, @@ -1227,12 +1237,17 @@ test_tap (void) NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); - g_assert_nonnull (strstr (output, "1..5\n")); + 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/a # SKIP\n")); - g_assert_nonnull (strstr (output, "\nok 3 /b/b # SKIP\n")); - g_assert_nonnull (strstr (output, "\nok 4 /c/a # SKIP\n")); - g_assert_nonnull (strstr (output, "\nok 5 /d/a # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 2 /b # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 3 /b/a # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 4 /b/b # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b/a # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 6 /prefix/a # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 7 /prefix/b/b # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 8 /prefix-long/a # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 9 /c/a # SKIP\n")); + g_assert_nonnull (strstr (output, "\nok 10 /d/a # SKIP\n")); g_spawn_check_exit_status (status, &error); g_assert_no_error (error); @@ -1260,9 +1275,10 @@ test_tap (void) g_assert_no_error (error); 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/a\n")); - g_assert_nonnull (strstr (output, "\nok 4 /b/b\n")); - g_assert_nonnull (strstr (output, "\n1..4\n")); + g_assert_nonnull (strstr (output, "\nok 3 /b\n")); + g_assert_nonnull (strstr (output, "\nok 4 /b/a\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b\n")); + g_assert_nonnull (strstr (output, "\n1..5\n")); g_spawn_check_exit_status (status, &error); g_assert_no_error (error); @@ -1270,6 +1286,90 @@ test_tap (void) 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, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + 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")); + g_assert_nonnull (strstr (output, "\nok 4 /b/a\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b\n")); + g_assert_nonnull (strstr (output, "\nok 6 /b/b/a\n")); + g_assert_nonnull (strstr (output, "\n1..6\n")); + + g_spawn_check_exit_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, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + 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")); + + g_spawn_check_exit_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, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_spawn_check_exit_status (status, &error); + g_assert_nonnull (error); + 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); @@ -1280,6 +1380,8 @@ test_tap (void) 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); @@ -1288,20 +1390,88 @@ test_tap (void) NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); - g_assert_nonnull (strstr (output, "1..5\n")); + 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")); /* "-s /b" would skip a test named exactly /b, but not a test named * /b/anything */ - g_assert_nonnull (strstr (output, "\nok 2 /b/a\n")); - g_assert_nonnull (strstr (output, "\nok 3 /b/b\n")); - g_assert_nonnull (strstr (output, "\nok 4 /c/a # SKIP by request")); - g_assert_nonnull (strstr (output, "\nok 5 /d/a\n")); + g_assert_nonnull (strstr (output, "\nok 3 /b/a\n")); + g_assert_nonnull (strstr (output, "\nok 4 /b/b\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b/a\n")); + g_assert_nonnull (strstr (output, "\nok 6 /prefix/a\n")); + g_assert_nonnull (strstr (output, "\nok 7 /prefix/b/b\n")); + g_assert_nonnull (strstr (output, "\nok 8 /prefix-long/a\n")); + g_assert_nonnull (strstr (output, "\nok 9 /c/a # SKIP by request")); + g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); g_spawn_check_exit_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, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + 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")); + g_assert_nonnull (strstr (output, "\nok 3 /b/a\n")); + g_assert_nonnull (strstr (output, "\nok 4 /b/b\n")); + g_assert_nonnull (strstr (output, "\nok 5 /b/b/a\n")); + /* "--skip-prefix /pre" will skip all test path which begins with /pre */ + g_assert_nonnull (strstr (output, "\nok 6 /prefix/a # SKIP by request")); + g_assert_nonnull (strstr (output, "\nok 7 /prefix/b/b # SKIP by request")); + g_assert_nonnull (strstr (output, "\nok 8 /prefix-long/a # SKIP by request")); + g_assert_nonnull (strstr (output, "\nok 9 /c/a # SKIP by request")); + g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); + + g_spawn_check_exit_status (status, &error); + g_assert_no_error (error); + + g_free (output); + g_ptr_array_unref (argv); + + g_test_message ("--skip-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, "-s"); + 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, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &output, NULL, &status, + &error); + g_assert_no_error (error); + g_spawn_check_exit_status (status, &error); + g_assert_nonnull (error); + 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); } static void