[glib] tests: port from g_test_trap_subprocess() to g_test_trap_fork()



commit e3d1869ee3b6e269b80723173dc4f85c7cc3eaea
Author: Dan Winship <danw gnome org>
Date:   Sat Nov 24 15:58:36 2012 -0500

    tests: port from g_test_trap_subprocess() to g_test_trap_fork()
    
    https://bugzilla.gnome.org/show_bug.cgi?id=679683

 gio/tests/gdbus-exit-on-close.c |  137 +++++++------
 gio/tests/gdbus-non-socket.c    |    1 +
 gio/tests/gdbus-proxy.c         |   20 +-
 gio/tests/gschema-compile.c     |   50 +++--
 gio/tests/gsettings.c           |  422 ++++++++++++++++++++++++++-------------
 glib/tests/array-test.c         |   27 ++-
 glib/tests/dataset.c            |   22 ++-
 glib/tests/gvariant.c           |   79 +++++---
 glib/tests/list.c               |   35 ++--
 glib/tests/logging.c            |  215 ++++++++++++--------
 glib/tests/mem-overflow.c       |  143 +++++++++-----
 glib/tests/option-context.c     |  382 ++++++++++++++++++++----------------
 glib/tests/scannerapi.c         |   21 ++-
 glib/tests/slice.c              |   14 +-
 glib/tests/test-printf.c        |  277 ++++++++++----------------
 glib/tests/testing.c            |  204 ++++++++++++-------
 glib/tests/utils.c              |   22 ++-
 gobject/tests/param.c           |   54 +++++-
 tests/Makefile.am               |    1 +
 tests/testglib.c                |   50 +++---
 20 files changed, 1263 insertions(+), 913 deletions(-)
---
diff --git a/gio/tests/gdbus-exit-on-close.c b/gio/tests/gdbus-exit-on-close.c
index 08338c4..befad74 100644
--- a/gio/tests/gdbus-exit-on-close.c
+++ b/gio/tests/gdbus-exit-on-close.c
@@ -109,78 +109,84 @@ close_async_cb (GObject *source G_GNUC_UNUSED,
 }
 
 static void
