]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: test-http-client-errors - Use the new sub-process test API.
authorStephan Bosch <stephan.bosch@open-xchange.com>
Mon, 6 Apr 2020 22:14:40 +0000 (00:14 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 22 May 2020 08:42:33 +0000 (08:42 +0000)
This makes an effort to terminate server processes gracefully. Killing them
bluntly hampers test coverage measurement and valgrind testing.

src/lib-http/test-http-client-errors.c

index f4949702b138d371e855f8acf8c1366a31109bdc..b76418c40245ab28d1cc0f64537d9dc417d06f70 100644 (file)
@@ -1,7 +1,6 @@
 /* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "lib-signals.h"
 #include "str.h"
 #include "str-sanitize.h"
 #include "hostpid.h"
 #include "sleep.h"
 #include "connection.h"
 #include "test-common.h"
+#include "test-subprocess.h"
 #include "http-url.h"
 #include "http-request.h"
 #include "http-client.h"
 
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
 #include <unistd.h>
 
 #define CLIENT_PROGRESS_TIMEOUT     10
+#define SERVER_KILL_TIMEOUT_SECS    20
+
+static void main_deinit(void);
 
 /*
  * Types
@@ -51,14 +51,9 @@ static in_port_t *bind_ports = 0;
 static struct ioloop *ioloop;
 static bool debug = FALSE;
 
-/* dns */
-static pid_t dns_pid = (pid_t)-1;
-
 /* server */
 static struct io *io_listen;
 static int fd_listen = -1;
-static pid_t *server_pids = NULL;
-static unsigned int server_pids_count = 0;
 static struct connection_list *server_conn_list;
 static size_t server_read_max = 0;
 static unsigned int server_index;
@@ -2913,8 +2908,10 @@ static void test_reconnect_failure_input(struct server_connection *conn)
                "Everything is OK\r\n";
 
        o_stream_nsend_str(conn->conn.output, resp);
+       io_loop_stop(current_ioloop);
+       io_remove(&io_listen);
        i_close_fd(&fd_listen);
-       i_sleep_intr_secs(500);
+       server_connection_deinit(&conn);
 }
 
 static void test_server_reconnect_failure(unsigned int index)
@@ -3369,6 +3366,11 @@ static void test_server_run(unsigned int index)
  * Tests
  */
 
+struct test_server_data {
+       unsigned int index;
+       test_server_init_t server_test;
+};
+
 static int test_open_server_fd(in_port_t *bind_port)
 {
        int fd = net_listen(&bind_ip, bind_port, 128);
@@ -3381,44 +3383,27 @@ static int test_open_server_fd(in_port_t *bind_port)
        return fd;
 }
 
-static void test_servers_kill_forced(void)
+static int test_run_server(struct test_server_data *data)
 {
-       unsigned int i;
-
-       if (server_pids_count > 0) {
-               for (i = 0; i < server_pids_count; i++) {
-                       if (server_pids[i] != (pid_t)-1) {
-                               (void)kill(server_pids[i], SIGKILL);
-                               (void)waitpid(server_pids[i], NULL, 0);
-                               server_pids[i] = -1;
-                       }
-               }
-       }
-       server_pids_count = 0;
-
-       if (dns_pid != (pid_t)-1) {
-               (void)kill(dns_pid, SIGKILL);
-               (void)waitpid(dns_pid, NULL, 0);
-               dns_pid = (pid_t)-1;
-       }
-}
-
-static void test_run_server(unsigned int index, test_server_init_t server_test)
-{
-       i_set_failure_prefix("SERVER[%u]: ", index + 1);
+       i_set_failure_prefix("SERVER[%u]: ", data->index + 1);
 
        if (debug)
                i_debug("PID=%s", my_pid);
 
        ioloop = io_loop_create();
-       server_test(index);
+       data->server_test(data->index);
        io_loop_destroy(&ioloop);
 
+       if (debug)
+               i_debug("Terminated");
+
        i_close_fd(&fd_listen);
        i_free(bind_ports);
+       main_deinit();
+       return 0;
 }
 
-static void test_run_dns(test_dns_init_t dns_test)
+static int test_run_dns(test_dns_init_t dns_test)
 {
        i_set_failure_prefix("DNS: ");
 
@@ -3429,8 +3414,13 @@ static void test_run_dns(test_dns_init_t dns_test)
        dns_test();
        io_loop_destroy(&ioloop);
 
+       if (debug)
+               i_debug("Terminated");
+
        i_close_fd(&fd_listen);
        i_free(bind_ports);
+       main_deinit();
+       return 0;
 }
 
 static void
@@ -3447,6 +3437,9 @@ test_run_client(const struct http_client_settings *client_set,
        ioloop = io_loop_create();
        test_client_run(client_test, client_set);
        io_loop_destroy(&ioloop);
+
+       if (debug)
+               i_debug("Terminated");
 }
 
 static void
