glib-unix: add function to ensure an fd is sealed
[platform/upstream/glib.git] / glib / gtestutils.c
index bfcc8e1..dede38a 100644 (file)
@@ -59,8 +59,7 @@
  * 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
 
 /**
  * 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().
  *
  * The macro can be turned off in final releases of code by defining
  * `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.
  */
 
 /**
  * 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 compare two strings. If the comparison fails,
  * 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 compare two integers.
  * 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 compare two unsigned integers.
  * 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 compare to unsigned integers.
  * 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 compare two floating point numbers.
  * the correct #GError.
  *
  * The effect of `g_assert_error (err, dom, c)` is
- * the same as `g_assert_true (err != NULL &amp;&amp; err->domain
- * == dom &amp;&amp; err->code == c)`. The advantage of this
+ * 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.
  *
@@ -1479,8 +1493,11 @@ g_test_get_root (void)
  * 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),
- *   77 if all tests were skipped with g_test_skip().
+ *   0 or 77 if all tests were skipped with g_test_skip()
  *
  * Since: 2.16
  */
@@ -1490,6 +1507,11 @@ g_test_run (void)
   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
@@ -2641,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*");
@@ -2677,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)
@@ -2758,7 +2784,7 @@ g_test_trap_fork (guint64        usec_timeout,
  *         return;
  *       }
  *
- *     /&ast; Reruns this same test in a subprocess &ast;/
+ *     // 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*");
@@ -3054,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;
 }