-test_exit_on_close (gconstpointer test_data)
+test_exit_on_close_subprocess (gconstpointer test_data)
 {
   const TestData *td = test_data;
-  GTestTrapFlags silence;
+  GDBusConnection *c;
 
-  /* all the tests rely on a shared main loop */
   loop = g_main_loop_new (NULL, FALSE);
 
+  session_bus_up ();
+  c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+
+  g_assert (c != NULL);
+
+  /* the default is meant to be TRUE */
+  if (td->exit_on_close != IMPLICITLY_TRUE)
+    g_dbus_connection_set_exit_on_close (c, td->exit_on_close);
+
+  g_assert_cmpint (g_dbus_connection_get_exit_on_close (c), ==,
+                   (td->exit_on_close != EXPLICITLY_FALSE));
+  g_assert (!g_dbus_connection_is_closed (c));
+
+  g_timeout_add (50, quit_later_cb, NULL);
+  g_main_loop_run (loop);
+
+  g_signal_connect (c, "closed", G_CALLBACK (closed_cb), (gpointer) td);
+
+  if (td->who_closes == LOCAL)
+    {
+      GVariant *v;
+      GError *error = NULL;
+
+      v = g_dbus_connection_call_sync (c, "org.freedesktop.DBus",
+                                       "/org/freedesktop/DBus",
+                                       "org.freedesktop.DBus",
+                                       "ListNames",
+                                       NULL,
+                                       G_VARIANT_TYPE ("(as)"),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       NULL,
+                                       &error);
+      g_assert_no_error (error);
+      g_assert (v != NULL);
+      g_variant_unref (v);
+
+      g_dbus_connection_close (c, NULL, close_async_cb, NULL);
+    }
+  else
+    {
+      session_bus_stop ();
+    }
+
+  g_main_loop_run (loop);
+  /* this is only reached when we turn off exit-on-close */
+  g_main_loop_unref (loop);
+  g_object_unref (c);
+
+  session_bus_down ();
+
+  exit (0);
+}
+
+static void
+test_exit_on_close (gconstpointer test_data)
+{
+  const TestData *td = test_data;
+  GTestSubprocessFlags flags;
+  char *child_name;
+
   g_test_dbus_unset ();
 
   if (g_test_verbose ())
-    silence = 0;
+    flags = G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR;
   else
-    silence = G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR;
+    flags = 0;
 
-  if (g_test_trap_fork (0, silence))
-    {
-      GDBusConnection *c;
-
-      session_bus_up ();
-      c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-
-      g_assert (c != NULL);
-
-      /* the default is meant to be TRUE */
-      if (td->exit_on_close != IMPLICITLY_TRUE)
-        g_dbus_connection_set_exit_on_close (c, td->exit_on_close);
-
-      g_assert_cmpint (g_dbus_connection_get_exit_on_close (c), ==,
-                       (td->exit_on_close != EXPLICITLY_FALSE));
-      g_assert (!g_dbus_connection_is_closed (c));
-
-      g_timeout_add (50, quit_later_cb, NULL);
-      g_main_loop_run (loop);
-
-      g_signal_connect (c, "closed", G_CALLBACK (closed_cb), (gpointer) td);
-
-      if (td->who_closes == LOCAL)
-        {
-          GVariant *v;
-          GError *error = NULL;
-
-          v = g_dbus_connection_call_sync (c, "org.freedesktop.DBus",
-                                           "/org/freedesktop/DBus",
-                                           "org.freedesktop.DBus",
-                                           "ListNames",
-                                           NULL,
-                                           G_VARIANT_TYPE ("(as)"),
-                                           G_DBUS_CALL_FLAGS_NONE,
-                                           -1,
-                                           NULL,
-                                           &error);
-          g_assert_no_error (error);
-          g_assert (v != NULL);
-          g_variant_unref (v);
-
-          g_dbus_connection_close (c, NULL, close_async_cb, NULL);
-        }
-      else
-        {
-          session_bus_stop ();
-        }
-
-      g_main_loop_run (loop);
-      /* this is only reached when we turn off exit-on-close */
-      g_main_loop_unref (loop);
-      g_object_unref (c);
-
-      session_bus_down ();
-
-      exit (0);
-    }
+  child_name = g_strdup_printf ("/gdbus/exit-on-close/%s/subprocess", td->name);
+  g_test_trap_subprocess (child_name, 0, flags);
+  g_free (child_name);
 
   if (td->exit_on_close == EXPLICITLY_FALSE ||
       td->who_closes == LOCAL)
@@ -207,10 +213,15 @@ main (int   argc,
 
   for (i = 0; cases[i].name != NULL; i++)
     {
-      gchar *name = g_strdup_printf ("/gdbus/exit-on-close/%s", cases[i].name);
+      gchar *name;
 
+      name = g_strdup_printf ("/gdbus/exit-on-close/%s", cases[i].name);
       g_test_add_data_func (name, &cases[i], test_exit_on_close);
       g_free (name);
+
+      name = g_strdup_printf ("/gdbus/exit-on-close/%s/subprocess", cases[i].name);
+      g_test_add_data_func (name, &cases[i], test_exit_on_close_subprocess);
+      g_free (name);
     }
 
   return g_test_run();
diff --git a/gio/tests/gdbus-non-socket.c b/gio/tests/gdbus-non-socket.c
index 77c814d..8866b1d 100644
--- a/gio/tests/gdbus-non-socket.c
+++ b/gio/tests/gdbus-non-socket.c
@@ -219,6 +219,7 @@ test_non_socket (void)
       break;
     }
 
+  /* This is #ifdef G_OS_UNIX anyway, so just use g_test_trap_fork() */
   if (!g_test_trap_fork (0, 0))
     {
       /* parent */
diff --git a/gio/tests/gdbus-proxy.c b/gio/tests/gdbus-proxy.c
index e9d94c4..a438255 100644
--- a/gio/tests/gdbus-proxy.c
+++ b/gio/tests/gdbus-proxy.c
@@ -620,12 +620,10 @@ test_expected_interface (GDBusProxy *proxy)
   if (g_test_undefined ())
     {
       /* Also check that we complain if setting a cached property of the wrong type */
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
-        {
-          g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
-        }
-      g_test_trap_assert_stderr ("*Trying to set property y of type s but according to the expected 
interface the type is y*");
-      g_test_trap_assert_failed();
+      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                             "*Trying to set property y of type s but according to the expected interface 
the type is y*");
+      g_dbus_proxy_set_cached_property (proxy, "y", g_variant_new_string ("error_me_out!"));
+      g_test_assert_expected_messages ();
     }
 
   /* this should work, however (since the type is correct) */
@@ -636,12 +634,10 @@ test_expected_interface (GDBusProxy *proxy)
       /* Try to get the value of a property where the type we expect is different from
        * what we have in our cache (e.g. what the service returned)
        */
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
-        {
-          value = g_dbus_proxy_get_cached_property (proxy, "i");
-        }
-      g_test_trap_assert_stderr ("*Trying to get property i with type i but according to the expected 
interface the type is u*");
-      g_test_trap_assert_failed();
+      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                             "*Trying to get property i with type i but according to the expected interface 
the type is u*");
+      value = g_dbus_proxy_get_cached_property (proxy, "i");
+      g_test_assert_expected_messages ();
     }
 
   /* Even if a property does not exist in expected_interface, looking it
diff --git a/gio/tests/gschema-compile.c b/gio/tests/gschema-compile.c
index a5ce10a..e29137d 100644
--- a/gio/tests/gschema-compile.c
+++ b/gio/tests/gschema-compile.c
@@ -12,27 +12,35 @@ typedef struct {
 } SchemaTest;
 
 static void
+test_schema_do_compile (gpointer data)
+{
+  SchemaTest *test = (SchemaTest *) data;
+  gchar *filename = g_strconcat (test->name, ".gschema.xml", NULL);
+  gchar *path = g_build_filename (SRCDIR, "schema-tests", filename, NULL);
+  gchar *argv[] = {
+    "../glib-compile-schemas",
+    "--strict",
+    "--dry-run",
+    "--schema-file", path,
+    (gchar *)test->opt,
+    NULL
+  };
+  gchar *envp[] = { NULL };
+
+  execve (argv[0], argv, envp);
+  g_assert_not_reached ();
+}
+
+static void
 test_schema (gpointer data)
 {
   SchemaTest *test = (SchemaTest *) data;
+  gchar *child_name;
+
+  child_name = g_strdup_printf ("/gschema/%s%s/subprocess/do_compile", test->name, test->opt ? "/opt" : "");
+  g_test_trap_subprocess (child_name, 0, 0);
+  g_free (child_name);
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      gchar *filename = g_strconcat (test->name, ".gschema.xml", NULL);
-      gchar *path = g_build_filename (SRCDIR, "schema-tests", filename, NULL);
-      gchar *argv[] = {
-        "../glib-compile-schemas",
-        "--strict",
-        "--dry-run",
-        "--schema-file", path,
-        (gchar *)test->opt,
-        NULL
-      };
-      gchar *envp[] = { NULL };
-      execve (argv[0], argv, envp);
-      g_free (filename);
-      g_free (path);
-    }
   if (test->err)
     {
       g_test_trap_assert_failed ();
@@ -135,9 +143,15 @@ main (int argc, char *argv[])
 
   for (i = 0; i < G_N_ELEMENTS (tests); ++i)
     {
-      gchar *name = g_strdup_printf ("/gschema/%s%s", tests[i].name, tests[i].opt ? "/opt" : "");
+      gchar *name;
+
+      name = g_strdup_printf ("/gschema/%s%s", tests[i].name, tests[i].opt ? "/opt" : "");
       g_test_add_data_func (name, &tests[i], (gpointer) test_schema);
       g_free (name);
+
+      name = g_strdup_printf ("/gschema/%s%s/subprocess/do_compile", tests[i].name, tests[i].opt ? "/opt" : 
"");
+      g_test_add_data_func (name, &tests[i], (gpointer) test_schema_do_compile);
+      g_free (name);
     }
 
   return g_test_run ();
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index 515fad2..3135234 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -83,23 +83,26 @@ test_basic (void)
  * that is not in the schema
  */
 static void
-test_unknown_key (void)
+test_unknown_key_subprocess (void)
 {
-  if (!g_test_undefined ())
-    return;
+  GSettings *settings;
+  GVariant *value;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GSettings *settings;
-      GVariant *value;
+  settings = g_settings_new ("org.gtk.test");
+  value = g_settings_get_value (settings, "no_such_key");
 
-      settings = g_settings_new ("org.gtk.test");
-      value = g_settings_get_value (settings, "no_such_key");
+  g_assert (value == NULL);
 
-      g_assert (value == NULL);
+  g_object_unref (settings);
+}
 
-      g_object_unref (settings);
-    }
+static void
+test_unknown_key (void)
+{
+  if (!g_test_undefined ())
+    return;
+
+  g_test_trap_subprocess ("/gsettings/unknown-key/subprocess", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*does not contain*");
 }
@@ -108,20 +111,22 @@ test_unknown_key (void)
  * has not been installed
  */
 static void
-test_no_schema (void)
+test_no_schema_subprocess (void)
 {
-  if (!g_test_undefined ())
-    return;
+  GSettings *settings;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GSettings *settings;
+  settings = g_settings_new ("no.such.schema");
 
-      settings = g_settings_new ("no.such.schema");
+  g_assert (settings == NULL);
+}
 
-      g_assert (settings == NULL);
-    }
+static void
+test_no_schema (void)
+{
+  if (!g_test_undefined ())
+    return;
 
+  g_test_trap_subprocess ("/gsettings/no-schema/subprocess", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*Settings schema 'no.such.schema' is not installed*");
 }
@@ -159,35 +164,39 @@ test_wrong_type (void)
 
 /* Check errors with explicit paths */
 static void
+test_wrong_path_subprocess (void)
+{
+  GSettings *settings G_GNUC_UNUSED;
+
+  settings = g_settings_new_with_path ("org.gtk.test", "/wrong-path/");
+}
+
+static void
 test_wrong_path (void)
 {
   if (!g_test_undefined ())
     return;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GSettings *settings G_GNUC_UNUSED;
-
-      settings = g_settings_new_with_path ("org.gtk.test", "/wrong-path/");
-    }
-
+  g_test_trap_subprocess ("/gsettings/wrong-path/subprocess", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*but path * specified by schema*");
 }
 
 static void
+test_no_path_subprocess (void)
+{
+  GSettings *settings G_GNUC_UNUSED;
+
+  settings = g_settings_new ("org.gtk.test.no-path");
+}
+
+static void
 test_no_path (void)
 {
   if (!g_test_undefined ())
     return;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GSettings *settings G_GNUC_UNUSED;
-
-      settings = g_settings_new ("org.gtk.test.no-path");
-    }
-
+  g_test_trap_subprocess ("/gsettings/no-path/subprocess", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*attempting to create schema * without a path**");
 }
@@ -1299,24 +1308,27 @@ test_directional_binding (void)
 /* Test that type mismatch is caught when creating a binding
  */
 static void
-test_typesafe_binding (void)
+test_typesafe_binding_subprocess (void)
 {
-  if (!g_test_undefined ())
-    return;
+  TestObject *obj;
+  GSettings *settings;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      TestObject *obj;
-      GSettings *settings;
+  settings = g_settings_new ("org.gtk.test.binding");
+  obj = test_object_new ();
 
-      settings = g_settings_new ("org.gtk.test.binding");
-      obj = test_object_new ();
+  g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
 
-      g_settings_bind (settings, "string", obj, "int", G_SETTINGS_BIND_DEFAULT);
+  g_object_unref (obj);
+  g_object_unref (settings);
+}
 
-      g_object_unref (obj);
-      g_object_unref (settings);
-    }
+static void
+test_typesafe_binding (void)
+{
+  if (!g_test_undefined ())
+    return;
+
+  g_test_trap_subprocess ("/gsettings/typesafe-binding/subprocess", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*not compatible*");
 }
@@ -1425,36 +1437,42 @@ test_no_change_binding (void)
  * works in 'GET' mode.
  */
 static void
-test_no_read_binding (void)
+test_no_read_binding_fail (void)
 {
-  if (g_test_undefined ())
-    {
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        {
-          TestObject *obj;
-          GSettings *settings;
+  TestObject *obj;
+  GSettings *settings;
 
-          settings = g_settings_new ("org.gtk.test.binding");
-          obj = test_object_new ();
+  settings = g_settings_new ("org.gtk.test.binding");
+  obj = test_object_new ();
 
-          g_settings_bind (settings, "string", obj, "no-read", 0);
-        }
-      g_test_trap_assert_failed ();
-      g_test_trap_assert_stderr ("*property*is not readable*");
-    }
+  g_settings_bind (settings, "string", obj, "no-read", 0);
+}
 
-  if (g_test_trap_fork (0, 0))
-    {
-      TestObject *obj;
-      GSettings *settings;
+static void
+test_no_read_binding_pass (void)
+{
+  TestObject *obj;
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.binding");
+  obj = test_object_new ();
 
-      settings = g_settings_new ("org.gtk.test.binding");
-      obj = test_object_new ();
+  g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
 
-      g_settings_bind (settings, "string", obj, "no-read", G_SETTINGS_BIND_GET);
+  exit (0);
+}
 
-      exit (0);
+static void
+test_no_read_binding (void)
+{
+  if (g_test_undefined ())
+    {
+      g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/fail", 0, 0);
+      g_test_trap_assert_failed ();
+      g_test_trap_assert_stderr ("*property*is not readable*");
     }
+
+  g_test_trap_subprocess ("/gsettings/no-read-binding/subprocess/pass", 0, 0);
   g_test_trap_assert_passed ();
 }
 
@@ -1462,36 +1480,42 @@ test_no_read_binding (void)
  * works in 'SET' mode.
  */
 static void
-test_no_write_binding (void)
+test_no_write_binding_fail (void)
 {
-  if (g_test_undefined ())
-    {
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        {
-          TestObject *obj;
-          GSettings *settings;
+  TestObject *obj;
+  GSettings *settings;
 
-          settings = g_settings_new ("org.gtk.test.binding");
-          obj = test_object_new ();
+  settings = g_settings_new ("org.gtk.test.binding");
+  obj = test_object_new ();
 
-          g_settings_bind (settings, "string", obj, "no-write", 0);
-        }
-      g_test_trap_assert_failed ();
-      g_test_trap_assert_stderr ("*property*is not writable*");
-    }
+  g_settings_bind (settings, "string", obj, "no-write", 0);
+}
 
-  if (g_test_trap_fork (0, 0))
-    {
-      TestObject *obj;
-      GSettings *settings;
+static void
+test_no_write_binding_pass (void)
+{
+  TestObject *obj;
+  GSettings *settings;
 
-      settings = g_settings_new ("org.gtk.test.binding");
-      obj = test_object_new ();
+  settings = g_settings_new ("org.gtk.test.binding");
+  obj = test_object_new ();
+
+  g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
 
-      g_settings_bind (settings, "string", obj, "no-write", G_SETTINGS_BIND_SET);
+  exit (0);
+}
 
-      exit (0);
+static void
+test_no_write_binding (void)
+{
+  if (g_test_undefined ())
+    {
+      g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/fail", 0, 0);
+      g_test_trap_assert_failed ();
+      g_test_trap_assert_stderr ("*property*is not writable*");
     }
+
+  g_test_trap_subprocess ("/gsettings/no-write-binding/subprocess/pass", 0, 0);
   g_test_trap_assert_passed ();
 }
 
@@ -1631,6 +1655,46 @@ test_strinfo (void)
 }
 
 static void
+test_enums_non_enum_key (void)
+{
+  GSettings *direct;
+
+  direct = g_settings_new ("org.gtk.test.enums.direct");
+  g_settings_get_enum (direct, "test");
+  g_assert_not_reached ();
+}
+
+static void
+test_enums_non_enum_value (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.enums");
+  g_settings_set_enum (settings, "test", 42);
+  g_assert_not_reached ();
+}
+
+static void
+test_enums_range (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.enums");
+  g_settings_set_string (settings, "test", "qux");
+  g_assert_not_reached ();
+}
+
+static void
+test_enums_non_flags (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.enums");
+  g_settings_get_flags (settings, "test");
+  g_assert_not_reached ();
+}
+
+static void
 test_enums (void)
 {
   GSettings *settings, *direct;
@@ -1641,23 +1705,19 @@ test_enums (void)
 
   if (g_test_undefined () && !backend_set)
     {
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_get_enum (direct, "test");
+      g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-key", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*not associated with an enum*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_set_enum (settings, "test", 42);
+      g_test_trap_subprocess ("/gsettings/enums/subprocess/non-enum-value", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*invalid enum value 42*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_set_string (settings, "test", "qux");
+      g_test_trap_subprocess ("/gsettings/enums/subprocess/range", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_get_flags (settings, "test");
+      g_test_trap_subprocess ("/gsettings/enums/subprocess/non-flags", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*not associated with a flags*");
     }
@@ -1688,6 +1748,47 @@ test_enums (void)
 }
 
 static void
+test_flags_non_flags_key (void)
+{
+  GSettings *direct;
+
+  direct = g_settings_new ("org.gtk.test.enums.direct");
+  g_settings_get_flags (direct, "test");
+  g_assert_not_reached ();
+}
+
+static void
+test_flags_non_flags_value (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.enums");
+  g_settings_set_flags (settings, "f-test", 0x42);
+  g_assert_not_reached ();
+}
+
+static void
+test_flags_range (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.enums");
+  g_settings_set_strv (settings, "f-test",
+                       (const gchar **) g_strsplit ("rock", ",", 0));
+  g_assert_not_reached ();
+}
+
+static void
+test_flags_non_enum (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.enums");
+  g_settings_get_enum (settings, "f-test");
+  g_assert_not_reached ();
+}
+
+static void
 test_flags (void)
 {
   GSettings *settings, *direct;
@@ -1699,24 +1800,19 @@ test_flags (void)
 
   if (g_test_undefined () && !backend_set)
     {
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_get_flags (direct, "test");
+      g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-key", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*not associated with a flags*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_set_flags (settings, "f-test", 0x42);
+      g_test_trap_subprocess ("/gsettings/flags/subprocess/non-flags-value", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_set_strv (settings, "f-test",
-                             (const gchar **) g_strsplit ("rock", ",", 0));
+      g_test_trap_subprocess ("/gsettings/flags/subprocess/range", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_get_enum (settings, "f-test");
+      g_test_trap_subprocess ("/gsettings/flags/subprocess/non-enum", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*not associated with an enum*");
     }
@@ -1760,6 +1856,26 @@ test_flags (void)
 }
 
 static void
+test_range_high (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.range");
+  g_settings_set_int (settings, "val", 45);
+  g_assert_not_reached ();
+}
+
+static void
+test_range_low (void)
+{
+  GSettings *settings;
+
+  settings = g_settings_new ("org.gtk.test.range");
+  g_settings_set_int (settings, "val", 1);
+  g_assert_not_reached ();
+}
+
+static void
 test_range (void)
 {
   GSettings *settings, *direct;
@@ -1770,13 +1886,11 @@ test_range (void)
 
   if (g_test_undefined () && !backend_set)
     {
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_set_int (settings, "val", 45);
+      g_test_trap_subprocess ("/gsettings/range/subprocess/high", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
 
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-        g_settings_set_int (settings, "val", 1);
+      g_test_trap_subprocess ("/gsettings/range/subprocess/low", 0, 0);
       g_test_trap_assert_failed ();
       g_test_trap_assert_stderr ("*g_settings_set_value*valid range*");
     }
@@ -2133,48 +2247,55 @@ main (int argc, char *argv[])
 
   setlocale (LC_ALL, "");
 
-  backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
-
-  g_setenv ("XDG_DATA_DIRS", ".", TRUE);
-  g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
-
-  if (!backend_set)
-    g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
-
   g_test_init (&argc, &argv, NULL);
 
-  g_remove ("org.gtk.test.enums.xml");
-  g_assert (g_spawn_command_line_sync ("../../gobject/glib-mkenums "
-                                       "--template " SRCDIR "/enums.xml.template "
-                                       SRCDIR "/testenum.h",
-                                       &enums, NULL, &result, NULL));
-  g_assert (result == 0);
-  g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
-  g_free (enums);
-
-  g_remove ("gschemas.compiled");
-  g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=. "
-                                       "--schema-file=org.gtk.test.enums.xml "
-                                       "--schema-file=" SRCDIR "/org.gtk.test.gschema.xml",
-                                       NULL, NULL, &result, NULL));
-  g_assert (result == 0);
-
-  g_remove ("schema-source/gschemas.compiled");
-  g_mkdir ("schema-source", 0777);
-  g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=schema-source "
-                                       "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
-                                       NULL, NULL, &result, NULL));
-  g_assert (result == 0);
+  if (!g_test_subprocess ())
+    {
+      backend_set = g_getenv ("GSETTINGS_BACKEND") != NULL;
+
+      g_setenv ("XDG_DATA_DIRS", ".", TRUE);
+      g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
+
+      if (!backend_set)
+        g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
+
+      g_remove ("org.gtk.test.enums.xml");
+      g_assert (g_spawn_command_line_sync ("../../gobject/glib-mkenums "
+                                           "--template " SRCDIR "/enums.xml.template "
+                                           SRCDIR "/testenum.h",
+                                           &enums, NULL, &result, NULL));
+      g_assert (result == 0);
+      g_assert (g_file_set_contents ("org.gtk.test.enums.xml", enums, -1, NULL));
+      g_free (enums);
+
+      g_remove ("gschemas.compiled");
+      g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=. "
+                                           "--schema-file=org.gtk.test.enums.xml "
+                                           "--schema-file=" SRCDIR "/org.gtk.test.gschema.xml",
+                                           NULL, NULL, &result, NULL));
+      g_assert (result == 0);
+
+      g_remove ("schema-source/gschemas.compiled");
+      g_mkdir ("schema-source", 0777);
+      g_assert (g_spawn_command_line_sync ("../glib-compile-schemas --targetdir=schema-source "
+                                           "--schema-file=" SRCDIR "/org.gtk.schemasourcecheck.gschema.xml",
+                                           NULL, NULL, &result, NULL));
+      g_assert (result == 0);
+    }
 
   g_test_add_func ("/gsettings/basic", test_basic);
 
   if (!backend_set)
     {
       g_test_add_func ("/gsettings/no-schema", test_no_schema);
+      g_test_add_func ("/gsettings/no-schema/subprocess", test_no_schema_subprocess);
       g_test_add_func ("/gsettings/unknown-key", test_unknown_key);
+      g_test_add_func ("/gsettings/unknown-key/subprocess", test_unknown_key_subprocess);
       g_test_add_func ("/gsettings/wrong-type", test_wrong_type);
       g_test_add_func ("/gsettings/wrong-path", test_wrong_path);
+      g_test_add_func ("/gsettings/wrong-path/subprocess", test_wrong_path_subprocess);
       g_test_add_func ("/gsettings/no-path", test_no_path);
+      g_test_add_func ("/gsettings/no-path/subprocess", test_no_path_subprocess);
     }
 
   g_test_add_func ("/gsettings/basic-types", test_basic_types);
@@ -2201,16 +2322,31 @@ main (int argc, char *argv[])
   if (!backend_set)
     {
       g_test_add_func ("/gsettings/typesafe-binding", test_typesafe_binding);
+      g_test_add_func ("/gsettings/typesafe-binding/subprocess", test_typesafe_binding_subprocess);
       g_test_add_func ("/gsettings/no-read-binding", test_no_read_binding);
+      g_test_add_func ("/gsettings/no-read-binding/subprocess/fail", test_no_read_binding_fail);
+      g_test_add_func ("/gsettings/no-read-binding/subprocess/pass", test_no_read_binding_pass);
       g_test_add_func ("/gsettings/no-write-binding", test_no_write_binding);
+      g_test_add_func ("/gsettings/no-write-binding/subprocess/fail", test_no_write_binding_fail);
+      g_test_add_func ("/gsettings/no-write-binding/subprocess/pass", test_no_write_binding_pass);
     }
 
   g_test_add_func ("/gsettings/keyfile", test_keyfile);
   g_test_add_func ("/gsettings/child-schema", test_child_schema);
   g_test_add_func ("/gsettings/strinfo", test_strinfo);
   g_test_add_func ("/gsettings/enums", test_enums);
+  g_test_add_func ("/gsettings/enums/subprocess/non-enum-key", test_enums_non_enum_key);
+  g_test_add_func ("/gsettings/enums/subprocess/non-enum-value", test_enums_non_enum_value);
+  g_test_add_func ("/gsettings/enums/subprocess/range", test_enums_range);
+  g_test_add_func ("/gsettings/enums/subprocess/non-flags", test_enums_non_flags);
   g_test_add_func ("/gsettings/flags", test_flags);
+  g_test_add_func ("/gsettings/flags/subprocess/non-flags-key", test_flags_non_flags_key);
+  g_test_add_func ("/gsettings/flags/subprocess/non-flags-value", test_flags_non_flags_value);
+  g_test_add_func ("/gsettings/flags/subprocess/range", test_flags_range);
+  g_test_add_func ("/gsettings/flags/subprocess/non-enum", test_flags_non_enum);
   g_test_add_func ("/gsettings/range", test_range);
+  g_test_add_func ("/gsettings/range/subprocess/high", test_range_high);
+  g_test_add_func ("/gsettings/range/subprocess/low", test_range_low);
   g_test_add_func ("/gsettings/list-items", test_list_items);
   g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
   g_test_add_func ("/gsettings/mapped", test_get_mapped);
diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c
index 255bb3f..51efaf3 100644
--- a/glib/tests/array-test.c
+++ b/glib/tests/array-test.c
@@ -216,23 +216,25 @@ static GMemVTable array_large_size_mem_vtable = {
 };
 
 static void
-array_large_size (void)
+array_large_size_subprocess (void)
 {
-  GArray* array;
-
-  g_test_bug ("568760");
+  GArray *array;
 
   array = g_array_new (FALSE, FALSE, sizeof (char));
 
-  if (g_test_trap_fork (5 /* s */ * 1000 /* ms */ * 1000 /* µs */, 0))
-    {
-      g_mem_set_vtable (&array_large_size_mem_vtable);
-      g_array_set_size (array, 1073750016);
-      g_assert_not_reached ();
-    }
-  g_test_trap_assert_passed ();
+  g_mem_set_vtable (&array_large_size_mem_vtable);
+  g_array_set_size (array, 1073750016);
+  g_assert_not_reached ();
+}
 
-  g_array_free (array, TRUE);
+static void
+array_large_size (void)
+{
+  g_test_bug ("568760");
+
+  g_test_trap_subprocess ("/array/large-size/subprocess",
+                          5 /* s */ * 1000 /* ms */ * 1000 /* µs */, 0);
+  g_test_trap_assert_passed ();
 }
 
 static int
@@ -851,6 +853,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/array/remove-range", array_remove_range);
   g_test_add_func ("/array/ref-count", array_ref_count);
   g_test_add_func ("/array/large-size", array_large_size);
+  g_test_add_func ("/array/large-size/subprocess", array_large_size_subprocess);
   g_test_add_func ("/array/sort", array_sort);
   g_test_add_func ("/array/sort-with-data", array_sort_with_data);
   g_test_add_func ("/array/clear-func", array_clear_func);
diff --git a/glib/tests/dataset.c b/glib/tests/dataset.c
index fa57d84..1715504 100644
--- a/glib/tests/dataset.c
+++ b/glib/tests/dataset.c
@@ -183,17 +183,20 @@ free_one (gpointer data)
 }
 
 static void
+test_datalist_clear_subprocess (void)
+{
+  g_datalist_init (&list);
+  g_datalist_set_data_full (&list, "one", GINT_TO_POINTER (1), free_one);
+  g_datalist_set_data_full (&list, "two", GINT_TO_POINTER (2), NULL);
+  g_datalist_clear (&list);
+  g_assert (list == NULL);
+}
+
+static void
 test_datalist_clear (void)
 {
-  if (g_test_trap_fork (500000, 0))
-    {
-      g_datalist_init (&list);
-      g_datalist_set_data_full (&list, "one", GINT_TO_POINTER (1), free_one);
-      g_datalist_set_data_full (&list, "two", GINT_TO_POINTER (2), NULL);
-      g_datalist_clear (&list);
-      g_assert (list == NULL);
-      exit (0);
-    }
+  /* Need to use a subprocess because it will deadlock if it fails */
+  g_test_trap_subprocess ("/datalist/recursive-clear/subprocess", 500000, 0);
   g_test_trap_assert_passed ();
 }
 
@@ -210,6 +213,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/dataset/foreach", test_dataset_foreach);
   g_test_add_func ("/dataset/destroy", test_dataset_destroy);
   g_test_add_func ("/datalist/recursive-clear", test_datalist_clear);
+  g_test_add_func ("/datalist/recursive-clear/subprocess", test_datalist_clear_subprocess);
 
   return g_test_run ();
 }
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 4e531c8..0558361 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -2809,24 +2809,12 @@ test_format_strings (void)
 }
 
 static void
-exit_on_abort (int signal)
+do_failed_test (const char *test,
+                const gchar *pattern)
 {
-  exit (signal);
-}
-
-static gboolean
-do_failed_test (const gchar *pattern)
-{
-  if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      signal (SIGABRT, exit_on_abort);
-      return TRUE;
-    }
-
+  g_test_trap_subprocess (test, 1000000, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr (pattern);
-
-  return FALSE;
 }
 
 static void
@@ -2875,6 +2863,14 @@ check_and_free (GVariant    *value,
 }
 
 static void
+test_varargs_empty_array (void)
+{
+  g_variant_new ("(a{s*})", NULL);
+
+  g_assert_not_reached ();
+}
+
+static void
 test_varargs (void)
 {
   {
@@ -3406,8 +3402,8 @@ test_varargs (void)
     g_variant_unref (value);
     g_free (str);
 
-    if (do_failed_test ("*which type of empty array*"))
-      g_variant_new ("(a{s*})", NULL);
+    do_failed_test ("/gvariant/varargs/subprocess/empty-array",
+                    "*which type of empty array*");
   }
 
   g_variant_type_info_assert_no_infos ();
@@ -3869,6 +3865,30 @@ test_parse_failures (void)
 }
 
 static void
+test_parse_bad_format_char (void)
+{
+  g_variant_new_parsed ("%z");
+
+  g_assert_not_reached ();
+}
+
+static void
+test_parse_bad_format_string (void)
+{
+  g_variant_new_parsed ("uint32 %i", 2);
+
+  g_assert_not_reached ();
+}
+
+static void
+test_parse_bad_args (void)
+{
+  g_variant_new_parsed ("% i", g_variant_new_uint32 (2));
+
+  g_assert_not_reached ();
+}
+
+static void
 test_parse_positional (void)
 {
   GVariant *value;
@@ -3883,23 +3903,14 @@ test_parse_positional (void)
 
   if (g_test_undefined ())
     {
-      if (do_failed_test ("*GVariant format string*"))
-        {
-          g_variant_new_parsed ("%z");
-          abort ();
-        }
+      do_failed_test ("/gvariant/parse/subprocess/bad-format-char",
+                      "*GVariant format string*");
 
-      if (do_failed_test ("*can not parse as*"))
-        {
-          g_variant_new_parsed ("uint32 %i", 2);
-          abort ();
-        }
+      do_failed_test ("/gvariant/parse/subprocess/bad-format-string",
+                      "*can not parse as*");
 
-      if (do_failed_test ("*expected GVariant of type `i'*"))
-        {
-          g_variant_new_parsed ("% i", g_variant_new_uint32 (2));
-          abort ();
-        }
+      do_failed_test ("/gvariant/parse/subprocess/bad-args",
+                      "*expected GVariant of type `i'*");
     }
 }
 
@@ -4326,6 +4337,7 @@ main (int argc, char **argv)
   g_test_add_func ("/gvariant/format-strings", test_format_strings);
   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
   g_test_add_func ("/gvariant/varargs", test_varargs);
+  g_test_add_func ("/gvariant/varargs/subprocess/empty-array", test_varargs_empty_array);
   g_test_add_func ("/gvariant/valist", test_valist);
   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
   g_test_add_func ("/gvariant/hashing", test_hashing);
@@ -4333,6 +4345,9 @@ main (int argc, char **argv)
   g_test_add_func ("/gvariant/parser", test_parses);
   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
+  g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char);
+  g_test_add_func ("/gvariant/parse/subprocess/bad-format-string", test_parse_bad_format_string);
+  g_test_add_func ("/gvariant/parse/subprocess/bad-args", test_parse_bad_args);
   g_test_add_func ("/gvariant/floating", test_floating);
   g_test_add_func ("/gvariant/bytestring", test_bytestring);
   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
diff --git a/glib/tests/list.c b/glib/tests/list.c
index 10d5236..28cf8e9 100644
--- a/glib/tests/list.c
+++ b/glib/tests/list.c
@@ -490,26 +490,28 @@ test_position (void)
 }
 
 static void
-test_double_free (void)
+test_double_free_subprocess (void)
 {
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GList *list, *link;
-      GList  intruder = { NULL, (gpointer)0xDEADBEEF, (gpointer)0xDEADBEEF };
+  GList *list, *link;
+  GList  intruder = { NULL, (gpointer)0xDEADBEEF, (gpointer)0xDEADBEEF };
 
-      list = NULL;
-      list = g_list_append (list, "a");
-      link = list = g_list_append (list, "b");
-      list = g_list_append (list, "c");
+  list = NULL;
+  list = g_list_append (list, "a");
+  link = list = g_list_append (list, "b");
+  list = g_list_append (list, "c");
 
-      list = g_list_remove_link (list, link);
-      link->prev = list;
-      link->next = &intruder;
-      list = g_list_remove_link (list, link);
+  list = g_list_remove_link (list, link);
+  link->prev = list;
+  link->next = &intruder;
+  list = g_list_remove_link (list, link);
 
-      g_list_free (list);
-      exit (0);
-    }
+  g_list_free (list);
+}
+
+static void
+test_double_free (void)
+{
+  g_test_trap_subprocess ("/list/double-free/subprocess", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*corrupted double-linked list detected*");
 }
@@ -543,6 +545,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/list/prepend", test_prepend);
   g_test_add_func ("/list/position", test_position);
   g_test_add_func ("/list/double-free", test_double_free);
+  g_test_add_func ("/list/double-free/subprocess", test_double_free_subprocess);
 
   return g_test_run ();
 }
