diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2020-03-26 06:52:39 +0000 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2020-03-26 15:43:10 +0000 |
commit | eeb56202603affbfcb8e0c0bb37fc4270c240b58 (patch) | |
tree | 99d8d04c242b1acef9d6092e20baf403c053f1ec | |
parent | 7b0435ef66af088c1a1be20b6bc6b0fcb76e4e1a (diff) |
test-termination: Check daemon terminates correctly sending SIGTERM
Check for https://gitlab.freedesktop.org/spice/linux/vd_agent/issues/18.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Victor Toso <victortoso@redhat.com>
-rw-r--r-- | .gitlab-ci.yml | 2 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | tests/test-termination.c | 143 |
3 files changed, 146 insertions, 1 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 279c6f3..8884309 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ variables: bzip2 python3-pyparsing meson ninja-build gtk-doc glib2-devel gettext gettext-devel libpciaccess-devel alsa-lib-devel libXfixes-devel libX11-devel libXrandr-devel libXinerama-devel - gtk3-devel dbus-devel systemd-devel + gtk3-devel dbus-devel systemd-devel procps-ng before_script: - dnf install -y $DEPS_COMMON diff --git a/Makefile.am b/Makefile.am index 787f158..2abb5ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -171,3 +171,5 @@ tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD) tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS) check_PROGRAMS += tests/test-device-info + +check_PROGRAMS += tests/test-termination diff --git a/tests/test-termination.c b/tests/test-termination.c new file mode 100644 index 0000000..5f9f221 --- /dev/null +++ b/tests/test-termination.c @@ -0,0 +1,143 @@ +/* test-termination.c tests program terminates correctly sending SIGTERM + * + * Copyright 2020 Red Hat, Inc. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> + +static pid_t child_pid; +static char socket_name[1024 + 64]; + +static void cleanup(void) +{ + if (child_pid) { + kill(child_pid, SIGKILL); + } + if (socket_name[0]) { + unlink(socket_name); + } +} + +static void handle_alarm(int sig) +{ + fprintf(stderr, "Alarm reached!\n"); + exit(1); +} + +static void check(int line, const char *cond_str, int cond_value) +{ + if (!cond_value) { + alarm(0); + fprintf(stderr, "%d: Check %s failed!\n", line, cond_str); + exit(1); + } +} +#define check(cond) check(__LINE__, #cond, cond) + +static pid_t get_daemon_pid(void) +{ + pid_t res = 0; + FILE *f = popen("ps -ef", "r"); + check(f != NULL); + char line[1024]; + while (fgets(line, sizeof(line), f)) { + if (strstr(line, socket_name) != NULL) { + int pid; + check(sscanf(line, "%*s %d", &pid) == 1); + res = pid; + } + } + pclose(f); + return res; +} + +int main(int argc, char **argv) +{ + atexit(cleanup); + + // create new filename for the socket + char cwd[1024]; + check(getcwd(cwd, sizeof(cwd)) != NULL); + snprintf(socket_name, sizeof(socket_name), "%s/sock-%u", cwd, (unsigned) getpid()); + + // daemon should not exist now + check(get_daemon_pid() == 0); + + // launch daemon with -S + int pipes[2]; + check(pipe(pipes) == 0); + child_pid = fork(); + check(child_pid != -1); + if (child_pid == 0) { + close(pipes[0]); + execl("src/spice-vdagentd", "spice-vdagentd", "-S", socket_name, NULL); + fprintf(stderr, "Error launching agent\n"); + return 1; + } + close(pipes[1]); + pipes[1] = -1; + + // test child exits with success after a bit (wait timed) + int status; + signal(SIGALRM, handle_alarm); + alarm(1); + check(waitpid(child_pid, &status, 0) == child_pid); + alarm(0); + check(WIFEXITED(status) != 0); + check(WEXITSTATUS(status) == 0); + child_pid = 0; + + // test child created the socket passed + struct stat sb; + check(stat(socket_name, &sb) == 0); + check((sb.st_mode & S_IFMT) == S_IFSOCK); + + // child should have created the daemon + child_pid = get_daemon_pid(); + check(child_pid != 0); + + // wait a bit (1 second) and test daemon is still there, not failed some initialization + sleep(1); + check(get_daemon_pid() != 0); + + // send a SIGTERM, process should close in a bit + kill(child_pid, SIGTERM); + + // test daemon exits after a while, we use the pipe we created above to + // check if daemon closed + alarm(1); + check(read(pipes[0], cwd, sizeof(cwd)) == 0); + alarm(0); + check(get_daemon_pid() == 0); + + // test the socket disappeared, so we know the program exited successful + check(stat(socket_name, &sb) == -1); + check(errno == ENOENT); + + // don't send a SIGKILL to a not existing process + child_pid = 0; + + return 0; +} |