2008-12-31 17:34:06 +00:00
|
|
|
// Copyright 2005, Google Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * 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.
|
|
|
|
// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
|
|
|
// OWNER 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.
|
|
|
|
//
|
|
|
|
// Author: wan@google.com (Zhanyong Wan)
|
|
|
|
//
|
|
|
|
// This file implements death tests.
|
|
|
|
|
|
|
|
#include <gtest/gtest-death-test.h>
|
|
|
|
#include <gtest/internal/gtest-port.h>
|
|
|
|
|
|
|
|
#ifdef GTEST_HAS_DEATH_TEST
|
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#endif // GTEST_HAS_DEATH_TEST
|
|
|
|
|
|
|
|
#include <gtest/gtest-message.h>
|
|
|
|
#include <gtest/internal/gtest-string.h>
|
|
|
|
|
|
|
|
// Indicates that this translation unit is part of Google Test's
|
|
|
|
// implementation. It must come before gtest-internal-inl.h is
|
|
|
|
// included, or there will be a compiler error. This trick is to
|
|
|
|
// prevent a user from accidentally including gtest-internal-inl.h in
|
|
|
|
// his code.
|
|
|
|
#define GTEST_IMPLEMENTATION
|
2009-01-01 02:05:43 +00:00
|
|
|
#include "gtest/internal/gtest-internal-inl.h"
|
2008-12-31 17:34:06 +00:00
|
|
|
#undef GTEST_IMPLEMENTATION
|
|
|
|
|
|
|
|
namespace testing {
|
|
|
|
|
|
|
|
// Constants.
|
|
|
|
|
|
|
|
// The default death test style.
|
|
|
|
static const char kDefaultDeathTestStyle[] = "fast";
|
|
|
|
|
|
|
|
GTEST_DEFINE_string_(
|
|
|
|
death_test_style,
|
|
|
|
internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
|
|
|
|
"Indicates how to run a death test in a forked child process: "
|
|
|
|
"\"threadsafe\" (child process re-executes the test binary "
|
|
|
|
"from the beginning, running only the specific death test) or "
|
|
|
|
"\"fast\" (child process runs the death test immediately "
|
|
|
|
"after forking).");
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
GTEST_DEFINE_string_(
|
|
|
|
internal_run_death_test, "",
|
|
|
|
"Indicates the file, line number, temporal index of "
|
|
|
|
"the single death test to run, and a file descriptor to "
|
|
|
|
"which a success code may be sent, all separated by "
|
|
|
|
"colons. This flag is specified if and only if the current "
|
|
|
|
"process is a sub-process launched for running a thread-safe "
|
|
|
|
"death test. FOR INTERNAL USE ONLY.");
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
#ifdef GTEST_HAS_DEATH_TEST
|
|
|
|
|
|
|
|
// ExitedWithCode constructor.
|
|
|
|
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExitedWithCode function-call operator.
|
|
|
|
bool ExitedWithCode::operator()(int exit_status) const {
|
|
|
|
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// KilledBySignal constructor.
|
|
|
|
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// KilledBySignal function-call operator.
|
|
|
|
bool KilledBySignal::operator()(int exit_status) const {
|
|
|
|
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
// Utilities needed for death tests.
|
|
|
|
|
|
|
|
// Generates a textual description of a given exit code, in the format
|
|
|
|
// specified by wait(2).
|
|
|
|
static String ExitSummary(int exit_code) {
|
|
|
|
Message m;
|
|
|
|
if (WIFEXITED(exit_code)) {
|
|
|
|
m << "Exited with exit status " << WEXITSTATUS(exit_code);
|
|
|
|
} else if (WIFSIGNALED(exit_code)) {
|
|
|
|
m << "Terminated by signal " << WTERMSIG(exit_code);
|
|
|
|
}
|
|
|
|
#ifdef WCOREDUMP
|
|
|
|
if (WCOREDUMP(exit_code)) {
|
|
|
|
m << " (core dumped)";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return m.GetString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if exit_status describes a process that was terminated
|
|
|
|
// by a signal, or exited normally with a nonzero exit code.
|
|
|
|
bool ExitedUnsuccessfully(int exit_status) {
|
|
|
|
return !ExitedWithCode(0)(exit_status);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generates a textual failure message when a death test finds more than
|
|
|
|
// one thread running, or cannot determine the number of threads, prior
|
|
|
|
// to executing the given statement. It is the responsibility of the
|
|
|
|
// caller not to pass a thread_count of 1.
|
|
|
|
static String DeathTestThreadWarning(size_t thread_count) {
|
|
|
|
Message msg;
|
|
|
|
msg << "Death tests use fork(), which is unsafe particularly"
|
|
|
|
<< " in a threaded context. For this test, " << GTEST_NAME << " ";
|
|
|
|
if (thread_count == 0)
|
|
|
|
msg << "couldn't detect the number of threads.";
|
|
|
|
else
|
|
|
|
msg << "detected " << thread_count << " threads.";
|
|
|
|
return msg.GetString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Static string containing a description of the outcome of the
|
|
|
|
// last death test.
|
|
|
|
static String last_death_test_message;
|
|
|
|
|
|
|
|
// Flag characters for reporting a death test that did not die.
|
|
|
|
static const char kDeathTestLived = 'L';
|
|
|
|
static const char kDeathTestReturned = 'R';
|
|
|
|
static const char kDeathTestInternalError = 'I';
|
|
|
|
|
|
|
|
// An enumeration describing all of the possible ways that a death test
|
|
|
|
// can conclude. DIED means that the process died while executing the
|
|
|
|
// test code; LIVED means that process lived beyond the end of the test
|
|
|
|
// code; and RETURNED means that the test statement attempted a "return,"
|
|
|
|
// which is not allowed. IN_PROGRESS means the test has not yet
|
|
|
|
// concluded.
|
|
|
|
enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED };
|
|
|
|
|
|
|
|
// Routine for aborting the program which is safe to call from an
|
|
|
|
// exec-style death test child process, in which case the the error
|
|
|
|
// message is propagated back to the parent process. Otherwise, the
|
|
|
|
// message is simply printed to stderr. In either case, the program
|
|
|
|
// then exits with status 1.
|
|
|
|
void DeathTestAbort(const char* format, ...) {
|
|
|
|
// This function may be called from a threadsafe-style death test
|
|
|
|
// child process, which operates on a very small stack. Use the
|
|
|
|
// heap for any additional non-miniscule memory requirements.
|
|
|
|
const InternalRunDeathTestFlag* const flag =
|
|
|
|
GetUnitTestImpl()->internal_run_death_test_flag();
|
|
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
|
|
|
|
|
|
if (flag != NULL) {
|
|
|
|
FILE* parent = fdopen(flag->status_fd, "w");
|
|
|
|
fputc(kDeathTestInternalError, parent);
|
|
|
|
vfprintf(parent, format, args);
|
|
|
|
fclose(parent);
|
|
|
|
va_end(args);
|
|
|
|
_exit(1);
|
|
|
|
} else {
|
|
|
|
vfprintf(stderr, format, args);
|
|
|
|
va_end(args);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A replacement for CHECK that calls DeathTestAbort if the assertion
|
|
|
|
// fails.
|
|
|
|
#define GTEST_DEATH_TEST_CHECK_(expression) \
|
|
|
|
do { \
|
|
|
|
if (!(expression)) { \
|
|
|
|
DeathTestAbort("CHECK failed: File %s, line %d: %s", \
|
|
|
|
__FILE__, __LINE__, #expression); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
|
|
|
|
// evaluating any system call that fulfills two conditions: it must return
|
|
|
|
// -1 on failure, and set errno to EINTR when it is interrupted and
|
|
|
|
// should be tried again. The macro expands to a loop that repeatedly
|
|
|
|
// evaluates the expression as long as it evaluates to -1 and sets
|
|
|
|
// errno to EINTR. If the expression evaluates to -1 but errno is
|
|
|
|
// something other than EINTR, DeathTestAbort is called.
|
|
|
|
#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
|
|
|
|
do { \
|
|
|
|
int retval; \
|
|
|
|
do { \
|
|
|
|
retval = (expression); \
|
|
|
|
} while (retval == -1 && errno == EINTR); \
|
|
|
|
if (retval == -1) { \
|
|
|
|
DeathTestAbort("CHECK failed: File %s, line %d: %s != -1", \
|
|
|
|
__FILE__, __LINE__, #expression); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
// Death test constructor. Increments the running death test count
|
|
|
|
// for the current test.
|
|
|
|
DeathTest::DeathTest() {
|
|
|
|
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
|
|
|
if (info == NULL) {
|
|
|
|
DeathTestAbort("Cannot run a death test outside of a TEST or "
|
|
|
|
"TEST_F construct");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates and returns a death test by dispatching to the current
|
|
|
|
// death test factory.
|
|
|
|
bool DeathTest::Create(const char* statement, const RE* regex,
|
|
|
|
const char* file, int line, DeathTest** test) {
|
|
|
|
return GetUnitTestImpl()->death_test_factory()->Create(
|
|
|
|
statement, regex, file, line, test);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* DeathTest::LastMessage() {
|
|
|
|
return last_death_test_message.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ForkingDeathTest provides implementations for most of the abstract
|
|
|
|
// methods of the DeathTest interface. Only the AssumeRole method is
|
|
|
|
// left undefined.
|
|
|
|
class ForkingDeathTest : public DeathTest {
|
|
|
|
public:
|
|
|
|
ForkingDeathTest(const char* statement, const RE* regex);
|
|
|
|
|
|
|
|
// All of these virtual functions are inherited from DeathTest.
|
|
|
|
virtual int Wait();
|
|
|
|
virtual bool Passed(bool status_ok);
|
|
|
|
virtual void Abort(AbortReason reason);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void set_forked(bool forked) { forked_ = forked; }
|
|
|
|
void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
|
|
|
|
void set_read_fd(int fd) { read_fd_ = fd; }
|
|
|
|
void set_write_fd(int fd) { write_fd_ = fd; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
// The textual content of the code this object is testing.
|
|
|
|
const char* const statement_;
|
|
|
|
// The regular expression which test output must match.
|
|
|
|
const RE* const regex_;
|
|
|
|
// True if the death test successfully forked.
|
|
|
|
bool forked_;
|
|
|
|
// PID of child process during death test; 0 in the child process itself.
|
|
|
|
pid_t child_pid_;
|
|
|
|
// File descriptors for communicating the death test's status byte.
|
|
|
|
int read_fd_; // Always -1 in the child process.
|
|
|
|
int write_fd_; // Always -1 in the parent process.
|
|
|
|
// The exit status of the child process.
|
|
|
|
int status_;
|
|
|
|
// How the death test concluded.
|
|
|
|
DeathTestOutcome outcome_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Constructs a ForkingDeathTest.
|
|
|
|
ForkingDeathTest::ForkingDeathTest(const char* statement, const RE* regex)
|
|
|
|
: DeathTest(),
|
|
|
|
statement_(statement),
|
|
|
|
regex_(regex),
|
|
|
|
forked_(false),
|
|
|
|
child_pid_(-1),
|
|
|
|
read_fd_(-1),
|
|
|
|
write_fd_(-1),
|
|
|
|
status_(-1),
|
|
|
|
outcome_(IN_PROGRESS) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reads an internal failure message from a file descriptor, then calls
|
|
|
|
// LOG(FATAL) with that message. Called from a death test parent process
|
|
|
|
// to read a failure message from the death test child process.
|
|
|
|
static void FailFromInternalError(int fd) {
|
|
|
|
Message error;
|
|
|
|
char buffer[256];
|
|
|
|
ssize_t num_read;
|
|
|
|
|
|
|
|
do {
|
|
|
|
while ((num_read = read(fd, buffer, 255)) > 0) {
|
|
|
|
buffer[num_read] = '\0';
|
|
|
|
error << buffer;
|
|
|
|
}
|
|
|
|
} while (num_read == -1 && errno == EINTR);
|
|
|
|
|
|
|
|
// TODO(smcafee): Maybe just FAIL the test instead?
|
|
|
|
if (num_read == 0) {
|
|
|
|
GTEST_LOG_(FATAL, error);
|
|
|
|
} else {
|
|
|
|
GTEST_LOG_(FATAL,
|
|
|
|
Message() << "Error while reading death test internal: "
|
|
|
|
<< strerror(errno) << " [" << errno << "]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Waits for the child in a death test to exit, returning its exit
|
|
|
|
// status, or 0 if no child process exists. As a side effect, sets the
|
|
|
|
// outcome data member.
|
|
|
|
int ForkingDeathTest::Wait() {
|
|
|
|
if (!forked_)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// The read() here blocks until data is available (signifying the
|
|
|
|
// failure of the death test) or until the pipe is closed (signifying
|
|
|
|
// its success), so it's okay to call this in the parent before
|
|
|
|
// the child process has exited.
|
|
|
|
char flag;
|
|
|
|
ssize_t bytes_read;
|
|
|
|
|
|
|
|
do {
|
|
|
|
bytes_read = read(read_fd_, &flag, 1);
|
|
|
|
} while (bytes_read == -1 && errno == EINTR);
|
|
|
|
|
|
|
|
if (bytes_read == 0) {
|
|
|
|
outcome_ = DIED;
|
|
|
|
} else if (bytes_read == 1) {
|
|
|
|
switch (flag) {
|
|
|
|
case kDeathTestReturned:
|
|
|
|
outcome_ = RETURNED;
|
|
|
|
break;
|
|
|
|
case kDeathTestLived:
|
|
|
|
outcome_ = LIVED;
|
|
|
|
break;
|
|
|
|
case kDeathTestInternalError:
|
|
|
|
FailFromInternalError(read_fd_); // Does not return.
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GTEST_LOG_(FATAL,
|
|
|
|
Message() << "Death test child process reported unexpected "
|
|
|
|
<< "status byte (" << static_cast<unsigned int>(flag)
|
|
|
|
<< ")");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GTEST_LOG_(FATAL,
|
|
|
|
Message() << "Read from death test child process failed: "
|
|
|
|
<< strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(read_fd_));
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_, 0));
|
|
|
|
return status_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assesses the success or failure of a death test, using both private
|
|
|
|
// members which have previously been set, and one argument:
|
|
|
|
//
|
|
|
|
// Private data members:
|
|
|
|
// outcome: an enumeration describing how the death test
|
|
|
|
// concluded: DIED, LIVED, or RETURNED. The death test fails
|
|
|
|
// in the latter two cases
|
|
|
|
// status: the exit status of the child process, in the format
|
|
|
|
// specified by wait(2)
|
|
|
|
// regex: a regular expression object to be applied to
|
|
|
|
// the test's captured standard error output; the death test
|
|
|
|
// fails if it does not match
|
|
|
|
//
|
|
|
|
// Argument:
|
|
|
|
// status_ok: true if exit_status is acceptable in the context of
|
|
|
|
// this particular death test, which fails if it is false
|
|
|
|
//
|
|
|
|
// Returns true iff all of the above conditions are met. Otherwise, the
|
|
|
|
// first failing condition, in the order given above, is the one that is
|
|
|
|
// reported. Also sets the static variable last_death_test_message.
|
|
|
|
bool ForkingDeathTest::Passed(bool status_ok) {
|
|
|
|
if (!forked_)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
#if GTEST_HAS_GLOBAL_STRING
|
|
|
|
const ::string error_message = GetCapturedStderr();
|
|
|
|
#else
|
|
|
|
const ::std::string error_message = GetCapturedStderr();
|
|
|
|
#endif // GTEST_HAS_GLOBAL_STRING
|
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
Message buffer;
|
|
|
|
|
|
|
|
buffer << "Death test: " << statement_ << "\n";
|
|
|
|
switch (outcome_) {
|
|
|
|
case LIVED:
|
|
|
|
buffer << " Result: failed to die.\n"
|
|
|
|
<< " Error msg: " << error_message;
|
|
|
|
break;
|
|
|
|
case RETURNED:
|
|
|
|
buffer << " Result: illegal return in test statement.\n"
|
|
|
|
<< " Error msg: " << error_message;
|
|
|
|
break;
|
|
|
|
case DIED:
|
|
|
|
if (status_ok) {
|
|
|
|
if (RE::PartialMatch(error_message, *regex_)) {
|
|
|
|
success = true;
|
|
|
|
} else {
|
|
|
|
buffer << " Result: died but not with expected error.\n"
|
|
|
|
<< " Expected: " << regex_->pattern() << "\n"
|
|
|
|
<< "Actual msg: " << error_message;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
buffer << " Result: died but not with expected exit code:\n"
|
|
|
|
<< " " << ExitSummary(status_) << "\n";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IN_PROGRESS:
|
|
|
|
default:
|
|
|
|
GTEST_LOG_(FATAL,
|
|
|
|
"DeathTest::Passed somehow called before conclusion of test");
|
|
|
|
}
|
|
|
|
|
|
|
|
last_death_test_message = buffer.GetString();
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Signals that the death test code which should have exited, didn't.
|
|
|
|
// Should be called only in a death test child process.
|
|
|
|
// Writes a status byte to the child's status file desriptor, then
|
|
|
|
// calls _exit(1).
|
|
|
|
void ForkingDeathTest::Abort(AbortReason reason) {
|
|
|
|
// The parent process considers the death test to be a failure if
|
|
|
|
// it finds any data in our pipe. So, here we write a single flag byte
|
|
|
|
// to the pipe, then exit.
|
|
|
|
const char flag =
|
|
|
|
reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned;
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(write(write_fd_, &flag, 1));
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(write_fd_));
|
|
|
|
_exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A concrete death test class that forks, then immediately runs the test
|
|
|
|
// in the child process.
|
|
|
|
class NoExecDeathTest : public ForkingDeathTest {
|
|
|
|
public:
|
|
|
|
NoExecDeathTest(const char* statement, const RE* regex) :
|
|
|
|
ForkingDeathTest(statement, regex) { }
|
|
|
|
virtual TestRole AssumeRole();
|
|
|
|
};
|
|
|
|
|
|
|
|
// The AssumeRole process for a fork-and-run death test. It implements a
|
|
|
|
// straightforward fork, with a simple pipe to transmit the status byte.
|
|
|
|
DeathTest::TestRole NoExecDeathTest::AssumeRole() {
|
|
|
|
const size_t thread_count = GetThreadCount();
|
|
|
|
if (thread_count != 1) {
|
|
|
|
GTEST_LOG_(WARNING, DeathTestThreadWarning(thread_count));
|
|
|
|
}
|
|
|
|
|
|
|
|
int pipe_fd[2];
|
|
|
|
GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
|
|
|
|
|
|
|
|
last_death_test_message = "";
|
|
|
|
CaptureStderr();
|
|
|
|
// When we fork the process below, the log file buffers are copied, but the
|
|
|
|
// file descriptors are shared. We flush all log files here so that closing
|
|
|
|
// the file descriptors in the child process doesn't throw off the
|
|
|
|
// synchronization between descriptors and buffers in the parent process.
|
|
|
|
// This is as close to the fork as possible to avoid a race condition in case
|
|
|
|
// there are multiple threads running before the death test, and another
|
|
|
|
// thread writes to the log file.
|
|
|
|
FlushInfoLog();
|
|
|
|
|
|
|
|
const pid_t child_pid = fork();
|
|
|
|
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
|
|
|
set_child_pid(child_pid);
|
|
|
|
if (child_pid == 0) {
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
|
|
|
|
set_write_fd(pipe_fd[1]);
|
|
|
|
// Redirects all logging to stderr in the child process to prevent
|
|
|
|
// concurrent writes to the log files. We capture stderr in the parent
|
|
|
|
// process and append the child process' output to a log.
|
|
|
|
LogToStderr();
|
|
|
|
return EXECUTE_TEST;
|
|
|
|
} else {
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
|
|
|
set_read_fd(pipe_fd[0]);
|
|
|
|
set_forked(true);
|
|
|
|
return OVERSEE_TEST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A concrete death test class that forks and re-executes the main
|
|
|
|
// program from the beginning, with command-line flags set that cause
|
|
|
|
// only this specific death test to be run.
|
|
|
|
class ExecDeathTest : public ForkingDeathTest {
|
|
|
|
public:
|
|
|
|
ExecDeathTest(const char* statement, const RE* regex,
|
|
|
|
const char* file, int line) :
|
|
|
|
ForkingDeathTest(statement, regex), file_(file), line_(line) { }
|
|
|
|
virtual TestRole AssumeRole();
|
|
|
|
private:
|
|
|
|
// The name of the file in which the death test is located.
|
|
|
|
const char* const file_;
|
|
|
|
// The line number on which the death test is located.
|
|
|
|
const int line_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Utility class for accumulating command-line arguments.
|
|
|
|
class Arguments {
|
|
|
|
public:
|
|
|
|
Arguments() {
|
|
|
|
args_.push_back(NULL);
|
|
|
|
}
|
|
|
|
~Arguments() {
|
|
|
|
for (std::vector<char*>::iterator i = args_.begin();
|
|
|
|
i + 1 != args_.end();
|
|
|
|
++i) {
|
|
|
|
free(*i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void AddArgument(const char* argument) {
|
|
|
|
args_.insert(args_.end() - 1, strdup(argument));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Str>
|
|
|
|
void AddArguments(const ::std::vector<Str>& arguments) {
|
|
|
|
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
|
|
|
i != arguments.end();
|
|
|
|
++i) {
|
|
|
|
args_.insert(args_.end() - 1, strdup(i->c_str()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char* const* Argv() {
|
|
|
|
return &args_[0];
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
std::vector<char*> args_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A struct that encompasses the arguments to the child process of a
|
|
|
|
// threadsafe-style death test process.
|
|
|
|
struct ExecDeathTestArgs {
|
|
|
|
char* const* argv; // Command-line arguments for the child's call to exec
|
|
|
|
int close_fd; // File descriptor to close; the read end of a pipe
|
|
|
|
};
|
|
|
|
|
|
|
|
// The main function for a threadsafe-style death test child process.
|
|
|
|
// This function is called in a clone()-ed process and thus must avoid
|
|
|
|
// any potentially unsafe operations like malloc or libc functions.
|
|
|
|
static int ExecDeathTestChildMain(void* child_arg) {
|
|
|
|
ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
|
|
|
|
|
|
|
|
// We need to execute the test program in the same environment where
|
|
|
|
// it was originally invoked. Therefore we change to the original
|
|
|
|
// working directory first.
|
|
|
|
const char* const original_dir =
|
|
|
|
UnitTest::GetInstance()->original_working_dir();
|
|
|
|
// We can safely call chdir() as it's a direct system call.
|
|
|
|
if (chdir(original_dir) != 0) {
|
|
|
|
DeathTestAbort("chdir(\"%s\") failed: %s",
|
|
|
|
original_dir, strerror(errno));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can safely call execve() as it's a direct system call. We
|
|
|
|
// cannot use execvp() as it's a libc function and thus potentially
|
|
|
|
// unsafe. Since execve() doesn't search the PATH, the user must
|
|
|
|
// invoke the test program via a valid path that contains at least
|
|
|
|
// one path separator.
|
|
|
|
execve(args->argv[0], args->argv, environ);
|
|
|
|
DeathTestAbort("execve(%s, ...) in %s failed: %s",
|
|
|
|
args->argv[0], original_dir, strerror(errno));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Two utility routines that together determine the direction the stack
|
|
|
|
// grows.
|
|
|
|
// This could be accomplished more elegantly by a single recursive
|
|
|
|
// function, but we want to guard against the unlikely possibility of
|
|
|
|
// a smart compiler optimizing the recursion away.
|
|
|
|
static bool StackLowerThanAddress(const void* ptr) {
|
|
|
|
int dummy;
|
|
|
|
return &dummy < ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool StackGrowsDown() {
|
|
|
|
int dummy;
|
|
|
|
return StackLowerThanAddress(&dummy);
|
|
|
|
}
|
|
|
|
|
|
|
|
// A threadsafe implementation of fork(2) for threadsafe-style death tests
|
|
|
|
// that uses clone(2). It dies with an error message if anything goes
|
|
|
|
// wrong.
|
|
|
|
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
|
|
|
static const bool stack_grows_down = StackGrowsDown();
|
|
|
|
const size_t stack_size = getpagesize();
|
|
|
|
void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
|
|
|
|
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
|
|
GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
|
|
|
|
void* const stack_top =
|
|
|
|
static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
|
|
|
|
ExecDeathTestArgs args = { argv, close_fd };
|
|
|
|
const pid_t child_pid = clone(&ExecDeathTestChildMain, stack_top,
|
|
|
|
SIGCHLD, &args);
|
|
|
|
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
|
|
|
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
|
|
|
return child_pid;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The AssumeRole process for a fork-and-exec death test. It re-executes the
|
|
|
|
// main program from the beginning, setting the --gtest_filter
|
|
|
|
// and --gtest_internal_run_death_test flags to cause only the current
|
|
|
|
// death test to be re-run.
|
|
|
|
DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
|
|
|
const UnitTestImpl* const impl = GetUnitTestImpl();
|
|
|
|
const InternalRunDeathTestFlag* const flag =
|
|
|
|
impl->internal_run_death_test_flag();
|
|
|
|
const TestInfo* const info = impl->current_test_info();
|
|
|
|
const int death_test_index = info->result()->death_test_count();
|
|
|
|
|
|
|
|
if (flag != NULL) {
|
|
|
|
set_write_fd(flag->status_fd);
|
|
|
|
return EXECUTE_TEST;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pipe_fd[2];
|
|
|
|
GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
|
|
|
|
// Clear the close-on-exec flag on the write end of the pipe, lest
|
|
|
|
// it be closed when the child process does an exec:
|
|
|
|
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
|
|
|
|
|
|
|
|
const String filter_flag =
|
|
|
|
String::Format("--%s%s=%s.%s",
|
|
|
|
GTEST_FLAG_PREFIX, kFilterFlag,
|
|
|
|
info->test_case_name(), info->name());
|
|
|
|
const String internal_flag =
|
|
|
|
String::Format("--%s%s=%s:%d:%d:%d",
|
|
|
|
GTEST_FLAG_PREFIX, kInternalRunDeathTestFlag, file_, line_,
|
|
|
|
death_test_index, pipe_fd[1]);
|
|
|
|
Arguments args;
|
|
|
|
args.AddArguments(GetArgvs());
|
|
|
|
args.AddArgument("--logtostderr");
|
|
|
|
args.AddArgument(filter_flag.c_str());
|
|
|
|
args.AddArgument(internal_flag.c_str());
|
|
|
|
|
|
|
|
last_death_test_message = "";
|
|
|
|
|
|
|
|
CaptureStderr();
|
|
|
|
// See the comment in NoExecDeathTest::AssumeRole for why the next line
|
|
|
|
// is necessary.
|
|
|
|
FlushInfoLog();
|
|
|
|
|
|
|
|
const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
|
|
|
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
|
|
|
set_child_pid(child_pid);
|
|
|
|
set_read_fd(pipe_fd[0]);
|
|
|
|
set_forked(true);
|
|
|
|
return OVERSEE_TEST;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates a concrete DeathTest-derived class that depends on the
|
|
|
|
// --gtest_death_test_style flag, and sets the pointer pointed to
|
|
|
|
// by the "test" argument to its address. If the test should be
|
|
|
|
// skipped, sets that pointer to NULL. Returns true, unless the
|
|
|
|
// flag is set to an invalid value.
|
|
|
|
bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
|
|
|
const char* file, int line,
|
|
|
|
DeathTest** test) {
|
|
|
|
UnitTestImpl* const impl = GetUnitTestImpl();
|
|
|
|
const InternalRunDeathTestFlag* const flag =
|
|
|
|
impl->internal_run_death_test_flag();
|
|
|
|
const int death_test_index = impl->current_test_info()
|
|
|
|
->increment_death_test_count();
|
|
|
|
|
|
|
|
if (flag != NULL) {
|
|
|
|
if (death_test_index > flag->index) {
|
|
|
|
last_death_test_message = String::Format(
|
|
|
|
"Death test count (%d) somehow exceeded expected maximum (%d)",
|
|
|
|
death_test_index, flag->index);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flag->file == file && flag->line == line &&
|
|
|
|
flag->index == death_test_index)) {
|
|
|
|
*test = NULL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GTEST_FLAG(death_test_style) == "threadsafe") {
|
|
|
|
*test = new ExecDeathTest(statement, regex, file, line);
|
|
|
|
} else if (GTEST_FLAG(death_test_style) == "fast") {
|
|
|
|
*test = new NoExecDeathTest(statement, regex);
|
|
|
|
} else {
|
|
|
|
last_death_test_message = String::Format(
|
|
|
|
"Unknown death test style \"%s\" encountered",
|
|
|
|
GTEST_FLAG(death_test_style).c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Splits a given string on a given delimiter, populating a given
|
|
|
|
// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
|
|
|
|
// ::std::string, so we can use it here.
|
|
|
|
static void SplitString(const ::std::string& str, char delimiter,
|
|
|
|
::std::vector< ::std::string>* dest) {
|
|
|
|
::std::vector< ::std::string> parsed;
|
|
|
|
::std::string::size_type pos = 0;
|
|
|
|
while (true) {
|
|
|
|
const ::std::string::size_type colon = str.find(delimiter, pos);
|
|
|
|
if (colon == ::std::string::npos) {
|
|
|
|
parsed.push_back(str.substr(pos));
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
parsed.push_back(str.substr(pos, colon - pos));
|
|
|
|
pos = colon + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dest->swap(parsed);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempts to parse a string into a positive integer. Returns true
|
|
|
|
// if that is possible. GTEST_HAS_DEATH_TEST implies that we have
|
|
|
|
// ::std::string, so we can use it here.
|
|
|
|
static bool ParsePositiveInt(const ::std::string& str, int* number) {
|
|
|
|
// Fail fast if the given string does not begin with a digit;
|
|
|
|
// this bypasses strtol's "optional leading whitespace and plus
|
|
|
|
// or minus sign" semantics, which are undesirable here.
|
|
|
|
if (str.empty() || !isdigit(str[0])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
char* endptr;
|
|
|
|
const long parsed = strtol(str.c_str(), &endptr, 10); // NOLINT
|
|
|
|
if (*endptr == '\0' && parsed <= INT_MAX) {
|
|
|
|
*number = static_cast<int>(parsed);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a newly created InternalRunDeathTestFlag object with fields
|
|
|
|
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
|
|
|
// the flag is specified; otherwise returns NULL.
|
|
|
|
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
|
|
|
if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
|
|
|
|
|
|
|
|
InternalRunDeathTestFlag* const internal_run_death_test_flag =
|
|
|
|
new InternalRunDeathTestFlag;
|
|
|
|
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
|
|
|
|
// can use it here.
|
|
|
|
::std::vector< ::std::string> fields;
|
|
|
|
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), ':', &fields);
|
|
|
|
if (fields.size() != 4
|
|
|
|
|| !ParsePositiveInt(fields[1], &internal_run_death_test_flag->line)
|
|
|
|
|| !ParsePositiveInt(fields[2], &internal_run_death_test_flag->index)
|
|
|
|
|| !ParsePositiveInt(fields[3],
|
|
|
|
&internal_run_death_test_flag->status_fd)) {
|
|
|
|
DeathTestAbort("Bad --gtest_internal_run_death_test flag: %s",
|
|
|
|
GTEST_FLAG(internal_run_death_test).c_str());
|
|
|
|
}
|
|
|
|
internal_run_death_test_flag->file = fields[0].c_str();
|
|
|
|
return internal_run_death_test_flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
#endif // GTEST_HAS_DEATH_TEST
|
|
|
|
|
|
|
|
} // namespace testing
|