diff --git a/glib/tests/logging.c b/glib/tests/logging.c
index e2df2b5..65589f7 100644
--- a/glib/tests/logging.c
+++ b/glib/tests/logging.c
@@ -5,19 +5,15 @@
 static void
 test_warnings (void)
 {
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_warn_if_reached ();
-    }
-  g_test_trap_assert_failed();
-  g_test_trap_assert_stderr ("*WARNING*test_warnings*should not be reached*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_warn_if_fail (FALSE);
-    }
-  g_test_trap_assert_failed();
-  g_test_trap_assert_stderr ("*WARNING*test_warnings*runtime check failed*");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "*test_warnings*should not be reached*");
+  g_warn_if_reached ();
+  g_test_assert_expected_messages ();
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "*test_warnings*runtime check failed*");
+  g_warn_if_fail (FALSE);
+  g_test_assert_expected_messages ();
 }
 
 static guint log_count = 0;
@@ -44,122 +40,155 @@ test_set_handler (void)
 
   id = g_log_set_handler ("bu", G_LOG_LEVEL_INFO, log_handler, NULL);
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      g_log ("bu", G_LOG_LEVEL_DEBUG, "message");
-      g_log ("ba", G_LOG_LEVEL_DEBUG, "message");
-      g_log ("bu", G_LOG_LEVEL_INFO, "message");
-      g_log ("ba", G_LOG_LEVEL_INFO, "message");
+  g_log ("bu", G_LOG_LEVEL_DEBUG, "message");
+  g_log ("ba", G_LOG_LEVEL_DEBUG, "message");
+  g_log ("bu", G_LOG_LEVEL_INFO, "message");
+  g_log ("ba", G_LOG_LEVEL_INFO, "message");
 
