mirror of
https://github.com/google/googletest.git
synced 2025-12-21 19:14:55 +08:00
Merge branch 'google:master' into master
This commit is contained in:
commit
2eebf3732a
@ -1919,6 +1919,58 @@ time.
|
|||||||
If you combine this with `--gtest_repeat=N`, googletest will pick a different
|
If you combine this with `--gtest_repeat=N`, googletest will pick a different
|
||||||
random seed and re-shuffle the tests in each iteration.
|
random seed and re-shuffle the tests in each iteration.
|
||||||
|
|
||||||
|
### Distributing Test Functions to Multiple Machines
|
||||||
|
|
||||||
|
If you have more than one machine you can use to run a test program, you might
|
||||||
|
want to run the test functions in parallel and get the result faster. We call
|
||||||
|
this technique *sharding*, where each machine is called a *shard*.
|
||||||
|
|
||||||
|
GoogleTest is compatible with test sharding. To take advantage of this feature,
|
||||||
|
your test runner (not part of GoogleTest) needs to do the following:
|
||||||
|
|
||||||
|
1. Allocate a number of machines (shards) to run the tests.
|
||||||
|
1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total
|
||||||
|
number of shards. It must be the same for all shards.
|
||||||
|
1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index
|
||||||
|
of the shard. Different shards must be assigned different indices, which
|
||||||
|
must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`.
|
||||||
|
1. Run the same test program on all shards. When GoogleTest sees the above two
|
||||||
|
environment variables, it will select a subset of the test functions to run.
|
||||||
|
Across all shards, each test function in the program will be run exactly
|
||||||
|
once.
|
||||||
|
1. Wait for all shards to finish, then collect and report the results.
|
||||||
|
|
||||||
|
Your project may have tests that were written without GoogleTest and thus don't
|
||||||
|
understand this protocol. In order for your test runner to figure out which test
|
||||||
|
supports sharding, it can set the environment variable `GTEST_SHARD_STATUS_FILE`
|
||||||
|
to a non-existent file path. If a test program supports sharding, it will create
|
||||||
|
this file to acknowledge that fact; otherwise it will not create it. The actual
|
||||||
|
contents of the file are not important at this time, although we may put some
|
||||||
|
useful information in it in the future.
|
||||||
|
|
||||||
|
Here's an example to make it clear. Suppose you have a test program `foo_test`
|
||||||
|
that contains the following 5 test functions:
|
||||||
|
|
||||||
|
```
|
||||||
|
TEST(A, V)
|
||||||
|
TEST(A, W)
|
||||||
|
TEST(B, X)
|
||||||
|
TEST(B, Y)
|
||||||
|
TEST(B, Z)
|
||||||
|
```
|
||||||
|
|
||||||
|
Suppose you have 3 machines at your disposal. To run the test functions in
|
||||||
|
parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and set
|
||||||
|
`GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively. Then you would
|
||||||
|
run the same `foo_test` on each machine.
|
||||||
|
|
||||||
|
GoogleTest reserves the right to change how the work is distributed across the
|
||||||
|
shards, but here's one possible scenario:
|
||||||
|
|
||||||
|
* Machine #0 runs `A.V` and `B.X`.
|
||||||
|
* Machine #1 runs `A.W` and `B.Y`.
|
||||||
|
* Machine #2 runs `B.Z`.
|
||||||
|
|
||||||
### Controlling Test Output
|
### Controlling Test Output
|
||||||
|
|
||||||
#### Colored Terminal Output
|
#### Colored Terminal Output
|
||||||
|
|||||||
@ -394,7 +394,7 @@ TEST_F(LogIsVisibleTest, WorksWhenVerbosityIsWarning) {
|
|||||||
// and log severity.
|
// and log severity.
|
||||||
void TestLogWithSeverity(const std::string& verbosity, LogSeverity severity,
|
void TestLogWithSeverity(const std::string& verbosity, LogSeverity severity,
|
||||||
bool should_print) {
|
bool should_print) {
|
||||||
const std::string old_flag = GMOCK_FLAG(verbose);
|
const std::string old_flag = GMOCK_FLAG_GET(verbose);
|
||||||
GMOCK_FLAG_SET(verbose, verbosity);
|
GMOCK_FLAG_SET(verbose, verbosity);
|
||||||
CaptureStdout();
|
CaptureStdout();
|
||||||
Log(severity, "Test log.\n", 0);
|
Log(severity, "Test log.\n", 0);
|
||||||
@ -413,7 +413,7 @@ void TestLogWithSeverity(const std::string& verbosity, LogSeverity severity,
|
|||||||
// Tests that when the stack_frames_to_skip parameter is negative,
|
// Tests that when the stack_frames_to_skip parameter is negative,
|
||||||
// Log() doesn't include the stack trace in the output.
|
// Log() doesn't include the stack trace in the output.
|
||||||
TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) {
|
TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) {
|
||||||
const std::string saved_flag = GMOCK_FLAG(verbose);
|
const std::string saved_flag = GMOCK_FLAG_GET(verbose);
|
||||||
GMOCK_FLAG_SET(verbose, kInfoVerbosity);
|
GMOCK_FLAG_SET(verbose, kInfoVerbosity);
|
||||||
CaptureStdout();
|
CaptureStdout();
|
||||||
Log(kInfo, "Test log.\n", -1);
|
Log(kInfo, "Test log.\n", -1);
|
||||||
@ -499,7 +499,7 @@ TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsInvalid) {
|
|||||||
// Verifies that Log() behaves correctly for the given verbosity level
|
// Verifies that Log() behaves correctly for the given verbosity level
|
||||||
// and log severity.
|
// and log severity.
|
||||||
std::string GrabOutput(void(*logger)(), const char* verbosity) {
|
std::string GrabOutput(void(*logger)(), const char* verbosity) {
|
||||||
const std::string saved_flag = GMOCK_FLAG(verbose);
|
const std::string saved_flag = GMOCK_FLAG_GET(verbose);
|
||||||
GMOCK_FLAG_SET(verbose, verbosity);
|
GMOCK_FLAG_SET(verbose, verbosity);
|
||||||
CaptureStdout();
|
CaptureStdout();
|
||||||
logger();
|
logger();
|
||||||
|
|||||||
@ -1123,6 +1123,9 @@ class TestEventListener {
|
|||||||
// Fired before the test starts.
|
// Fired before the test starts.
|
||||||
virtual void OnTestStart(const TestInfo& test_info) = 0;
|
virtual void OnTestStart(const TestInfo& test_info) = 0;
|
||||||
|
|
||||||
|
// Fired when a test is disabled
|
||||||
|
virtual void OnTestDisabled(const TestInfo& /*test_info*/) {}
|
||||||
|
|
||||||
// Fired after a failed assertion or a SUCCEED() invocation.
|
// Fired after a failed assertion or a SUCCEED() invocation.
|
||||||
// If you want to throw an exception from this function to skip to the next
|
// If you want to throw an exception from this function to skip to the next
|
||||||
// TEST, it must be AssertionException defined above, or inherited from it.
|
// TEST, it must be AssertionException defined above, or inherited from it.
|
||||||
@ -1172,6 +1175,7 @@ class EmptyTestEventListener : public TestEventListener {
|
|||||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
void OnTestStart(const TestInfo& /*test_info*/) override {}
|
void OnTestStart(const TestInfo& /*test_info*/) override {}
|
||||||
|
void OnTestDisabled(const TestInfo& /*test_info*/) override {}
|
||||||
void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
|
void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
|
||||||
void OnTestEnd(const TestInfo& /*test_info*/) override {}
|
void OnTestEnd(const TestInfo& /*test_info*/) override {}
|
||||||
void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
|
void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
|
||||||
|
|||||||
@ -260,9 +260,17 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
// #include <condition_variable> // Guarded by GTEST_IS_THREADSAFE below
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <locale>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
// #include <mutex> // Guarded by GTEST_IS_THREADSAFE below
|
||||||
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifndef _WIN32_WCE
|
#ifndef _WIN32_WCE
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
@ -274,13 +282,6 @@
|
|||||||
# include <TargetConditionals.h>
|
# include <TargetConditionals.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream> // NOLINT
|
|
||||||
#include <locale>
|
|
||||||
#include <memory>
|
|
||||||
#include <string> // NOLINT
|
|
||||||
#include <tuple>
|
|
||||||
#include <vector> // NOLINT
|
|
||||||
|
|
||||||
#include "gtest/internal/custom/gtest-port.h"
|
#include "gtest/internal/custom/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-port-arch.h"
|
#include "gtest/internal/gtest-port-arch.h"
|
||||||
|
|
||||||
@ -757,6 +758,12 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
|||||||
|
|
||||||
#endif // GTEST_IS_THREADSAFE
|
#endif // GTEST_IS_THREADSAFE
|
||||||
|
|
||||||
|
#if GTEST_IS_THREADSAFE
|
||||||
|
// Some platforms don't support including these threading related headers.
|
||||||
|
#include <condition_variable> // NOLINT
|
||||||
|
#include <mutex> // NOLINT
|
||||||
|
#endif // GTEST_IS_THREADSAFE
|
||||||
|
|
||||||
// GTEST_API_ qualifies all symbols that must be exported. The definitions below
|
// GTEST_API_ qualifies all symbols that must be exported. The definitions below
|
||||||
// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in
|
// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in
|
||||||
// gtest/internal/custom/gtest-port.h
|
// gtest/internal/custom/gtest-port.h
|
||||||
@ -1161,71 +1168,8 @@ void ClearInjectableArgvs();
|
|||||||
|
|
||||||
// Defines synchronization primitives.
|
// Defines synchronization primitives.
|
||||||
#if GTEST_IS_THREADSAFE
|
#if GTEST_IS_THREADSAFE
|
||||||
# if GTEST_HAS_PTHREAD
|
|
||||||
// Sleeps for (roughly) n milliseconds. This function is only for testing
|
|
||||||
// Google Test's own constructs. Don't use it in user tests, either
|
|
||||||
// directly or indirectly.
|
|
||||||
inline void SleepMilliseconds(int n) {
|
|
||||||
const timespec time = {
|
|
||||||
0, // 0 seconds.
|
|
||||||
n * 1000L * 1000L, // And n ms.
|
|
||||||
};
|
|
||||||
nanosleep(&time, nullptr);
|
|
||||||
}
|
|
||||||
# endif // GTEST_HAS_PTHREAD
|
|
||||||
|
|
||||||
# if GTEST_HAS_NOTIFICATION_
|
|
||||||
// Notification has already been imported into the namespace.
|
|
||||||
// Nothing to do here.
|
|
||||||
|
|
||||||
# elif GTEST_HAS_PTHREAD
|
|
||||||
// Allows a controller thread to pause execution of newly created
|
|
||||||
// threads until notified. Instances of this class must be created
|
|
||||||
// and destroyed in the controller thread.
|
|
||||||
//
|
|
||||||
// This class is only for testing Google Test's own constructs. Do not
|
|
||||||
// use it in user tests, either directly or indirectly.
|
|
||||||
class Notification {
|
|
||||||
public:
|
|
||||||
Notification() : notified_(false) {
|
|
||||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
|
|
||||||
}
|
|
||||||
~Notification() {
|
|
||||||
pthread_mutex_destroy(&mutex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifies all threads created with this notification to start. Must
|
|
||||||
// be called from the controller thread.
|
|
||||||
void Notify() {
|
|
||||||
pthread_mutex_lock(&mutex_);
|
|
||||||
notified_ = true;
|
|
||||||
pthread_mutex_unlock(&mutex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blocks until the controller thread notifies. Must be called from a test
|
|
||||||
// thread.
|
|
||||||
void WaitForNotification() {
|
|
||||||
for (;;) {
|
|
||||||
pthread_mutex_lock(&mutex_);
|
|
||||||
const bool notified = notified_;
|
|
||||||
pthread_mutex_unlock(&mutex_);
|
|
||||||
if (notified)
|
|
||||||
break;
|
|
||||||
SleepMilliseconds(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
pthread_mutex_t mutex_;
|
|
||||||
bool notified_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
|
|
||||||
};
|
|
||||||
|
|
||||||
# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
|
|
||||||
|
|
||||||
GTEST_API_ void SleepMilliseconds(int n);
|
|
||||||
|
|
||||||
|
# if GTEST_OS_WINDOWS
|
||||||
// Provides leak-safe Windows kernel handle ownership.
|
// Provides leak-safe Windows kernel handle ownership.
|
||||||
// Used in death tests and in threading support.
|
// Used in death tests and in threading support.
|
||||||
class GTEST_API_ AutoHandle {
|
class GTEST_API_ AutoHandle {
|
||||||
@ -1254,23 +1198,45 @@ class GTEST_API_ AutoHandle {
|
|||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
|
||||||
};
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if GTEST_HAS_NOTIFICATION_
|
||||||
|
// Notification has already been imported into the namespace.
|
||||||
|
// Nothing to do here.
|
||||||
|
|
||||||
|
# else
|
||||||
// Allows a controller thread to pause execution of newly created
|
// Allows a controller thread to pause execution of newly created
|
||||||
// threads until notified. Instances of this class must be created
|
// threads until notified. Instances of this class must be created
|
||||||
// and destroyed in the controller thread.
|
// and destroyed in the controller thread.
|
||||||
//
|
//
|
||||||
// This class is only for testing Google Test's own constructs. Do not
|
// This class is only for testing Google Test's own constructs. Do not
|
||||||
// use it in user tests, either directly or indirectly.
|
// use it in user tests, either directly or indirectly.
|
||||||
|
// TODO(b/203539622): Replace unconditionally with absl::Notification.
|
||||||
class GTEST_API_ Notification {
|
class GTEST_API_ Notification {
|
||||||
public:
|
public:
|
||||||
Notification();
|
Notification() : notified_(false) {}
|
||||||
void Notify();
|
Notification(const Notification&) = delete;
|
||||||
void WaitForNotification();
|
Notification& operator=(const Notification&) = delete;
|
||||||
|
|
||||||
|
// Notifies all threads created with this notification to start. Must
|
||||||
|
// be called from the controller thread.
|
||||||
|
void Notify() {
|
||||||
|
std::lock_guard<std::mutex> lock(mu_);
|
||||||
|
notified_ = true;
|
||||||
|
cv_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocks until the controller thread notifies. Must be called from a test
|
||||||
|
// thread.
|
||||||
|
void WaitForNotification() {
|
||||||
|
std::unique_lock<std::mutex> lock(mu_);
|
||||||
|
cv_.wait(lock, [this]() { return notified_; });
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AutoHandle event_;
|
std::mutex mu_;
|
||||||
|
std::condition_variable cv_;
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
|
bool notified_;
|
||||||
};
|
};
|
||||||
# endif // GTEST_HAS_NOTIFICATION_
|
# endif // GTEST_HAS_NOTIFICATION_
|
||||||
|
|
||||||
|
|||||||
@ -280,10 +280,6 @@ size_t GetThreadCount() {
|
|||||||
|
|
||||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
||||||
|
|
||||||
void SleepMilliseconds(int n) {
|
|
||||||
::Sleep(static_cast<DWORD>(n));
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoHandle::AutoHandle()
|
AutoHandle::AutoHandle()
|
||||||
: handle_(INVALID_HANDLE_VALUE) {}
|
: handle_(INVALID_HANDLE_VALUE) {}
|
||||||
|
|
||||||
@ -322,23 +318,6 @@ bool AutoHandle::IsCloseable() const {
|
|||||||
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification::Notification()
|
|
||||||
: event_(::CreateEvent(nullptr, // Default security attributes.
|
|
||||||
TRUE, // Do not reset automatically.
|
|
||||||
FALSE, // Initially unset.
|
|
||||||
nullptr)) { // Anonymous event.
|
|
||||||
GTEST_CHECK_(event_.Get() != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notification::Notify() {
|
|
||||||
GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notification::WaitForNotification() {
|
|
||||||
GTEST_CHECK_(
|
|
||||||
::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mutex::Mutex()
|
Mutex::Mutex()
|
||||||
: owner_thread_id_(0),
|
: owner_thread_id_(0),
|
||||||
type_(kDynamic),
|
type_(kDynamic),
|
||||||
|
|||||||
@ -2855,20 +2855,20 @@ void UnitTestImpl::RegisterParameterizedTests() {
|
|||||||
// Creates the test object, runs it, records its result, and then
|
// Creates the test object, runs it, records its result, and then
|
||||||
// deletes it.
|
// deletes it.
|
||||||
void TestInfo::Run() {
|
void TestInfo::Run() {
|
||||||
if (!should_run_) return;
|
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
|
||||||
|
if (!should_run_) {
|
||||||
|
if (is_disabled_) repeater->OnTestDisabled(*this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Tells UnitTest where to store test result.
|
// Tells UnitTest where to store test result.
|
||||||
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
||||||
impl->set_current_test_info(this);
|
impl->set_current_test_info(this);
|
||||||
|
|
||||||
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
|
|
||||||
|
|
||||||
// Notifies the unit test event listeners that a test is about to start.
|
// Notifies the unit test event listeners that a test is about to start.
|
||||||
repeater->OnTestStart(*this);
|
repeater->OnTestStart(*this);
|
||||||
|
|
||||||
result_.set_start_timestamp(internal::GetTimeInMillis());
|
result_.set_start_timestamp(internal::GetTimeInMillis());
|
||||||
internal::Timer timer;
|
internal::Timer timer;
|
||||||
|
|
||||||
impl->os_stack_trace_getter()->UponLeavingGTest();
|
impl->os_stack_trace_getter()->UponLeavingGTest();
|
||||||
|
|
||||||
// Creates the test object.
|
// Creates the test object.
|
||||||
@ -3398,6 +3398,7 @@ class PrettyUnitTestResultPrinter : public TestEventListener {
|
|||||||
#endif // OnTestCaseStart
|
#endif // OnTestCaseStart
|
||||||
|
|
||||||
void OnTestStart(const TestInfo& test_info) override;
|
void OnTestStart(const TestInfo& test_info) override;
|
||||||
|
void OnTestDisabled(const TestInfo& test_info) override;
|
||||||
|
|
||||||
void OnTestPartResult(const TestPartResult& result) override;
|
void OnTestPartResult(const TestPartResult& result) override;
|
||||||
void OnTestEnd(const TestInfo& test_info) override;
|
void OnTestEnd(const TestInfo& test_info) override;
|
||||||
@ -3497,6 +3498,13 @@ void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrettyUnitTestResultPrinter::OnTestDisabled(const TestInfo& test_info) {
|
||||||
|
ColoredPrintf(GTestColor::kYellow, "[ DISABLED ] ");
|
||||||
|
PrintTestName(test_info.test_suite_name(), test_info.name());
|
||||||
|
printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
// Called after an assertion failure.
|
// Called after an assertion failure.
|
||||||
void PrettyUnitTestResultPrinter::OnTestPartResult(
|
void PrettyUnitTestResultPrinter::OnTestPartResult(
|
||||||
const TestPartResult& result) {
|
const TestPartResult& result) {
|
||||||
@ -3705,6 +3713,7 @@ class BriefUnitTestResultPrinter : public TestEventListener {
|
|||||||
#endif // OnTestCaseStart
|
#endif // OnTestCaseStart
|
||||||
|
|
||||||
void OnTestStart(const TestInfo& /*test_info*/) override {}
|
void OnTestStart(const TestInfo& /*test_info*/) override {}
|
||||||
|
void OnTestDisabled(const TestInfo& /*test_info*/) override {}
|
||||||
|
|
||||||
void OnTestPartResult(const TestPartResult& result) override;
|
void OnTestPartResult(const TestPartResult& result) override;
|
||||||
void OnTestEnd(const TestInfo& test_info) override;
|
void OnTestEnd(const TestInfo& test_info) override;
|
||||||
@ -3817,6 +3826,7 @@ class TestEventRepeater : public TestEventListener {
|
|||||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
void OnTestSuiteStart(const TestSuite& parameter) override;
|
void OnTestSuiteStart(const TestSuite& parameter) override;
|
||||||
void OnTestStart(const TestInfo& test_info) override;
|
void OnTestStart(const TestInfo& test_info) override;
|
||||||
|
void OnTestDisabled(const TestInfo& test_info) override;
|
||||||
void OnTestPartResult(const TestPartResult& result) override;
|
void OnTestPartResult(const TestPartResult& result) override;
|
||||||
void OnTestEnd(const TestInfo& test_info) override;
|
void OnTestEnd(const TestInfo& test_info) override;
|
||||||
// Legacy API is deprecated but still available
|
// Legacy API is deprecated but still available
|
||||||
@ -3887,6 +3897,7 @@ GTEST_REPEATER_METHOD_(OnTestCaseStart, TestSuite)
|
|||||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite)
|
GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite)
|
||||||
GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
|
GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
|
||||||
|
GTEST_REPEATER_METHOD_(OnTestDisabled, TestInfo)
|
||||||
GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
|
GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
|
||||||
GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
|
GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
|
||||||
GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
|
GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
|
||||||
|
|||||||
@ -36,8 +36,10 @@
|
|||||||
# include <time.h>
|
# include <time.h>
|
||||||
#endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
|
#include <chrono> // NOLINT
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <thread> // NOLINT
|
||||||
#include <utility> // For std::pair and std::make_pair.
|
#include <utility> // For std::pair and std::make_pair.
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -333,7 +335,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SleepMilliseconds(100);
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retry if an arbitrary other thread was created or destroyed.
|
// Retry if an arbitrary other thread was created or destroyed.
|
||||||
@ -1050,7 +1052,7 @@ class AtomicCounterWithMutex {
|
|||||||
int temp = value_;
|
int temp = value_;
|
||||||
{
|
{
|
||||||
// We need to put up a memory barrier to prevent reads and writes to
|
// We need to put up a memory barrier to prevent reads and writes to
|
||||||
// value_ rearranged with the call to SleepMilliseconds when observed
|
// value_ rearranged with the call to sleep_for when observed
|
||||||
// from other threads.
|
// from other threads.
|
||||||
#if GTEST_HAS_PTHREAD
|
#if GTEST_HAS_PTHREAD
|
||||||
// On POSIX, locking a mutex puts up a memory barrier. We cannot use
|
// On POSIX, locking a mutex puts up a memory barrier. We cannot use
|
||||||
@ -1061,7 +1063,8 @@ class AtomicCounterWithMutex {
|
|||||||
pthread_mutex_init(&memory_barrier_mutex, nullptr));
|
pthread_mutex_init(&memory_barrier_mutex, nullptr));
|
||||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
|
||||||
|
|
||||||
SleepMilliseconds(static_cast<int>(random_.Generate(30)));
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::milliseconds(random_.Generate(30)));
|
||||||
|
|
||||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
|
||||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex));
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex));
|
||||||
@ -1069,7 +1072,8 @@ class AtomicCounterWithMutex {
|
|||||||
// On Windows, performing an interlocked access puts up a memory barrier.
|
// On Windows, performing an interlocked access puts up a memory barrier.
|
||||||
volatile LONG dummy = 0;
|
volatile LONG dummy = 0;
|
||||||
::InterlockedIncrement(&dummy);
|
::InterlockedIncrement(&dummy);
|
||||||
SleepMilliseconds(static_cast<int>(random_.Generate(30)));
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::milliseconds(random_.Generate(30)));
|
||||||
::InterlockedIncrement(&dummy);
|
::InterlockedIncrement(&dummy);
|
||||||
#else
|
#else
|
||||||
# error "Memory barrier not implemented on this platform."
|
# error "Memory barrier not implemented on this platform."
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
# pylint: disable-msg=C6204
|
# pylint: disable-msg=C6204
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
IS_WINDOWS = os.name == 'nt'
|
IS_WINDOWS = os.name == 'nt'
|
||||||
@ -42,13 +43,6 @@ import atexit
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest as _test_module
|
import unittest as _test_module
|
||||||
|
|
||||||
try:
|
|
||||||
import subprocess
|
|
||||||
_SUBPROCESS_MODULE_AVAILABLE = True
|
|
||||||
except:
|
|
||||||
import popen2
|
|
||||||
_SUBPROCESS_MODULE_AVAILABLE = False
|
|
||||||
# pylint: enable-msg=C6204
|
# pylint: enable-msg=C6204
|
||||||
|
|
||||||
GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
|
GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
|
||||||
@ -224,69 +218,18 @@ class Subprocess:
|
|||||||
combined in a string.
|
combined in a string.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The subprocess module is the preferable way of running programs
|
if capture_stderr:
|
||||||
# since it is available and behaves consistently on all platforms,
|
stderr = subprocess.STDOUT
|
||||||
# including Windows. But it is only available starting in python 2.4.
|
|
||||||
# In earlier python versions, we revert to the popen2 module, which is
|
|
||||||
# available in python 2.0 and later but doesn't provide required
|
|
||||||
# functionality (Popen4) under Windows. This allows us to support Mac
|
|
||||||
# OS X 10.4 Tiger, which has python 2.3 installed.
|
|
||||||
if _SUBPROCESS_MODULE_AVAILABLE:
|
|
||||||
if capture_stderr:
|
|
||||||
stderr = subprocess.STDOUT
|
|
||||||
else:
|
|
||||||
stderr = subprocess.PIPE
|
|
||||||
|
|
||||||
p = subprocess.Popen(command,
|
|
||||||
stdout=subprocess.PIPE, stderr=stderr,
|
|
||||||
cwd=working_dir, universal_newlines=True, env=env)
|
|
||||||
# communicate returns a tuple with the file object for the child's
|
|
||||||
# output.
|
|
||||||
self.output = p.communicate()[0]
|
|
||||||
self._return_code = p.returncode
|
|
||||||
else:
|
else:
|
||||||
old_dir = os.getcwd()
|
stderr = subprocess.PIPE
|
||||||
|
|
||||||
def _ReplaceEnvDict(dest, src):
|
p = subprocess.Popen(command,
|
||||||
# Changes made by os.environ.clear are not inheritable by child
|
stdout=subprocess.PIPE, stderr=stderr,
|
||||||
# processes until Python 2.6. To produce inheritable changes we have
|
cwd=working_dir, universal_newlines=True, env=env)
|
||||||
# to delete environment items with the del statement.
|
# communicate returns a tuple with the file object for the child's
|
||||||
for key in dest.keys():
|
# output.
|
||||||
del dest[key]
|
self.output = p.communicate()[0]
|
||||||
dest.update(src)
|
self._return_code = p.returncode
|
||||||
|
|
||||||
# When 'env' is not None, backup the environment variables and replace
|
|
||||||
# them with the passed 'env'. When 'env' is None, we simply use the
|
|
||||||
# current 'os.environ' for compatibility with the subprocess.Popen
|
|
||||||
# semantics used above.
|
|
||||||
if env is not None:
|
|
||||||
old_environ = os.environ.copy()
|
|
||||||
_ReplaceEnvDict(os.environ, env)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if working_dir is not None:
|
|
||||||
os.chdir(working_dir)
|
|
||||||
if capture_stderr:
|
|
||||||
p = popen2.Popen4(command)
|
|
||||||
else:
|
|
||||||
p = popen2.Popen3(command)
|
|
||||||
p.tochild.close()
|
|
||||||
self.output = p.fromchild.read()
|
|
||||||
ret_code = p.wait()
|
|
||||||
finally:
|
|
||||||
os.chdir(old_dir)
|
|
||||||
|
|
||||||
# Restore the old environment variables
|
|
||||||
# if they were replaced.
|
|
||||||
if env is not None:
|
|
||||||
_ReplaceEnvDict(os.environ, old_environ)
|
|
||||||
|
|
||||||
# Converts ret_code to match the semantics of
|
|
||||||
# subprocess.Popen.returncode.
|
|
||||||
if os.WIFSIGNALED(ret_code):
|
|
||||||
self._return_code = -os.WTERMSIG(ret_code)
|
|
||||||
else: # os.WIFEXITED(ret_code) should return True here.
|
|
||||||
self._return_code = os.WEXITSTATUS(ret_code)
|
|
||||||
|
|
||||||
if bool(self._return_code & 0x80000000):
|
if bool(self._return_code & 0x80000000):
|
||||||
self.terminated_by_signal = True
|
self.terminated_by_signal = True
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user