15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <poll.h>
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <signal.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/resource.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/third_party/valgrind/valgrind.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "build/build_config.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/tests/unit_tests.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string TestFailedMessage(const std::string& msg) {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return msg.empty() ? std::string() : "Actual test failure: " + msg;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetSubProcessTimeoutTimeInSeconds() {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 10s ought to be enough for anybody.
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 10;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the number of threads of the current process or -1.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int CountThreads() {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct stat task_stat;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int task_d = stat("/proc/self/task", &task_stat);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // task_stat.st_nlink should be the number of tasks + 2 (accounting for
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // "." and "..".
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (task_d != 0 || task_stat.st_nlink < 3)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int num_threads = task_stat.st_nlink - 2;
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return num_threads;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IsAndroid() {
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_ANDROID)
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#else
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IsArchitectureArm() {
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(ARCH_CPU_ARM_FAMILY)
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#else
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// TODO(jln): figure out why base/.../dynamic_annotations.h's
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// RunningOnValgrind() cannot link.
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IsRunningOnValgrind() {
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return RUNNING_ON_VALGRIND;
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kExpectedValue = 42;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kIgnoreThisTest = 43;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kExitWithAssertionFailure = 1;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kExitForTimeout = 2;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void SigAlrmHandler(int) {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char failure_message[] = "Timeout reached!\n";
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure that we never block here.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!fcntl(2, F_SETFL,  O_NONBLOCK)) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (write(2, failure_message, sizeof(failure_message) - 1) < 0) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    _exit(kExitForTimeout);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Set a timeout with a handler that will automatically fail the
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// test.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void SetProcessTimeout(int time_in_seconds) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct sigaction act = {};
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  act.sa_handler = SigAlrmHandler;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(sigemptyset(&act.sa_mask) == 0);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  act.sa_flags = 0;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct sigaction old_act;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(sigaction(SIGALRM, &act, &old_act) == 0);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We don't implemenet signal chaining, so make sure that nothing else
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is expecting to handle SIGALRM.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT((old_act.sa_flags & SA_SIGINFO) == 0);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(old_act.sa_handler == SIG_DFL);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sigset_t sigalrm_set;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(sigemptyset(&sigalrm_set) == 0);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(sigaddset(&sigalrm_set, SIGALRM) == 0);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(sigprocmask(SIG_UNBLOCK, &sigalrm_set, NULL) == 0);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(alarm(time_in_seconds) == 0);  // There should be no previous
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                // alarm.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Runs a test in a sub-process. This is necessary for most of the code
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// in the BPF sandbox, as it potentially makes global state changes and as
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// it also tends to raise fatal errors, if the code has been used in an
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// insecure manner.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UnitTests::RunTestInProcess(UnitTests::Test test, void *arg,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 DeathCheck death, const void *death_aux) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We need to fork(), so we can't be multi-threaded, as threads could hold
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // locks.
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int num_threads = CountThreads();
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(THREAD_SANITIZER)
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Under TSAN, there is a special helper thread. It should be completely
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // invisible to our testing, so we ignore it. It should be ok to fork()
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // with this thread. It's currently buggy, but it's the best we can do until
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // there is a way to delay the start of the thread
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // (https://code.google.com/p/thread-sanitizer/issues/detail?id=19).
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  num_threads--;
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(1, num_threads) << "Running sandbox tests with multiple threads "
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            << "is not supported and will make the tests "
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            << "flaky.\n";
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fds[2];
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, pipe(fds));
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that our pipe is not on one of the standard file descriptor.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SANDBOX_ASSERT(fds[0] > 2 && fds[1] > 2);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pid_t pid;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_LE(0, (pid = fork()));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pid) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In child process
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Redirect stderr to our pipe. This way, we can capture all error
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // messages, if we decide we want to do so in our tests.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(dup2(fds[1], 2) == 2);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(!close(fds[0]));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(!close(fds[1]));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Don't set a timeout if running on Valgrind, since it's generally much
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // slower.
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!IsRunningOnValgrind()) {
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetProcessTimeout(GetSubProcessTimeoutTimeInSeconds());
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Disable core files. They are not very useful for our individual test
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // cases.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct rlimit no_core = { 0 };
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setrlimit(RLIMIT_CORE, &no_core);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test(arg);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _exit(kExpectedValue);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void)HANDLE_EINTR(close(fds[1]));
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<char> msg_buf;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t rc;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure read() will never block as we'll use poll() to
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // block with a timeout instead.
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int fcntl_ret = fcntl(fds[0], F_SETFL,  O_NONBLOCK);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(fcntl_ret, 0);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct pollfd poll_fd = { fds[0], POLLIN | POLLRDHUP, 0 };
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int poll_ret;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We prefer the SIGALRM timeout to trigger in the child than this timeout
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // so we double the common value here.
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int poll_timeout = GetSubProcessTimeoutTimeInSeconds() * 2 * 1000;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while ((poll_ret = poll(&poll_fd, 1, poll_timeout) > 0)) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const size_t kCapacity = 256;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const size_t len = msg_buf.size();
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg_buf.resize(len + kCapacity);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rc = HANDLE_EINTR(read(fds[0], &msg_buf[len], kCapacity));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg_buf.resize(len + std::max(rc, static_cast<ssize_t>(0)));
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rc <= 0)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_NE(poll_ret, -1) << "poll() failed";
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_NE(poll_ret, 0) << "Timeout while reading child state";
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void)HANDLE_EINTR(close(fds[0]));
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string msg(msg_buf.begin(), msg_buf.end());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int status = 0;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int waitpid_returned = HANDLE_EINTR(waitpid(pid, &status, 0));
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(pid, waitpid_returned) << TestFailedMessage(msg);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At run-time, we sometimes decide that a test shouldn't actually
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // run (e.g. when testing sandbox features on a kernel that doesn't
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // have sandboxing support). When that happens, don't attempt to
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // call the "death" function, as it might be looking for a
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // death-test condition that would never have triggered.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!WIFEXITED(status) || WEXITSTATUS(status) != kIgnoreThisTest ||
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !msg.empty()) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We use gtest's ASSERT_XXX() macros instead of the DeathCheck
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // functions.  This means, on failure, "return" is called. This
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // only works correctly, if the call of the "death" callback is
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the very last thing in our function.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    death(status, msg, death_aux);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UnitTests::DeathSuccess(int status, const std::string& msg,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const void *) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string details(TestFailedMessage(msg));
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool subprocess_terminated_normally = WIFEXITED(status);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(subprocess_terminated_normally) << details;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int subprocess_exit_status = WEXITSTATUS(status);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool subprocess_exited_but_printed_messages = !msg.empty();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(subprocess_exited_but_printed_messages) << details;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UnitTests::DeathMessage(int status, const std::string& msg,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const void *aux) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string details(TestFailedMessage(msg));
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char *expected_msg = static_cast<const char *>(aux);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool subprocess_terminated_normally = WIFEXITED(status);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(subprocess_terminated_normally) << details;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int subprocess_exit_status = WEXITSTATUS(status);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(kExitWithAssertionFailure, subprocess_exit_status) << details;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool subprocess_exited_without_matching_message =
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    msg.find(expected_msg) == std::string::npos;
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(subprocess_exited_without_matching_message) << details;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UnitTests::DeathExitCode(int status, const std::string& msg,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const void *aux) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expected_exit_code = static_cast<int>(reinterpret_cast<intptr_t>(aux));
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string details(TestFailedMessage(msg));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool subprocess_terminated_normally = WIFEXITED(status);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(subprocess_terminated_normally) << details;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int subprocess_exit_status = WEXITSTATUS(status);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(subprocess_exit_status, expected_exit_code) << details;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UnitTests::DeathBySignal(int status, const std::string& msg,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const void *aux) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int expected_signo = static_cast<int>(reinterpret_cast<intptr_t>(aux));
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string details(TestFailedMessage(msg));
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool subprocess_terminated_by_signal = WIFSIGNALED(status);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(subprocess_terminated_by_signal) << details;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int subprocess_signal_number = WTERMSIG(status);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(subprocess_signal_number, expected_signo) << details;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UnitTests::AssertionFailure(const char *expr, const char *file,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 int line) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stderr, "%s:%d:%s", file, line, expr);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fflush(stderr);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _exit(kExitWithAssertionFailure);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UnitTests::IgnoreThisTest() {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fflush(stderr);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _exit(kIgnoreThisTest);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
262