-      g_assert_cmpint (log_count, ==, 1);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
+  g_assert_cmpint (log_count, ==, 1);
 
   g_log_remove_handler ("bu", id);
 }
 
 static void
+test_default_handler_error (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+  g_error ("message1");
+  exit (0);
+}
+
+static void
+test_default_handler_critical (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+  g_critical ("message2");
+  exit (0);
+}
+
+static void
+test_default_handler_warning (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+  g_warning ("message3");
+  exit (0);
+}
+
+static void
+test_default_handler_message (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+  g_message ("message4");
+  exit (0);
+}
+
+static void
+test_default_handler_info (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "message5");
+  exit (0);
+}
+
+static void
+test_default_handler_bar_info (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+
+  g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE);
+
+  g_log ("bar", G_LOG_LEVEL_INFO, "message5");
+  exit (0);
+}
+
+static void
+test_default_handler_baz_debug (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+
+  g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE);
+
+  g_log ("baz", G_LOG_LEVEL_DEBUG, "message6");
+  exit (0);
+}
+
+static void
+test_default_handler_debug (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+
+  g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+
+  g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
+  g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
+  g_log ("baz", G_LOG_LEVEL_DEBUG, "6");
+  exit (0);
+}
+
+static void
+test_default_handler_0x400 (void)
+{
+  g_log_set_default_handler (g_log_default_handler, NULL);
+  g_log (G_LOG_DOMAIN, 1<<10, "message7");
+  exit (0);
+}
+
+static void
 test_default_handler (void)
 {
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_error ("message1");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/error", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*ERROR*message1*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_critical ("message2");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/critical", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*CRITICAL*message2*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_warning ("message3");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/warning", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*WARNING*message3*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_message ("message4");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/message", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stderr ("*Message*message4*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "message5");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/info", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stdout_unmatched ("*INFO*message5*");
 
-  g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE);
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_log ("bar", G_LOG_LEVEL_INFO, "message5");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/bar-info", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stdout ("*INFO*message5*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_log ("baz", G_LOG_LEVEL_DEBUG, "message6");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/baz-debug", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stdout ("*DEBUG*message6*");
 
-  g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
-      g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
-      g_log ("baz", G_LOG_LEVEL_DEBUG, "6");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/debug", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stdout ("*DEBUG*6*6*6*");
 
-  g_unsetenv ("G_MESSAGES_DEBUG");
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      g_log_set_default_handler (g_log_default_handler, NULL);
-      g_log (G_LOG_DOMAIN, 1<<10, "message7");
-      exit (0);
-    }
+  g_test_trap_subprocess ("/logging/default-handler/subprocess/0x400", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stdout ("*LOG-0x400*message7*");
 }
 
 /* test that setting levels as fatal works */
 static void
-test_fatal_log_mask (void)
+test_fatal_log_mask_subprocess (void)
 {
-  GLogLevelFlags flags;
+  g_log_set_fatal_mask ("bu", G_LOG_LEVEL_INFO);
+  g_log ("bu", G_LOG_LEVEL_INFO, "fatal");
+  exit (0);
+}
 
-  flags = g_log_set_fatal_mask ("bu", G_LOG_LEVEL_INFO);
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    g_log ("bu", G_LOG_LEVEL_INFO, "fatal");
+static void
+test_fatal_log_mask (void)
+{
+  g_test_trap_subprocess ("/logging/fatal-log-mask/subprocess", 0, 0);
   g_test_trap_assert_failed ();
-  g_log_set_fatal_mask ("bu", flags);
+  /* G_LOG_LEVEL_INFO isn't printed by default */
+  g_test_trap_assert_stdout_unmatched ("*fatal*");
 }
 
 static gint my_print_count = 0;
@@ -264,8 +293,18 @@ main (int argc, char *argv[])
   g_test_bug_base ("http://bugzilla.gnome.org/";);
 
   g_test_add_func ("/logging/default-handler", test_default_handler);
+  g_test_add_func ("/logging/default-handler/subprocess/error", test_default_handler_error);
+  g_test_add_func ("/logging/default-handler/subprocess/critical", test_default_handler_critical);
+  g_test_add_func ("/logging/default-handler/subprocess/warning", test_default_handler_warning);
+  g_test_add_func ("/logging/default-handler/subprocess/message", test_default_handler_message);
+  g_test_add_func ("/logging/default-handler/subprocess/info", test_default_handler_info);
+  g_test_add_func ("/logging/default-handler/subprocess/bar-info", test_default_handler_bar_info);
+  g_test_add_func ("/logging/default-handler/subprocess/baz-debug", test_default_handler_baz_debug);
+  g_test_add_func ("/logging/default-handler/subprocess/debug", test_default_handler_debug);
+  g_test_add_func ("/logging/default-handler/subprocess/0x400", test_default_handler_0x400);
   g_test_add_func ("/logging/warnings", test_warnings);
   g_test_add_func ("/logging/fatal-log-mask", test_fatal_log_mask);
+  g_test_add_func ("/logging/fatal-log-mask/subprocess", test_fatal_log_mask_subprocess);
   g_test_add_func ("/logging/set-handler", test_set_handler);
   g_test_add_func ("/logging/print-handler", test_print_handler);
   g_test_add_func ("/logging/printerr-handler", test_printerr_handler);
diff --git a/glib/tests/mem-overflow.c b/glib/tests/mem-overflow.c
index c7ea218..44ae333 100644
--- a/glib/tests/mem-overflow.c
+++ b/glib/tests/mem-overflow.c
@@ -26,13 +26,48 @@
 #include "glib.h"
 #include <stdlib.h>
 
+static gsize a = G_MAXSIZE / 10 + 10;
+static gsize b = 10;
+typedef char X[10];
+
+#define MEM_OVERFLOW_TEST(name, code) \
+static void                           \
+mem_overflow_ ## name (void)          \
+{                                     \
+  gpointer p;                         \
+  code;                               \
+  g_free (p);                         \
+  exit (0);                           \
+}
+
+MEM_OVERFLOW_TEST (malloc_n_a_a, p = g_malloc_n (a, a))
+MEM_OVERFLOW_TEST (malloc_n_a_b, p = g_malloc_n (a, b))
+MEM_OVERFLOW_TEST (malloc_n_b_a, p = g_malloc_n (b, a))
+MEM_OVERFLOW_TEST (malloc_n_b_b, p = g_malloc_n (b, b))
+
+MEM_OVERFLOW_TEST (malloc0_n_a_a, p = g_malloc0_n (a, a))
+MEM_OVERFLOW_TEST (malloc0_n_a_b, p = g_malloc0_n (a, b))
+MEM_OVERFLOW_TEST (malloc0_n_b_a, p = g_malloc0_n (b, a))
+MEM_OVERFLOW_TEST (malloc0_n_b_b, p = g_malloc0_n (b, b))
+
+MEM_OVERFLOW_TEST (realloc_n_a_a, p = g_malloc (1); p = g_realloc_n (p, a, a))
+MEM_OVERFLOW_TEST (realloc_n_a_b, p = g_malloc (1); p = g_realloc_n (p, a, b))
+MEM_OVERFLOW_TEST (realloc_n_b_a, p = g_malloc (1); p = g_realloc_n (p, b, a))
+MEM_OVERFLOW_TEST (realloc_n_b_b, p = g_malloc (1); p = g_realloc_n (p, b, b))
+
+MEM_OVERFLOW_TEST (new_a, p = g_new (X, a))
+MEM_OVERFLOW_TEST (new_b, p = g_new (X, b))
+
+MEM_OVERFLOW_TEST (new0_a, p = g_new0 (X, a))
+MEM_OVERFLOW_TEST (new0_b, p = g_new0 (X, b))
+
+MEM_OVERFLOW_TEST (renew_a, p = g_malloc (1); p = g_renew (X, p, a))
+MEM_OVERFLOW_TEST (renew_b, p = g_malloc (1); p = g_renew (X, p, b))
+
 static void
 mem_overflow (void)
 {
-  gsize a = G_MAXSIZE / 10 + 10;
-  gsize b = 10;
   gpointer p, q;
-  typedef char X[10];
 
   /* "FAIL" here apparently means "fail to overflow"... */
 #define CHECK_PASS(P)  p = (P); g_assert (p == NULL);
@@ -70,60 +105,45 @@ mem_overflow (void)
   CHECK_FAIL (g_try_renew (X, q, b));
   free (p);
 
-#undef CHECK_FAIL
-#undef CHECK_PASS
-
-#define CHECK_FAIL(P)  do { \
+#define CHECK_SUBPROCESS_FAIL(name) do { \
       if (g_test_undefined ()) \
         { \
-          if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) \
-            { \
-              p = (P); \
-              exit (0); \
-            } \
-          \
+          g_test_trap_subprocess ("/mem/overflow/subprocess/" #name, 0, 0); \
           g_test_trap_assert_failed(); \
         } \
     } while (0)
 
