diff options
author | zhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925> | 2010-03-04 22:15:53 (GMT) |
---|---|---|
committer | zhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925> | 2010-03-04 22:15:53 (GMT) |
commit | 12a92c26fc0e0de81f687dbe739a6aa24f37f9dd (patch) | |
tree | 9a7a9aac24a5946d5bca4e04ec681ecd38b6199c /include | |
parent | 0928f00c6b995af037b787b710fde509267ad624 (diff) | |
download | googletest-12a92c26fc0e0de81f687dbe739a6aa24f37f9dd.zip googletest-12a92c26fc0e0de81f687dbe739a6aa24f37f9dd.tar.gz googletest-12a92c26fc0e0de81f687dbe739a6aa24f37f9dd.tar.bz2 |
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).
Diffstat (limited to 'include')
-rw-r--r-- | include/gtest/internal/gtest-port.h | 183 | ||||
-rw-r--r-- | include/gtest/internal/gtest-string.h | 13 |
2 files changed, 108 insertions, 88 deletions
diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h index 6910c7b..b1b9203 100644 --- a/include/gtest/internal/gtest-port.h +++ b/include/gtest/internal/gtest-port.h @@ -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 diff --git a/include/gtest/internal/gtest-string.h b/include/gtest/internal/gtest-string.h index 6f9ba05..280645e 100644 --- a/include/gtest/internal/gtest-string.h +++ b/include/gtest/internal/gtest-string.h @@ -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. |