glib-unix: add function to ensure an fd is sealed
[platform/upstream/glib.git] / glib / gtestutils.c
index 3aec27e..dede38a 100644 (file)
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 
 #include "gtestutils.h"
-#include "gmessages-private.h"
 #include "gfileutils.h"
 
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <glib/gstdio.h>
 #endif
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif
 #include "gslice.h"
 #include "gspawn.h"
 #include "glib-private.h"
-#include "gmessages-private.h"
 
 
 /**
  * SECTION:testing
  * @title: Testing
  * @short_description: a test framework
- * @see_also: <link linkend="gtester">gtester</link>,
- *            <link linkend="gtester-report">gtester-report</link>
+ * @see_also: [gtester][gtester], [gtester-report][gtester-report]
  *
  * GLib provides a framework for writing and maintaining unit tests
  * in parallel to the code they are testing. The API is designed according
  * to established concepts found in the other test frameworks (JUnit, NUnit,
  * RUnit), which in turn is based on smalltalk unit testing concepts.
  *
- * <variablelist>
- *   <varlistentry>
- *     <term>Test case</term>
- *     <listitem>Tests (test methods) are grouped together with their
- *       fixture into test cases.</listitem>
- *   </varlistentry>
- *   <varlistentry>
- *     <term>Fixture</term>
- *     <listitem>A test fixture consists of fixture data and setup and
- *       teardown methods to establish the environment for the test
- *       functions. We use fresh fixtures, i.e. fixtures are newly set
- *       up and torn down around each test invocation to avoid dependencies
- *       between tests.</listitem>
- *   </varlistentry>
- *   <varlistentry>
- *     <term>Test suite</term>
- *     <listitem>Test cases can be grouped into test suites, to allow
- *       subsets of the available tests to be run. Test suites can be
- *       grouped into other test suites as well.</listitem>
- *   </varlistentry>
- * </variablelist>
+ * - Test case: Tests (test methods) are grouped together with their
+ *   fixture into test cases.
+ *
+ * - Fixture: A test fixture consists of fixture data and setup and
+ *   teardown methods to establish the environment for the test
+ *   functions. We use fresh fixtures, i.e. fixtures are newly set
+ *   up and torn down around each test invocation to avoid dependencies
+ *   between tests.
+ *
+ * - Test suite: Test cases can be grouped into test suites, to allow
+ *   subsets of the available tests to be run. Test suites can be
+ *   grouped into other test suites as well.
+ *
  * The API is designed to handle creation and registration of test suites
  * and test cases implicitly. A simple call like
- * |[
+ * |[<!-- language="C" --> 
  *   g_test_add_func ("/misc/assertions", test_assertions);
  * ]|
  * creates a test suite called "misc" with a single test case named
 /**
  * GTestTrapFlags:
  * @G_TEST_TRAP_SILENCE_STDOUT: Redirect stdout of the test child to
- *     <filename>/dev/null</filename> so it cannot be observed on the
- *     console during test runs. The actual output is still captured
- *     though to allow later tests with g_test_trap_assert_stdout().
+ *     `/dev/null` so it cannot be observed on the console during test
+ *     runs. The actual output is still captured though to allow later
+ *     tests with g_test_trap_assert_stdout().
  * @G_TEST_TRAP_SILENCE_STDERR: Redirect stderr of the test child to
- *     <filename>/dev/null</filename> so it cannot be observed on the
- *     console during test runs. The actual output is still captured
- *     though to allow later tests with g_test_trap_assert_stderr().
+ *     `/dev/null` so it cannot be observed on the console during test
+ *     runs. The actual output is still captured though to allow later
+ *     tests with g_test_trap_assert_stderr().
  * @G_TEST_TRAP_INHERIT_STDIN: If this flag is given, stdin of the
  *     child process is shared with stdin of its parent process.
- *     It is redirected to <filename>/dev/null</filename> otherwise.
+ *     It is redirected to `/dev/null` otherwise.
  *
  * Test traps are guards around forked tests.
  * These flags determine what traps to set.
  * GTestSubprocessFlags:
  * @G_TEST_SUBPROCESS_INHERIT_STDIN: If this flag is given, the child
  *     process will inherit the parent's stdin. Otherwise, the child's
- *     stdin is redirected to <filename>/dev/null</filename>.
+ *     stdin is redirected to `/dev/null`.
  * @G_TEST_SUBPROCESS_INHERIT_STDOUT: If this flag is given, the child
  *     process will inherit the parent's stdout. Otherwise, the child's
  *     stdout will not be visible, but it will be captured to allow
 
 /**
  * g_test_trap_assert_stdout:
- * @soutpattern: a glob-style
- *     <link linkend="glib-Glob-style-pattern-matching">pattern</link>
+ * @soutpattern: a glob-style [pattern][glib-Glob-style-pattern-matching]
  *
  * Assert that the stdout output of the last test subprocess matches
  * @soutpattern. See g_test_trap_subprocess().
 
 /**
  * g_test_trap_assert_stdout_unmatched:
- * @soutpattern: a glob-style
- *     <link linkend="glib-Glob-style-pattern-matching">pattern</link>
+ * @soutpattern: a glob-style [pattern][glib-Glob-style-pattern-matching]
  *
  * Assert that the stdout output of the last test subprocess
  * does not match @soutpattern. See g_test_trap_subprocess().
 
 /**
  * g_test_trap_assert_stderr:
- * @serrpattern: a glob-style
- *     <link linkend="glib-Glob-style-pattern-matching">pattern</link>
+ * @serrpattern: a glob-style [pattern][glib-Glob-style-pattern-matching]
  *
  * Assert that the stderr output of the last test subprocess
  * matches @serrpattern. See  g_test_trap_subprocess().
 
 /**
  * g_test_trap_assert_stderr_unmatched:
- * @serrpattern: a glob-style
- *     <link linkend="glib-Glob-style-pattern-matching">pattern</link>
+ * @serrpattern: a glob-style [pattern][glib-Glob-style-pattern-matching]
  *
  * Assert that the stderr output of the last test subprocess
  * does not match @serrpattern. See g_test_trap_subprocess().
  * an error message is logged and the application is terminated.
  *
  * The macro can be turned off in final releases of code by defining
- * <envar>G_DISABLE_ASSERT</envar> when compiling the application.
+ * `G_DISABLE_ASSERT` when compiling the application.
+ *
+ * For a version which is guaranteed to evaluate side effects in @expr,
+ * see g_assert_se().
+ */
+
+/**
+ * g_assert_se:
+ * @expr: the expression to check
+ *
+ * Debugging macro to terminate the application if the assertion
+ * fails. If the assertion fails (i.e. the expression is not true),
+ * an error message is logged and the application is terminated.
+ *
+ * The check can be turned off in final releases of code by defining
+ * `G_DISABLE_ASSERT` when compiling the application.
+ *
+ * Unlike g_assert(), this macro is guaranteed to evaluate side effects
+ * of @expr, even if checks are disabled.  It is still undefined if the
+ * program will actually be aborted or not.
  */
 
 /**
  * application is terminated.
  *
  * The macro can be turned off in final releases of code by defining
- * <envar>G_DISABLE_ASSERT</envar> when compiling the application.
+ * `G_DISABLE_ASSERT` when compiling the application.
  */
 
 /**
  *
  * Debugging macro to check that an expression is true.
  *
+ * If the assertion fails (i.e. the expression is not true),
+ * an error message is logged and the application is either
+ * terminated or the testcase marked as failed.
+ *
+ * See g_test_set_nonfatal_assertions().
+ *
  * Since: 2.38
  */
 
  *
  * Debugging macro to check an expression is false.
  *
+ * If the assertion fails (i.e. the expression is not false),
+ * an error message is logged and the application is either
+ * terminated or the testcase marked as failed.
+ *
+ * See g_test_set_nonfatal_assertions().
+ *
  * Since: 2.38
  */
 
  *
  * Debugging macro to check an expression is %NULL.
  *
+ * If the assertion fails (i.e. the expression is not %NULL),
+ * an error message is logged and the application is either
+ * terminated or the testcase marked as failed.
+ *
+ * See g_test_set_nonfatal_assertions().
+ *
  * Since: 2.38
  */
 
 /**
+ * g_assert_nonnull:
+ * @expr: the expression to check
+ *
+ * Debugging macro to check an expression is not %NULL.
+ *
+ * If the assertion fails (i.e. the expression is %NULL),
+ * an error message is logged and the application is either
+ * terminated or the testcase marked as failed.
+ *
+ * See g_test_set_nonfatal_assertions().
+ *
+ * Since: 2.40
+ */
+
+/**
  * g_assert_cmpstr:
  * @s1: a string (may be %NULL)
  * @cmp: The comparison operator to use.
- *     One of ==, !=, &lt;, &gt;, &lt;=, &gt;=.
+ *     One of ==, !=, <, >, <=, >=.
  * @s2: another string (may be %NULL)
  *
- * Debugging macro to terminate the application with a warning
- * message if a string comparison fails. The strings are compared
- * using g_strcmp0().
+ * Debugging macro to compare two strings. If the comparison fails,
+ * an error message is logged and the application is either terminated
+ * or the testcase marked as failed.
+ * The strings are compared using g_strcmp0().
  *
- * The effect of <literal>g_assert_cmpstr (s1, op, s2)</literal> is
- * the same as <literal>g_assert (g_strcmp0 (s1, s2) op 0)</literal>.
+ * The effect of `g_assert_cmpstr (s1, op, s2)` is
+ * the same as `g_assert_true (g_strcmp0 (s1, s2) op 0)`.
  * The advantage of this macro is that it can produce a message that
  * includes the actual values of @s1 and @s2.
  *
- * |[
+ * |[<!-- language="C" --> 
  *   g_assert_cmpstr (mystring, ==, "fubar");
  * ]|
  *
  * g_assert_cmpint:
  * @n1: an integer
  * @cmp: The comparison operator to use.
- *     One of ==, !=, &lt;, &gt;, &lt;=, &gt;=.
+ *     One of ==, !=, <, >, <=, >=.
  * @n2: another integer
  *
- * Debugging macro to terminate the application with a warning
- * message if an integer comparison fails.
+ * Debugging macro to compare two integers.
  *
- * The effect of <literal>g_assert_cmpint (n1, op, n2)</literal> is
- * the same as <literal>g_assert (n1 op n2)</literal>. The advantage
+ * The effect of `g_assert_cmpint (n1, op, n2)` is
+ * the same as `g_assert_true (n1 op n2)`. The advantage
  * of this macro is that it can produce a message that includes the
  * actual values of @n1 and @n2.
  *
  * g_assert_cmpuint:
  * @n1: an unsigned integer
  * @cmp: The comparison operator to use.
- *     One of ==, !=, &lt;, &gt;, &lt;=, &gt;=.
+ *     One of ==, !=, <, >, <=, >=.
  * @n2: another unsigned integer
  *
- * Debugging macro to terminate the application with a warning
- * message if an unsigned integer comparison fails.
+ * Debugging macro to compare two unsigned integers.
  *
- * The effect of <literal>g_assert_cmpuint (n1, op, n2)</literal> is
- * the same as <literal>g_assert (n1 op n2)</literal>. The advantage
+ * The effect of `g_assert_cmpuint (n1, op, n2)` is
+ * the same as `g_assert_true (n1 op n2)`. The advantage
  * of this macro is that it can produce a message that includes the
  * actual values of @n1 and @n2.
  *
  * g_assert_cmphex:
  * @n1: an unsigned integer
  * @cmp: The comparison operator to use.
- *     One of ==, !=, &lt;, &gt;, &lt;=, &gt;=.
+ *     One of ==, !=, <, >, <=, >=.
  * @n2: another unsigned integer
  *
- * Debugging macro to terminate the application with a warning
- * message if an unsigned integer comparison fails.
+ * Debugging macro to compare to unsigned integers.
  *
  * This is a variant of g_assert_cmpuint() that displays the numbers
  * in hexadecimal notation in the message.
  * g_assert_cmpfloat:
  * @n1: an floating point number
  * @cmp: The comparison operator to use.
- *     One of ==, !=, &lt;, &gt;, &lt;=, &gt;=.
+ *     One of ==, !=, <, >, <=, >=.
  * @n2: another floating point number
  *
- * Debugging macro to terminate the application with a warning
- * message if a floating point number comparison fails.
+ * Debugging macro to compare two floating point numbers.
  *
- * The effect of <literal>g_assert_cmpfloat (n1, op, n2)</literal> is
- * the same as <literal>g_assert (n1 op n2)</literal>. The advantage
+ * The effect of `g_assert_cmpfloat (n1, op, n2)` is
+ * the same as `g_assert_true (n1 op n2)`. The advantage
  * of this macro is that it can produce a message that includes the
  * actual values of @n1 and @n2.
  *
  * g_assert_no_error:
  * @err: a #GError, possibly %NULL
  *
- * Debugging macro to terminate the application with a warning
- * message if a method has returned a #GError.
+ * Debugging macro to check that a #GError is not set.
  *
- * The effect of <literal>g_assert_no_error (err)</literal> is
- * the same as <literal>g_assert (err == NULL)</literal>. The advantage
+ * The effect of `g_assert_no_error (err)` is
+ * the same as `g_assert_true (err == NULL)`. The advantage
  * of this macro is that it can produce a message that includes
  * the error message and code.
  *
  * @dom: the expected error domain (a #GQuark)
  * @c: the expected error code
  *
- * Debugging macro to terminate the application with a warning
- * message if a method has not returned the correct #GError.
+ * Debugging macro to check that a method has returned
+ * the correct #GError.
  *
- * The effect of <literal>g_assert_error (err, dom, c)</literal> is
- * the same as <literal>g_assert (err != NULL &amp;&amp; err->domain
- * == dom &amp;&amp; err->code == c)</literal>. The advantage of this
+ * The effect of `g_assert_error (err, dom, c)` is
+ * the same as `g_assert_true (err != NULL && err->domain
+ * == dom && err->code == c)`. The advantage of this
  * macro is that it can produce a message that includes the incorrect
  * error message and code.
  *
  * This can only be used to test for a specific error. If you want to
  * test that @err is set, but don't care what it's set to, just use
- * <literal>g_assert (err != NULL)</literal>
+ * `g_assert (err != NULL)`
  *
  * Since: 2.20
  */
@@ -582,9 +611,10 @@ static gchar      *test_run_name = "";
 static GSList    **test_filename_free_list;
 static guint       test_run_forks = 0;
 static guint       test_run_count = 0;
+static guint       test_skipped_count = 0;
 static GTestResult test_run_success = G_TEST_RUN_FAILURE;
 static gchar      *test_run_msg = NULL;
-static guint       test_skip_count = 0;
+static guint       test_startup_skip_count = 0;
 static GTimer     *test_user_timer = NULL;
 static double      test_user_stamp = 0;
 static GSList     *test_paths = NULL;
@@ -615,6 +645,7 @@ static GTestConfig mutable_test_config_vars = {
   TRUE,         /* test_undefined */
 };
 const GTestConfig * const g_test_config_vars = &mutable_test_config_vars;
+static gboolean  no_g_set_prgname = FALSE;
 
 /* --- functions --- */
 const char*
@@ -739,6 +770,8 @@ g_test_log (GTestLogType lbit,
             g_print ("Bail out!\n");
           abort();
         }
+      if (largs[0] == G_TEST_RUN_SKIPPED)
+        test_skipped_count++;
       break;
     case G_TEST_LOG_MIN_RESULT:
       if (test_tap_log)
@@ -843,11 +876,11 @@ parse_args (gint    *argc_p,
         {
           gchar *equal = argv[i] + 16;
           if (*equal == '=')
-            test_skip_count = g_ascii_strtoull (equal + 1, NULL, 0);
+            test_startup_skip_count = g_ascii_strtoull (equal + 1, NULL, 0);
           else if (i + 1 < argc)
             {
               argv[i++] = NULL;
-              test_skip_count = g_ascii_strtoull (argv[i], NULL, 0);
+              test_startup_skip_count = g_ascii_strtoull (argv[i], NULL, 0);
             }
           argv[i] = NULL;
         }
@@ -864,7 +897,6 @@ parse_args (gint    *argc_p,
             (void) setrlimit (RLIMIT_CORE, &limit);
           }
 #endif
-          _g_log_set_exit_on_fatal ();
           argv[i] = NULL;
         }
       else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