-#define CHECK_PASS(P)  do { \
-      if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) \
+#define CHECK_SUBPROCESS_PASS(name) do { \
+      if (g_test_undefined ()) \
         { \
-          p = (P); \
-          g_free (p); \
-          exit (0); \
+          g_test_trap_subprocess ("/mem/overflow/subprocess/" #name, 0, 0); \
+          g_test_trap_assert_passed(); \
         } \
-      \
-      g_test_trap_assert_passed(); \
     } while (0)
 
-  CHECK_FAIL (g_malloc_n (a, a));
-  CHECK_FAIL (g_malloc_n (a, b));
-  CHECK_FAIL (g_malloc_n (b, a));
-  CHECK_PASS (g_malloc_n (b, b));
+  CHECK_SUBPROCESS_FAIL (malloc_n_a_a);
+  CHECK_SUBPROCESS_FAIL (malloc_n_a_b);
+  CHECK_SUBPROCESS_FAIL (malloc_n_b_a);
+  CHECK_SUBPROCESS_PASS (malloc_n_b_b);
 
-  CHECK_FAIL (g_malloc0_n (a, a));
-  CHECK_FAIL (g_malloc0_n (a, b));
-  CHECK_FAIL (g_malloc0_n (b, a));
-  CHECK_PASS (g_malloc0_n (b, b));
+  CHECK_SUBPROCESS_FAIL (malloc0_n_a_a);
+  CHECK_SUBPROCESS_FAIL (malloc0_n_a_b);
+  CHECK_SUBPROCESS_FAIL (malloc0_n_b_a);
+  CHECK_SUBPROCESS_PASS (malloc0_n_b_b);
 
-  q = g_malloc (1);
-  CHECK_FAIL (g_realloc_n (q, a, a));
-  CHECK_FAIL (g_realloc_n (q, a, b));
-  CHECK_FAIL (g_realloc_n (q, b, a));
-  CHECK_PASS (g_realloc_n (q, b, b));
-  g_free (q);
+  CHECK_SUBPROCESS_FAIL (realloc_n_a_a);
+  CHECK_SUBPROCESS_FAIL (realloc_n_a_b);
+  CHECK_SUBPROCESS_FAIL (realloc_n_b_a);
+  CHECK_SUBPROCESS_PASS (realloc_n_b_b);
 
-  CHECK_FAIL (g_new (X, a));
-  CHECK_PASS (g_new (X, b));
+  CHECK_SUBPROCESS_FAIL (new_a);
+  CHECK_SUBPROCESS_PASS (new_b);
 
-  CHECK_FAIL (g_new0 (X, a));
-  CHECK_PASS (g_new0 (X, b));
+  CHECK_SUBPROCESS_FAIL (new0_a);
+  CHECK_SUBPROCESS_PASS (new0_b);
 
-  q = g_malloc (1);
-  CHECK_FAIL (g_renew (X, q, a));
-  CHECK_PASS (g_renew (X, q, b));
-  g_free (q);
+  CHECK_SUBPROCESS_FAIL (renew_a);
+  CHECK_SUBPROCESS_PASS (renew_b);
 }
 
 typedef struct
@@ -131,20 +151,23 @@ typedef struct
 } Empty;
 
 static void
+empty_alloc_subprocess (void)
+{
+  Empty *empty;
+
+  empty = g_new0 (Empty, 1);
+  g_assert (empty == NULL);
+  exit (0);
+}
+
+static void
 empty_alloc (void)
 {
   g_test_bug ("615379");
 
   g_assert_cmpint (sizeof (Empty), ==, 0);
 
-  if (g_test_trap_fork (0, 0))
-    {
-      Empty *empty;
-
-      empty = g_new0 (Empty, 1);
-      g_assert (empty == NULL);
-      exit (0);
-    }
+  g_test_trap_subprocess ("/mem/empty-alloc/subprocess", 0, 0);
   g_test_trap_assert_passed ();
 }
 
@@ -157,7 +180,27 @@ main (int   argc,
   g_test_bug_base ("http://bugzilla.gnome.org/";);
 
   g_test_add_func ("/mem/overflow", mem_overflow);
+  g_test_add_func ("/mem/overflow/subprocess/malloc_n_a_a", mem_overflow_malloc_n_a_a);
+  g_test_add_func ("/mem/overflow/subprocess/malloc_n_a_b", mem_overflow_malloc_n_a_b);
+  g_test_add_func ("/mem/overflow/subprocess/malloc_n_b_a", mem_overflow_malloc_n_b_a);
+  g_test_add_func ("/mem/overflow/subprocess/malloc_n_b_b", mem_overflow_malloc_n_b_b);
+  g_test_add_func ("/mem/overflow/subprocess/malloc0_n_a_a", mem_overflow_malloc0_n_a_a);
+  g_test_add_func ("/mem/overflow/subprocess/malloc0_n_a_b", mem_overflow_malloc0_n_a_b);
+  g_test_add_func ("/mem/overflow/subprocess/malloc0_n_b_a", mem_overflow_malloc0_n_b_a);
+  g_test_add_func ("/mem/overflow/subprocess/malloc0_n_b_b", mem_overflow_malloc0_n_b_b);
+  g_test_add_func ("/mem/overflow/subprocess/realloc_n_a_a", mem_overflow_realloc_n_a_a);
+  g_test_add_func ("/mem/overflow/subprocess/realloc_n_a_b", mem_overflow_realloc_n_a_b);
+  g_test_add_func ("/mem/overflow/subprocess/realloc_n_b_a", mem_overflow_realloc_n_b_a);
+  g_test_add_func ("/mem/overflow/subprocess/realloc_n_b_b", mem_overflow_realloc_n_b_b);
+  g_test_add_func ("/mem/overflow/subprocess/new_a", mem_overflow_new_a);
+  g_test_add_func ("/mem/overflow/subprocess/new_b", mem_overflow_new_b);
+  g_test_add_func ("/mem/overflow/subprocess/new0_a", mem_overflow_new0_a);
+  g_test_add_func ("/mem/overflow/subprocess/new0_b", mem_overflow_new0_b);
+  g_test_add_func ("/mem/overflow/subprocess/renew_a", mem_overflow_renew_a);
+  g_test_add_func ("/mem/overflow/subprocess/renew_b", mem_overflow_renew_b);
+
   g_test_add_func ("/mem/empty-alloc", empty_alloc);
+  g_test_add_func ("/mem/empty-alloc/subprocess", empty_alloc_subprocess);
 
   return g_test_run();
 }
diff --git a/glib/tests/option-context.c b/glib/tests/option-context.c
index 3eb360c..75ec4fd 100644
--- a/glib/tests/option-context.c
+++ b/glib/tests/option-context.c
@@ -27,25 +27,92 @@
 #include <string.h>
 #include <locale.h>
 
+static GOptionEntry main_entries[] = {
+  { "main-switch", 0, 0,
+    G_OPTION_ARG_NONE, NULL,
+    "A switch that is in the main group", NULL },
+  { NULL }
+};
+
+static GOptionEntry group_entries[] = {
+  { "test-switch", 0, 0,
+    G_OPTION_ARG_NONE, NULL,
+    "A switch that is in the test group", NULL },
+  { NULL }
+};
+
+static GOptionContext *
+make_options (int test_number)
+{
+  GOptionContext *options;
+  GOptionGroup   *group = NULL;
+  gboolean have_main_entries = (0 != (test_number & 1));
+  gboolean have_test_entries = (0 != (test_number & 2));
+
+  options = g_option_context_new (NULL);
+
+  if (have_main_entries)
+    g_option_context_add_main_entries (options, main_entries, NULL);
+  if (have_test_entries)
+    {
+      group = g_option_group_new ("test", "Test Options",
+                                  "Show all test options",
+                                  NULL, NULL);
+      g_option_context_add_group (options, group);
+      g_option_group_add_entries (group, group_entries);
+    }
+
+  return options;
+}
+
 static void
-test_group_captions (void)
+print_help (GOptionContext *options, gchar **argv)
 {
-  gchar *help_variants[] = { "--help", "--help-all", "--help-test" };
+  gint    argc = 3;
+  GError *error = NULL;
 
-  GOptionEntry main_entries[] = {
-    { "main-switch", 0, 0,
-      G_OPTION_ARG_NONE, NULL,
-      "A switch that is in the main group", NULL },
-    { NULL }
-  };
+  g_setenv ("LANG", "C", TRUE);
 
-  GOptionEntry group_entries[] = {
-    { "test-switch", 0, 0,
-      G_OPTION_ARG_NONE, NULL,
-      "A switch that is in the test group", NULL },
-    { NULL }
-  };
+  g_option_context_parse (options, &argc, &argv, &error);
+  g_option_context_free (options);
+  exit(0);
+}
+
+static void
+test_group_captions_help (gconstpointer test_number)
+{
+  GOptionContext *options;
+  gchar *argv[] = { __FILE__, "--help", NULL };
+
+  options = make_options (GPOINTER_TO_INT (test_number));
+  print_help (options, argv);
+}
 
