summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2018-09-28 15:53:40 +0100
committerSimon McVittie <smcv@collabora.com>2019-01-21 15:15:16 +0000
commit037d19a3282a2ae090d127297708f69b2876f98f (patch)
tree2a6a6e24f52fb35d14626ad96cf88ce397d96da4 /test
parentd7644b7d4ffd0171891d00e819ef000494dfd63e (diff)
downloaddbus-037d19a3282a2ae090d127297708f69b2876f98f.tar.gz
Convert spawn test into a standalone test executable
This test is sufficiently well-separated that there's no real need to embed it in libdbus. Move it into the test directory instead. Signed-off-by: Simon McVittie <smcv@collabora.com>
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am15
-rw-r--r--test/internals/spawn-oom.c304
2 files changed, 318 insertions, 1 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index 1e7c2db4..f408a168 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -58,8 +58,12 @@ EXTRA_DIST += glib-tap-test.sh
EXTRA_DIST += tap-test.sh.in
TESTS =
+noinst_PROGRAMS =
if DBUS_ENABLE_EMBEDDED_TESTS
+
+uninstallable_test_programs =
+
## break-loader removed for now
## these binaries are used in tests but are not themselves tests
TEST_BINARIES = \
@@ -71,6 +75,10 @@ TEST_BINARIES = \
test-shell-service \
$(NULL)
+if !DBUS_WINCE
+uninstallable_test_programs += test-spawn-oom
+endif
+
## These are conceptually part of directories that come earlier in SUBDIRS
## order, but we don't want to run them til we arrive in this directory,
## since they depend on stuff from this directory. We wrap some of them in a
@@ -85,13 +93,16 @@ endif
TESTS += ../dbus/test-dbus$(EXEEXT)
+noinst_PROGRAMS += $(uninstallable_test_programs)
+TESTS += $(uninstallable_test_programs)
+
else !DBUS_ENABLE_EMBEDDED_TESTS
TEST_BINARIES=
endif !DBUS_ENABLE_EMBEDDED_TESTS
-noinst_PROGRAMS= $(TEST_BINARIES)
+noinst_PROGRAMS += $(TEST_BINARIES)
# This helper is meant to crash, so if we're compiling the rest with
# AddressSanitizer, we need to stop it from catching the SIGSEGV and
@@ -108,6 +119,8 @@ test_shell_SOURCES = shell-test.c
test_shell_LDADD = libdbus-testutils.la
test_spawn_SOURCES = spawn-test.c
test_spawn_LDADD = $(top_builddir)/dbus/libdbus-internal.la
+test_spawn_oom_SOURCES = internals/spawn-oom.c
+test_spawn_oom_LDADD = $(top_builddir)/dbus/libdbus-internal.la
test_assertions_SOURCES = internals/assertions.c
test_assertions_LDADD = libdbus-testutils.la $(GLIB_LIBS)
diff --git a/test/internals/spawn-oom.c b/test/internals/spawn-oom.c
new file mode 100644
index 00000000..8551effe
--- /dev/null
+++ b/test/internals/spawn-oom.c
@@ -0,0 +1,304 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-spawn-test.c
+ *
+ * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include <config.h>
+
+#include "dbus/dbus-internals.h"
+#include "dbus/dbus-spawn.h"
+#include "dbus/dbus-sysdeps.h"
+#include "dbus/dbus-test.h"
+#include "dbus/dbus-test-wrappers.h"
+
+static char *
+get_test_exec (const char *exe,
+ DBusString *scratch_space)
+{
+ const char *dbus_test_exec;
+
+ dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
+
+ if (dbus_test_exec == NULL)
+ return NULL;
+
+ if (!_dbus_string_init (scratch_space))
+ return NULL;
+
+ if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
+ dbus_test_exec, exe, DBUS_EXEEXT))
+ {
+ _dbus_string_free (scratch_space);
+ return NULL;
+ }
+
+ return _dbus_string_get_data (scratch_space);
+}
+
+static dbus_bool_t
+check_spawn_nonexistent (void *data,
+ dbus_bool_t have_memory)
+{
+ static const char arg_does_not_exist[] = "/this/does/not/exist/32542sdgafgafdg";
+
+ const char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+
+ /*** Test launching nonexistent binary */
+
+ argv[0] = arg_does_not_exist;
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent",
+ (char * const *) argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_block_for_child_exit (sitter);
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error launching nonexistent executable");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
+ {
+ _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_segfault (void *data,
+ dbus_bool_t have_memory)
+{
+ char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusString argv0;
+
+ /*** Test launching segfault binary */
+
+ argv[0] = get_test_exec ("test-segfault", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
+ return TRUE;
+ }
+
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_block_for_child_exit (sitter);
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ _dbus_string_free (&argv0);
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error launching segfaulting binary");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+#ifdef DBUS_WIN
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+#else
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
+#endif
+ {
+ _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_exit (void *data,
+ dbus_bool_t have_memory)
+{
+ char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusString argv0;
+
+ /*** Test launching exit failure binary */
+
+ argv[0] = get_test_exec ("test-exit", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
+ return TRUE;
+ }
+
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_block_for_child_exit (sitter);
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ _dbus_string_free (&argv0);
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error launching binary that exited with failure code");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+ {
+ _dbus_warn ("Not expecting error when launching exiting executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_and_kill (void *data,
+ dbus_bool_t have_memory)
+{
+ char *argv[4] = { NULL, NULL, NULL, NULL };
+ DBusBabysitter *sitter = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusString argv0;
+
+ /*** Test launching sleeping binary then killing it */
+
+ argv[0] = get_test_exec ("test-sleep-forever", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
+ return TRUE;
+ }
+
+ if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
+ NULL, DBUS_SPAWN_NONE, NULL, NULL,
+ &error))
+ {
+ _dbus_babysitter_kill_child (sitter);
+
+ _dbus_babysitter_block_for_child_exit (sitter);
+
+ _dbus_babysitter_set_child_exit_error (sitter, &error);
+ }
+
+ _dbus_string_free (&argv0);
+
+ if (sitter)
+ _dbus_babysitter_unref (sitter);
+
+ if (!dbus_error_is_set (&error))
+ {
+ _dbus_warn ("Did not get an error after killing spawned binary");
+ return FALSE;
+ }
+
+ if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+#ifdef DBUS_WIN
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+#else
+ dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
+#endif
+ {
+ _dbus_warn ("Not expecting error when killing executable: %s: %s",
+ error.name, error.message);
+ dbus_error_free (&error);
+ return FALSE;
+ }
+
+ dbus_error_free (&error);
+
+ return TRUE;
+}
+
+static dbus_bool_t
+_dbus_spawn_test (const char *test_data_dir)
+{
+ if (!_dbus_test_oom_handling ("spawn_nonexistent",
+ check_spawn_nonexistent,
+ NULL))
+ return FALSE;
+
+ if (!_dbus_test_oom_handling ("spawn_segfault",
+ check_spawn_segfault,
+ NULL))
+ return FALSE;
+
+ if (!_dbus_test_oom_handling ("spawn_exit",
+ check_spawn_exit,
+ NULL))
+ return FALSE;
+
+ if (!_dbus_test_oom_handling ("spawn_and_kill",
+ check_spawn_and_kill,
+ NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+static DBusTestCase test = { "spawn", _dbus_spawn_test };
+
+int
+main (int argc,
+ char **argv)
+{
+ return _dbus_test_main (argc, argv, 1, &test,
+ DBUS_TEST_FLAGS_CHECK_MEMORY_LEAKS,
+ NULL, NULL);
+}