gtestutils: Allow whole test suites to be skipped

Before executing a test squite, check that its name isn't present in
the list of skipped paths and if so, skip the whole suite. Per other
cases, report it skipped only if in verbose mode.

This enables skipping a whole test suite using `-s /suite-name`.

Fixes #1908
diff --git a/glib/gtestutils.c b/glib/gtestutils.c
index 43fba1a..72beb9c 100644
--- a/glib/gtestutils.c
+++ b/glib/gtestutils.c
@@ -2709,35 +2709,43 @@
 
   g_return_val_if_fail (suite != NULL, -1);
 
-  g_test_log (G_TEST_LOG_START_SUITE, suite->name, NULL, 0, NULL);
-
-  for (iter = suite->cases; iter; iter = iter->next)
+  if (!g_slist_find_custom (test_paths_skipped, old_name, (GCompareFunc)g_strcmp0))
     {
-      GTestCase *tc = iter->data;
+      g_test_log (G_TEST_LOG_START_SUITE, suite->name, NULL, 0, NULL);
 
-      test_run_name = g_build_path ("/", old_name, tc->name, NULL);
-      if (test_should_run (test_run_name, path))
+      for (iter = suite->cases; iter; iter = iter->next)
         {
-          if (!test_case_run (tc))
-            n_bad++;
+          GTestCase *tc = iter->data;
+
+          test_run_name = g_build_path ("/", old_name, tc->name, NULL);
+          if (test_should_run (test_run_name, path))
+            {
+              if (!test_case_run (tc))
+                n_bad++;
+            }
+          g_free (test_run_name);
         }
-      g_free (test_run_name);
+
+      for (iter = suite->suites; iter; iter = iter->next)
+        {
+          GTestSuite *ts = iter->data;
+
+          test_run_name = g_build_path ("/", old_name, ts->name, NULL);
+          if (!path || path_has_prefix (path, test_run_name))
+            n_bad += g_test_run_suite_internal (ts, path);
+          g_free (test_run_name);
+        }
+
+      g_test_log (G_TEST_LOG_STOP_SUITE, suite->name, NULL, 0, NULL);
     }
-
-  for (iter = suite->suites; iter; iter = iter->next)
+  else
     {
-      GTestSuite *ts = iter->data;
-
-      test_run_name = g_build_path ("/", old_name, ts->name, NULL);
-      if (!path || path_has_prefix (path, test_run_name))
-        n_bad += g_test_run_suite_internal (ts, path);
-      g_free (test_run_name);
+    if (g_test_verbose ())
+      g_print ("GTest: skipping: %s\n", old_name);
     }
 
   test_run_name = old_name;
 
-  g_test_log (G_TEST_LOG_STOP_SUITE, suite->name, NULL, 0, NULL);
-
   return n_bad;
 }
 
@@ -2745,26 +2753,34 @@
 g_test_suite_count (GTestSuite *suite)
 {
   int n = 0;
+  gchar *old_name = test_run_name;
   GSList *iter;
 
   g_return_val_if_fail (suite != NULL, -1);
 
-  for (iter = suite->cases; iter; iter = iter->next)
+  if (!g_slist_find_custom (test_paths_skipped, old_name, (GCompareFunc)g_strcmp0))
     {
-      GTestCase *tc = iter->data;
 
-      if (strcmp (tc->name, "subprocess") != 0)
-        n++;
+      for (iter = suite->cases; iter; iter = iter->next)
+        {
+          GTestCase *tc = iter->data;
+
+          if (strcmp (tc->name, "subprocess") != 0)
+            n++;
+        }
+
+      for (iter = suite->suites; iter; iter = iter->next)
+        {
+          GTestSuite *ts = iter->data;
+
+          test_run_name = g_build_path ("/", old_name, ts->name, NULL);
+          if (strcmp (ts->name, "subprocess") != 0)
+            n += g_test_suite_count (ts);
+          g_free (test_run_name);
+        }
     }
 
-  for (iter = suite->suites; iter; iter = iter->next)
-    {
-      GTestSuite *ts = iter->data;
-
-      if (strcmp (ts->name, "subprocess") != 0)
-        n += g_test_suite_count (ts);
-    }
-
+  test_run_name = old_name;
   return n;
 }
 
@@ -2793,9 +2809,8 @@
   g_return_val_if_fail (g_test_run_once == TRUE, -1);
 
   g_test_run_once = FALSE;
-  test_count = g_test_suite_count (suite);
-
   test_run_name = g_strdup_printf ("/%s", suite->name);
+  test_count = g_test_suite_count (suite);
 
   if (test_paths)
     {
diff --git a/glib/tests/testing-helper.c b/glib/tests/testing-helper.c
index 07820f6..94aaa08 100644
--- a/glib/tests/testing-helper.c
+++ b/glib/tests/testing-helper.c
@@ -120,6 +120,7 @@
       g_test_add_func ("/b/a", test_pass);
       g_test_add_func ("/b/b", test_pass);
       g_test_add_func ("/c/a", test_pass);
+      g_test_add_func ("/c/b", test_pass);
       g_test_add_func ("/d/a", test_pass);
     }
   else if (g_strcmp0 (argv1, "summary") == 0)
diff --git a/glib/tests/testing.c b/glib/tests/testing.c
index d0ce2c1..22e086b 100644
--- a/glib/tests/testing.c
+++ b/glib/tests/testing.c
@@ -1092,12 +1092,13 @@
                 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..6\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 5 /c/b\n"));
+  g_assert_nonnull (strstr (output, "\nok 6 /d/a\n"));
 
   g_spawn_check_exit_status (status, &error);
   g_assert_no_error (error);
@@ -1119,12 +1120,13 @@
                 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..6\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 5 /c/b\n"));
+  g_assert_nonnull (strstr (output, "\nok 6 /d/a\n"));
 
   g_spawn_check_exit_status (status, &error);
   g_assert_no_error (error);
@@ -1146,12 +1148,13 @@
                 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..6\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 5 /c/b # SKIP\n"));
+  g_assert_nonnull (strstr (output, "\nok 6 /d/a # SKIP\n"));
 
   g_spawn_check_exit_status (status, &error);
   g_assert_no_error (error);
@@ -1207,14 +1210,11 @@
                 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..4\n"));
   g_assert_nonnull (strstr (output, "\nok 1 /a # 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 2 /c/a # SKIP by request"));
+  g_assert_nonnull (strstr (output, "\nok 3 /c/b\n"));
+  g_assert_nonnull (strstr (output, "\nok 4 /d/a\n"));
 
   g_spawn_check_exit_status (status, &error);
   g_assert_no_error (error);