+static void
+test_group_captions_help_all (gconstpointer test_number)
+{
+  GOptionContext *options;
+  gchar *argv[] = { __FILE__, "--help-all", NULL };
+
+  options = make_options (GPOINTER_TO_INT (test_number));
+  print_help (options, argv);
+}
+
+static void
+test_group_captions_help_test (gconstpointer test_number)
+{
+  GOptionContext *options;
+  gchar *argv[] = { __FILE__, "--help-test", NULL };
+
+  options = make_options (GPOINTER_TO_INT (test_number));
+  print_help (options, argv);
+}
+
+static void
+test_group_captions (void)
+{
+  const gchar *test_name_base[] = { "help", "help-all", "help-test" };
+  gchar *test_name;
   gint i, j;
 
   g_test_bug ("504142");
@@ -55,115 +122,76 @@ test_group_captions (void)
       gboolean have_main_entries = (0 != (i & 1));
       gboolean have_test_entries = (0 != (i & 2));
 
-      GOptionContext *options;
-      GOptionGroup   *group = NULL;
-
-      options = g_option_context_new (NULL);
-
-      if (have_main_entries)
-        g_option_context_add_main_entries (options, main_entries, NULL);
-      if (have_test_entries)
-        {
-          group = g_option_group_new ("test", "Test Options",
-                                      "Show all test options",
-                                      NULL, NULL);
-          g_option_context_add_group (options, group);
-          g_option_group_add_entries (group, group_entries);
-        }
-
-      for (j = 0; j < G_N_ELEMENTS (help_variants); ++j)
+      for (j = 0; j < G_N_ELEMENTS (test_name_base); ++j)
         {
-          GTestTrapFlags trap_flags = 0;
-          gchar *args[3];
-
-          args[0] = __FILE__;
-          args[1] = help_variants[j];
-          args[2] = NULL;
-
-          if (!g_test_verbose ())
-            trap_flags |= G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR;
+          GTestSubprocessFlags trap_flags = 0;
+          gboolean expect_main_description = FALSE;
+          gboolean expect_main_switch      = FALSE;
+          gboolean expect_test_description = FALSE;
+          gboolean expect_test_switch      = FALSE;
+          gboolean expect_test_group       = FALSE;
+
+          if (g_test_verbose ())
+            trap_flags |= G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR;
+
+          test_name = g_strdup_printf ("/option/group/captions/subprocess/%s-%d",
+                                       test_name_base[j], i);
+          g_test_trap_subprocess (test_name, 0, trap_flags);
+          g_free (test_name);
+          g_test_trap_assert_passed ();
+          g_test_trap_assert_stderr ("");
+
+          switch (j)
+            {
+            case 0:
+              g_assert_cmpstr ("help", ==, test_name_base[j]);
+              expect_main_switch = have_main_entries;
+              expect_test_group  = have_test_entries;
+              break;
+
+            case 1:
+              g_assert_cmpstr ("help-all", ==, test_name_base[j]);
+              expect_main_switch = have_main_entries;
+              expect_test_switch = have_test_entries;
+              expect_test_group  = have_test_entries;
+              break;
+
+            case 2:
+              g_assert_cmpstr ("help-test", ==, test_name_base[j]);
+              expect_test_switch = have_test_entries;
+              break;
+
+            default:
+              g_assert_not_reached ();
+              break;
+            }
 
-          g_test_message ("test setup: args='%s', main-entries=%d, test-entries=%d",
-                          args[1], have_main_entries, have_test_entries);
+          expect_main_description |= expect_main_switch;
+          expect_test_description |= expect_test_switch;
 
-          if (g_test_trap_fork (0, trap_flags))
-            {
-              gchar **argv = args;
-              gint    argc = 2;
-              GError *error = NULL;
+          if (expect_main_description)
+            g_test_trap_assert_stdout           ("*Application Options*");
+          else
+            g_test_trap_assert_stdout_unmatched ("*Application Options*");
+          if (expect_main_switch)
+            g_test_trap_assert_stdout           ("*--main-switch*");
+          else
+            g_test_trap_assert_stdout_unmatched ("*--main-switch*");
 
-              g_setenv ("LANG", "C", TRUE);
+          if (expect_test_description)
+            g_test_trap_assert_stdout           ("*Test Options*");
+          else
+            g_test_trap_assert_stdout_unmatched ("*Test Options*");
+          if (expect_test_switch)
+            g_test_trap_assert_stdout           ("*--test-switch*");
+          else
+            g_test_trap_assert_stdout_unmatched ("*--test-switch*");
 
-              g_option_context_parse (options, &argc, &argv, &error);
-              g_option_context_free (options);
-              exit(0);
-            }
+          if (expect_test_group)
+            g_test_trap_assert_stdout           ("*--help-test*");
           else
-            {
-              gboolean expect_main_description = FALSE;
-              gboolean expect_main_switch      = FALSE;
-
-              gboolean expect_test_description = FALSE;
-              gboolean expect_test_switch      = FALSE;
-              gboolean expect_test_group       = FALSE;
-
-              g_test_trap_assert_passed ();
-              g_test_trap_assert_stderr ("");
-
-              switch (j)
-                {
-                  case 0:
-                    g_assert_cmpstr ("--help", ==, args[1]);
-                    expect_main_switch = have_main_entries;
-                    expect_test_group  = have_test_entries;
-                    break;
-
-                  case 1:
-                    g_assert_cmpstr ("--help-all", ==, args[1]);
-                    expect_main_switch = have_main_entries;
-                    expect_test_switch = have_test_entries;
-                    expect_test_group  = have_test_entries;
-                    break;
-
-                  case 2:
-                    g_assert_cmpstr ("--help-test", ==, args[1]);
-                    expect_test_switch = have_test_entries;
-                    break;
-
-                  default:
-                    g_assert_not_reached ();
-                    break;
-                }
-
-              expect_main_description |= expect_main_switch;
-              expect_test_description |= expect_test_switch;
-
-              if (expect_main_description)
-                g_test_trap_assert_stdout           ("*Application Options*");
-              else
-                g_test_trap_assert_stdout_unmatched ("*Application Options*");
-              if (expect_main_switch)
-                g_test_trap_assert_stdout           ("*--main-switch*");
-              else
-                g_test_trap_assert_stdout_unmatched ("*--main-switch*");
-
-              if (expect_test_description)
-                g_test_trap_assert_stdout           ("*Test Options*");
-              else
-                g_test_trap_assert_stdout_unmatched ("*Test Options*");
-              if (expect_test_switch)
-                g_test_trap_assert_stdout           ("*--test-switch*");
-              else
-                g_test_trap_assert_stdout_unmatched ("*--test-switch*");
-
-              if (expect_test_group)
-                g_test_trap_assert_stdout           ("*--help-test*");
-              else
-                g_test_trap_assert_stdout_unmatched ("*--help-test*");
-            }
+            g_test_trap_assert_stdout_unmatched ("*--help-test*");
         }
-
-      g_option_context_free (options);
     }
 }
 
@@ -2216,74 +2244,74 @@ test_group_parse (void)
 static void
 flag_reverse_string (void)
 {
+  GOptionContext *context;
+  gchar *arg = NULL;
+  GOptionEntry entries [] =
+    { { "test", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_STRING, &arg, NULL, NULL },
+      { NULL } };
+  gchar **argv;
+  gint argc;
+  gboolean retval;
+  GError *error = NULL;
+
   if (!g_test_undefined ())
     return;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GOptionContext *context;
-      gchar *arg = NULL;
-      GOptionEntry entries [] =
-        { { "test", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_STRING, &arg, NULL, NULL },
-          { NULL } };
-      gchar **argv;
-      gint argc;
-      gboolean retval;
-      GError *error = NULL;
-
-      context = g_option_context_new (NULL);
-      g_option_context_add_main_entries (context, entries, NULL);
-
-      argv = split_string ("program --test bla", &argc);
-
-      retval = g_option_context_parse (context, &argc, &argv, &error);
-      g_assert (retval == FALSE);
-      g_clear_error (&error);
-      g_strfreev (argv);
-      g_option_context_free (context);
-      exit (0);
-    }
-  g_test_trap_assert_failed ();
-  g_test_trap_assert_stderr ("*ignoring reverse flag*");
+  context = g_option_context_new (NULL);
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "*ignoring reverse flag*");
+  g_option_context_add_main_entries (context, entries, NULL);
+  g_test_assert_expected_messages ();
+
+  argv = split_string ("program --test bla", &argc);
+
+  retval = g_option_context_parse (context, &argc, &argv, &error);
+  g_assert (retval == TRUE);
+  g_assert_no_error (error);
+  g_strfreev (argv);
+  g_option_context_free (context);
 }
 
 static void
 flag_optional_int (void)
 {
+  GOptionContext *context;
+  gint arg = 0;
+  GOptionEntry entries [] =
+    { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &arg, NULL, NULL },
+      { NULL } };
+  gchar **argv;
+  gint argc;
+  gboolean retval;
+  GError *error = NULL;
+
   if (!g_test_undefined ())
     return;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      GOptionContext *context;
-      gint arg = 0;
-      GOptionEntry entries [] =
-        { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &arg, NULL, NULL },
-          { NULL } };
-      gchar **argv;
-      gint argc;
-      gboolean retval;
-      GError *error = NULL;
-
-      context = g_option_context_new (NULL);
-      g_option_context_add_main_entries (context, entries, NULL);
-
-      argv = split_string ("program --test 5", &argc);
-
-      retval = g_option_context_parse (context, &argc, &argv, &error);
-      g_assert (retval == FALSE);
-      g_clear_error (&error);
-      g_strfreev (argv);
-      g_option_context_free (context);
-      exit (0);
-    }
-  g_test_trap_assert_failed ();
-  g_test_trap_assert_stderr ("*ignoring no-arg, optional-arg or filename flags*");
+  context = g_option_context_new (NULL);
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "*ignoring no-arg, optional-arg or filename flags*");
+  g_option_context_add_main_entries (context, entries, NULL);
+  g_test_assert_expected_messages ();
+
+  argv = split_string ("program --test 5", &argc);
+
+  retval = g_option_context_parse (context, &argc, &argv, &error);
+  g_assert (retval == TRUE);
+  g_assert_no_error (error);
+  g_strfreev (argv);
+  g_option_context_free (context);
 }
+
 int
 main (int   argc,
       char *argv[])
 {
+  int i;
+  gchar *test_name;
+
   g_test_init (&argc, &argv, NULL);
 
   g_test_bug_base ("http://bugzilla.gnome.org/";);
@@ -2292,7 +2320,25 @@ main (int   argc,
   g_test_add_func ("/option/help/no-help-options", test_help_no_help_options);
 
   g_test_add_func ("/option/basic", test_basic);
+
   g_test_add_func ("/option/group/captions", test_group_captions);
+  for (i = 0; i < 4; i++)
+    {
+      test_name = g_strdup_printf ("/option/group/captions/subprocess/help-%d", i);
+      g_test_add_data_func (test_name, GINT_TO_POINTER (i),
+                            test_group_captions_help);
+      g_free (test_name);
+      test_name = g_strdup_printf ("/option/group/captions/subprocess/help-all-%d", i);
+      g_test_add_data_func (test_name, GINT_TO_POINTER (i),
+                            test_group_captions_help_all);
+      g_free (test_name);
+      test_name = g_strdup_printf ("/option/group/captions/subprocess/help-test-%d", i);
+      g_test_add_data_func (test_name, GINT_TO_POINTER (i),
+                            test_group_captions_help_test);
+                            
+      g_free (test_name);
+    }
+
   g_test_add_func ("/option/group/main", test_main_group);
   g_test_add_func ("/option/group/error-hook", test_error_hook);
   g_test_add_func ("/option/group/parse", test_group_parse);
diff --git a/glib/tests/scannerapi.c b/glib/tests/scannerapi.c
index 85cd92c..3b8e2ec 100644
--- a/glib/tests/scannerapi.c
+++ b/glib/tests/scannerapi.c
@@ -59,17 +59,21 @@ test_scanner_warn (ScannerFixture *fix,
 }
 
 static void
+test_scanner_error_subprocess (ScannerFixture *fix,
+                               gconstpointer   test_data)
+{
+  int pe = fix->scanner->parse_errors;
+  g_scanner_error (fix->scanner, "scanner-error-message-test");
+  g_assert_cmpint (fix->scanner->parse_errors, ==, pe + 1);
+  exit (0);
+}
+
+static void
 test_scanner_error (ScannerFixture *fix,
                     gconstpointer   test_data)
 {
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
-    {
-      int pe = fix->scanner->parse_errors;
-      g_scanner_error (fix->scanner, "scanner-error-message-test");
-      g_assert_cmpint (fix->scanner->parse_errors, ==, pe + 1);
-      exit (0);
-    }
-  g_test_trap_assert_passed();
+  g_test_trap_subprocess ("/scanner/error/subprocess", 0, 0);
+  g_test_trap_assert_passed ();
   g_test_trap_assert_stderr ("*scanner-error-message-test*");
 }
 
@@ -135,6 +139,7 @@ main (int   argc,
 
   g_test_add ("/scanner/warn", ScannerFixture, 0, scanner_fixture_setup, test_scanner_warn, 
scanner_fixture_teardown);
   g_test_add ("/scanner/error", ScannerFixture, 0, scanner_fixture_setup, test_scanner_error, 
scanner_fixture_teardown);
+  g_test_add ("/scanner/error/subprocess", ScannerFixture, 0, scanner_fixture_setup, 
test_scanner_error_subprocess, scanner_fixture_teardown);
   g_test_add ("/scanner/symbols", ScannerFixture, 0, scanner_fixture_setup, test_scanner_symbols, 
scanner_fixture_teardown);
   g_test_add ("/scanner/tokens", ScannerFixture, 0, scanner_fixture_setup, test_scanner_tokens, 
scanner_fixture_teardown);
 
diff --git a/glib/tests/slice.c b/glib/tests/slice.c
index 50bbed1..cb1c527 100644
--- a/glib/tests/slice.c
+++ b/glib/tests/slice.c
@@ -4,14 +4,15 @@
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 
 static void
-test_slice_config (void)
+test_slice_config_subprocess (void)
 {
-  if (!g_test_undefined ())
-    return;
-
-  if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
-    g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE);
+  g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE);
+}
 
+static void
+test_slice_config (void)
+{
+  g_test_trap_subprocess ("/slice/config/subprocess", 1000000, 0);
   g_test_trap_assert_failed ();
 }
 
@@ -29,6 +30,7 @@ main (int argc, char **argv)
   g_test_init (&argc, &argv, NULL);
 
   g_test_add_func ("/slice/config", test_slice_config);
+  g_test_add_func ("/slice/config/subprocess", test_slice_config_subprocess);
 
   return g_test_run ();
 }
