testing: fix ASAN_OPTIONS
[awesomized/libmemcached] / test / setup.cpp
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;
+}