tests: Add torture library from socket_wrapper
authorJakub Hrozek <jakub.hrozek@gmail.com>
Fri, 12 Sep 2014 12:49:16 +0000 (14:49 +0200)
committerMichael Adam <obnox@samba.org>
Tue, 21 Oct 2014 11:39:39 +0000 (13:39 +0200)
Pretty much a blatant copy of the torture library from socket_wrapper,
just s/echo_srv/dns_srv/

Signed-off-by: Jakub Hrozek <jakub.hrozek@gmail.com>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
tests/CMakeLists.txt
tests/torture.c [new file with mode: 0644]
tests/torture.h [new file with mode: 0644]

index adc348f42df60032ac5567e3e5ea55dbfbcbb13a..06a3800405c13472b83a528659981c74d2afbfba 100644 (file)
@@ -7,17 +7,25 @@ include_directories(
   ${CMOCKA_INCLUDE_DIR}
 )
 
+set(TORTURE_LIBRARY torture)
+
 # A simple DNS server for testing
 add_executable(dns_srv dns_srv.c)
 target_link_libraries(dns_srv ${RWRAP_REQUIRED_LIBRARIES})
 
+add_library(${TORTURE_LIBRARY} STATIC torture.c)
+target_link_libraries(${TORTURE_LIBRARY}
+    ${CMOCKA_LIBRARY}
+    ${SWRAP_REQUIRED_LIBRARIES})
+
+
 set(TESTSUITE_LIBRARIES ${RWRAP_REQUIRED_LIBRARIES} ${CMOCKA_LIBRARY})
 
 set(RWRAP_TESTS
     test_res_init)
 
 foreach(_RWRAP_TEST ${RWRAP_TESTS})