diff --git a/glib/tests/test-printf.c b/glib/tests/test-printf.c
index dbfc8fc..ef1ce16 100644
--- a/glib/tests/test-printf.c
+++ b/glib/tests/test-printf.c
@@ -609,36 +609,26 @@ test_positional_params (void)
 }
 
 static void
-test_positional_params2 (void)
+test_positional_params2_subprocess (void)
 {
   gint res;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%2$c %1$c", 'b', 'a');
-      g_assert_cmpint (res, ==, 3);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*a b*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%1$*2$.*3$s", "abc", 5, 2);
-      g_assert_cmpint (res, ==, 5);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*   ab*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%1$s%1$s", "abc");
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
+  res = g_printf ("%2$c %1$c\n", 'b', 'a');
+  g_assert_cmpint (res, ==, 4);
+
+  res = g_printf ("%1$*2$.*3$s\n", "abc", 5, 2);
+  g_assert_cmpint (res, ==, 6);
+
+  res = g_printf ("%1$s%1$s\n", "abc");
+  g_assert_cmpint (res, ==, 7);
+}
+
+static void
+test_positional_params2 (void)
+{
+  g_test_trap_subprocess ("/printf/test-positional-params/subprocess", 0, 0);
   g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*abcabc*");
+  g_test_trap_assert_stdout ("a b\n   ab\nabcabc\n");
 }
 
 static void
@@ -661,16 +651,18 @@ test_positional_params3 (void)
 }
 
 static void
-test_percent2 (void)
+test_percent2_subprocess (void)
 {
   gint res;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%%");
-      g_assert_cmpint (res, ==, 1);
-      exit (0);
-    }
+  res = g_printf ("%%");
+  g_assert_cmpint (res, ==, 1);
+}
+
+static void
+test_percent2 (void)
+{
+  g_test_trap_subprocess ("/printf/test-percent/subprocess", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stdout ("*%*");
 }
@@ -770,83 +762,41 @@ _Pragma ("GCC diagnostic pop")
 }
 
 static void
-test_64bit2 (void)
+test_64bit2_base (void)
 {
   gint res;
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" G_GINT64_FORMAT, (gint64)123456);
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*123456*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" G_GINT64_FORMAT, (gint64)-123456);
-      g_assert_cmpint (res, ==, 7);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*-123456*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" G_GUINT64_FORMAT, (guint64)123456);
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*123456*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" G_GINT64_MODIFIER "o", (gint64)123456);
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*361100*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%#" G_GINT64_MODIFIER "o", (gint64)123456);
-      g_assert_cmpint (res, ==, 7);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*0361100*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" G_GINT64_MODIFIER "x", (gint64)123456);
-      g_assert_cmpint (res, ==, 5);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*1e240*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%#" G_GINT64_MODIFIER "x", (gint64)123456);
-      g_assert_cmpint (res, ==, 7);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*0x1e240*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" G_GINT64_MODIFIER "X", (gint64)123456);
-      g_assert_cmpint (res, ==, 5);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*1E240*");
+  res = g_printf ("%" G_GINT64_FORMAT "\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 7);
+
+  res = g_printf ("%" G_GINT64_FORMAT "\n", (gint64)-123456);
+  g_assert_cmpint (res, ==, 8);
+
+  res = g_printf ("%" G_GUINT64_FORMAT "\n", (guint64)123456);
+  g_assert_cmpint (res, ==, 7);
+
+  res = g_printf ("%" G_GINT64_MODIFIER "o\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 7);
+
+  res = g_printf ("%#" G_GINT64_MODIFIER "o\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 8);
+
+  res = g_printf ("%" G_GINT64_MODIFIER "x\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 6);
+
+  res = g_printf ("%#" G_GINT64_MODIFIER "x\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 8);
+
+  res = g_printf ("%" G_GINT64_MODIFIER "X\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 6);
+}
 
 #ifdef G_OS_WIN32
+static void
+test_64bit2_win32 (void)
+{
+  gint res;
+
   /* On Win32, test that the "ll" modifier also works, for backward
    * compatibility. One really should use the G_GINT64_MODIFIER (which
    * on Win32 is the "I64" that the (msvcrt) C library's printf uses),
@@ -863,82 +813,51 @@ _Pragma ("GCC diagnostic ignored \"-Wformat\"")
 _Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"")
 #endif
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" "lli", (gint64)123456);
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*123456*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" "lli", (gint64)-123456);
-      g_assert_cmpint (res, ==, 7);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*-123456*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" "llu", (guint64)123456);
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*123456*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" "ll" "o", (gint64)123456);
-      g_assert_cmpint (res, ==, 6);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*361100*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%#" "ll" "o", (gint64)123456);
-      g_assert_cmpint (res, ==, 7);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*0361100*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" "ll" "x", (gint64)123456);
-      g_assert_cmpint (res, ==, 5);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*1e240*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%#" "ll" "x", (gint64)123456);
-      g_assert_cmpint (res, ==, 7);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*0x1e240*");
-
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT))
-    {
-      res = g_printf ("%" "ll" "X", (gint64)123456);
-      g_assert_cmpint (res, ==, 5);
-      exit (0);
-    }
-  g_test_trap_assert_passed ();
-  g_test_trap_assert_stdout ("*1E240*");
+  res = g_printf ("%" "lli\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 7);
+
+  res = g_printf ("%" "lli\n", (gint64)-123456);
+  g_assert_cmpint (res, ==, 8);
+
+  res = g_printf ("%" "llu\n", (guint64)123456);
+  g_assert_cmpint (res, ==, 7);
+
+  res = g_printf ("%" "ll" "o\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 7);
+
+  res = g_printf ("%#" "ll" "o\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 8);
+
+  res = g_printf ("%" "ll" "x\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 6);
+
+  res = g_printf ("%#" "ll" "x\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 8);
+
+  res = g_printf ("%" "ll" "X\n", (gint64)123456);
+  g_assert_cmpint (res, ==, 6);
 
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
 _Pragma ("GCC diagnostic pop")
 #endif
+}
+#endif
+
+static void
+test_64bit2 (void)
+{
+  g_test_trap_subprocess ("/printf/test-64bit/subprocess/base", 0, 0);
+  g_test_trap_assert_passed ();
+  g_test_trap_assert_stdout ("123456\n-123456\n123456\n"
+                             "361100\n0361100\n1e240\n"
+                             "0x1e240\n1E240\n");
 
+#ifdef G_OS_WIN32
+  g_test_trap_subprocess ("/printf/test-64bit/subprocess/win32", 0, 0);
+  g_test_trap_assert_passed ();
+  g_test_trap_assert_stdout ("123456\n-123456\n123456\n"
+                             "361100\n0361100\n1e240\n"
+                             "0x1e240\n1E240\n");
 #endif
 }
 
@@ -987,8 +906,14 @@ main (int   argc,
   g_test_add_func ("/snprintf/test-64bit", test_64bit);
 
   g_test_add_func ("/printf/test-percent", test_percent2);
+  g_test_add_func ("/printf/test-percent/subprocess", test_percent2_subprocess);
   g_test_add_func ("/printf/test-positional-params", test_positional_params2);
+  g_test_add_func ("/printf/test-positional-params/subprocess", test_positional_params2_subprocess);
   g_test_add_func ("/printf/test-64bit", test_64bit2);
+  g_test_add_func ("/printf/test-64bit/subprocess/base", test_64bit2_base);
+#ifdef G_OS_WIN32
+  g_test_add_func ("/printf/test-64bit/subprocess/win32", test_64bit2_win32);
+#endif
 
   g_test_add_func ("/sprintf/test-positional-params", test_positional_params3);
   g_test_add_func ("/sprintf/upper-bound", test_upper_bound);
diff --git a/glib/tests/testing.c b/glib/tests/testing.c
index 090c2c0..0de05c0 100644
--- a/glib/tests/testing.c
+++ b/glib/tests/testing.c
@@ -23,9 +23,24 @@
 #include <glib.h>
 
 #include <stdlib.h>
+#include <string.h>
 
 /* test assertion variants */
 static void
+test_assertions_bad_cmpstr (void)
+{
+  g_assert_cmpstr ("fzz", !=, "fzz");
+  exit (0);
+}
+
+static void
+test_assertions_bad_cmpint (void)
+{
+  g_assert_cmpint (4, !=, 4);
+  exit (0);
+}
+
+static void
 test_assertions (void)
 {
   gchar *fuu;
@@ -46,17 +61,11 @@ test_assertions (void)
   g_assert_cmpstr ("fzz", >, "faa");
   g_assert_cmpstr ("fzz", ==, "fzz");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_assert_cmpstr ("fzz", !=, "fzz");
-    }
+  g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpstr", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*assertion failed*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_assert_cmpint (4, !=, 4);
-    }
+  g_test_trap_subprocess ("/misc/assertions/subprocess/bad_cmpint", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*assertion failed*");
 }
@@ -279,108 +288,143 @@ fatal_handler (const gchar    *log_domain,
 }
 
 static void
-test_fatal_log_handler (void)
+test_fatal_log_handler_critical_pass (void)
 {
   g_test_log_set_fatal_handler (fatal_handler, NULL);
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_str_has_prefix (NULL, "file://");
-      g_critical ("Test passing");
-      exit (0);
-    }
+  g_str_has_prefix (NULL, "file://");
+  g_critical ("Test passing");
+  exit (0);
+}
+
+static void
+test_fatal_log_handler_error_fail (void)
+{
+  g_error ("Test failing");
+  exit (0);
+}
+
+static void
+test_fatal_log_handler_critical_fail (void)
+{
+  g_str_has_prefix (NULL, "file://");
+  g_critical ("Test passing");
+  exit (0);
+}
+
+static void
+test_fatal_log_handler (void)
+{
+  g_test_trap_subprocess ("/misc/fatal-log-handler/subprocess/critical-pass", 0, 0);
   g_test_trap_assert_passed ();
+  g_test_trap_assert_stderr ("*CRITICAL*g_str_has_prefix*");
+  g_test_trap_assert_stderr ("*CRITICAL*Test passing*");
 
-  g_test_log_set_fatal_handler (NULL, NULL);
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    g_error ("Test failing");
+  g_test_trap_subprocess ("/misc/fatal-log-handler/subprocess/error-fail", 0, 0);
   g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*ERROR*Test failing*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    g_str_has_prefix (NULL, "file://");
+  g_test_trap_subprocess ("/misc/fatal-log-handler/subprocess/critical-fail", 0, 0);
   g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*CRITICAL*g_str_has_prefix*");
+  g_test_trap_assert_stderr_unmatched ("*CRITICAL*Test passing*");
 }
 
 static void
-expected_messages_helper (void)
+test_expected_messages_warning (void)
 {
   g_warning ("This is a %d warning", g_random_int ());
   g_return_if_reached ();
 }
 
 static void
+test_expected_messages_expect_warning (void)
+{
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "This is a * warning");
+  test_expected_messages_warning ();
+}
+
+static void
+test_expected_messages_wrong_warning (void)
+{
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "*should not be *");
+  test_expected_messages_warning ();
+}
+
+static void
+test_expected_messages_expected (void)
+{
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "This is a * warning");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "*should not be reached");
+
+  test_expected_messages_warning ();
+
+  g_test_assert_expected_messages ();
+  exit (0);
+}
+
+static void
+test_expected_messages_extra_warning (void)
+{
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "This is a * warning");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "*should not be reached");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "nope");
+
+  test_expected_messages_warning ();
+
+  /* If we don't assert, it won't notice the missing message */
+  exit (0);
+}
+
+static void
+test_expected_messages_unexpected_extra_warning (void)
+{
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "This is a * warning");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "*should not be reached");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "nope");
+
+  test_expected_messages_warning ();
+
+  g_test_assert_expected_messages ();
+  exit (0);
+}
+
+static void
 test_expected_messages (void)
 {
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      expected_messages_helper ();
-      exit (0);
-    }
+  g_test_trap_subprocess ("/misc/expected-messages/subprocess/warning", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*This is a * warning*");
   g_test_trap_assert_stderr_unmatched ("*should not be reached*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
-                             "This is a * warning");
-      expected_messages_helper ();
-      exit (0);
-    }
+  g_test_trap_subprocess ("/misc/expected-messages/subprocess/expect-warning", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr_unmatched ("*This is a * warning*");
   g_test_trap_assert_stderr ("*should not be reached*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                             "*should not be *");
-      expected_messages_helper ();
-      exit (0);
-    }
+  g_test_trap_subprocess ("/misc/expected-messages/subprocess/wrong-warning", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr_unmatched ("*should not be reached*");
   g_test_trap_assert_stderr ("*Did not see expected message CRITICAL*should not be *WARNING*This is a * 
warning*");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
-                             "This is a * warning");
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                             "*should not be reached");
-      expected_messages_helper ();
-      g_test_assert_expected_messages ();
-      exit (0);
-    }
+  g_test_trap_subprocess ("/misc/expected-messages/subprocess/expected", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stderr ("");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
-                             "This is a * warning");
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                             "*should not be reached");
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                             "nope");
-      expected_messages_helper ();
-      /* If we don't assert, it won't notice the missing message */
-      exit (0);
-    }
+  g_test_trap_subprocess ("/misc/expected-messages/subprocess/extra-warning", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stderr ("");
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
-                             "This is a * warning");
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                             "*should not be reached");
-      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                             "nope");
-      expected_messages_helper ();
-      g_test_assert_expected_messages ();
-      exit (0);
-    }
+  g_test_trap_subprocess ("/misc/expected-messages/subprocess/unexpected-extra-warning", 0, 0);
   g_test_trap_assert_failed ();
   g_test_trap_assert_stderr ("*Did not see expected message CRITICAL*nope*");
 }
