testing: fix ASAN_OPTIONS
authorMichael Wallner <mike@php.net>
Wed, 30 Sep 2020 10:00:35 +0000 (12:00 +0200)
committerMichael Wallner <mike@php.net>
Wed, 30 Sep 2020 10:00:35 +0000 (12:00 +0200)
test/main.cpp
test/setup.cpp [new file with mode: 0644]
test/setup.hpp [new file with mode: 0644]

index 2908745b909ead26a9fda56ed1c2ed3d0afa3acc..34513e542375663a229227904aa71a8767dfcf42 100644 (file)
@@ -1,24 +1,8 @@
 #define CATCH_CONFIG_RUNNER
 #include "lib/catch.hpp"
-#include "mem_config.h"
-#include <cstdlib>
-
-#if HAVE_SETENV
-# define SET_ENV(n, k, v) setenv(k, v, 0);
-#else // !HAVE_SETENV
-# define SET_ENV(n, k, v) static char n ## _env[] = k "=" v; putenv(n ## _env)
-#endif
+#include "setup.hpp"
 
 int main(int argc, char *argv[]) {
-
-#if HAVE_ASAN
-  SET_ENV(asan, "ASAN_OPTIONS", "halt_on_error=0")
-#endif
-
-#if LIBMEMCACHED_WITH_SASL_SUPPORT
-  SET_ENV(sasl_pwdb, "MEMCACHED_SASL_PWDB", LIBMEMCACHED_WITH_SASL_PWDB);
-  SET_ENV(sasl_conf, "SASL_CONF_PATH", LIBMEMCACHED_WITH_SASL_CONF);
-#endif
-
+  setup(argc, &argv);
   return Catch::Session().run(argc, argv);
 }
diff --git a/test/setup.cpp b/test/setup.cpp
new file mode 100644 (file)
index 0000000..1f4c9a4
--- /dev/null
@@ -0,0 +1,91 @@
+#include "mem_config.h"
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <csignal>
+#include <iostream>
+#include <string>
+#include <unistd.h>
+
+#if HAVE_SETENV
+# define SET_ENV(n, k, v) setenv(k, v, 0)
+#else // !HAVE_SETENV
+# define SET_ENV(n, k, v) static char n ## _env[] = k "=" v; putenv(n ## _env)
+#endif
+
+static void sigchld(int, siginfo_t *si, void *) {
+  switch (si->si_code) {
+  case CLD_EXITED:
+    // expected
+    break;
+  case CLD_KILLED:
+    if (si->si_status == SIGKILL) {
+      // expected
+      break;
+    }
+    [[fallthrough]];
+  case CLD_DUMPED:
+    std::cerr << "Server{pid="
+              << std::to_string(si->si_pid)
+              << "} died: "
+              << strsignal(si->si_status)
+              << std::endl;
+    break;
+  }
+}
+
+static inline void setup_signals() {
+  struct sigaction sa;
+
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_flags = SA_NOCLDSTOP | SA_RESTART | SA_SIGINFO | SA_NODEFER;
+
+  sa.sa_sigaction = sigchld;
+  if (0 > sigaction(SIGCHLD, &sa, nullptr)) {
+    perror("sigaction(CHLD)");
+  }
+}
+
+#if HAVE_ASAN
+// this has to be a macro for putenv() to work
+# define ASAN_OPTIONS \
+    "check_initialization_order=1," \
+    "replace_str=1," \
+    "replace_intrin=1," \
+    "detect_stack_use_after_return=1," \
+    "alloc_dealloc_mismatch=1," \
+    "new_delete_type_mismatch=1," \
+    "detect_odr_violation=2," \
+    "halt_on_error=0," \
+    "verify_asan_link_order=1," \
+    "abort_on_error=0," \
+    ""
+static inline void setup_asan(char **argv) {
+  const auto set = getenv("ASAN_OPTIONS");
+
+  if (!set || !*set) {
+    SET_ENV(asan, "ASAN_OPTIONS", ASAN_OPTIONS);
+    execvp(argv[0], argv);
+    perror("exec()");
+  }
+}
+#else
+# define setup_asan(a)
+#endif
+
+#if LIBMEMCACHED_WITH_SASL_SUPPORT
+static inline void setup_sasl() {
+  SET_ENV(sasl_pwdb, "MEMCACHED_SASL_PWDB", LIBMEMCACHED_WITH_SASL_PWDB);
+  SET_ENV(sasl_conf, "SASL_CONF_PATH", LIBMEMCACHED_WITH_SASL_CONF);
+}
+#else
+# define setup_sasl()
+#endif
+
+int setup(int &, char ***argv) {
+  setup_signals();
+  setup_asan(*argv);
+  setup_sasl();
+
+  return 0;
+}
diff --git a/test/setup.hpp b/test/setup.hpp
new file mode 100644 (file)
index 0000000..cb008a5
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+int setup(int &argc, char ***argv);