@@ -3458,50 +3451,27 @@ test_run_client_server(const struct http_client_settings *client_set,
 {
        unsigned int i;
 
-       server_pids = NULL;
-       server_pids_count = 0;
-
        test_server_init = NULL;
        test_server_deinit = NULL;
        test_server_input = NULL;
 
-       lib_signals_ioloop_detach();
-
        if (server_tests_count > 0) {
                int fds[server_tests_count];
 
                bind_ports = i_new(in_port_t, server_tests_count);
-
-               server_pids = i_new(pid_t, server_tests_count);
-               for (i = 0; i < server_tests_count; i++)
-                       server_pids[i] = (pid_t)-1;
-               server_pids_count = server_tests_count;
-
                for (i = 0; i < server_tests_count; i++)
                        fds[i] = test_open_server_fd(&bind_ports[i]);
 
                for (i = 0; i < server_tests_count; i++) {
+                       struct test_server_data data;
+
+                       i_zero(&data);
+                       data.index = i;
+                       data.server_test = server_test;
+
+                       /* Fork server */
                        fd_listen = fds[i];
-                       if ((server_pids[i] = fork()) == (pid_t)-1)
-                               i_fatal("fork() failed: %m");
-                       if (server_pids[i] == 0) {
-                               server_pids[i] = (pid_t)-1;
-                               server_pids_count = 0;
-                               hostpid_init();
-                               lib_signals_deinit();
-
-                               /* child: server */
-                               test_run_server(i, server_test);
-
-                               i_close_fd(&fd_listen);
-                               i_free(bind_ports);
-                               i_free(server_pids);
-                               /* wait for it to be killed; this way, valgrind
-                                  will not object to this process going away
-                                  inelegantly. */
-                               i_sleep_intr_secs(60);
-                               exit(1);
-                       }
+                       test_subprocess_fork(test_run_server, &data, FALSE);
                        i_close_fd(&fd_listen);
                }
        }
@@ -3515,34 +3485,17 @@ test_run_client_server(const struct http_client_settings *client_set,
                        i_fatal("listen(./dns-test) failed: %m");
                }
 
+               /* Fork DNS service */
                fd_listen = fd;
-               if ((dns_pid = fork()) == (pid_t)-1)
-                       i_fatal("fork() failed: %m");
-               if (dns_pid == 0) {
-                       dns_pid = (pid_t)-1;
-                       hostpid_init();
-                       lib_signals_deinit();
-
-                       /* child: server */
-                       test_run_dns(dns_test);
-
-                       i_close_fd(&fd_listen);
-                       /* wait for it to be killed; this way, valgrind will not
-                          object to this process going away inelegantly. */
-                       i_sleep_intr_secs(60);
-                       exit(1);
-               }
+               test_subprocess_fork(test_run_dns, dns_test, FALSE);
                i_close_fd(&fd_listen);
        }
 
-       lib_signals_ioloop_attach();
-
-       /* parent: client */
+       /* Run client */
        test_run_client(client_set, client_test);
 
        i_unset_failure_prefix();
-       test_servers_kill_forced();
-       i_free(server_pids);
+       test_subprocess_kill_all(SERVER_KILL_TIMEOUT_SECS);
        i_free(bind_ports);
 
        i_unlink_if_exists("./dns-test");
@@ -3552,44 +3505,14 @@ test_run_client_server(const struct http_client_settings *client_set,
  * Main
  */
 
-volatile sig_atomic_t terminating = 0;
-
-static void test_signal_handler(const siginfo_t *si, void *context ATTR_UNUSED)
-{
-       int signo = si->si_signo;
-
-       if (terminating != 0)
-               raise(signo);
-       terminating = 1;
-
-       /* make sure we don't leave any pesky children alive */
-       test_servers_kill_forced();
-
-       (void)signal(signo, SIG_DFL);
-       raise(signo);
-}
-
-static void test_atexit(void)
-{
-       test_servers_kill_forced();
-}
-
 static void main_init(void)
 {
-       lib_signals_init();
-
-       atexit(test_atexit);
-       lib_signals_ignore(SIGPIPE, TRUE);
-       lib_signals_set_handler(SIGTERM, 0, test_signal_handler, NULL);
-       lib_signals_set_handler(SIGQUIT, 0, test_signal_handler, NULL);
-       lib_signals_set_handler(SIGINT, 0, test_signal_handler, NULL);
-       lib_signals_set_handler(SIGSEGV, 0, test_signal_handler, NULL);
-       lib_signals_set_handler(SIGABRT, 0, test_signal_handler, NULL);
+       /* nothing yet */
 }
 
 static void main_deinit(void)
 {
-       lib_signals_deinit();
+       /* nothing yet; also called from sub-processes */
 }
 
 int main(int argc, char *argv[])
@@ -3610,6 +3533,8 @@ int main(int argc, char *argv[])
                }
        }
 
+       test_subprocesses_init(debug);
+
        /* listen on localhost */
        i_zero(&bind_ip);
        bind_ip.family = AF_INET;
@@ -3617,6 +3542,7 @@ int main(int argc, char *argv[])
 
        ret = test_run(test_functions);
 
+       test_subprocesses_deinit();
        main_deinit();
        lib_deinit();