-    add_cmocka_test(${_RWRAP_TEST} ${_RWRAP_TEST}.c ${TESTSUITE_LIBRARIES})
+    add_cmocka_test(${_RWRAP_TEST} ${_RWRAP_TEST}.c ${TORTURE_LIBRARY} ${TESTSUITE_LIBRARIES})
 
     if (OSX)
         set_property(
diff --git a/tests/torture.c b/tests/torture.c
new file mode 100644 (file)
index 0000000..402eb53
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "torture.h"
+
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdbool.h>
+
+#define TORTURE_DNS_SRV_IPV4 "127.0.0.10"
+/* socket wrapper IPv6 prefix  fd00::5357:5fxx */
+#define TORTURE_DNS_SRV_IPV6 "fd00::5357:5f0a"
+#define TORTURE_DNS_SRV_PORT 53
+
+#define TORTURE_SOCKET_DIR "/tmp/test_socket_wrapper_XXXXXX"
+#define TORTURE_DNS_SRV_PIDFILE "dns_srv.pid"
+#define TORTURE_PCAP_FILE "socket_trace.pcap"
+
+const char *torture_server_address(int family)
+{
+       switch (family) {
+       case AF_INET: {
+               const char *ip4 = getenv("TORTURE_SERVER_ADDRESS_IPV4");
+
+               if (ip4 != NULL && ip4[0] != '\0') {
+                       return ip4;
+               }
+
+               return TORTURE_DNS_SRV_IPV4;
+       }
+#ifdef HAVE_IPV6
+       case AF_INET6: {
+               const char *ip6 = getenv("TORTURE_SERVER_ADDRESS_IPV6");
+
+               if (ip6 != NULL && ip6[0] != '\0') {
+                       return ip6;
+               }
+
+               return TORTURE_DNS_SRV_IPV6;
+       }
+#endif
+       default:
+               return NULL;
+       }
+
+       return NULL;
+}
+
+int torture_server_port(void)
+{
+       char *env = getenv("TORTURE_SERVER_PORT");
+
+       if (env != NULL && env[0] != '\0' && strlen(env) < 6) {
+               int port = atoi(env);
+
+               if (port > 0 && port < 65536) {
+                       return port;
+               }
+       }
+
+       return TORTURE_DNS_SRV_PORT;
+}
+
+void torture_setup_socket_dir(void **state)
+{
+       struct torture_state *s;
+       const char *p;
+       size_t len;
+
+       s = malloc(sizeof(struct torture_state));
+       assert_non_null(s);
+
+       s->socket_dir = strdup(TORTURE_SOCKET_DIR);
+       assert_non_null(s->socket_dir);
+
+       p = mkdtemp(s->socket_dir);
+       assert_non_null(p);
+
+       /* pcap file */
+       len = strlen(p) + 1 + strlen(TORTURE_PCAP_FILE) + 1;
+
+       s->pcap_file = malloc(len);
+       assert_non_null(s->pcap_file);
+
+       snprintf(s->pcap_file, len, "%s/%s", p, TORTURE_PCAP_FILE);
+
+       /* pid file */
+       len = strlen(p) + 1 + strlen(TORTURE_DNS_SRV_PIDFILE) + 1;
+
+       s->srv_pidfile = malloc(len);
+       assert_non_null(s->srv_pidfile);
+
+       snprintf(s->srv_pidfile, len, "%s/%s", p, TORTURE_DNS_SRV_PIDFILE);
+
+       setenv("SOCKET_WRAPPER_DIR", p, 1);
+       setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "170", 1);
+       setenv("SOCKET_WRAPPER_PCAP_FILE", s->pcap_file, 1);
+
+       *state = s;
+}
+
+static void torture_setup_dns_srv_ip(void **state,
+                                    const char *ip,
+                                    int port)
+{
+       struct torture_state *s;
+       char start_dns_srv[1024] = {0};
+       int count = 0;
+       int rc;
+
+       torture_setup_socket_dir(state);
+
+       s = (struct torture_state *) *state;
+
+       /* set default iface for the server */
+       setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
+
+       snprintf(start_dns_srv, sizeof(start_dns_srv),
+                "%s/tests/dns_srv -b %s -p %d -D --pid %s",
+                BINARYDIR, ip, port, s->srv_pidfile);
+
+       rc = system(start_dns_srv);
+       assert_int_equal(rc, 0);
+
+       do {
+               struct stat sb;
+
+               count++;
+               if (count > 100) {
+                       break;
+               }
+
+               rc = stat(s->srv_pidfile, &sb);
+               usleep(50);
+       } while (rc != 0);
+       assert_int_equal(rc, 0);
+
+       /* set default iface for the client */
+       setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "170", 1);
+}
+
+void torture_setup_dns_srv_ipv4(void **state)
+{
+       torture_setup_dns_srv_ip(state,
+                                "0.0.0.0",
+                                torture_server_port());
+}
+
+void torture_setup_dns_srv_ipv6(void **state)
+{
+       torture_setup_dns_srv_ip(state,
+                                "::",
+                                torture_server_port());
+}
+
+void torture_teardown_socket_dir(void **state)
+{
+       struct torture_state *s = (struct torture_state *) *state;
+       char *env = getenv("TORTURE_SKIP_CLEANUP");
+       char remove_cmd[1024] = {0};
+       int rc;
+
+       if (env != NULL && env[0] == '1') {
+               fprintf(stderr, ">>> Skipping cleanup of %s", s->socket_dir);
+       } else {
+               snprintf(remove_cmd, sizeof(remove_cmd), "rm -rf %s", s->socket_dir);
+
+               rc = system(remove_cmd);
+               if (rc < 0) {
+                       fprintf(stderr, "%s failed: %s", remove_cmd, strerror(errno));
+               }
+       }
+
+       free(s->socket_dir);
+       free(s->pcap_file);
+       free(s->srv_pidfile);
+       free(s);
+}
+
+void torture_teardown_dns_srv(void **state)
+{
+       struct torture_state *s = (struct torture_state *) *state;
+       char buf[8] = {0};
+       long int tmp;
+       ssize_t rc;
+       pid_t pid;
+       int fd;
+       bool is_running = true;
+       int count;
+
+       /* read the pidfile */
+       fd = open(s->srv_pidfile, O_RDONLY);
+       if (fd < 0) {
+               goto done;
+       }
+
+       rc = read(fd, buf, sizeof(buf));
+       close(fd);
+       if (rc <= 0) {
+               goto done;
+       }
+
+       buf[sizeof(buf) - 1] = '\0';
+
+       tmp = strtol(buf, NULL, 10);
+       if (tmp == 0 || tmp > 0xFFFF || errno == ERANGE) {
+               goto done;
+       }
+
+       pid = (pid_t)(tmp & 0xFFFF);
+
+       /* Make sure the daemon goes away! */
+       for (count = 0; count < 10; count++) {
+               kill(pid, SIGTERM);
+
+               usleep(100);
+
+               rc = kill(pid, 0);
+               if (rc != 0) {
+                       is_running = false;
+                       break;
+               }
+       }
+
+       if (is_running) {
+               fprintf(stderr,
+                       "WARNING the DNS server is still running!\n");
+       }
+
+done:
+       torture_teardown_socket_dir(state);
+}
+
+void torture_generate_random_buffer(uint8_t *out, int len)
+{
+       int i;
+
+       srand(time(NULL));
+
+       for (i = 0; i < len; i++) {
+               out[i] = (uint8_t)rand();
+       }
+}
diff --git a/tests/torture.h b/tests/torture.h
new file mode 100644 (file)
index 0000000..a82fba9
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _TORTURE_H
+#define _TORTURE_H
+
+#include "config.h"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <stdint.h>
+#include <string.h>
+
+struct torture_address {
+       socklen_t sa_socklen;
+       union {
+               struct sockaddr s;
+               struct sockaddr_in in;
+#ifdef HAVE_IPV6
+               struct sockaddr_in6 in6;
+#endif
+               struct sockaddr_un un;
+               struct sockaddr_storage ss;
+       } sa;
+};
+
+struct torture_state {
+       char *socket_dir;
+       char *pcap_file;
+       char *srv_pidfile;
+};
+
+#ifndef ZERO_STRUCT
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+#endif
+
+const char *torture_server_address(int domain);
+int torture_server_port(void);
+
+void torture_setup_socket_dir(void **state);
+void torture_setup_dns_srv_ipv4(void **state);
+void torture_setup_dns_srv_ipv6(void **state);
+
+void torture_teardown_socket_dir(void **state);
+void torture_teardown_dns_srv(void **state);
+
+void torture_generate_random_buffer(uint8_t *out, int len);
+#endif /* _TORTURE_H */
+