Renames ThreadStartSempahore to Notificaton (by Vlad Losev); adds threading tests for SCOPED_TRACE() (by Vlad Losev); replaces native pthread calls with gtest's threading constructs (by Vlad Losev); fixes flakiness in CountedDestructor (by Vlad Losev); minor MSVC 7.1 clean-up (by Zhanyong Wan).
This commit is contained in:
parent
0928f00c6b
commit
12a92c26fc
|
@ -463,13 +463,10 @@
|
|||
#include <vector> // NOLINT
|
||||
#endif
|
||||
|
||||
// Determines whether to support value-parameterized tests.
|
||||
|
||||
#if defined(__GNUC__) || (_MSC_VER >= 1400)
|
||||
// TODO(vladl@google.com): get the implementation rid of vector and list
|
||||
// to compile on MSVC 7.1.
|
||||
// We don't support MSVC 7.1 with exceptions disabled now. Therefore
|
||||
// all the compilers we care about are adequate for supporting
|
||||
// value-parameterized tests.
|
||||
#define GTEST_HAS_PARAM_TEST 1
|
||||
#endif // defined(__GNUC__) || (_MSC_VER >= 1400)
|
||||
|
||||
// Determines whether to support type-driven tests.
|
||||
|
||||
|
@ -774,6 +771,97 @@ const ::std::vector<String>& GetArgvs();
|
|||
|
||||
#if GTEST_HAS_PTHREAD
|
||||
|
||||
// Sleeps for (roughly) n milli-seconds. 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, NULL);
|
||||
}
|
||||
|
||||
// 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) {}
|
||||
|
||||
// Notifies all threads created with this notification to start. Must
|
||||
// be called from the controller thread.
|
||||
void Notify() { notified_ = true; }
|
||||
|
||||
// Blocks until the controller thread notifies. Must be called from a test
|
||||
// thread.
|
||||
void WaitForNotification() {
|
||||
while(!notified_) {
|
||||
SleepMilliseconds(10);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
volatile bool notified_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
|
||||
};
|
||||
|
||||
// Helper class for testing Google Test's multi-threading constructs.
|
||||
// To use it, derive a class template ThreadWithParam<T> from
|
||||
// ThreadWithParamBase<T> and implement thread creation and startup in
|
||||
// the constructor and joining the thread in JoinUnderlyingThread().
|
||||
// Then you can write:
|
||||
//
|
||||
// void ThreadFunc(int param) { /* Do things with param */ }
|
||||
// Notification thread_can_start;
|
||||
// ...
|
||||
// // The thread_can_start parameter is optional; you can supply NULL.
|
||||
// ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
|
||||
// thread_can_start.Notify();
|
||||
//
|
||||
// These classes are only for testing Google Test's own constructs. Do
|
||||
// not use them in user tests, either directly or indirectly.
|
||||
template <typename T>
|
||||
class ThreadWithParamBase {
|
||||
public:
|
||||
typedef void (*UserThreadFunc)(T);
|
||||
|
||||
ThreadWithParamBase(
|
||||
UserThreadFunc func, T param, Notification* thread_can_start)
|
||||
: func_(func),
|
||||
param_(param),
|
||||
thread_can_start_(thread_can_start),
|
||||
finished_(false) {}
|
||||
virtual ~ThreadWithParamBase() {}
|
||||
|
||||
void Join() {
|
||||
if (!finished_) {
|
||||
JoinUnderlyingThread();
|
||||
finished_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void JoinUnderlyingThread() = 0;
|
||||
|
||||
void ThreadMain() {
|
||||
if (thread_can_start_ != NULL)
|
||||
thread_can_start_->WaitForNotification();
|
||||
func_(param_);
|
||||
}
|
||||
|
||||
protected:
|
||||
const UserThreadFunc func_; // User-supplied thread function.
|
||||
const T param_; // User-supplied parameter to the thread function.
|
||||
// When non-NULL, used to block execution until the controller thread
|
||||
// notifies.
|
||||
Notification* const thread_can_start_;
|
||||
bool finished_; // true iff we know that the thread function has finished.
|
||||
};
|
||||
|
||||
// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
|
||||
// true.
|
||||
#include <pthread.h>
|
||||
|
@ -936,99 +1024,32 @@ class ThreadLocal {
|
|||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
|
||||
};
|
||||
|
||||
// Sleeps for (roughly) n milli-seconds. 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, NULL);
|
||||
}
|
||||
|
||||
// Allows a controller thread to pause execution of newly created
|
||||
// threads until signalled. 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 ThreadStartSemaphore {
|
||||
public:
|
||||
ThreadStartSemaphore() : signalled_(false) {}
|
||||
|
||||
// Signals to all threads created with this semaphore to start. Must
|
||||
// be called from the controller thread.
|
||||
void Signal() { signalled_ = true; }
|
||||
|
||||
// Blocks until the controller thread signals. Must be called from a test
|
||||
// thread.
|
||||
void Wait() {
|
||||
while(!signalled_) {
|
||||
SleepMilliseconds(10);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
volatile bool signalled_;
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadStartSemaphore);
|
||||
};
|
||||
|
||||
// Helper class for testing Google Test's multi-threading constructs.
|
||||
// Use:
|
||||
//
|
||||
// void ThreadFunc(int param) { /* Do things with param */ }
|
||||
// ThreadStartSemaphore semaphore;
|
||||
// ...
|
||||
// // The semaphore parameter is optional; you can supply NULL.
|
||||
// ThreadWithParam<int> thread(&ThreadFunc, 5, &semaphore);
|
||||
// semaphore.Signal(); // Allows the thread to start.
|
||||
//
|
||||
// This class is only for testing Google Test's own constructs. Do not
|
||||
// use it in user tests, either directly or indirectly.
|
||||
template <typename T>
|
||||
class ThreadWithParam {
|
||||
class ThreadWithParam : public ThreadWithParamBase<T> {
|
||||
public:
|
||||
typedef void (*UserThreadFunc)(T);
|
||||
|
||||
ThreadWithParam(UserThreadFunc func, T param, ThreadStartSemaphore* semaphore)
|
||||
: func_(func),
|
||||
param_(param),
|
||||
start_semaphore_(semaphore),
|
||||
finished_(false) {
|
||||
ThreadWithParam(void (*func)(T), T param, Notification* thread_can_start)
|
||||
: ThreadWithParamBase<T>(func, param, thread_can_start) {
|
||||
// The thread can be created only after all fields except thread_
|
||||
// have been initialized.
|
||||
GTEST_CHECK_POSIX_SUCCESS_(
|
||||
pthread_create(&thread_, 0, ThreadMainStatic, this));
|
||||
}
|
||||
~ThreadWithParam() { Join(); }
|
||||
virtual ~ThreadWithParam() { this->Join(); }
|
||||
|
||||
void Join() {
|
||||
if (!finished_) {
|
||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
|
||||
finished_ = true;
|
||||
}
|
||||
virtual void JoinUnderlyingThread() {
|
||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
|
||||
}
|
||||
|
||||
private:
|
||||
void ThreadMain() {
|
||||
if (start_semaphore_ != NULL)
|
||||
start_semaphore_->Wait();
|
||||
func_(param_);
|
||||
}
|
||||
static void* ThreadMainStatic(void* thread_with_param) {
|
||||
static_cast<ThreadWithParam<T>*>(thread_with_param)->ThreadMain();
|
||||
return NULL; // We are not interested in the thread exit code.
|
||||
}
|
||||
|
||||
const UserThreadFunc func_; // User-supplied thread function.
|
||||
const T param_; // User-supplied parameter to the thread function.
|
||||
// When non-NULL, used to block execution until the controller thread
|
||||
// signals.
|
||||
ThreadStartSemaphore* const start_semaphore_;
|
||||
bool finished_; // Has the thread function finished?
|
||||
pthread_t thread_; // The native thread object.
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
|
||||
};
|
||||
|
||||
#define GTEST_IS_THREADSAFE 1
|
||||
|
|
|
@ -51,14 +51,13 @@ namespace internal {
|
|||
|
||||
// String - a UTF-8 string class.
|
||||
//
|
||||
// We cannot use std::string as Microsoft's STL implementation in
|
||||
// Visual C++ 7.1 has problems when exception is disabled. There is a
|
||||
// hack to work around this, but we've seen cases where the hack fails
|
||||
// to work.
|
||||
// For historic reasons, we don't use std::string.
|
||||
//
|
||||
// Also, String is different from std::string in that it can represent
|
||||
// both NULL and the empty string, while std::string cannot represent
|
||||
// NULL.
|
||||
// TODO(wan@google.com): replace this class with std::string or
|
||||
// implement it in terms of the latter.
|
||||
//
|
||||
// Note that String can represent both NULL and the empty string,
|
||||
// while std::string cannot represent NULL.
|
||||
//
|
||||
// NULL and the empty string are considered different. NULL is less
|
||||
// than anything (including the empty string) except itself.
|
||||
|
|
|
@ -121,12 +121,12 @@ INSTANTIATE_TEST_CASE_P(
|
|||
|
||||
#else
|
||||
|
||||
// Google Test doesn't support value-parameterized tests on some platforms
|
||||
// and compilers, such as MSVC 7.1. If we use conditional compilation to
|
||||
// compile out all code referring to the gtest_main library, MSVC linker
|
||||
// will not link that library at all and consequently complain about
|
||||
// missing entry point defined in that library (fatal error LNK1561:
|
||||
// entry point must be defined). This dummy test keeps gtest_main linked in.
|
||||
// Google Test may not support value-parameterized tests with some
|
||||
// compilers. If we use conditional compilation to compile out all
|
||||
// code referring to the gtest_main library, MSVC linker will not link
|
||||
// that library at all and consequently complain about missing entry
|
||||
// point defined in that library (fatal error LNK1561: entry point
|
||||
// must be defined). This dummy test keeps gtest_main linked in.
|
||||
TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
|
||||
|
||||
#endif // GTEST_HAS_PARAM_TEST
|
||||
|
|
|
@ -162,12 +162,12 @@ INSTANTIATE_TEST_CASE_P(MeaningfulTestParameters,
|
|||
|
||||
#else
|
||||
|
||||
// Google Test doesn't support Combine() on some platforms and compilers,
|
||||
// such as MSVC 7.1. If we use conditional compilation to compile out
|
||||
// all code referring to the gtest_main library, MSVC linker will not
|
||||
// link that library at all and consequently complain about missing entry
|
||||
// point defined in that library (fatal error LNK1561: entry point must
|
||||
// be defined). This dummy test keeps gtest_main linked in.
|
||||
// Google Test may not support Combine() with some compilers. If we
|
||||
// use conditional compilation to compile out all code referring to
|
||||
// the gtest_main library, MSVC linker will not link that library at
|
||||
// all and consequently complain about missing entry point defined in
|
||||
// that library (fatal error LNK1561: entry point must be
|
||||
// defined). This dummy test keeps gtest_main linked in.
|
||||
TEST(DummyTest, CombineIsNotSupportedOnThisPlatform) {}
|
||||
|
||||
#endif // GTEST_HAS_COMBINE
|
||||
|
|
|
@ -1037,8 +1037,6 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
|
|||
// 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.
|
||||
// TODO(vladl@google.com): Get rid of std::vector to be able to build on
|
||||
// Visual C++ 7.1 with exceptions disabled.
|
||||
static void SplitString(const ::std::string& str, char delimiter,
|
||||
::std::vector< ::std::string>* dest) {
|
||||
::std::vector< ::std::string> parsed;
|
||||
|
|
|
@ -803,7 +803,7 @@ TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
|||
{ MutexLock lock(&m); }
|
||||
m.AssertHeld();
|
||||
},
|
||||
"The current thread is not holding the mutex @.+");
|
||||
"thread .*hold");
|
||||
}
|
||||
|
||||
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
||||
|
@ -859,16 +859,16 @@ TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
|||
const int kCycleCount = 20;
|
||||
const int kThreadCount = 7;
|
||||
scoped_ptr<ThreadType> counting_threads[kThreadCount];
|
||||
ThreadStartSemaphore semaphore;
|
||||
Notification threads_can_start;
|
||||
// Creates and runs kThreadCount threads that increment locked_counter
|
||||
// kCycleCount times each.
|
||||
for (int i = 0; i < kThreadCount; ++i) {
|
||||
counting_threads[i].reset(new ThreadType(&CountingThreadFunc,
|
||||
make_pair(&locked_counter,
|
||||
kCycleCount),
|
||||
&semaphore));
|
||||
&threads_can_start));
|
||||
}
|
||||
semaphore.Signal(); // Starts the threads.
|
||||
threads_can_start.Notify();
|
||||
for (int i = 0; i < kThreadCount; ++i)
|
||||
counting_threads[i]->Join();
|
||||
|
||||
|
@ -901,16 +901,29 @@ TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
|
|||
EXPECT_STREQ("foo", result.c_str());
|
||||
}
|
||||
|
||||
class CountedDestructor {
|
||||
// DestructorTracker keeps track of whether the class instances have been
|
||||
// destroyed. The static synchronization mutex has to be defined outside
|
||||
// of the class, due to syntax of its definition.
|
||||
static GTEST_DEFINE_STATIC_MUTEX_(destructor_tracker_mutex);
|
||||
|
||||
static std::vector<bool> g_destroyed;
|
||||
|
||||
class DestructorTracker {
|
||||
public:
|
||||
~CountedDestructor() { counter_++; }
|
||||
static int counter() { return counter_; }
|
||||
static void set_counter(int value) { counter_ = value; }
|
||||
DestructorTracker() : index_(GetNewIndex()) {}
|
||||
~DestructorTracker() {
|
||||
MutexLock lock(&destructor_tracker_mutex);
|
||||
g_destroyed[index_] = true;
|
||||
}
|
||||
|
||||
private:
|
||||
static int counter_;
|
||||
static int GetNewIndex() {
|
||||
MutexLock lock(&destructor_tracker_mutex);
|
||||
g_destroyed.push_back(false);
|
||||
return g_destroyed.size() - 1;
|
||||
}
|
||||
const int index_;
|
||||
};
|
||||
int CountedDestructor::counter_ = 0;
|
||||
|
||||
template <typename T>
|
||||
void CallThreadLocalGet(ThreadLocal<T>* threadLocal) {
|
||||
|
@ -918,16 +931,19 @@ void CallThreadLocalGet(ThreadLocal<T>* threadLocal) {
|
|||
}
|
||||
|
||||
TEST(ThreadLocalTest, DestroysManagedObjectsNoLaterThanSelf) {
|
||||
CountedDestructor::set_counter(0);
|
||||
g_destroyed.clear();
|
||||
{
|
||||
ThreadLocal<CountedDestructor> thread_local;
|
||||
ThreadWithParam<ThreadLocal<CountedDestructor>*> thread(
|
||||
&CallThreadLocalGet<CountedDestructor>, &thread_local, NULL);
|
||||
ThreadLocal<DestructorTracker> thread_local;
|
||||
ThreadWithParam<ThreadLocal<DestructorTracker>*> thread(
|
||||
&CallThreadLocalGet<DestructorTracker>, &thread_local, NULL);
|
||||
thread.Join();
|
||||
}
|
||||
// There should be 2 desctuctor calls as ThreadLocal also contains a member
|
||||
// T - used as a prototype for copy ctr version.
|
||||
EXPECT_EQ(2, CountedDestructor::counter());
|
||||
// Verifies that all DestructorTracker objects there were have been
|
||||
// destroyed.
|
||||
for (size_t i = 0; i < g_destroyed.size(); ++i)
|
||||
EXPECT_TRUE(g_destroyed[i]) << "at index " << i;
|
||||
|
||||
g_destroyed.clear();
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
|
||||
|
|
|
@ -349,12 +349,12 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, NumericTest, NumericTypes);
|
|||
|
||||
#if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
|
||||
|
||||
// Google Test doesn't support type-parameterized tests on some platforms
|
||||
// and compilers, such as MSVC 7.1. If we use conditional compilation to
|
||||
// compile out all code referring to the gtest_main library, MSVC linker
|
||||
// will not link that library at all and consequently complain about
|
||||
// missing entry point defined in that library (fatal error LNK1561:
|
||||
// entry point must be defined). This dummy test keeps gtest_main linked in.
|
||||
// Google Test may not support type-parameterized tests with some
|
||||
// compilers. If we use conditional compilation to compile out all
|
||||
// code referring to the gtest_main library, MSVC linker will not link
|
||||
// that library at all and consequently complain about missing entry
|
||||
// point defined in that library (fatal error LNK1561: entry point
|
||||
// must be defined). This dummy test keeps gtest_main linked in.
|
||||
TEST(DummyTest, TypedTestsAreNotSupportedOnThisPlatform) {}
|
||||
|
||||
#endif // #if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
|
||||
|
|
|
@ -282,7 +282,7 @@ class GTestOutputTest(gtest_test_utils.TestCase):
|
|||
normalized_golden = RemoveTypeInfoDetails(golden)
|
||||
|
||||
if CAN_GENERATE_GOLDEN_FILE:
|
||||
self.assert_(normalized_golden == normalized_actual)
|
||||
self.assertEqual(normalized_golden, normalized_actual)
|
||||
else:
|
||||
normalized_actual = RemoveTestCounts(normalized_actual)
|
||||
normalized_golden = RemoveTestCounts(self.RemoveUnsupportedTests(
|
||||
|
@ -299,7 +299,7 @@ class GTestOutputTest(gtest_test_utils.TestCase):
|
|||
'_gtest_output_test_normalized_golden.txt'), 'wb').write(
|
||||
normalized_golden)
|
||||
|
||||
self.assert_(normalized_golden == normalized_actual)
|
||||
self.assertEqual(normalized_golden, normalized_actual)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -46,15 +46,17 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if GTEST_HAS_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif // GTEST_HAS_PTHREAD
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
using testing::ScopedFakeTestPartResultReporter;
|
||||
using testing::TestPartResultArray;
|
||||
|
||||
using testing::internal::Notification;
|
||||
using testing::internal::ThreadWithParam;
|
||||
#endif
|
||||
|
||||
namespace posix = ::testing::internal::posix;
|
||||
using testing::internal::String;
|
||||
using testing::internal::scoped_ptr;
|
||||
|
||||
// Tests catching fatal failures.
|
||||
|
||||
|
@ -214,6 +216,83 @@ TEST(SCOPED_TRACETest, CanBeRepeated) {
|
|||
<< "trace point A, B, and D.";
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
// Tests that SCOPED_TRACE()s can be used concurrently from multiple
|
||||
// threads. Namely, an assertion should be affected by
|
||||
// SCOPED_TRACE()s in its own thread only.
|
||||
|
||||
// Here's the sequence of actions that happen in the test:
|
||||
//
|
||||
// Thread A (main) | Thread B (spawned)
|
||||
// ===============================|================================
|
||||
// spawns thread B |
|
||||
// -------------------------------+--------------------------------
|
||||
// waits for n1 | SCOPED_TRACE("Trace B");
|
||||
// | generates failure #1
|
||||
// | notifies n1
|
||||
// -------------------------------+--------------------------------
|
||||
// SCOPED_TRACE("Trace A"); | waits for n2
|
||||
// generates failure #2 |
|
||||
// notifies n2 |
|
||||
// -------------------------------|--------------------------------
|
||||
// waits for n3 | generates failure #3
|
||||
// | trace B dies
|
||||
// | generates failure #4
|
||||
// | notifies n3
|
||||
// -------------------------------|--------------------------------
|
||||
// generates failure #5 | finishes
|
||||
// trace A dies |
|
||||
// generates failure #6 |
|
||||
// -------------------------------|--------------------------------
|
||||
// waits for thread B to finish |
|
||||
|
||||
struct CheckPoints {
|
||||
Notification n1;
|
||||
Notification n2;
|
||||
Notification n3;
|
||||
};
|
||||
|
||||
static void ThreadWithScopedTrace(CheckPoints* check_points) {
|
||||
{
|
||||
SCOPED_TRACE("Trace B");
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #1 (in thread B, only trace B alive).";
|
||||
check_points->n1.Notify();
|
||||
check_points->n2.WaitForNotification();
|
||||
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #3 (in thread B, trace A & B both alive).";
|
||||
} // Trace B dies here.
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #4 (in thread B, only trace A alive).";
|
||||
check_points->n3.Notify();
|
||||
}
|
||||
|
||||
TEST(SCOPED_TRACETest, WorksConcurrently) {
|
||||
printf("(expecting 6 failures)\n");
|
||||
|
||||
CheckPoints check_points;
|
||||
ThreadWithParam<CheckPoints*> thread(&ThreadWithScopedTrace,
|
||||
&check_points,
|
||||
NULL);
|
||||
check_points.n1.WaitForNotification();
|
||||
|
||||
{
|
||||
SCOPED_TRACE("Trace A");
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #2 (in thread A, trace A & B both alive).";
|
||||
check_points.n2.Notify();
|
||||
check_points.n3.WaitForNotification();
|
||||
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #5 (in thread A, only trace A alive).";
|
||||
} // Trace A dies here.
|
||||
ADD_FAILURE()
|
||||
<< "Expected failure #6 (in thread A, no trace alive).";
|
||||
thread.Join();
|
||||
}
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
TEST(DisabledTestsWarningTest,
|
||||
DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning) {
|
||||
// This test body is intentionally empty. Its sole purpose is for
|
||||
|
@ -479,6 +558,63 @@ TEST_F(ExceptionInTearDownTest, ExceptionInTearDown) {
|
|||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
// A unary function that may die.
|
||||
void DieIf(bool should_die) {
|
||||
GTEST_CHECK_(!should_die) << " - death inside DieIf().";
|
||||
}
|
||||
|
||||
// Tests running death tests in a multi-threaded context.
|
||||
|
||||
// Used for coordination between the main and the spawn thread.
|
||||
struct SpawnThreadNotifications {
|
||||
SpawnThreadNotifications() {}
|
||||
|
||||
Notification spawn_thread_started;
|
||||
Notification spawn_thread_ok_to_terminate;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(SpawnThreadNotifications);
|
||||
};
|
||||
|
||||
// The function to be executed in the thread spawn by the
|
||||
// MultipleThreads test (below).
|
||||
static void ThreadRoutine(SpawnThreadNotifications* notifications) {
|
||||
// Signals the main thread that this thread has started.
|
||||
notifications->spawn_thread_started.Notify();
|
||||
|
||||
// Waits for permission to finish from the main thread.
|
||||
notifications->spawn_thread_ok_to_terminate.WaitForNotification();
|
||||
}
|
||||
|
||||
// This is a death-test test, but it's not named with a DeathTest
|
||||
// suffix. It starts threads which might interfere with later
|
||||
// death tests, so it must run after all other death tests.
|
||||
class DeathTestAndMultiThreadsTest : public testing::Test {
|
||||
protected:
|
||||
// Starts a thread and waits for it to begin.
|
||||
virtual void SetUp() {
|
||||
thread_.reset(new ThreadWithParam<SpawnThreadNotifications*>(
|
||||
&ThreadRoutine, ¬ifications_, NULL));
|
||||
notifications_.spawn_thread_started.WaitForNotification();
|
||||
}
|
||||
// Tells the thread to finish, and reaps it.
|
||||
// Depending on the version of the thread library in use,
|
||||
// a manager thread might still be left running that will interfere
|
||||
// with later death tests. This is unfortunate, but this class
|
||||
// cleans up after itself as best it can.
|
||||
virtual void TearDown() {
|
||||
notifications_.spawn_thread_ok_to_terminate.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
SpawnThreadNotifications notifications_;
|
||||
scoped_ptr<ThreadWithParam<SpawnThreadNotifications*> > thread_;
|
||||
};
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
// The MixedUpTestCaseTest test case verifies that Google Test will fail a
|
||||
// test if it uses a different fixture class than what other tests in
|
||||
// the same test case use. It deliberately contains two fixture
|
||||
|
@ -849,23 +985,13 @@ TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
|
|||
"failure.");
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
class ExpectFailureWithThreadsTest : public ExpectFailureTest {
|
||||
protected:
|
||||
static void AddFailureInOtherThread(FailureMode failure) {
|
||||
pthread_t tid;
|
||||
pthread_create(&tid,
|
||||
NULL,
|
||||
ExpectFailureWithThreadsTest::FailureThread,
|
||||
&failure);
|
||||
pthread_join(tid, NULL);
|
||||
}
|
||||
private:
|
||||
static void* FailureThread(void* attr) {
|
||||
FailureMode* failure = static_cast<FailureMode*>(attr);
|
||||
AddFailure(*failure);
|
||||
return NULL;
|
||||
ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
|
||||
thread.Join();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -901,7 +1027,7 @@ TEST_F(ScopedFakeTestPartResultReporterTest, InterceptOnlyCurrentThread) {
|
|||
EXPECT_EQ(0, results.size()) << "This shouldn't fail.";
|
||||
}
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
|
||||
// Expected fatal failure, but succeeds.
|
||||
|
|
|
@ -7,7 +7,7 @@ Expected: true
|
|||
gtest_output_test_.cc:#: Failure
|
||||
Value of: 3
|
||||
Expected: 2
|
||||
[0;32m[==========] [mRunning 59 tests from 25 test cases.
|
||||
[0;32m[==========] [mRunning 60 tests from 25 test cases.
|
||||
[0;32m[----------] [mGlobal test environment set-up.
|
||||
FooEnvironment::SetUp() called.
|
||||
BarEnvironment::SetUp() called.
|
||||
|
@ -65,7 +65,7 @@ i == 3
|
|||
gtest_output_test_.cc:#: Failure
|
||||
Expected: (3) >= (a[i]), actual: 3 vs 6
|
||||
[0;31m[ FAILED ] [mLoggingTest.InterleavingLoggingAndAssertions
|
||||
[0;32m[----------] [m5 tests from SCOPED_TRACETest
|
||||
[0;32m[----------] [m6 tests from SCOPED_TRACETest
|
||||
[0;32m[ RUN ] [mSCOPED_TRACETest.ObeysScopes
|
||||
(expected to fail)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
|
@ -148,6 +148,35 @@ gtest_output_test_.cc:#: D
|
|||
gtest_output_test_.cc:#: B
|
||||
gtest_output_test_.cc:#: A
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.CanBeRepeated
|
||||
[0;32m[ RUN ] [mSCOPED_TRACETest.WorksConcurrently
|
||||
(expecting 6 failures)
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #1 (in thread B, only trace B alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace B
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #2 (in thread A, trace A & B both alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace A
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #3 (in thread B, trace A & B both alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace B
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #4 (in thread B, only trace A alive).
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #5 (in thread A, only trace A alive).
|
||||
Google Test trace:
|
||||
gtest_output_test_.cc:#: Trace A
|
||||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected failure #6 (in thread A, no trace alive).
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.WorksConcurrently
|
||||
[0;32m[----------] [m1 test from NonFatalFailureInFixtureConstructorTest
|
||||
[0;32m[ RUN ] [mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
|
||||
(expecting 5 failures)
|
||||
|
@ -544,9 +573,9 @@ FooEnvironment::TearDown() called.
|
|||
gtest_output_test_.cc:#: Failure
|
||||
Failed
|
||||
Expected fatal failure.
|
||||
[0;32m[==========] [m59 tests from 25 test cases ran.
|
||||
[0;32m[==========] [m60 tests from 25 test cases ran.
|
||||
[0;32m[ PASSED ] [m21 tests.
|
||||
[0;31m[ FAILED ] [m38 tests, listed below:
|
||||
[0;31m[ FAILED ] [m39 tests, listed below:
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInSubroutine
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.FatalFailureInNestedSubroutine
|
||||
[0;31m[ FAILED ] [mFatalFailureTest.NonfatalFailureInSubroutine
|
||||
|
@ -556,6 +585,7 @@ Expected fatal failure.
|
|||
[0;31m[ FAILED ] [mSCOPED_TRACETest.WorksInSubroutine
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.CanBeNested
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.CanBeRepeated
|
||||
[0;31m[ FAILED ] [mSCOPED_TRACETest.WorksConcurrently
|
||||
[0;31m[ FAILED ] [mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
|
||||
[0;31m[ FAILED ] [mFatalFailureInFixtureConstructorTest.FailureInConstructor
|
||||
[0;31m[ FAILED ] [mNonFatalFailureInSetUpTest.FailureInSetUp
|
||||
|
@ -586,7 +616,7 @@ Expected fatal failure.
|
|||
[0;31m[ FAILED ] [mExpectFailureWithThreadsTest.ExpectNonFatalFailure
|
||||
[0;31m[ FAILED ] [mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
|
||||
|
||||
38 FAILED TESTS
|
||||
39 FAILED TESTS
|
||||
[0;33m YOU HAVE 1 DISABLED TEST
|
||||
|
||||
[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
|
||||
|
|
|
@ -49,16 +49,15 @@
|
|||
namespace testing {
|
||||
namespace {
|
||||
|
||||
using internal::scoped_ptr;
|
||||
using internal::Notification;
|
||||
using internal::String;
|
||||
using internal::TestPropertyKeyIs;
|
||||
using internal::ThreadStartSemaphore;
|
||||
using internal::ThreadWithParam;
|
||||
using internal::scoped_ptr;
|
||||
|
||||
// In order to run tests in this file, for platforms where Google Test is
|
||||
// thread safe, implement ThreadWithParam and ThreadStartSemaphore. See the
|
||||
// description of their API in gtest-port.h, where they are defined for
|
||||
// already supported platforms.
|
||||
// thread safe, implement ThreadWithParam. See the description of its API
|
||||
// in gtest-port.h, where it is defined for already supported platforms.
|
||||
|
||||
// How many threads to create?
|
||||
const int kThreadCount = 50;
|
||||
|
@ -129,11 +128,13 @@ void CheckTestFailureCount(int expected_failures) {
|
|||
TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
|
||||
{
|
||||
scoped_ptr<ThreadWithParam<int> > threads[kThreadCount];
|
||||
ThreadStartSemaphore semaphore;
|
||||
Notification threads_can_start;
|
||||
for (int i = 0; i != kThreadCount; i++)
|
||||
threads[i].reset(new ThreadWithParam<int>(&ManyAsserts, i, &semaphore));
|
||||
threads[i].reset(new ThreadWithParam<int>(&ManyAsserts,
|
||||
i,
|
||||
&threads_can_start));
|
||||
|
||||
semaphore.Signal(); // Starts all the threads.
|
||||
threads_can_start.Notify();
|
||||
|
||||
// Blocks until all the threads are done.
|
||||
for (int i = 0; i != kThreadCount; i++)
|
||||
|
|
|
@ -71,10 +71,6 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
|
|||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#if GTEST_HAS_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif // GTEST_HAS_PTHREAD
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace testing {
|
||||
|
@ -191,6 +187,10 @@ using testing::internal::CaptureStdout;
|
|||
using testing::internal::GetCapturedStdout;
|
||||
#endif // GTEST_HAS_STREAM_REDIRECTION_
|
||||
|
||||
#if GTEST_IS_THREADSAFE
|
||||
using testing::internal::ThreadWithParam;
|
||||
#endif
|
||||
|
||||
class TestingVector : public std::vector<int> {
|
||||
};
|
||||
|
||||
|
@ -1283,25 +1283,14 @@ TEST_F(ScopedFakeTestPartResultReporterTest, DeprecatedConstructor) {
|
|||
EXPECT_EQ(1, results.size());
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
class ScopedFakeTestPartResultReporterWithThreadsTest
|
||||
: public ScopedFakeTestPartResultReporterTest {
|
||||
protected:
|
||||
static void AddFailureInOtherThread(FailureMode failure) {
|
||||
pthread_t tid;
|
||||
pthread_create(&tid,
|
||||
NULL,
|
||||
ScopedFakeTestPartResultReporterWithThreadsTest::
|
||||
FailureThread,
|
||||
&failure);
|
||||
pthread_join(tid, NULL);
|
||||
}
|
||||
private:
|
||||
static void* FailureThread(void* attr) {
|
||||
FailureMode* failure = static_cast<FailureMode*>(attr);
|
||||
AddFailure(*failure);
|
||||
return NULL;
|
||||
ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
|
||||
thread.Join();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1324,7 +1313,7 @@ TEST_F(ScopedFakeTestPartResultReporterWithThreadsTest,
|
|||
EXPECT_TRUE(results.GetTestPartResult(3).fatally_failed());
|
||||
}
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
// Tests EXPECT_FATAL_FAILURE{,ON_ALL_THREADS}. Makes sure that they
|
||||
// work even if the failure is generated in a called function rather than
|
||||
|
@ -1435,7 +1424,7 @@ TEST_F(ExpectNonfatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
|
|||
}, "");
|
||||
}
|
||||
|
||||
#if GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#if GTEST_IS_THREADSAFE
|
||||
|
||||
typedef ScopedFakeTestPartResultReporterWithThreadsTest
|
||||
ExpectFailureWithThreadsTest;
|
||||
|
@ -1450,7 +1439,7 @@ TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailureOnAllThreads) {
|
|||
AddFailureInOtherThread(NONFATAL_FAILURE), "Expected non-fatal failure.");
|
||||
}
|
||||
|
||||
#endif // GTEST_IS_THREADSAFE && GTEST_HAS_PTHREAD
|
||||
#endif // GTEST_IS_THREADSAFE
|
||||
|
||||
// Tests the TestProperty class.
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user