diff options
author | Simon McVittie <smcv@collabora.com> | 2018-09-28 15:53:40 +0100 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2019-01-21 15:15:16 +0000 |
commit | 037d19a3282a2ae090d127297708f69b2876f98f (patch) | |
tree | 2a6a6e24f52fb35d14626ad96cf88ce397d96da4 /test | |
parent | d7644b7d4ffd0171891d00e819ef000494dfd63e (diff) | |
download | dbus-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.am | 15 | ||||
-rw-r--r-- | test/internals/spawn-oom.c | 304 |
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); +} |