@@ -489,6 +533,8 @@ main (int   argc,
   g_test_add_func ("/random-generator/rand-2", test_rand2);
   g_test_add_func ("/random-generator/random-conversions", test_random_conversions);
   g_test_add_func ("/misc/assertions", test_assertions);
+  g_test_add_func ("/misc/assertions/subprocess/bad_cmpstr", test_assertions_bad_cmpstr);
+  g_test_add_func ("/misc/assertions/subprocess/bad_cmpint", test_assertions_bad_cmpint);
   g_test_add_data_func ("/misc/test-data", (void*) 0xc0c0baba, test_data_test);
   g_test_add ("/misc/primetoul", Fixturetest, (void*) 0xc0cac01a, fixturetest_setup, fixturetest_test, 
fixturetest_teardown);
   if (g_test_perf())
@@ -514,7 +560,17 @@ main (int   argc,
   g_test_add_func ("/trap_subprocess/patterns/subprocess", test_subprocess_patterns_child);
 
   g_test_add_func ("/misc/fatal-log-handler", test_fatal_log_handler);
+  g_test_add_func ("/misc/fatal-log-handler/subprocess/critical-pass", test_fatal_log_handler_critical_pass);
+  g_test_add_func ("/misc/fatal-log-handler/subprocess/error-fail", test_fatal_log_handler_error_fail);
+  g_test_add_func ("/misc/fatal-log-handler/subprocess/critical-fail", test_fatal_log_handler_critical_fail);
+
   g_test_add_func ("/misc/expected-messages", test_expected_messages);
+  g_test_add_func ("/misc/expected-messages/subprocess/warning", test_expected_messages_warning);
+  g_test_add_func ("/misc/expected-messages/subprocess/expect-warning", 
test_expected_messages_expect_warning);
+  g_test_add_func ("/misc/expected-messages/subprocess/wrong-warning", test_expected_messages_wrong_warning);
+  g_test_add_func ("/misc/expected-messages/subprocess/expected", test_expected_messages_expected);
+  g_test_add_func ("/misc/expected-messages/subprocess/extra-warning", test_expected_messages_extra_warning);
+  g_test_add_func ("/misc/expected-messages/subprocess/unexpected-extra-warning", 
test_expected_messages_unexpected_extra_warning);
 
   g_test_add_func ("/misc/dash-p", test_dash_p);
   g_test_add_func ("/misc/dash-p/child", test_dash_p_child);
diff --git a/glib/tests/utils.c b/glib/tests/utils.c
index 1e4fbbc..f45e372 100644
--- a/glib/tests/utils.c
+++ b/glib/tests/utils.c
@@ -261,6 +261,20 @@ test_find_program (void)
 }
 
 static void
+test_debug_help (void)
+{
+  GDebugKey keys[] = {
+    { "key1", 1 },
+    { "key2", 2 },
+    { "key3", 4 },
+  };
+  guint res;
+
+  res = g_parse_debug_string ("help", keys, G_N_ELEMENTS (keys));
+  g_assert_cmpint (res, ==, 0);
+}
+
+static void
 test_debug (void)
 {
   GDebugKey keys[] = {
@@ -294,12 +308,7 @@ test_debug (void)
   res = g_parse_debug_string ("all", keys, G_N_ELEMENTS (keys));
   g_assert_cmpint (res, ==, 7);
 
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
-    {
-      res = g_parse_debug_string ("help", keys, G_N_ELEMENTS (keys));
-      g_assert_cmpint (res, ==, 0);
-      exit (0);
-    }
+  g_test_trap_subprocess ("/utils/debug/subprocess/help", 0, 0);
   g_test_trap_assert_passed ();
   g_test_trap_assert_stderr ("*Supported debug values: key1 key2 key3 all help*");
 }
@@ -535,6 +544,7 @@ main (int   argc,
   g_test_add_func ("/utils/swap", test_swap);
   g_test_add_func ("/utils/find-program", test_find_program);
   g_test_add_func ("/utils/debug", test_debug);
+  g_test_add_func ("/utils/debug/subprocess/help", test_debug_help);
   g_test_add_func ("/utils/codeset", test_codeset);
   g_test_add_func ("/utils/basename", test_basename);
   g_test_add_func ("/utils/gettext", test_gettext);
diff --git a/gobject/tests/param.c b/gobject/tests/param.c
index 31515dc..0215dc0 100644
--- a/gobject/tests/param.c
+++ b/gobject/tests/param.c
@@ -695,9 +695,18 @@ static void test_implementation_class_init (TestImplementationClass *class)
   g_object_class_install_property (class, 1, pspec);
 }
 
+typedef struct {
+  gint change_this_flag;
+  gint change_this_type;
+  gint use_this_flag;
+  gint use_this_type;
+} TestParamImplementData;
+
 static void
-test_param_implement (void)
+test_param_implement_child (gconstpointer user_data)
 {
+  TestParamImplementData *data = (gpointer) user_data;
+
   /* GObject oddity: GObjectClass must be initialised before we can
    * initialise a GTypeInterface.
    */
@@ -706,6 +715,22 @@ test_param_implement (void)
   /* Bring up the interface first. */
   g_type_default_interface_ref (test_interface_get_type ());
 
+  /* Copy the flags into the global vars so
+   * test_implementation_class_init() will see them.
+   */
+  change_this_flag = data->change_this_flag;
+  change_this_type = data->change_this_type;
+  use_this_flag = data->use_this_flag;
+  use_this_type = data->use_this_type;
+
+  g_type_class_ref (test_implementation_get_type ());
+}
+
+static void
+test_param_implement (void)
+{
+  gchar *test_path;
+
   for (change_this_flag = 0; change_this_flag < 16; change_this_flag++)
     for (change_this_type = 0; change_this_type < 3; change_this_type++)
       for (use_this_flag = 0; use_this_flag < 16; use_this_flag++)
@@ -721,11 +746,11 @@ test_param_implement (void)
                   continue;
               }
 
-            if (g_test_trap_fork (G_TIME_SPAN_SECOND, G_TEST_TRAP_SILENCE_STDERR))
-              {
-                g_type_class_ref (test_implementation_get_type ());
-                exit (0);
-              }
+            test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
+                                         change_this_flag, change_this_type,
+                                         use_this_flag, use_this_type);
+            g_test_trap_subprocess (test_path, G_TIME_SPAN_SECOND, 0);
+            g_free (test_path);
 
             /* We want to ensure that any flags mismatch problems are reported first. */
             switch (valid_impl_flags[change_this_flag][use_this_flag])
@@ -804,6 +829,9 @@ test_param_default (void)
 int
 main (int argc, char *argv[])
 {
+  TestParamImplementData data, *test_data;
+  gchar *test_path;
+
   g_test_init (&argc, &argv, NULL);
 
   g_test_add_func ("/param/value", test_param_value);
@@ -811,7 +839,21 @@ main (int argc, char *argv[])
   g_test_add_func ("/param/qdata", test_param_qdata);
   g_test_add_func ("/param/validate", test_param_validate);
   g_test_add_func ("/param/convert", test_param_convert);
+
   g_test_add_func ("/param/implement", test_param_implement);
+  for (data.change_this_flag = 0; data.change_this_flag < 16; data.change_this_flag++)
+    for (data.change_this_type = 0; data.change_this_type < 3; data.change_this_type++)
+      for (data.use_this_flag = 0; data.use_this_flag < 16; data.use_this_flag++)
+        for (data.use_this_type = 0; data.use_this_type < 4; data.use_this_type++)
+          {
+            test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
+                                         data.change_this_flag, data.change_this_type,
+                                         data.use_this_flag, data.use_this_type);
+            test_data = g_memdup (&data, sizeof (TestParamImplementData));
+            g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
+            g_free (test_path);
+          }
+
   g_test_add_func ("/value/transform", test_value_transform);
   g_test_add_func ("/param/default", test_param_default);
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a5af03a..1a69a4e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS=gobject refcount
 AM_CPPFLAGS = \
        $(gmodule_INCLUDES)                     \
        -DGLIB_DISABLE_DEPRECATION_WARNINGS     \
+       -DG_LOG_DOMAIN=\"GLib\"                 \
        $(GLIB_DEBUG_FLAGS)
 
 AM_CFLAGS = -g
diff --git a/tests/testglib.c b/tests/testglib.c
index d41d674..b674fa9 100644
--- a/tests/testglib.c
+++ b/tests/testglib.c
@@ -552,32 +552,30 @@ test_g_parse_debug_string (void)
 static void
 log_warning_error_tests (void)
 {
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_message ("this is a g_message test.");
-      g_message ("non-printable UTF-8: \"\xc3\xa4\xda\x85\"");
-      g_message ("unsafe chars: \"\x10\x11\x12\n\t\x7f\x81\x82\x83\"");
-      exit (0);
-    }
-  g_test_trap_assert_passed();
-  g_test_trap_assert_stderr ("*is a g_message test*");
-  g_test_trap_assert_stderr ("*non-printable UTF-8*");
-  g_test_trap_assert_stderr ("*unsafe chars*");
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_warning ("harmless warning with parameters: %d %s %#x", 42, "Boo", 12345);
-      exit (0);
-    }
-  g_test_trap_assert_failed(); /* we have fatal-warnings enabled */
-  g_test_trap_assert_stderr ("*harmless warning*");
-  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
-    {
-      g_print (NULL);
-      exit (0);
-    }
-  g_test_trap_assert_failed(); /* we have fatal-warnings enabled */
-  g_test_trap_assert_stderr ("*g_print*assertion*failed*");
-  g_test_trap_assert_stderr ("*NULL*");
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
+                         "*is a g_message test*");
+  g_message ("this is a g_message test.");
+  g_test_assert_expected_messages ();
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
+                         "*non-printable UTF-8*");
+  g_message ("non-printable UTF-8: \"\xc3\xa4\xda\x85\"");
+  g_test_assert_expected_messages ();
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
+                         "*unsafe chars*");
+  g_message ("unsafe chars: \"\x10\x11\x12\n\t\x7f\x81\x82\x83\"");
+  g_test_assert_expected_messages ();
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "*harmless warning*");
+  g_warning ("harmless warning with parameters: %d %s %#x", 42, "Boo", 12345);
+  g_test_assert_expected_messages ();
+
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                         "*g_print*assertion*failed*");
+  g_print (NULL);
+  g_test_assert_expected_messages ();
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]