@@ -991,87 +1023,39 @@ parse_args (gint    *argc_p,
  *        Changed if any arguments were handled.
  * @argv: Address of the @argv parameter of main().
  *        Any parameters understood by g_test_init() stripped before return.
- * @...: Reserved for future extension. Currently, you must pass %NULL.
+ * @...: %NULL-terminated list of special options. Currently the only
+ *       defined option is `"no_g_set_prgname"`, which
+ *       will cause g_test_init() to not call g_set_prgname().
  *
  * Initialize the GLib testing framework, e.g. by seeding the
  * test random number generator, the name for g_get_prgname()
  * and parsing test related command line args.
+ *
  * So far, the following arguments are understood:
- * <variablelist>
- *   <varlistentry>
- *     <term><option>-l</option></term>
- *     <listitem><para>
- *       List test cases available in a test executable.
- *     </para></listitem>
- *   </varlistentry>
- *   <varlistentry>
- *     <term><option>--seed=<replaceable>RANDOMSEED</replaceable></option></term>
- *     <listitem><para>
- *       Provide a random seed to reproduce test runs using random numbers.
- *     </para></listitem>
- *     </varlistentry>
- *     <varlistentry>
- *       <term><option>--verbose</option></term>
- *       <listitem><para>Run tests verbosely.</para></listitem>
- *     </varlistentry>
- *     <varlistentry>
- *       <term><option>-q</option>, <option>--quiet</option></term>
- *       <listitem><para>Run tests quietly.</para></listitem>
- *     </varlistentry>
- *     <varlistentry>
- *       <term><option>-p <replaceable>TESTPATH</replaceable></option></term>
- *       <listitem><para>
- *         Execute all tests matching <replaceable>TESTPATH</replaceable>.
- *         This can also be used to force a test to run that would otherwise
- *         be skipped (ie, a test whose name contains "/subprocess").
- *       </para></listitem>
- *     </varlistentry>
- *     <varlistentry>
- *       <term><option>-m {perf|slow|thorough|quick|undefined|no-undefined}</option></term>
- *       <listitem><para>
- *         Execute tests according to these test modes:
- *         <variablelist>
- *           <varlistentry>
- *             <term>perf</term>
- *             <listitem><para>
- *               Performance tests, may take long and report results.
- *             </para></listitem>
- *           </varlistentry>
- *           <varlistentry>
- *             <term>slow, thorough</term>
- *             <listitem><para>
- *               Slow and thorough tests, may take quite long and
- *               maximize coverage.
- *             </para></listitem>
- *           </varlistentry>
- *           <varlistentry>
- *             <term>quick</term>
- *             <listitem><para>
- *               Quick tests, should run really quickly and give good coverage.
- *             </para></listitem>
- *           </varlistentry>
- *           <varlistentry>
- *             <term>undefined</term>
- *             <listitem><para>
- *               Tests for undefined behaviour, may provoke programming errors
- *               under g_test_trap_subprocess() or g_test_expect_messages() to check
- *               that appropriate assertions or warnings are given
- *             </para></listitem>
- *           </varlistentry>
- *           <varlistentry>
- *             <term>no-undefined</term>
- *             <listitem><para>
- *               Avoid tests for undefined behaviour
- *             </para></listitem>
- *           </varlistentry>
- *         </variablelist>
- *       </para></listitem>
- *     </varlistentry>
- *     <varlistentry>
- *       <term><option>--debug-log</option></term>
- *       <listitem><para>Debug test logging output.</para></listitem>
- *     </varlistentry>
- *  </variablelist>
+ *
+ * - `-l`: List test cases available in a test executable.
+ * - `--seed=SEED`: Provide a random seed to reproduce test
+ *   runs using random numbers.
+ * - `--verbose`: Run tests verbosely.
+ * - `-q`, `--quiet`: Run tests quietly.
+ * - `-p PATH`: Execute all tests matching the given path.
+ *   This can also be used to force a test to run that would otherwise
+ *   be skipped (ie, a test whose name contains "/subprocess").
+ * - `-m {perf|slow|thorough|quick|undefined|no-undefined}`: Execute tests according to these test modes:
+ *
+ *   `perf`: Performance tests, may take long and report results.
+ *
+ *   `slow`, `thorough`: Slow and thorough tests, may take quite long and maximize coverage.
+ *
+ *   `quick`: Quick tests, should run really quickly and give good coverage.
+ *
+ *   `undefined`: Tests for undefined behaviour, may provoke programming errors
+ *   under g_test_trap_subprocess() or g_test_expect_messages() to check
+ *   that appropriate assertions or warnings are given
+ *
+ *   `no-undefined`: Avoid tests for undefined behaviour
+ *
+ * - `--debug-log`: Debug test logging output.
  *
  * Since: 2.16
  */
@@ -1082,9 +1066,10 @@ g_test_init (int    *argc,
 {
   static char seedstr[4 + 4 * 8 + 1];
   va_list args;
-  gpointer vararg1;
+  gpointer option;
   /* make warnings and criticals fatal for all test programs */
   GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
+
   fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
   g_log_set_always_fatal (fatal_mask);
   /* check caller args */
@@ -1094,9 +1079,12 @@ g_test_init (int    *argc,
   mutable_test_config_vars.test_initialized = TRUE;
 
   va_start (args, argv);
-  vararg1 = va_arg (args, gpointer); /* reserved for future extensions */
+  while ((option = va_arg (args, char *)))
+    {
+      if (g_strcmp0 (option, "no_g_set_prgname") == 0)
+        no_g_set_prgname = TRUE;
+    }
   va_end (args);
-  g_return_if_fail (vararg1 == NULL);
 
   /* setup random seed string */
   g_snprintf (seedstr, sizeof (seedstr), "R02S%08x%08x%08x%08x", g_random_int(), g_random_int(), g_random_int(), g_random_int());
@@ -1104,7 +1092,8 @@ g_test_init (int    *argc,
 
   /* parse args, sets up mode, changes seed, etc. */
   parse_args (argc, argv);
-  if (!g_get_prgname())
+
+  if (!g_get_prgname() && !no_g_set_prgname)
     g_set_prgname ((*argv)[0]);
 
   /* verify GRand reliability, needed for reliable seeds */
@@ -1478,20 +1467,55 @@ g_test_get_root (void)
  *
  * Runs all tests under the toplevel suite which can be retrieved
  * with g_test_get_root(). Similar to g_test_run_suite(), the test
- * cases to be run are filtered according to
- * test path arguments (-p <replaceable>testpath</replaceable>) as 
- * parsed by g_test_init().
- * g_test_run_suite() or g_test_run() may only be called once
- * in a program.
- *
- * Returns: 0 on success
+ * cases to be run are filtered according to test path arguments
+ * (`-p testpath`) as parsed by g_test_init(). g_test_run_suite()
+ * or g_test_run() may only be called once in a program.
+ *
+ * In general, the tests and sub-suites within each suite are run in
+ * the order in which they are defined. However, note that prior to
+ * GLib 2.36, there was a bug in the `g_test_add_*`
+ * functions which caused them to create multiple suites with the same
+ * name, meaning that if you created tests "/foo/simple",
+ * "/bar/simple", and "/foo/using-bar" in that order, they would get
+ * run in that order (since g_test_run() would run the first "/foo"
+ * suite, then the "/bar" suite, then the second "/foo" suite). As of
+ * 2.36, this bug is fixed, and adding the tests in that order would
+ * result in a running order of "/foo/simple", "/foo/using-bar",
+ * "/bar/simple". If this new ordering is sub-optimal (because it puts
+ * more-complicated tests before simpler ones, making it harder to
+ * figure out exactly what has failed), you can fix it by changing the
+ * test paths to group tests by suite in a way that will result in the
+ * desired running order. Eg, "/simple/foo", "/simple/bar",
+ * "/complex/foo-using-bar".
+ *
+ * However, you should never make the actual result of a test depend
+ * on the order that tests are run in. If you need to ensure that some
+ * particular code runs before or after a given test case, use
+ * g_test_add(), which lets you specify setup and teardown functions.
+ *
+ * If all tests are skipped, this function will return 0 if
+ * producing TAP output, or 77 (treated as "skip test" by Automake) otherwise.
+ *
+ * Returns: 0 on success, 1 on failure (assuming it returns at all),
+ *   0 or 77 if all tests were skipped with g_test_skip()
  *
  * Since: 2.16
  */
 int
 g_test_run (void)
 {
-  return g_test_run_suite (g_test_get_root());
+  if (g_test_run_suite (g_test_get_root()) != 0)
+    return 1;
+
+  /* 77 is special to Automake's default driver, but not Automake's TAP driver
+   * or Perl's prove(1) TAP driver. */
+  if (test_tap_log)
+    return 0;
+
+  if (test_run_count > 0 && test_run_count == test_skipped_count)
+    return 77;
+  else
+    return 0;
 }
 
 /**
@@ -1734,7 +1758,9 @@ g_test_failed (void)
  * g_assert_true(), g_assert_false(), g_assert_null(), g_assert_no_error(),
  * g_assert_error(), g_test_assert_expected_messages() and the various
  * g_test_trap_assert_*() macros to not abort to program, but instead
- * call g_test_fail() and continue.
+ * call g_test_fail() and continue. (This also changes the behavior of
+ * g_test_fail() so that it will not cause the test program to abort
+ * after completing the failed test.)
  *
  * Note that the g_assert_not_reached() and g_assert() are not
  * affected by this.
@@ -1749,6 +1775,7 @@ g_test_set_nonfatal_assertions (void)
   if (!g_test_config_vars->test_initialized)
     g_error ("g_test_set_nonfatal_assertions called without g_test_init");
   test_nonfatal_assertions = TRUE;
+  test_mode_fatal = FALSE;
 }
 
 /**
@@ -1771,8 +1798,7 @@ g_test_set_nonfatal_assertions (void)
  *
  * If @testpath includes the component "subprocess" anywhere in it,
  * the test will be skipped by default, and only run if explicitly
- * required via the <option>-p</option> command-line option or
- * g_test_trap_subprocess().
+ * required via the `-p` command-line option or g_test_trap_subprocess().
  *
  * Since: 2.16
  */
@@ -1810,8 +1836,7 @@ g_test_add_func (const char *testpath,
  *
  * If @testpath includes the component "subprocess" anywhere in it,
  * the test will be skipped by default, and only run if explicitly
- * required via the <option>-p</option> command-line option or
- * g_test_trap_subprocess().
+ * required via the `-p` command-line option or g_test_trap_subprocess().
  *
  * Since: 2.16
  */
@@ -2028,7 +2053,7 @@ test_case_run (GTestCase *tc)
         }
     }
 
-  if (++test_run_count <= test_skip_count)
+  if (++test_run_count <= test_startup_skip_count)
     g_test_log (G_TEST_LOG_SKIP_CASE, test_run_name, NULL, 0, NULL);
   else if (test_run_list)
     {
@@ -2082,7 +2107,8 @@ test_case_run (GTestCase *tc)
   g_free (test_uri_base);
   test_uri_base = old_base;
 
-  return success == G_TEST_RUN_SUCCESS;
+  return (success == G_TEST_RUN_SUCCESS ||
+          success == G_TEST_RUN_SKIPPED);
 }
 
 static int
@@ -2138,8 +2164,10 @@ g_test_run_suite_internal (GTestSuite *suite,
  *
  * Execute the tests within @suite and all nested #GTestSuites.
  * The test suites to be executed are filtered according to
- * test path arguments (-p <replaceable>testpath</replaceable>) 
- * as parsed by g_test_init().
+ * test path arguments (`-p testpath`) as parsed by g_test_init().
+ * See the g_test_run() documentation for more information on the
+ * order that tests are run in.
+ *
  * g_test_run_suite() or g_test_run() may only be called once
  * in a program.
  *
@@ -2251,17 +2279,35 @@ g_assertion_message (const char     *domain,
                    " ", message, NULL);
   g_printerr ("**\n%s\n", s);
 
+  g_test_log (G_TEST_LOG_ERROR, s, NULL, 0, NULL);
+
+  if (test_nonfatal_assertions)
+    {
+      g_free (s);
+      g_test_fail ();
+      return;
+    }
+
   /* store assertion message in global variable, so that it can be found in a
    * core dump */
   if (__glib_assert_msg != NULL)
-      /* free the old one */
-      free (__glib_assert_msg);
+    /* free the old one */
+    free (__glib_assert_msg);
   __glib_assert_msg = (char*) malloc (strlen (s) + 1);
   strcpy (__glib_assert_msg, s);
 
-  g_test_log (G_TEST_LOG_ERROR, s, NULL, 0, NULL);
   g_free (s);
-  _g_log_abort ();
+
+  if (test_in_subprocess)
+    {
+      /* If this is a test case subprocess then it probably hit this
+       * assertion on purpose, so just exit() rather than abort()ing,
+       * to avoid triggering any system crash-reporting daemon.
+       */
+      _exit (1);
+    }
+  else
+    abort ();
 }
 
 void
@@ -2278,7 +2324,15 @@ g_assertion_message_expr (const char     *domain,
     s = g_strconcat ("assertion failed: (", expr, ")", NULL);
   g_assertion_message (domain, file, line, func, s);
   g_free (s);
-  abort ();
+
+  /* Normally g_assertion_message() won't return, but we need this for
+   * when test_nonfatal_assertions is set, since
+   * g_assertion_message_expr() is used for always-fatal assertions.
+   */
+  if (test_in_subprocess)
+    _exit (1);
+  else
+    abort ();
 }
 
 void
@@ -2601,7 +2655,7 @@ wait_for_child (GPid pid,
  * The forking parent process then asserts successful child program
  * termination and validates child program outputs.
  *
- * |[
+ * |[<!-- language="C" --> 
  *   static void
  *   test_fork_patterns (void)
  *   {
@@ -2609,7 +2663,7 @@ wait_for_child (GPid pid,
  *       {
  *         g_print ("some stdout text: somagic17\n");
  *         g_printerr ("some stderr text: semagic43\n");
- *         exit (0); /&ast; successful test run &ast;/
+ *         exit (0); // successful test run
  *       }
  *     g_test_trap_assert_passed ();
  *     g_test_trap_assert_stdout ("*somagic17*");
@@ -2645,7 +2699,11 @@ g_test_trap_fork (guint64        usec_timeout,
       close (stdout_pipe[0]);
       close (stderr_pipe[0]);
       if (!(test_trap_flags & G_TEST_TRAP_INHERIT_STDIN))
-        fd0 = g_open ("/dev/null", O_RDONLY, 0);
+        {
+          fd0 = g_open ("/dev/null", O_RDONLY, 0);
+          if (fd0 < 0)
+            g_error ("failed to open /dev/null for stdin redirection");
+        }
       if (sane_dup2 (stdout_pipe[1], 1) < 0 || sane_dup2 (stderr_pipe[1], 2) < 0 || (fd0 >= 0 && sane_dup2 (fd0, 0) < 0))
         g_error ("failed to dup2() in forked test program: %s", g_strerror (errno));
       if (fd0 >= 3)
@@ -2677,18 +2735,23 @@ g_test_trap_fork (guint64        usec_timeout,
 
 /**
  * g_test_trap_subprocess:
- * @test_path:    Test to run in a subprocess
+ * @test_path: (allow-none): Test to run in a subprocess
  * @usec_timeout: Timeout for the subprocess test in micro seconds.
  * @test_flags:   Flags to modify subprocess behaviour.
  *
  * Respawns the test program to run only @test_path in a subprocess.
  * This can be used for a test case that might not return, or that
- * might abort. @test_path will normally be the name of the parent
- * test, followed by "<literal>/subprocess/</literal>" and then a name
- * for the specific subtest (or just ending with
- * "<literal>/subprocess</literal>" if the test only has one child
- * test); tests with names of this form will automatically be skipped
- * in the parent process.
+ * might abort.
+ *
+ * If @test_path is %NULL then the same test is re-run in a subprocess.
+ * You can use g_test_subprocess() to determine whether the test is in
+ * a subprocess or not.
+ *
+ * @test_path can also be the name of the parent test, followed by
+ * "`/subprocess/`" and then a name for the specific subtest (or just
+ * ending with "`/subprocess`" if the test only has one child test);
+ * tests with names of this form will automatically be skipped in the
+ * parent process.
  *
  * If @usec_timeout is non-0, the test subprocess is aborted and
  * considered failing if its run time exceeds it.
@@ -2703,25 +2766,26 @@ g_test_trap_fork (guint64        usec_timeout,
  * cannot be used if @test_flags specifies that the child should
  * inherit the parent stdout/stderr.) 
  *
- * If your <literal>main ()</literal> needs to behave differently in
+ * If your `main ()` needs to behave differently in
  * the subprocess, you can call g_test_subprocess() (after calling
  * g_test_init()) to see whether you are in a subprocess.
  *
  * The following example tests that calling
- * <literal>my_object_new(1000000)</literal> will abort with an error
+ * `my_object_new(1000000)` will abort with an error
  * message.
  *
- * |[
+ * |[<!-- language="C" --> 
  *   static void
  *   test_create_large_object_subprocess (void)
  *   {
- *     my_object_new (1000000);
- *   }
+ *     if (g_test_subprocess ())
+ *       {
+ *         my_object_new (1000000);
+ *         return;
+ *       }
  *
- *   static void
- *   test_create_large_object (void)
- *   {
- *     g_test_trap_subprocess ("/myobject/create_large_object/subprocess", 0, 0);
+ *     // Reruns this same test in a subprocess
+ *     g_test_trap_subprocess (NULL, 0, 0);
  *     g_test_trap_assert_failed ();
  *     g_test_trap_assert_stderr ("*ERROR*too large*");
  *   }
@@ -2733,12 +2797,6 @@ g_test_trap_fork (guint64        usec_timeout,
  *
  *     g_test_add_func ("/myobject/create_large_object",
  *                      test_create_large_object);
- *     /&ast; Because of the '/subprocess' in the name, this test will
- *      &ast; not be run by the g_test_run () call below.
- *      &ast;/
- *     g_test_add_func ("/myobject/create_large_object/subprocess",
- *                      test_create_large_object_subprocess);
- *
  *     return g_test_run ();
  *   }
  * ]|
@@ -2759,8 +2817,15 @@ g_test_trap_subprocess (const char           *test_path,
   /* Sanity check that they used GTestSubprocessFlags, not GTestTrapFlags */
   g_assert ((test_flags & (G_TEST_TRAP_INHERIT_STDIN | G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) == 0);
 
-  if (!g_test_suite_case_exists (g_test_get_root (), test_path))
-    g_error ("g_test_trap_subprocess: test does not exist: %s", test_path);
+  if (test_path)
+    {
+      if (!g_test_suite_case_exists (g_test_get_root (), test_path))
+        g_error ("g_test_trap_subprocess: test does not exist: %s", test_path);
+    }
+  else
+    {
+      test_path = test_run_name;
+    }
 
   if (g_test_verbose ())
     g_print ("GTest: subprocess: %s\n", test_path);
@@ -2850,7 +2915,7 @@ g_test_trap_has_passed (void)
 gboolean
 g_test_trap_reached_timeout (void)
 {
-  return test_trap_last_status != G_TEST_STATUS_TIMED_OUT;
+  return test_trap_last_status == G_TEST_STATUS_TIMED_OUT;
 }
 
 void
@@ -3015,9 +3080,11 @@ g_test_log_extract (GTestLogBuffer *tbuffer)
           tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg)));
           return TRUE;
         }
+
+      g_free (msg.nums);
+      g_strfreev (msg.strings);
     }
-  g_free (msg.nums);
-  g_strfreev (msg.strings);
+
   g_error ("corrupt log stream from test program");
   return FALSE;
 }
@@ -3152,7 +3219,7 @@ g_test_build_filename_va (GTestFileType  file_type,
  *
  * In order for this function to work in srcdir != builddir situations,
  * the G_TEST_SRCDIR and G_TEST_BUILDDIR environment variables need to
- * have been defined.  As of 2.38, this is done by the Makefile.decl
+ * have been defined.  As of 2.38, this is done by the glib.mk
  * included in GLib.  Please ensure that your copy is up to date before
  * using this function.
  *
@@ -3179,9 +3246,9 @@ g_test_build_filename_va (GTestFileType  file_type,
  * 'built' terminology that automake uses and are explicitly used to
  * distinguish between the 'srcdir' and 'builddir' being separate.  All
  * files in your project should either be dist (in the
- * <literal>DIST_EXTRA</literal> or <literal>dist_schema_DATA</literal>
+ * `DIST_EXTRA` or `dist_schema_DATA`
  * sense, in which case they will always be in the srcdir) or built (in
- * the <literal>BUILT_SOURCES</literal> sense, in which case they will
+ * the `BUILT_SOURCES` sense, in which case they will
  * always be in the builddir).
  *
  * Note: as a general rule of automake, files that are generated only as