summaryrefslogtreecommitdiff
path: root/tests/test-libglnx-testing.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-libglnx-testing.c')
-rw-r--r--tests/test-libglnx-testing.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/tests/test-libglnx-testing.c b/tests/test-libglnx-testing.c
new file mode 100644
index 0000000..279e0e1
--- /dev/null
+++ b/tests/test-libglnx-testing.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2022 Simon McVittie
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "libglnx-config.h"
+#include "libglnx.h"
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#if GLIB_CHECK_VERSION (2, 38, 0)
+#define GTEST_TAP_OR_VERBOSE "--tap"
+#else
+#define GTEST_TAP_OR_VERBOSE "--verbose"
+#endif
+
+static const char *null = NULL;
+static const char *nonnull = "not null";
+
+static void
+test_assertions (void)
+{
+ const char *other_nonnull = "not null";
+ g_autoptr(GVariant) va = g_variant_ref_sink (g_variant_new ("i", 42));
+ g_autoptr(GVariant) vb = g_variant_ref_sink (g_variant_new ("i", 42));
+ const char * const strv1[] = {"one", "two", NULL};
+ const char * const strv2[] = {"one", "two", NULL};
+ GStatBuf statbuf;
+
+ g_assert_null (null);
+ g_assert_nonnull (nonnull);
+ g_assert_cmpmem (null, 0, null, 0);
+ g_assert_cmpmem (nonnull, strlen (nonnull), other_nonnull, strlen (other_nonnull));
+ g_assert_cmpfloat_with_epsilon (1.0, 1.00001, 0.01);
+ g_assert_cmpvariant (va, vb);
+ g_assert_no_errno (g_stat ("/", &statbuf));
+ g_assert_cmpstrv (NULL, NULL);
+ g_assert_cmpstrv (&null, &null);
+ g_assert_cmpstrv (strv1, strv2);
+}
+
+static void
+test_assertion_failures (void)
+{
+ static const char * const assertion_failures[] =
+ {
+ "nonnull",
+ "null",
+ "mem_null_nonnull",
+ "mem_nonnull_null",
+ "mem_len",
+ "mem_cmp",
+ "cmpfloat_with_epsilon",
+ "cmpvariant",
+ "errno",
+ "cmpstrv_null_nonnull",
+ "cmpstrv_nonnull_null",
+ "cmpstrv_len",
+ "cmpstrv_cmp",
+ };
+ g_autoptr(GError) error = NULL;
+ g_autofree char *self = NULL;
+ g_autofree char *dir = NULL;
+ g_autofree char *exe = NULL;
+ gsize i;
+
+ self = glnx_readlinkat_malloc (-1, "/proc/self/exe", NULL, &error);
+ g_assert_no_error (error);
+
+ dir = g_path_get_dirname (self);
+ exe = g_build_filename (dir, "testing-helper", NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (assertion_failures); i++)
+ {
+ g_autofree char *out = NULL;
+ g_autofree char *err = NULL;
+ g_autofree char *name = g_strdup_printf ("/assertion-failure/%s", assertion_failures[i]);
+ int wait_status = -1;
+ const char *argv[] = { NULL, "assertion-failures", "-p", NULL, NULL, NULL };
+ char *line;
+ char *saveptr = NULL;
+
+ argv[0] = exe;
+ argv[3] = name;
+ argv[4] = GTEST_TAP_OR_VERBOSE;
+ g_test_message ("%s assertion-failures -p %s %s...", exe, name, GTEST_TAP_OR_VERBOSE);
+
+ g_spawn_sync (NULL, /* cwd */
+ (char **) argv,
+ NULL, /* envp */
+ G_SPAWN_DEFAULT,
+ NULL, /* child setup */
+ NULL, /* user data */
+ &out,
+ &err,
+ &wait_status,
+ &error);
+ g_assert_no_error (error);
+
+ g_assert_nonnull (out);
+ g_assert_nonnull (err);
+
+ for (line = strtok_r (out, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stdout: %s", line);
+
+ saveptr = NULL;
+
+ for (line = strtok_r (err, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stderr: %s", line);
+
+ g_test_message ("wait status: 0x%x", wait_status);
+
+ /* It exited with a nonzero status that was not exit status 77 */
+ G_STATIC_ASSERT (WIFEXITED (0));
+ G_STATIC_ASSERT (WEXITSTATUS (0) == 0);
+ g_assert_cmphex (wait_status, !=, 0);
+ G_STATIC_ASSERT (WIFEXITED (77 << 8));
+ G_STATIC_ASSERT (WEXITSTATUS (77 << 8) == 77);
+ g_assert_cmphex (wait_status, !=, (77 << 8));
+ }
+}
+
+static void
+test_failures (void)
+{
+ static const char * const failures[] =
+ {
+ "fail",
+ "fail-printf",
+ };
+ g_autoptr(GError) error = NULL;
+ g_autofree char *self = NULL;
+ g_autofree char *dir = NULL;
+ g_autofree char *exe = NULL;
+ gsize i;
+
+ self = glnx_readlinkat_malloc (-1, "/proc/self/exe", NULL, &error);
+ g_assert_no_error (error);
+
+ dir = g_path_get_dirname (self);
+ exe = g_build_filename (dir, "testing-helper", NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (failures); i++)
+ {
+ g_autofree char *out = NULL;
+ g_autofree char *err = NULL;
+ int wait_status = -1;
+ const char *argv[] = { NULL, NULL, NULL, NULL };
+ char *line;
+ char *saveptr;
+
+ argv[0] = exe;
+ argv[1] = failures[i];
+ argv[2] = GTEST_TAP_OR_VERBOSE;
+ g_test_message ("%s %s %s...", exe, failures[i], GTEST_TAP_OR_VERBOSE);
+
+ g_spawn_sync (NULL, /* cwd */
+ (char **) argv,
+ NULL, /* envp */
+ G_SPAWN_DEFAULT,
+ NULL, /* child setup */
+ NULL, /* user data */
+ &out,
+ &err,
+ &wait_status,
+ &error);
+ g_assert_no_error (error);
+
+ for (line = strtok_r (out, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stdout: %s", line);
+
+ for (line = strtok_r (err, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stderr: %s", line);
+
+ g_test_message ("wait status: 0x%x", wait_status);
+
+ G_STATIC_ASSERT (WIFEXITED (0));
+ G_STATIC_ASSERT (WEXITSTATUS (0) == 0);
+ G_STATIC_ASSERT (WIFEXITED (77 << 8));
+ G_STATIC_ASSERT (WEXITSTATUS (77 << 8) == 77);
+
+ g_assert_cmphex (wait_status, !=, 0);
+ g_assert_cmphex (wait_status, !=, (77 << 8));
+ }
+}
+
+static void
+test_skips (void)
+{
+ static const char * const skips[] =
+ {
+ "skip",
+ "skip-printf",
+ "incomplete",
+ "incomplete-printf",
+ };
+ g_autoptr(GError) error = NULL;
+ g_autofree char *self = NULL;
+ g_autofree char *dir = NULL;
+ g_autofree char *exe = NULL;
+ gsize i;
+
+ self = glnx_readlinkat_malloc (-1, "/proc/self/exe", NULL, &error);
+ g_assert_no_error (error);
+
+ dir = g_path_get_dirname (self);
+ exe = g_build_filename (dir, "testing-helper", NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (skips); i++)
+ {
+ g_autofree char *out = NULL;
+ g_autofree char *err = NULL;
+ int wait_status = -1;
+ const char *argv[] = { NULL, NULL, NULL, NULL };
+ char *line;
+ char *saveptr;
+
+ argv[0] = exe;
+ argv[1] = skips[i];
+ argv[2] = GTEST_TAP_OR_VERBOSE;
+ g_test_message ("%s %s %s...", exe, skips[i], GTEST_TAP_OR_VERBOSE);
+
+ g_spawn_sync (NULL, /* cwd */
+ (char **) argv,
+ NULL, /* envp */
+ G_SPAWN_DEFAULT,
+ NULL, /* child setup */
+ NULL, /* user data */
+ &out,
+ &err,
+ &wait_status,
+ &error);
+ g_assert_no_error (error);
+
+ for (line = strtok_r (out, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stdout: %s", line);
+
+ for (line = strtok_r (err, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stderr: %s", line);
+
+ g_test_message ("wait status: 0x%x", wait_status);
+
+ G_STATIC_ASSERT (WIFEXITED (0));
+ G_STATIC_ASSERT (WEXITSTATUS (0) == 0);
+ G_STATIC_ASSERT (WIFEXITED (77 << 8));
+ G_STATIC_ASSERT (WEXITSTATUS (77 << 8) == 77);
+
+ /* Ideally the exit status is 77, but it might be 0 with older GLib */
+ if (wait_status != 0)
+ g_assert_cmphex (wait_status, ==, (77 << 8));
+ }
+}
+
+static void
+test_successes (void)
+{
+ static const char * const successes[] =
+ {
+ "messages",
+ "pass",
+ "summary",
+ };
+ g_autoptr(GError) error = NULL;
+ g_autofree char *self = NULL;
+ g_autofree char *dir = NULL;
+ g_autofree char *exe = NULL;
+ gsize i;
+
+ self = glnx_readlinkat_malloc (-1, "/proc/self/exe", NULL, &error);
+ g_assert_no_error (error);
+
+ dir = g_path_get_dirname (self);
+ exe = g_build_filename (dir, "testing-helper", NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (successes); i++)
+ {
+ g_autofree char *out = NULL;
+ g_autofree char *err = NULL;
+ int wait_status = -1;
+ const char *argv[] = { NULL, NULL, NULL, NULL };
+ char *line;
+ char *saveptr;
+
+ argv[0] = exe;
+ argv[1] = successes[i];
+ argv[2] = GTEST_TAP_OR_VERBOSE;
+ g_test_message ("%s %s %s...", exe, successes[i], GTEST_TAP_OR_VERBOSE);
+
+ g_spawn_sync (NULL, /* cwd */
+ (char **) argv,
+ NULL, /* envp */
+ G_SPAWN_DEFAULT,
+ NULL, /* child setup */
+ NULL, /* user data */
+ &out,
+ &err,
+ &wait_status,
+ &error);
+ g_assert_no_error (error);
+
+ for (line = strtok_r (out, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stdout: %s", line);
+
+ for (line = strtok_r (err, "\n", &saveptr);
+ line != NULL;
+ line = strtok_r (NULL, "\n", &saveptr))
+ g_test_message ("stderr: %s", line);
+
+ g_test_message ("wait status: 0x%x", wait_status);
+
+ G_STATIC_ASSERT (WIFEXITED (0));
+ G_STATIC_ASSERT (WEXITSTATUS (0) == 0);
+ g_assert_cmphex (wait_status, ==, 0);
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_test_add_func ("/assertions", test_assertions);
+ g_test_add_func ("/assertion_failures", test_assertion_failures);
+ g_test_add_func ("/failures", test_failures);
+ g_test_add_func ("/skips", test_skips);
+ g_test_add_func ("/successes", test_successes);
+ return g_test_run();
+}