| /* -*- 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-spawn.h" |
| #include "dbus-sysdeps.h" |
| #include "dbus-test.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) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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; |
| } |
| |
| 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; |
| } |