mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 07:17:32 +09:00
Update NSS to 3.41
This commit is contained in:
parent
d5f6e64f43
commit
5f0986e66f
540 changed files with 49568 additions and 10631 deletions
|
|
@ -26,10 +26,9 @@
|
|||
// 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: mheule@google.com (Markus Heule)
|
||||
//
|
||||
// Google C++ Testing Framework (Google Test)
|
||||
// Google C++ Testing and Mocking Framework (Google Test)
|
||||
//
|
||||
// Sometimes it's desirable to build Google Test by compiling a single file.
|
||||
// This file serves this purpose.
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@
|
|||
// 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), vladl@google.com (Vlad Losev)
|
||||
|
||||
//
|
||||
// This file implements death tests.
|
||||
|
||||
#include "gtest/gtest-death-test.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/internal/custom/gtest.h"
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
|
@ -61,26 +61,30 @@
|
|||
# include <spawn.h>
|
||||
# endif // GTEST_OS_QNX
|
||||
|
||||
# if GTEST_OS_FUCHSIA
|
||||
# include <lib/fdio/io.h>
|
||||
# include <lib/fdio/spawn.h>
|
||||
# include <zircon/processargs.h>
|
||||
# include <zircon/syscalls.h>
|
||||
# include <zircon/syscalls/port.h>
|
||||
# endif // GTEST_OS_FUCHSIA
|
||||
|
||||
#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 exists to
|
||||
// prevent the accidental inclusion of gtest-internal-inl.h in the
|
||||
// user's code.
|
||||
#define GTEST_IMPLEMENTATION_ 1
|
||||
#include "src/gtest-internal-inl.h"
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Constants.
|
||||
|
||||
// The default death test style.
|
||||
static const char kDefaultDeathTestStyle[] = "fast";
|
||||
//
|
||||
// This is defined in internal/gtest-port.h as "fast", but can be overridden by
|
||||
// a definition in internal/custom/gtest-port.h. The recommended value, which is
|
||||
// used internally at Google, is "threadsafe".
|
||||
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
|
||||
|
||||
GTEST_DEFINE_string_(
|
||||
death_test_style,
|
||||
|
|
@ -120,7 +124,9 @@ namespace internal {
|
|||
|
||||
// Valid only for fast death tests. Indicates the code is running in the
|
||||
// child process of a fast style death test.
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
static bool g_in_fast_death_test_child = false;
|
||||
# endif
|
||||
|
||||
// Returns a Boolean value indicating whether the caller is currently
|
||||
// executing in the context of the death test child process. Tools such as
|
||||
|
|
@ -128,10 +134,10 @@ static bool g_in_fast_death_test_child = false;
|
|||
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
||||
// implementation of death tests. User code MUST NOT use it.
|
||||
bool InDeathTestChild() {
|
||||
# if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
// On Windows, death tests are thread-safe regardless of the value of the
|
||||
// death_test_style flag.
|
||||
// On Windows and Fuchsia, death tests are thread-safe regardless of the value
|
||||
// of the death_test_style flag.
|
||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
||||
|
||||
# else
|
||||
|
|
@ -151,7 +157,7 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
|
|||
|
||||
// ExitedWithCode function-call operator.
|
||||
bool ExitedWithCode::operator()(int exit_status) const {
|
||||
# if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
return exit_status == exit_code_;
|
||||
|
||||
|
|
@ -159,19 +165,27 @@ bool ExitedWithCode::operator()(int exit_status) const {
|
|||
|
||||
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
|
||||
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
}
|
||||
|
||||
# if !GTEST_OS_WINDOWS
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
// KilledBySignal constructor.
|
||||
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
|
||||
}
|
||||
|
||||
// KilledBySignal function-call operator.
|
||||
bool KilledBySignal::operator()(int exit_status) const {
|
||||
# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||
{
|
||||
bool result;
|
||||
if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
|
||||
}
|
||||
# endif // !GTEST_OS_WINDOWS
|
||||
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
|
@ -182,7 +196,7 @@ namespace internal {
|
|||
static std::string ExitSummary(int exit_code) {
|
||||
Message m;
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
m << "Exited with exit status " << exit_code;
|
||||
|
||||
|
|
@ -198,7 +212,7 @@ static std::string ExitSummary(int exit_code) {
|
|||
m << " (core dumped)";
|
||||
}
|
||||
# endif
|
||||
# endif // GTEST_OS_WINDOWS
|
||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||
|
||||
return m.GetString();
|
||||
}
|
||||
|
|
@ -209,7 +223,7 @@ bool ExitedUnsuccessfully(int exit_status) {
|
|||
return !ExitedWithCode(0)(exit_status);
|
||||
}
|
||||
|
||||
# if !GTEST_OS_WINDOWS
|
||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
// 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
|
||||
|
|
@ -218,13 +232,19 @@ static std::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)
|
||||
if (thread_count == 0) {
|
||||
msg << "couldn't detect the number of threads.";
|
||||
else
|
||||
} else {
|
||||
msg << "detected " << thread_count << " threads.";
|
||||
}
|
||||
msg << " See "
|
||||
"https://github.com/google/googletest/blob/master/googletest/docs/"
|
||||
"advanced.md#death-tests-and-threads"
|
||||
<< " for more explanation and suggested solutions, especially if"
|
||||
<< " this is the last message you see before your test times out.";
|
||||
return msg.GetString();
|
||||
}
|
||||
# endif // !GTEST_OS_WINDOWS
|
||||
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||
|
||||
// Flag characters for reporting a death test that did not die.
|
||||
static const char kDeathTestLived = 'L';
|
||||
|
|
@ -232,6 +252,13 @@ static const char kDeathTestReturned = 'R';
|
|||
static const char kDeathTestThrew = 'T';
|
||||
static const char kDeathTestInternalError = 'I';
|
||||
|
||||
#if GTEST_OS_FUCHSIA
|
||||
|
||||
// File descriptor used for the pipe in the child process.
|
||||
static const int kFuchsiaReadPipeFd = 3;
|
||||
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
|
|
@ -239,7 +266,7 @@ static const char kDeathTestInternalError = 'I';
|
|||
// statement, which is not allowed; THREW means that the test statement
|
||||
// returned control by throwing an exception. IN_PROGRESS means the test
|
||||
// has not yet concluded.
|
||||
// TODO(vladl@google.com): Unify names and possibly values for
|
||||
// FIXME: Unify names and possibly values for
|
||||
// AbortReason, DeathTestOutcome, and flag characters above.
|
||||
enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
|
||||
|
||||
|
|
@ -248,7 +275,7 @@ enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
|
|||
// 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 std::string& message) {
|
||||
static void DeathTestAbort(const std::string& message) {
|
||||
// On a POSIX system, 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-minuscule memory requirements.
|
||||
|
|
@ -552,7 +579,12 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
|||
break;
|
||||
case DIED:
|
||||
if (status_ok) {
|
||||
# if GTEST_USES_PCRE
|
||||
// PCRE regexes support embedded NULs.
|
||||
const bool matched = RE::PartialMatch(error_message, *regex());
|
||||
# else
|
||||
const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
|
||||
# endif // GTEST_USES_PCRE
|
||||
if (matched) {
|
||||
success = true;
|
||||
} else {
|
||||
|
|
@ -768,7 +800,200 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
|||
set_spawned(true);
|
||||
return OVERSEE_TEST;
|
||||
}
|
||||
# else // We are not on Windows.
|
||||
|
||||
# elif GTEST_OS_FUCHSIA
|
||||
|
||||
class FuchsiaDeathTest : public DeathTestImpl {
|
||||
public:
|
||||
FuchsiaDeathTest(const char* a_statement,
|
||||
const RE* a_regex,
|
||||
const char* file,
|
||||
int line)
|
||||
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
|
||||
virtual ~FuchsiaDeathTest() {
|
||||
zx_status_t status = zx_handle_close(child_process_);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
status = zx_handle_close(port_);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
}
|
||||
|
||||
// All of these virtual functions are inherited from DeathTest.
|
||||
virtual int Wait();
|
||||
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_;
|
||||
|
||||
zx_handle_t child_process_ = ZX_HANDLE_INVALID;
|
||||
zx_handle_t port_ = ZX_HANDLE_INVALID;
|
||||
};
|
||||
|
||||
// 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 != args_.end();
|
||||
++i) {
|
||||
free(*i);
|
||||
}
|
||||
}
|
||||
void AddArgument(const char* argument) {
|
||||
args_.insert(args_.end() - 1, posix::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, posix::StrDup(i->c_str()));
|
||||
}
|
||||
}
|
||||
char* const* Argv() {
|
||||
return &args_[0];
|
||||
}
|
||||
|
||||
int size() {
|
||||
return args_.size() - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char*> args_;
|
||||
};
|
||||
|
||||
// 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 FuchsiaDeathTest::Wait() {
|
||||
if (!spawned())
|
||||
return 0;
|
||||
|
||||
// Register to wait for the child process to terminate.
|
||||
zx_status_t status_zx;
|
||||
status_zx = zx_object_wait_async(child_process_,
|
||||
port_,
|
||||
0 /* key */,
|
||||
ZX_PROCESS_TERMINATED,
|
||||
ZX_WAIT_ASYNC_ONCE);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
// Wait for it to terminate, or an exception to be received.
|
||||
zx_port_packet_t packet;
|
||||
status_zx = zx_port_wait(port_, ZX_TIME_INFINITE, &packet);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
if (ZX_PKT_IS_EXCEPTION(packet.type)) {
|
||||
// Process encountered an exception. Kill it directly rather than letting
|
||||
// other handlers process the event.
|
||||
status_zx = zx_task_kill(child_process_);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
// Now wait for |child_process_| to terminate.
|
||||
zx_signals_t signals = 0;
|
||||
status_zx = zx_object_wait_one(
|
||||
child_process_, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, &signals);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
GTEST_DEATH_TEST_CHECK_(signals & ZX_PROCESS_TERMINATED);
|
||||
} else {
|
||||
// Process terminated.
|
||||
GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
|
||||
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
|
||||
}
|
||||
|
||||
ReadAndInterpretStatusByte();
|
||||
|
||||
zx_info_process_t buffer;
|
||||
status_zx = zx_object_get_info(
|
||||
child_process_,
|
||||
ZX_INFO_PROCESS,
|
||||
&buffer,
|
||||
sizeof(buffer),
|
||||
nullptr,
|
||||
nullptr);
|
||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||
|
||||
GTEST_DEATH_TEST_CHECK_(buffer.exited);
|
||||
set_status(buffer.return_code);
|
||||
return status();
|
||||
}
|
||||
|
||||
// The AssumeRole process for a Fuchsia death test. It creates a child
|
||||
// process with the same executable as the current process to run the
|
||||
// death test. The child process is given the --gtest_filter and
|
||||
// --gtest_internal_run_death_test flags such that it knows to run the
|
||||
// current death test only.
|
||||
DeathTest::TestRole FuchsiaDeathTest::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) {
|
||||
// ParseInternalRunDeathTestFlag() has performed all the necessary
|
||||
// processing.
|
||||
set_write_fd(kFuchsiaReadPipeFd);
|
||||
return EXECUTE_TEST;
|
||||
}
|
||||
|
||||
CaptureStderr();
|
||||
// Flush the log buffers since the log streams are shared with the child.
|
||||
FlushInfoLog();
|
||||
|
||||
// Build the child process command line.
|
||||
const std::string filter_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
|
||||
+ info->test_case_name() + "." + info->name();
|
||||
const std::string internal_flag =
|
||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
||||
+ file_ + "|"
|
||||
+ StreamableToString(line_) + "|"
|
||||
+ StreamableToString(death_test_index);
|
||||
Arguments args;
|
||||
args.AddArguments(GetInjectableArgvs());
|
||||
args.AddArgument(filter_flag.c_str());
|
||||
args.AddArgument(internal_flag.c_str());
|
||||
|
||||
// Build the pipe for communication with the child.
|
||||
zx_status_t status;
|
||||
zx_handle_t child_pipe_handle;
|
||||
uint32_t type;
|
||||
status = fdio_pipe_half(&child_pipe_handle, &type);
|
||||
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
||||
set_read_fd(status);
|
||||
|
||||
// Set the pipe handle for the child.
|
||||
fdio_spawn_action_t add_handle_action = {};
|
||||
add_handle_action.action = FDIO_SPAWN_ACTION_ADD_HANDLE;
|
||||
add_handle_action.h.id = PA_HND(type, kFuchsiaReadPipeFd);
|
||||
add_handle_action.h.handle = child_pipe_handle;
|
||||
|
||||
// Spawn the child process.
|
||||
status = fdio_spawn_etc(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL,
|
||||
args.Argv()[0], args.Argv(), nullptr, 1,
|
||||
&add_handle_action, &child_process_, nullptr);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
|
||||
// Create an exception port and attach it to the |child_process_|, to allow
|
||||
// us to suppress the system default exception handler from firing.
|
||||
status = zx_port_create(0, &port_);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
status = zx_task_bind_exception_port(
|
||||
child_process_, port_, 0 /* key */, 0 /*options */);
|
||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||
|
||||
set_spawned(true);
|
||||
return OVERSEE_TEST;
|
||||
}
|
||||
|
||||
#else // We are neither on Windows, nor on Fuchsia.
|
||||
|
||||
// ForkingDeathTest provides implementations for most of the abstract
|
||||
// methods of the DeathTest interface. Only the AssumeRole method is
|
||||
|
|
@ -872,9 +1097,13 @@ class ExecDeathTest : public ForkingDeathTest {
|
|||
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
|
||||
virtual TestRole AssumeRole();
|
||||
private:
|
||||
static ::std::vector<testing::internal::string>
|
||||
GetArgvsForDeathTestChildProcess() {
|
||||
::std::vector<testing::internal::string> args = GetInjectableArgvs();
|
||||
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
||||
::std::vector<std::string> args = GetInjectableArgvs();
|
||||
# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||
::std::vector<std::string> extra_args =
|
||||
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
|
||||
args.insert(args.end(), extra_args.begin(), extra_args.end());
|
||||
# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||
return args;
|
||||
}
|
||||
// The name of the file in which the death test is located.
|
||||
|
|
@ -970,6 +1199,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
|||
}
|
||||
# endif // !GTEST_OS_QNX
|
||||
|
||||
# if GTEST_HAS_CLONE
|
||||
// Two utility routines that together determine the direction the stack
|
||||
// grows.
|
||||
// This could be accomplished more elegantly by a single recursive
|
||||
|
|
@ -979,20 +1209,22 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
|||
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
|
||||
// StackLowerThanAddress into StackGrowsDown, which then doesn't give
|
||||
// correct answer.
|
||||
void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
|
||||
void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||
static void StackLowerThanAddress(const void* ptr,
|
||||
bool* result) GTEST_NO_INLINE_;
|
||||
static void StackLowerThanAddress(const void* ptr, bool* result) {
|
||||
int dummy;
|
||||
*result = (&dummy < ptr);
|
||||
}
|
||||
|
||||
// Make sure AddressSanitizer does not tamper with the stack here.
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
bool StackGrowsDown() {
|
||||
static bool StackGrowsDown() {
|
||||
int dummy;
|
||||
bool result;
|
||||
StackLowerThanAddress(&dummy, &result);
|
||||
return result;
|
||||
}
|
||||
# endif // GTEST_HAS_CLONE
|
||||
|
||||
// Spawns a child process with the same executable as the current process in
|
||||
// a thread-safe manner and instructs it to run the death test. The
|
||||
|
|
@ -1184,6 +1416,13 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
|||
*test = new WindowsDeathTest(statement, regex, file, line);
|
||||
}
|
||||
|
||||
# elif GTEST_OS_FUCHSIA
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
||||
GTEST_FLAG(death_test_style) == "fast") {
|
||||
*test = new FuchsiaDeathTest(statement, regex, file, line);
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
if (GTEST_FLAG(death_test_style) == "threadsafe") {
|
||||
|
|
@ -1204,31 +1443,11 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
|||
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 (::testing::internal::AlwaysTrue()) {
|
||||
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);
|
||||
}
|
||||
|
||||
# if GTEST_OS_WINDOWS
|
||||
// Recreates the pipe and event handles from the provided parameters,
|
||||
// signals the event, and returns a file descriptor wrapped around the pipe
|
||||
// handle. This function is called in the child process only.
|
||||
int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||
static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||
size_t write_handle_as_size_t,
|
||||
size_t event_handle_as_size_t) {
|
||||
AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
|
||||
|
|
@ -1239,7 +1458,7 @@ int GetStatusFileDescriptor(unsigned int parent_process_id,
|
|||
StreamableToString(parent_process_id));
|
||||
}
|
||||
|
||||
// TODO(vladl@google.com): Replace the following check with a
|
||||
// FIXME: Replace the following check with a
|
||||
// compile-time assertion when available.
|
||||
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
|
||||
|
||||
|
|
@ -1247,7 +1466,7 @@ int GetStatusFileDescriptor(unsigned int parent_process_id,
|
|||
reinterpret_cast<HANDLE>(write_handle_as_size_t);
|
||||
HANDLE dup_write_handle;
|
||||
|
||||
// The newly initialized handle is accessible only in in the parent
|
||||
// The newly initialized handle is accessible only in the parent
|
||||
// process. To obtain one accessible within the child, we need to use
|
||||
// DuplicateHandle.
|
||||
if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
|
||||
|
|
@ -1324,6 +1543,16 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
|||
write_fd = GetStatusFileDescriptor(parent_process_id,
|
||||
write_handle_as_size_t,
|
||||
event_handle_as_size_t);
|
||||
|
||||
# elif GTEST_OS_FUCHSIA
|
||||
|
||||
if (fields.size() != 3
|
||||
|| !ParseNaturalNumber(fields[1], &line)
|
||||
|| !ParseNaturalNumber(fields[2], &index)) {
|
||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
|
||||
+ GTEST_FLAG(internal_run_death_test));
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
if (fields.size() != 4
|
||||
|
|
|
|||
|
|
@ -26,14 +26,12 @@
|
|||
// 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.
|
||||
//
|
||||
// Authors: keith.ray@gmail.com (Keith Ray)
|
||||
|
||||
#include "gtest/gtest-message.h"
|
||||
#include "gtest/internal/gtest-filepath.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/gtest-message.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
# include <windows.h>
|
||||
|
|
@ -48,6 +46,8 @@
|
|||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# define GTEST_PATH_MAX_ _MAX_PATH
|
||||
#elif defined(PATH_MAX)
|
||||
|
|
@ -58,8 +58,6 @@
|
|||
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
|
|
@ -130,7 +128,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
|
|||
return *this;
|
||||
}
|
||||
|
||||
// Returns a pointer to the last occurence of a valid path separator in
|
||||
// Returns a pointer to the last occurrence of a valid path separator in
|
||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||
// separators. Returns NULL if no path separator was found.
|
||||
const char* FilePath::FindLastPathSeparator() const {
|
||||
|
|
@ -252,7 +250,7 @@ bool FilePath::DirectoryExists() const {
|
|||
// root directory per disk drive.)
|
||||
bool FilePath::IsRootDirectory() const {
|
||||
#if GTEST_OS_WINDOWS
|
||||
// TODO(wan@google.com): on Windows a network share like
|
||||
// FIXME: on Windows a network share like
|
||||
// \\server\share can be a root directory, although it cannot be the
|
||||
// current directory. Handle this properly.
|
||||
return pathname_.length() == 3 && IsAbsolutePath();
|
||||
|
|
@ -352,7 +350,7 @@ FilePath FilePath::RemoveTrailingPathSeparator() const {
|
|||
// Removes any redundant separators that might be in the pathname.
|
||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||
// redundancies that might be in a pathname involving "." or "..".
|
||||
// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
|
||||
// FIXME: handle Windows network shares (e.g. \\server\share).
|
||||
void FilePath::Normalize() {
|
||||
if (pathname_.c_str() == NULL) {
|
||||
pathname_ = "";
|
||||
|
|
|
|||
|
|
@ -27,24 +27,13 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Utility functions and classes used by the Google C++ testing framework.
|
||||
//
|
||||
// Author: wan@google.com (Zhanyong Wan)
|
||||
//
|
||||
// Utility functions and classes used by the Google C++ testing framework.//
|
||||
// This file contains purely Google Test's internal implementation. Please
|
||||
// DO NOT #INCLUDE IT IN A USER PROGRAM.
|
||||
|
||||
#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
#define GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
|
||||
// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
|
||||
// part of Google Test's implementation; otherwise it's undefined.
|
||||
#if !GTEST_IMPLEMENTATION_
|
||||
// If this file is included from the user's code, just say no.
|
||||
# error "gtest-internal-inl.h is part of Google Test's internal implementation."
|
||||
# error "It must not be included except by Google Test itself."
|
||||
#endif // GTEST_IMPLEMENTATION_
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
# include <errno.h>
|
||||
#endif // !_WIN32_WCE
|
||||
|
|
@ -67,9 +56,12 @@
|
|||
# include <windows.h> // NOLINT
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include "gtest/gtest.h" // NOLINT
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/gtest-spi.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
namespace testing {
|
||||
|
||||
// Declares the flags.
|
||||
|
|
@ -94,12 +86,14 @@ const char kFilterFlag[] = "filter";
|
|||
const char kListTestsFlag[] = "list_tests";
|
||||
const char kOutputFlag[] = "output";
|
||||
const char kPrintTimeFlag[] = "print_time";
|
||||
const char kPrintUTF8Flag[] = "print_utf8";
|
||||
const char kRandomSeedFlag[] = "random_seed";
|
||||
const char kRepeatFlag[] = "repeat";
|
||||
const char kShuffleFlag[] = "shuffle";
|
||||
const char kStackTraceDepthFlag[] = "stack_trace_depth";
|
||||
const char kStreamResultToFlag[] = "stream_result_to";
|
||||
const char kThrowOnFailureFlag[] = "throw_on_failure";
|
||||
const char kFlagfileFlag[] = "flagfile";
|
||||
|
||||
// A valid random seed must be in [1, kMaxRandomSeed].
|
||||
const int kMaxRandomSeed = 99999;
|
||||
|
|
@ -173,6 +167,7 @@ class GTestFlagSaver {
|
|||
list_tests_ = GTEST_FLAG(list_tests);
|
||||
output_ = GTEST_FLAG(output);
|
||||
print_time_ = GTEST_FLAG(print_time);
|
||||
print_utf8_ = GTEST_FLAG(print_utf8);
|
||||
random_seed_ = GTEST_FLAG(random_seed);
|
||||
repeat_ = GTEST_FLAG(repeat);
|
||||
shuffle_ = GTEST_FLAG(shuffle);
|
||||
|
|
@ -194,6 +189,7 @@ class GTestFlagSaver {
|
|||
GTEST_FLAG(list_tests) = list_tests_;
|
||||
GTEST_FLAG(output) = output_;
|
||||
GTEST_FLAG(print_time) = print_time_;
|
||||
GTEST_FLAG(print_utf8) = print_utf8_;
|
||||
GTEST_FLAG(random_seed) = random_seed_;
|
||||
GTEST_FLAG(repeat) = repeat_;
|
||||
GTEST_FLAG(shuffle) = shuffle_;
|
||||
|
|
@ -215,6 +211,7 @@ class GTestFlagSaver {
|
|||
bool list_tests_;
|
||||
std::string output_;
|
||||
bool print_time_;
|
||||
bool print_utf8_;
|
||||
internal::Int32 random_seed_;
|
||||
internal::Int32 repeat_;
|
||||
bool shuffle_;
|
||||
|
|
@ -425,13 +422,17 @@ class OsStackTraceGetterInterface {
|
|||
// in the trace.
|
||||
// skip_count - the number of top frames to be skipped; doesn't count
|
||||
// against max_depth.
|
||||
virtual string CurrentStackTrace(int max_depth, int skip_count) = 0;
|
||||
virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0;
|
||||
|
||||
// UponLeavingGTest() should be called immediately before Google Test calls
|
||||
// user code. It saves some information about the current stack that
|
||||
// CurrentStackTrace() will use to find and hide Google Test stack frames.
|
||||
virtual void UponLeavingGTest() = 0;
|
||||
|
||||
// This string is inserted in place of stack frames that are part of
|
||||
// Google Test's implementation.
|
||||
static const char* const kElidedFramesMarker;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
|
||||
};
|
||||
|
|
@ -439,25 +440,21 @@ class OsStackTraceGetterInterface {
|
|||
// A working implementation of the OsStackTraceGetterInterface interface.
|
||||
class OsStackTraceGetter : public OsStackTraceGetterInterface {
|
||||
public:
|
||||
OsStackTraceGetter() : caller_frame_(NULL) {}
|
||||
OsStackTraceGetter() {}
|
||||
|
||||
virtual string CurrentStackTrace(int max_depth, int skip_count)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
|
||||
// This string is inserted in place of stack frames that are part of
|
||||
// Google Test's implementation.
|
||||
static const char* const kElidedFramesMarker;
|
||||
virtual std::string CurrentStackTrace(int max_depth, int skip_count);
|
||||
virtual void UponLeavingGTest();
|
||||
|
||||
private:
|
||||
Mutex mutex_; // protects all internal state
|
||||
#if GTEST_HAS_ABSL
|
||||
Mutex mutex_; // Protects all internal state.
|
||||
|
||||
// We save the stack frame below the frame that calls user code.
|
||||
// We do this because the address of the frame immediately below
|
||||
// the user code changes between the call to UponLeavingGTest()
|
||||
// and any calls to CurrentStackTrace() from within the user code.
|
||||
void* caller_frame_;
|
||||
// and any calls to the stack trace code from within the user code.
|
||||
void* caller_frame_ = nullptr;
|
||||
#endif // GTEST_HAS_ABSL
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
|
||||
};
|
||||
|
|
@ -673,13 +670,11 @@ class GTEST_API_ UnitTestImpl {
|
|||
tear_down_tc)->AddTestInfo(test_info);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// Returns ParameterizedTestCaseRegistry object used to keep track of
|
||||
// value-parameterized tests and instantiate and register them.
|
||||
internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
|
||||
return parameterized_test_registry_;
|
||||
}
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
||||
// Sets the TestCase object for the test that's currently running.
|
||||
void set_current_test_case(TestCase* a_current_test_case) {
|
||||
|
|
@ -854,14 +849,12 @@ class GTEST_API_ UnitTestImpl {
|
|||
// shuffled order.
|
||||
std::vector<int> test_case_indices_;
|
||||
|
||||
#if GTEST_HAS_PARAM_TEST
|
||||
// ParameterizedTestRegistry object used to register value-parameterized
|
||||
// tests.
|
||||
internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
|
||||
|
||||
// Indicates whether RegisterParameterizedTests() has been called already.
|
||||
bool parameterized_tests_registered_;
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
||||
// Index of the last death test case registered. Initially -1.
|
||||
int last_death_test_case_;
|
||||
|
|
@ -1001,7 +994,7 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
|
|||
|
||||
const bool parse_success = *end == '\0' && errno == 0;
|
||||
|
||||
// TODO(vladl@google.com): Convert this to compile time assertion when it is
|
||||
// FIXME: Convert this to compile time assertion when it is
|
||||
// available.
|
||||
GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
|
||||
|
||||
|
|
@ -1049,21 +1042,19 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
virtual ~AbstractSocketWriter() {}
|
||||
|
||||
// Sends a string to the socket.
|
||||
virtual void Send(const string& message) = 0;
|
||||
virtual void Send(const std::string& message) = 0;
|
||||
|
||||
// Closes the socket.
|
||||
virtual void CloseConnection() {}
|
||||
|
||||
// Sends a string and a newline to the socket.
|
||||
void SendLn(const string& message) {
|
||||
Send(message + "\n");
|
||||
}
|
||||
void SendLn(const std::string& message) { Send(message + "\n"); }
|
||||
};
|
||||
|
||||
// Concrete class for actually writing strings to a socket.
|
||||
class SocketWriter : public AbstractSocketWriter {
|
||||
public:
|
||||
SocketWriter(const string& host, const string& port)
|
||||
SocketWriter(const std::string& host, const std::string& port)
|
||||
: sockfd_(-1), host_name_(host), port_num_(port) {
|
||||
MakeConnection();
|
||||
}
|
||||
|
|
@ -1074,7 +1065,7 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
}
|
||||
|
||||
// Sends a string to the socket.
|
||||
virtual void Send(const string& message) {
|
||||
virtual void Send(const std::string& message) {
|
||||
GTEST_CHECK_(sockfd_ != -1)
|
||||
<< "Send() can be called only when there is a connection.";
|
||||
|
||||
|
|
@ -1100,17 +1091,19 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
}
|
||||
|
||||
int sockfd_; // socket file descriptor
|
||||
const string host_name_;
|
||||
const string port_num_;
|
||||
const std::string host_name_;
|
||||
const std::string port_num_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
|
||||
}; // class SocketWriter
|
||||
|
||||
// Escapes '=', '&', '%', and '\n' characters in str as "%xx".
|
||||
static string UrlEncode(const char* str);
|
||||
static std::string UrlEncode(const char* str);
|
||||
|
||||
StreamingListener(const string& host, const string& port)
|
||||
: socket_writer_(new SocketWriter(host, port)) { Start(); }
|
||||
StreamingListener(const std::string& host, const std::string& port)
|
||||
: socket_writer_(new SocketWriter(host, port)) {
|
||||
Start();
|
||||
}
|
||||
|
||||
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
||||
: socket_writer_(socket_writer) { Start(); }
|
||||
|
|
@ -1171,13 +1164,13 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
|
||||
private:
|
||||
// Sends the given message and a newline to the socket.
|
||||
void SendLn(const string& message) { socket_writer_->SendLn(message); }
|
||||
void SendLn(const std::string& message) { socket_writer_->SendLn(message); }
|
||||
|
||||
// Called at the start of streaming to notify the receiver what
|
||||
// protocol we are using.
|
||||
void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
|
||||
|
||||
string FormatBool(bool value) { return value ? "1" : "0"; }
|
||||
std::string FormatBool(bool value) { return value ? "1" : "0"; }
|
||||
|
||||
const scoped_ptr<AbstractSocketWriter> socket_writer_;
|
||||
|
||||
|
|
@ -1189,4 +1182,6 @@ class StreamingListener : public EmptyTestEventListener {
|
|||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@
|
|||
// 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)
|
||||
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
|
|
@ -35,6 +34,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
# include <windows.h>
|
||||
|
|
@ -57,19 +57,21 @@
|
|||
# include <sys/procfs.h>
|
||||
#endif // GTEST_OS_QNX
|
||||
|
||||
#if GTEST_OS_AIX
|
||||
# include <procinfo.h>
|
||||
# include <sys/types.h>
|
||||
#endif // GTEST_OS_AIX
|
||||
|
||||
#if GTEST_OS_FUCHSIA
|
||||
# include <zircon/process.h>
|
||||
# include <zircon/syscalls.h>
|
||||
#endif // GTEST_OS_FUCHSIA
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "gtest/gtest-message.h"
|
||||
#include "gtest/internal/gtest-internal.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 exists to
|
||||
// prevent the accidental inclusion of gtest-internal-inl.h in the
|
||||
// user's code.
|
||||
#define GTEST_IMPLEMENTATION_ 1
|
||||
#include "src/gtest-internal-inl.h"
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
|
@ -83,10 +85,31 @@ const int kStdOutFileno = STDOUT_FILENO;
|
|||
const int kStdErrFileno = STDERR_FILENO;
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if GTEST_OS_MAC
|
||||
#if GTEST_OS_LINUX
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
T ReadProcFileField(const std::string& filename, int field) {
|
||||
std::string dummy;
|
||||
std::ifstream file(filename.c_str());
|
||||
while (field-- > 0) {
|
||||
file >> dummy;
|
||||
}
|
||||
T output = 0;
|
||||
file >> output;
|
||||
return output;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Returns the number of active threads, or 0 when there is an error.
|
||||
size_t GetThreadCount() {
|
||||
const std::string filename =
|
||||
(Message() << "/proc/" << getpid() << "/stat").GetString();
|
||||
return ReadProcFileField<int>(filename, 19);
|
||||
}
|
||||
|
||||
#elif GTEST_OS_MAC
|
||||
|
||||
// Returns the number of threads running in the process, or 0 to indicate that
|
||||
// we cannot detect it.
|
||||
size_t GetThreadCount() {
|
||||
const task_t task = mach_task_self();
|
||||
mach_msg_type_number_t thread_count;
|
||||
|
|
@ -124,6 +147,38 @@ size_t GetThreadCount() {
|
|||
}
|
||||
}
|
||||
|
||||
#elif GTEST_OS_AIX
|
||||
|
||||
size_t GetThreadCount() {
|
||||
struct procentry64 entry;
|
||||
pid_t pid = getpid();
|
||||
int status = getprocs64(&entry, sizeof(entry), NULL, 0, &pid, 1);
|
||||
if (status == 1) {
|
||||
return entry.pi_thcount;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#elif GTEST_OS_FUCHSIA
|
||||
|
||||
size_t GetThreadCount() {
|
||||
int dummy_buffer;
|
||||
size_t avail;
|
||||
zx_status_t status = zx_object_get_info(
|
||||
zx_process_self(),
|
||||
ZX_INFO_PROCESS_THREADS,
|
||||
&dummy_buffer,
|
||||
0,
|
||||
nullptr,
|
||||
&avail);
|
||||
if (status == ZX_OK) {
|
||||
return avail;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
size_t GetThreadCount() {
|
||||
|
|
@ -132,7 +187,7 @@ size_t GetThreadCount() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_MAC
|
||||
#endif // GTEST_OS_LINUX
|
||||
|
||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
||||
|
||||
|
|
@ -196,8 +251,8 @@ void Notification::WaitForNotification() {
|
|||
}
|
||||
|
||||
Mutex::Mutex()
|
||||
: type_(kDynamic),
|
||||
owner_thread_id_(0),
|
||||
: owner_thread_id_(0),
|
||||
type_(kDynamic),
|
||||
critical_section_init_phase_(0),
|
||||
critical_section_(new CRITICAL_SECTION) {
|
||||
::InitializeCriticalSection(critical_section_);
|
||||
|
|
@ -206,9 +261,9 @@ Mutex::Mutex()
|
|||
Mutex::~Mutex() {
|
||||
// Static mutexes are leaked intentionally. It is not thread-safe to try
|
||||
// to clean them up.
|
||||
// TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires
|
||||
// FIXME: Switch to Slim Reader/Writer (SRW) Locks, which requires
|
||||
// nothing to clean it up but is available only on Vista and later.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/Sync/slim-reader-writer--srw--locks
|
||||
if (type_ == kDynamic) {
|
||||
::DeleteCriticalSection(critical_section_);
|
||||
delete critical_section_;
|
||||
|
|
@ -239,6 +294,43 @@ void Mutex::AssertHeld() {
|
|||
<< "The current thread is not holding the mutex @" << this;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Use the RAII idiom to flag mem allocs that are intentionally never
|
||||
// deallocated. The motivation is to silence the false positive mem leaks
|
||||
// that are reported by the debug version of MS's CRT which can only detect
|
||||
// if an alloc is missing a matching deallocation.
|
||||
// Example:
|
||||
// MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
// critical_section_ = new CRITICAL_SECTION;
|
||||
//
|
||||
class MemoryIsNotDeallocated
|
||||
{
|
||||
public:
|
||||
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
||||
#ifdef _MSC_VER
|
||||
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
|
||||
// doesn't report mem leak if there's no matching deallocation.
|
||||
_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
|
||||
~MemoryIsNotDeallocated() {
|
||||
#ifdef _MSC_VER
|
||||
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
|
||||
_CrtSetDbgFlag(old_crtdbg_flag_);
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
|
||||
private:
|
||||
int old_crtdbg_flag_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Initializes owner_thread_id_ and critical_section_ in static mutexes.
|
||||
void Mutex::ThreadSafeLazyInit() {
|
||||
// Dynamic mutexes are initialized in the constructor.
|
||||
|
|
@ -249,7 +341,11 @@ void Mutex::ThreadSafeLazyInit() {
|
|||
// If critical_section_init_phase_ was 0 before the exchange, we
|
||||
// are the first to test it and need to perform the initialization.
|
||||
owner_thread_id_ = 0;
|
||||
critical_section_ = new CRITICAL_SECTION;
|
||||
{
|
||||
// Use RAII to flag that following mem alloc is never deallocated.
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
critical_section_ = new CRITICAL_SECTION;
|
||||
}
|
||||
::InitializeCriticalSection(critical_section_);
|
||||
// Updates the critical_section_init_phase_ to 2 to signal
|
||||
// initialization complete.
|
||||
|
|
@ -288,7 +384,7 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
|||
Notification* thread_can_start) {
|
||||
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
|
||||
DWORD thread_id;
|
||||
// TODO(yukawa): Consider to use _beginthreadex instead.
|
||||
// FIXME: Consider to use _beginthreadex instead.
|
||||
HANDLE thread_handle = ::CreateThread(
|
||||
NULL, // Default security.
|
||||
0, // Default stack size.
|
||||
|
|
@ -456,7 +552,7 @@ class ThreadLocalRegistryImpl {
|
|||
FALSE,
|
||||
thread_id);
|
||||
GTEST_CHECK_(thread != NULL);
|
||||
// We need to to pass a valid thread ID pointer into CreateThread for it
|
||||
// We need to pass a valid thread ID pointer into CreateThread for it
|
||||
// to work correctly under Win98.
|
||||
DWORD watcher_thread_id;
|
||||
HANDLE watcher_thread = ::CreateThread(
|
||||
|
|
@ -491,7 +587,8 @@ class ThreadLocalRegistryImpl {
|
|||
// Returns map of thread local instances.
|
||||
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
|
||||
mutex_.AssertHeld();
|
||||
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals;
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
@ -631,7 +728,7 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
|||
}
|
||||
|
||||
// Helper function used by ValidateRegex() to format error messages.
|
||||
std::string FormatRegexSyntaxError(const char* regex, int index) {
|
||||
static std::string FormatRegexSyntaxError(const char* regex, int index) {
|
||||
return (Message() << "Syntax error at index " << index
|
||||
<< " in simple regular expression \"" << regex << "\": ").GetString();
|
||||
}
|
||||
|
|
@ -640,7 +737,7 @@ std::string FormatRegexSyntaxError(const char* regex, int index) {
|
|||
// otherwise returns true.
|
||||
bool ValidateRegex(const char* regex) {
|
||||
if (regex == NULL) {
|
||||
// TODO(wan@google.com): fix the source file location in the
|
||||
// FIXME: fix the source file location in the
|
||||
// assertion failures to match where the regex is used in user
|
||||
// code.
|
||||
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
|
||||
|
|
@ -865,7 +962,6 @@ GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
|||
return file_name + ":" + StreamableToString(line);
|
||||
}
|
||||
|
||||
|
||||
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
|
||||
: severity_(severity) {
|
||||
const char* const marker =
|
||||
|
|
@ -884,9 +980,10 @@ GTestLog::~GTestLog() {
|
|||
posix::Abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Microsoft deprecation warnings for POSIX functions called from
|
||||
// this class (creat, dup, dup2, and close)
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
|
||||
GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
|
||||
|
||||
#if GTEST_HAS_STREAM_REDIRECTION
|
||||
|
||||
|
|
@ -962,12 +1059,6 @@ class CapturedStream {
|
|||
}
|
||||
|
||||
private:
|
||||
// Reads the entire content of a file as an std::string.
|
||||
static std::string ReadEntireFile(FILE* file);
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
static size_t GetFileSize(FILE* file);
|
||||
|
||||
const int fd_; // A stream to capture.
|
||||
int uncaptured_fd_;
|
||||
// Name of the temporary file holding the stderr output.
|
||||
|
|
@ -976,42 +1067,14 @@ class CapturedStream {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
|
||||
};
|
||||
|
||||
// Returns the size (in bytes) of a file.
|
||||
size_t CapturedStream::GetFileSize(FILE* file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
return static_cast<size_t>(ftell(file));
|
||||
}
|
||||
|
||||
// Reads the entire content of a file as a string.
|
||||
std::string CapturedStream::ReadEntireFile(FILE* file) {
|
||||
const size_t file_size = GetFileSize(file);
|
||||
char* const buffer = new char[file_size];
|
||||
|
||||
size_t bytes_last_read = 0; // # of bytes read in the last fread()
|
||||
size_t bytes_read = 0; // # of bytes read so far
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
// Keeps reading the file until we cannot read further or the
|
||||
// pre-determined file size is reached.
|
||||
do {
|
||||
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
||||
bytes_read += bytes_last_read;
|
||||
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||
|
||||
const std::string content(buffer, bytes_read);
|
||||
delete[] buffer;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||
|
||||
static CapturedStream* g_captured_stderr = NULL;
|
||||
static CapturedStream* g_captured_stdout = NULL;
|
||||
|
||||
// Starts capturing an output stream (stdout/stderr).
|
||||
void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
|
||||
static void CaptureStream(int fd, const char* stream_name,
|
||||
CapturedStream** stream) {
|
||||
if (*stream != NULL) {
|
||||
GTEST_LOG_(FATAL) << "Only one " << stream_name
|
||||
<< " capturer can exist at a time.";
|
||||
|
|
@ -1020,7 +1083,7 @@ void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
|
|||
}
|
||||
|
||||
// Stops capturing the output stream and returns the captured string.
|
||||
std::string GetCapturedStream(CapturedStream** captured_stream) {
|
||||
static std::string GetCapturedStream(CapturedStream** captured_stream) {
|
||||
const std::string content = (*captured_stream)->GetCapturedString();
|
||||
|
||||
delete *captured_stream;
|
||||
|
|
@ -1051,25 +1114,67 @@ std::string GetCapturedStderr() {
|
|||
|
||||
#endif // GTEST_HAS_STREAM_REDIRECTION
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
|
||||
// A copy of all command line arguments. Set by InitGoogleTest().
|
||||
::std::vector<testing::internal::string> g_argvs;
|
||||
|
||||
static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
|
||||
NULL; // Owned.
|
||||
|
||||
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
|
||||
if (g_injected_test_argvs != argvs)
|
||||
delete g_injected_test_argvs;
|
||||
g_injected_test_argvs = argvs;
|
||||
|
||||
size_t GetFileSize(FILE* file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
return static_cast<size_t>(ftell(file));
|
||||
}
|
||||
|
||||
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
|
||||
std::string ReadEntireFile(FILE* file) {
|
||||
const size_t file_size = GetFileSize(file);
|
||||
char* const buffer = new char[file_size];
|
||||
|
||||
size_t bytes_last_read = 0; // # of bytes read in the last fread()
|
||||
size_t bytes_read = 0; // # of bytes read so far
|
||||
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
// Keeps reading the file until we cannot read further or the
|
||||
// pre-determined file size is reached.
|
||||
do {
|
||||
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
||||
bytes_read += bytes_last_read;
|
||||
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||
|
||||
const std::string content(buffer, bytes_read);
|
||||
delete[] buffer;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
static const std::vector<std::string>* g_injected_test_argvs = NULL; // Owned.
|
||||
|
||||
std::vector<std::string> GetInjectableArgvs() {
|
||||
if (g_injected_test_argvs != NULL) {
|
||||
return *g_injected_test_argvs;
|
||||
}
|
||||
return g_argvs;
|
||||
return GetArgvs();
|
||||
}
|
||||
|
||||
void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
|
||||
if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
|
||||
g_injected_test_argvs = new_argvs;
|
||||
}
|
||||
|
||||
void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
|
||||
SetInjectableArgvs(
|
||||
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
void SetInjectableArgvs(const std::vector< ::string>& new_argvs) {
|
||||
SetInjectableArgvs(
|
||||
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
void ClearInjectableArgvs() {
|
||||
delete g_injected_test_argvs;
|
||||
g_injected_test_argvs = NULL;
|
||||
}
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
|
|
@ -1143,16 +1248,23 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
|
|||
//
|
||||
// The value is considered true iff it's not "0".
|
||||
bool BoolFromGTestEnv(const char* flag, bool default_value) {
|
||||
#if defined(GTEST_GET_BOOL_FROM_ENV_)
|
||||
return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
|
||||
#else
|
||||
const std::string env_var = FlagToEnvVar(flag);
|
||||
const char* const string_value = posix::GetEnv(env_var.c_str());
|
||||
return string_value == NULL ?
|
||||
default_value : strcmp(string_value, "0") != 0;
|
||||
#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
|
||||
}
|
||||
|
||||
// Reads and returns a 32-bit integer stored in the environment
|
||||
// variable corresponding to the given flag; if it isn't set or
|
||||
// doesn't represent a valid 32-bit integer, returns default_value.
|
||||
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
||||
#if defined(GTEST_GET_INT32_FROM_ENV_)
|
||||
return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
|
||||
#else
|
||||
const std::string env_var = FlagToEnvVar(flag);
|
||||
const char* const string_value = posix::GetEnv(env_var.c_str());
|
||||
if (string_value == NULL) {
|
||||
|
|
@ -1170,14 +1282,36 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
|
|||
}
|
||||
|
||||
return result;
|
||||
#endif // defined(GTEST_GET_INT32_FROM_ENV_)
|
||||
}
|
||||
|
||||
// As a special case for the 'output' flag, if GTEST_OUTPUT is not
|
||||
// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
|
||||
// system. The value of XML_OUTPUT_FILE is a filename without the
|
||||
// "xml:" prefix of GTEST_OUTPUT.
|
||||
// Note that this is meant to be called at the call site so it does
|
||||
// not check that the flag is 'output'
|
||||
// In essence this checks an env variable called XML_OUTPUT_FILE
|
||||
// and if it is set we prepend "xml:" to its value, if it not set we return ""
|
||||
std::string OutputFlagAlsoCheckEnvVar(){
|
||||
std::string default_value_for_output_flag = "";
|
||||
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
|
||||
if (NULL != xml_output_file_env) {
|
||||
default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
|
||||
}
|
||||
return default_value_for_output_flag;
|
||||
}
|
||||
|
||||
// Reads and returns the string environment variable corresponding to
|
||||
// the given flag; if it's not set, returns default_value.
|
||||
const char* StringFromGTestEnv(const char* flag, const char* default_value) {
|
||||
#if defined(GTEST_GET_STRING_FROM_ENV_)
|
||||
return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
|
||||
#else
|
||||
const std::string env_var = FlagToEnvVar(flag);
|
||||
const char* const value = posix::GetEnv(env_var.c_str());
|
||||
return value == NULL ? default_value : value;
|
||||
#endif // defined(GTEST_GET_STRING_FROM_ENV_)
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
|
|
|||
|
|
@ -26,10 +26,9 @@
|
|||
// 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)
|
||||
|
||||
// Google Test - The Google C++ Testing Framework
|
||||
|
||||
// Google Test - The Google C++ Testing and Mocking Framework
|
||||
//
|
||||
// This file implements a universal value printer that can print a
|
||||
// value of any type T:
|
||||
|
|
@ -43,12 +42,13 @@
|
|||
// defines Foo.
|
||||
|
||||
#include "gtest/gtest-printers.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <cctype>
|
||||
#include <cwchar>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
|||
// If the object size is bigger than kThreshold, we'll have to omit
|
||||
// some details by printing only the first and the last kChunkSize
|
||||
// bytes.
|
||||
// TODO(wan): let the user control the threshold using a flag.
|
||||
// FIXME: let the user control the threshold using a flag.
|
||||
if (count < kThreshold) {
|
||||
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
||||
} else {
|
||||
|
|
@ -123,7 +123,7 @@ namespace internal {
|
|||
// Depending on the value of a char (or wchar_t), we print it in one
|
||||
// of three formats:
|
||||
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
||||
// - as a hexidecimal escape sequence (e.g. '\x7F'), or
|
||||
// - as a hexadecimal escape sequence (e.g. '\x7F'), or
|
||||
// - as a special escape sequence (e.g. '\r', '\n').
|
||||
enum CharFormat {
|
||||
kAsIs,
|
||||
|
|
@ -180,7 +180,10 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
|||
*os << static_cast<char>(c);
|
||||
return kAsIs;
|
||||
} else {
|
||||
*os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
|
||||
ostream::fmtflags flags = os->flags();
|
||||
*os << "\\x" << std::hex << std::uppercase
|
||||
<< static_cast<int>(static_cast<UnsignedChar>(c));
|
||||
os->flags(flags);
|
||||
return kHexEscape;
|
||||
}
|
||||
}
|
||||
|
|
@ -227,7 +230,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
|
|||
return;
|
||||
*os << " (" << static_cast<int>(c);
|
||||
|
||||
// For more convenience, we print c's code again in hexidecimal,
|
||||
// For more convenience, we print c's code again in hexadecimal,
|
||||
// unless c was already printed in the form '\x##' or the code is in
|
||||
// [1, 9].
|
||||
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
||||
|
|
@ -259,11 +262,12 @@ template <typename CharType>
|
|||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
||||
static void PrintCharsAsStringTo(
|
||||
static CharFormat PrintCharsAsStringTo(
|
||||
const CharType* begin, size_t len, ostream* os) {
|
||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||
*os << kQuoteBegin;
|
||||
bool is_previous_hex = false;
|
||||
CharFormat print_format = kAsIs;
|
||||
for (size_t index = 0; index < len; ++index) {
|
||||
const CharType cur = begin[index];
|
||||
if (is_previous_hex && IsXDigit(cur)) {
|
||||
|
|
@ -273,8 +277,13 @@ static void PrintCharsAsStringTo(
|
|||
*os << "\" " << kQuoteBegin;
|
||||
}
|
||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||
// Remember if any characters required hex escaping.
|
||||
if (is_previous_hex) {
|
||||
print_format = kHexEscape;
|
||||
}
|
||||
}
|
||||
*os << "\"";
|
||||
return print_format;
|
||||
}
|
||||
|
||||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||
|
|
@ -344,15 +353,90 @@ void PrintTo(const wchar_t* s, ostream* os) {
|
|||
}
|
||||
#endif // wchar_t is native
|
||||
|
||||
namespace {
|
||||
|
||||
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
|
||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
unsigned char ch = *s++;
|
||||
if (std::iscntrl(ch)) {
|
||||
switch (ch) {
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
|
||||
|
||||
bool IsValidUTF8(const char* str, size_t length) {
|
||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
||||
|
||||
for (size_t i = 0; i < length;) {
|
||||
unsigned char lead = s[i++];
|
||||
|
||||
if (lead <= 0x7f) {
|
||||
continue; // single-byte character (ASCII) 0..7F
|
||||
}
|
||||
if (lead < 0xc2) {
|
||||
return false; // trail byte or non-shortest form
|
||||
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
|
||||
++i; // 2-byte character
|
||||
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
|
||||
IsUTF8TrailByte(s[i]) &&
|
||||
IsUTF8TrailByte(s[i + 1]) &&
|
||||
// check for non-shortest form and surrogate
|
||||
(lead != 0xe0 || s[i] >= 0xa0) &&
|
||||
(lead != 0xed || s[i] < 0xa0)) {
|
||||
i += 2; // 3-byte character
|
||||
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
|
||||
IsUTF8TrailByte(s[i]) &&
|
||||
IsUTF8TrailByte(s[i + 1]) &&
|
||||
IsUTF8TrailByte(s[i + 2]) &&
|
||||
// check for non-shortest form
|
||||
(lead != 0xf0 || s[i] >= 0x90) &&
|
||||
(lead != 0xf4 || s[i] < 0x90)) {
|
||||
i += 3; // 4-byte character
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||
if (!ContainsUnprintableControlCodes(str, length) &&
|
||||
IsValidUTF8(str, length)) {
|
||||
*os << "\n As Text: \"" << str << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Prints a ::string object.
|
||||
#if GTEST_HAS_GLOBAL_STRING
|
||||
void PrintStringTo(const ::string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||
if (GTEST_FLAG(print_utf8)) {
|
||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // GTEST_HAS_GLOBAL_STRING
|
||||
|
||||
void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||
if (GTEST_FLAG(print_utf8)) {
|
||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prints a ::wstring object.
|
||||
|
|
|
|||
|
|
@ -26,21 +26,12 @@
|
|||
// 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: mheule@google.com (Markus Heule)
|
||||
//
|
||||
// The Google C++ Testing Framework (Google Test)
|
||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||
|
||||
#include "gtest/gtest-test-part.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 exists to
|
||||
// prevent the accidental inclusion of gtest-internal-inl.h in the
|
||||
// user's code.
|
||||
#define GTEST_IMPLEMENTATION_ 1
|
||||
#include "src/gtest-internal-inl.h"
|
||||
#undef GTEST_IMPLEMENTATION_
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@
|
|||
// 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)
|
||||
|
||||
|
||||
#include "gtest/gtest-typed-test.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
|
|
@ -45,33 +45,41 @@ static const char* SkipSpaces(const char* str) {
|
|||
return str;
|
||||
}
|
||||
|
||||
static std::vector<std::string> SplitIntoTestNames(const char* src) {
|
||||
std::vector<std::string> name_vec;
|
||||
src = SkipSpaces(src);
|
||||
for (; src != NULL; src = SkipComma(src)) {
|
||||
name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
|
||||
}
|
||||
return name_vec;
|
||||
}
|
||||
|
||||
// Verifies that registered_tests match the test names in
|
||||
// defined_test_names_; returns registered_tests if successful, or
|
||||
// registered_tests_; returns registered_tests if successful, or
|
||||
// aborts the program otherwise.
|
||||
const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||
const char* file, int line, const char* registered_tests) {
|
||||
typedef ::std::set<const char*>::const_iterator DefinedTestIter;
|
||||
typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
|
||||
registered_ = true;
|
||||
|
||||
// Skip initial whitespace in registered_tests since some
|
||||
// preprocessors prefix stringizied literals with whitespace.
|
||||
registered_tests = SkipSpaces(registered_tests);
|
||||
std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
|
||||
|
||||
Message errors;
|
||||
::std::set<std::string> tests;
|
||||
for (const char* names = registered_tests; names != NULL;
|
||||
names = SkipComma(names)) {
|
||||
const std::string name = GetPrefixUntilComma(names);
|
||||
|
||||
std::set<std::string> tests;
|
||||
for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
|
||||
name_it != name_vec.end(); ++name_it) {
|
||||
const std::string& name = *name_it;
|
||||
if (tests.count(name) != 0) {
|
||||
errors << "Test " << name << " is listed more than once.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (DefinedTestIter it = defined_test_names_.begin();
|
||||
it != defined_test_names_.end();
|
||||
for (RegisteredTestIter it = registered_tests_.begin();
|
||||
it != registered_tests_.end();
|
||||
++it) {
|
||||
if (name == *it) {
|
||||
if (name == it->first) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -85,11 +93,11 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
|||
}
|
||||
}
|
||||
|
||||
for (DefinedTestIter it = defined_test_names_.begin();
|
||||
it != defined_test_names_.end();
|
||||
for (RegisteredTestIter it = registered_tests_.begin();
|
||||
it != registered_tests_.end();
|
||||
++it) {
|
||||
if (tests.count(*it) == 0) {
|
||||
errors << "You forgot to list test " << *it << ".\n";
|
||||
if (tests.count(it->first) == 0) {
|
||||
errors << "You forgot to list test " << it->first << ".\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,11 +28,10 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
GTEST_API_ int main(int argc, char **argv) {
|
||||
printf("Running main() from gtest_main.cc\n");
|
||||
printf("Running main() from %s\n", __FILE__);
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue