diff options
Diffstat (limited to 'googletest/test/googletest-port-test.cc')
-rw-r--r-- | googletest/test/googletest-port-test.cc | 253 |
1 files changed, 141 insertions, 112 deletions
diff --git a/googletest/test/googletest-port-test.cc b/googletest/test/googletest-port-test.cc index 60d637c32f63..32a2a7b4d642 100644 --- a/googletest/test/googletest-port-test.cc +++ b/googletest/test/googletest-port-test.cc @@ -32,17 +32,20 @@ #include "gtest/internal/gtest-port.h" -#if GTEST_OS_MAC -# include <time.h> +#ifdef GTEST_OS_MAC +#include <time.h> #endif // GTEST_OS_MAC +#include <chrono> // NOLINT #include <list> #include <memory> +#include <string> +#include <thread> // NOLINT #include <utility> // For std::pair and std::make_pair. #include <vector> -#include "gtest/gtest.h" #include "gtest/gtest-spi.h" +#include "gtest/gtest.h" #include "src/gtest-internal-inl.h" using std::make_pair; @@ -90,11 +93,11 @@ TEST(IsXDigitTest, ReturnsFalseForWideNonAscii) { class Base { public: - // Copy constructor and assignment operator do exactly what we need, so we - // use them. Base() : member_(0) {} explicit Base(int n) : member_(n) {} - virtual ~Base() {} + Base(const Base&) = default; + Base& operator=(const Base&) = default; + virtual ~Base() = default; int member() { return member_; } private: @@ -201,6 +204,13 @@ TEST(ImplicitCastTest, CanUseImplicitConstructor) { EXPECT_TRUE(converted); } +// The following code intentionally tests a suboptimal syntax. +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdangling-else" +#pragma GCC diagnostic ignored "-Wempty-body" +#pragma GCC diagnostic ignored "-Wpragmas" +#endif TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) { if (AlwaysFalse()) GTEST_CHECK_(false) << "This should never be executed; " @@ -216,6 +226,9 @@ TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) { else GTEST_CHECK_(true) << ""; } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif TEST(GtestCheckSyntaxTest, WorksWithSwitch) { switch (0) { @@ -226,8 +239,8 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) { } switch (0) - case 0: - GTEST_CHECK_(true) << "Check failed in switch case"; + case 0: + GTEST_CHECK_(true) << "Check failed in switch case"; } // Verifies behavior of FormatFileLocation. @@ -268,9 +281,11 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) { EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1)); } -#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA || \ - GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ - GTEST_OS_NETBSD || GTEST_OS_OPENBSD +#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_MAC) || \ + defined(GTEST_OS_QNX) || defined(GTEST_OS_FUCHSIA) || \ + defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \ + defined(GTEST_OS_GNU_KFREEBSD) || defined(GTEST_OS_NETBSD) || \ + defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_GNU_HURD) void* ThreadFunc(void* data) { internal::Mutex* mutex = static_cast<internal::Mutex*>(data); mutex->Lock(); @@ -279,36 +294,61 @@ void* ThreadFunc(void* data) { } TEST(GetThreadCountTest, ReturnsCorrectValue) { - const size_t starting_count = GetThreadCount(); - pthread_t thread_id; + size_t starting_count; + size_t thread_count_after_create; + size_t thread_count_after_join; + + // We can't guarantee that no other thread was created or destroyed between + // any two calls to GetThreadCount(). We make multiple attempts, hoping that + // background noise is not constant and we would see the "right" values at + // some point. + for (int attempt = 0; attempt < 20; ++attempt) { + starting_count = GetThreadCount(); + pthread_t thread_id; + + internal::Mutex mutex; + { + internal::MutexLock lock(&mutex); + pthread_attr_t attr; + ASSERT_EQ(0, pthread_attr_init(&attr)); + ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); + + const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex); + ASSERT_EQ(0, pthread_attr_destroy(&attr)); + ASSERT_EQ(0, status); + } - internal::Mutex mutex; - { - internal::MutexLock lock(&mutex); - pthread_attr_t attr; - ASSERT_EQ(0, pthread_attr_init(&attr)); - ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); - - const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex); - ASSERT_EQ(0, pthread_attr_destroy(&attr)); - ASSERT_EQ(0, status); - EXPECT_EQ(starting_count + 1, GetThreadCount()); - } + thread_count_after_create = GetThreadCount(); - void* dummy; - ASSERT_EQ(0, pthread_join(thread_id, &dummy)); + void* dummy; + ASSERT_EQ(0, pthread_join(thread_id, &dummy)); - // The OS may not immediately report the updated thread count after - // joining a thread, causing flakiness in this test. To counter that, we - // wait for up to .5 seconds for the OS to report the correct value. - for (int i = 0; i < 5; ++i) { - if (GetThreadCount() == starting_count) - break; + // Join before we decide whether we need to retry the test. Retry if an + // arbitrary other thread was created or destroyed in the meantime. + if (thread_count_after_create != starting_count + 1) continue; + + // The OS may not immediately report the updated thread count after + // joining a thread, causing flakiness in this test. To counter that, we + // wait for up to .5 seconds for the OS to report the correct value. + bool thread_count_matches = false; + for (int i = 0; i < 5; ++i) { + thread_count_after_join = GetThreadCount(); + if (thread_count_after_join == starting_count) { + thread_count_matches = true; + break; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + // Retry if an arbitrary other thread was created or destroyed. + if (!thread_count_matches) continue; - SleepMilliseconds(100); + break; } - EXPECT_EQ(starting_count, GetThreadCount()); + EXPECT_EQ(thread_count_after_create, starting_count + 1); + EXPECT_EQ(thread_count_after_join, starting_count); } #else TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) { @@ -320,25 +360,27 @@ TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) { const bool a_false_condition = false; const char regex[] = #ifdef _MSC_VER - "googletest-port-test\\.cc\\(\\d+\\):" -#elif GTEST_USES_POSIX_RE - "googletest-port-test\\.cc:[0-9]+" + "googletest-port-test\\.cc\\(\\d+\\):" +#elif defined(GTEST_USES_POSIX_RE) + "googletest-port-test\\.cc:[0-9]+" #else - "googletest-port-test\\.cc:\\d+" + "googletest-port-test\\.cc:\\d+" #endif // _MSC_VER - ".*a_false_condition.*Extra info.*"; + ".*a_false_condition.*Extra info.*"; EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info", regex); } -#if GTEST_HAS_DEATH_TEST +#ifdef GTEST_HAS_DEATH_TEST TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) { - EXPECT_EXIT({ - GTEST_CHECK_(true) << "Extra info"; - ::std::cerr << "Success\n"; - exit(0); }, + EXPECT_EXIT( + { + GTEST_CHECK_(true) << "Extra info"; + ::std::cerr << "Success\n"; + exit(0); + }, ::testing::ExitedWithCode(0), "Success"); } @@ -348,22 +390,16 @@ TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) { // the platform. The test will produce compiler errors in case of failure. // For simplicity, we only cover the most important platforms here. TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) { -#if !GTEST_USES_PCRE -# if GTEST_HAS_POSIX_RE - +#ifdef GTEST_HAS_ABSL + EXPECT_TRUE(GTEST_USES_RE2); +#elif GTEST_HAS_POSIX_RE EXPECT_TRUE(GTEST_USES_POSIX_RE); - -# else - +#else EXPECT_TRUE(GTEST_USES_SIMPLE_RE); - -# endif -#endif // !GTEST_USES_PCRE +#endif } -#if GTEST_USES_POSIX_RE - -# if GTEST_HAS_TYPED_TEST +#ifdef GTEST_USES_POSIX_RE template <typename Str> class RETest : public ::testing::Test {}; @@ -388,9 +424,9 @@ TYPED_TEST(RETest, ImplicitConstructorWorks) { // Tests that RE's constructors reject invalid regular expressions. TYPED_TEST(RETest, RejectsInvalidRegex) { - EXPECT_NONFATAL_FAILURE({ - const RE invalid(TypeParam("?")); - }, "\"?\" is not a valid POSIX Extended regular expression."); + EXPECT_NONFATAL_FAILURE( + { const RE invalid(TypeParam("?")); }, + "\"?\" is not a valid POSIX Extended regular expression."); } // Tests RE::FullMatch(). @@ -420,9 +456,7 @@ TYPED_TEST(RETest, PartialMatchWorks) { EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re)); } -# endif // GTEST_HAS_TYPED_TEST - -#elif GTEST_USES_SIMPLE_RE +#elif defined(GTEST_USES_SIMPLE_RE) TEST(IsInSetTest, NulCharIsNotInAnySet) { EXPECT_FALSE(IsInSet('\0', "")); @@ -786,8 +820,7 @@ TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) { EXPECT_TRUE(MatchRegexAtHead("a?b", "ab")); } -TEST(MatchRegexAtHeadTest, - WorksWhenRegexStartsWithRepetionOfEscapeSequence) { +TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetionOfEscapeSequence) { EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc")); EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b")); @@ -843,17 +876,14 @@ TEST(RETest, ImplicitConstructorWorks) { // Tests that RE's constructors reject invalid regular expressions. TEST(RETest, RejectsInvalidRegex) { - EXPECT_NONFATAL_FAILURE({ - const RE normal(NULL); - }, "NULL is not a valid simple regular expression"); + EXPECT_NONFATAL_FAILURE({ const RE normal(NULL); }, + "NULL is not a valid simple regular expression"); - EXPECT_NONFATAL_FAILURE({ - const RE normal(".*(\\w+"); - }, "'(' is unsupported"); + EXPECT_NONFATAL_FAILURE({ const RE normal(".*(\\w+"); }, + "'(' is unsupported"); - EXPECT_NONFATAL_FAILURE({ - const RE invalid("^?"); - }, "'?' can only follow a repeatable token"); + EXPECT_NONFATAL_FAILURE({ const RE invalid("^?"); }, + "'?' can only follow a repeatable token"); } // Tests RE::FullMatch(). @@ -888,7 +918,7 @@ TEST(RETest, PartialMatchWorks) { #endif // GTEST_USES_POSIX_RE -#if !GTEST_OS_WINDOWS_MOBILE +#ifndef GTEST_OS_WINDOWS_MOBILE TEST(CaptureTest, CapturesStdout) { CaptureStdout(); @@ -949,14 +979,14 @@ TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) { EXPECT_EQ(&i, t2.get()); } -class NoDefaultContructor { +class NoDefaultConstructor { public: - explicit NoDefaultContructor(const char*) {} - NoDefaultContructor(const NoDefaultContructor&) {} + explicit NoDefaultConstructor(const char*) {} + NoDefaultConstructor(const NoDefaultConstructor&) = default; }; TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) { - ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo")); + ThreadLocal<NoDefaultConstructor> bar(NoDefaultConstructor("foo")); bar.pointer(); } @@ -981,7 +1011,7 @@ TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) { EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer()); } -#if GTEST_IS_THREADSAFE +#ifdef GTEST_IS_THREADSAFE void AddTwo(int* param) { *param += 2; } @@ -995,12 +1025,13 @@ TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) { TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) { // AssertHeld() is flaky only in the presence of multiple threads accessing // the lock. In this case, the test is robust. - EXPECT_DEATH_IF_SUPPORTED({ - Mutex m; - { MutexLock lock(&m); } - m.AssertHeld(); - }, - "thread .*hold"); + EXPECT_DEATH_IF_SUPPORTED( + { + Mutex m; + { MutexLock lock(&m); } + m.AssertHeld(); + }, + "thread .*hold"); } TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) { @@ -1011,15 +1042,15 @@ TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) { class AtomicCounterWithMutex { public: - explicit AtomicCounterWithMutex(Mutex* mutex) : - value_(0), mutex_(mutex), random_(42) {} + explicit AtomicCounterWithMutex(Mutex* mutex) + : value_(0), mutex_(mutex), random_(42) {} void Increment() { MutexLock lock(mutex_); int temp = value_; { // 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. #if GTEST_HAS_PTHREAD // On POSIX, locking a mutex puts up a memory barrier. We cannot use @@ -1030,18 +1061,20 @@ class AtomicCounterWithMutex { pthread_mutex_init(&memory_barrier_mutex, nullptr)); 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_destroy(&memory_barrier_mutex)); -#elif GTEST_OS_WINDOWS +#elif defined(GTEST_OS_WINDOWS) // On Windows, performing an interlocked access puts up a memory barrier. volatile LONG dummy = 0; ::InterlockedIncrement(&dummy); - SleepMilliseconds(static_cast<int>(random_.Generate(30))); + std::this_thread::sleep_for( + std::chrono::milliseconds(random_.Generate(30))); ::InterlockedIncrement(&dummy); #else -# error "Memory barrier not implemented on this platform." +#error "Memory barrier not implemented on this platform." #endif // GTEST_HAS_PTHREAD } value_ = temp + 1; @@ -1051,12 +1084,11 @@ class AtomicCounterWithMutex { private: volatile int value_; Mutex* const mutex_; // Protects value_. - Random random_; + Random random_; }; void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) { - for (int i = 0; i < param.second; ++i) - param.first->Increment(); + for (int i = 0; i < param.second; ++i) param.first->Increment(); } // Tests that the mutex only lets one thread at a time to lock it. @@ -1072,14 +1104,12 @@ TEST(MutexTest, OnlyOneThreadCanLockAtATime) { // 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), - &threads_can_start)); + counting_threads[i] = std::make_unique<ThreadType>( + &CountingThreadFunc, make_pair(&locked_counter, kCycleCount), + &threads_can_start); } threads_can_start.Notify(); - for (int i = 0; i < kThreadCount; ++i) - counting_threads[i]->Join(); + for (int i = 0; i < kThreadCount; ++i) counting_threads[i]->Join(); // If the mutex lets more than one thread to increment the counter at a // time, they are likely to encounter a race condition and have some @@ -1089,7 +1119,7 @@ TEST(MutexTest, OnlyOneThreadCanLockAtATime) { } template <typename T> -void RunFromThread(void (func)(T), T param) { +void RunFromThread(void(func)(T), T param) { ThreadWithParam<T> thread(func, param, nullptr); thread.Join(); } @@ -1118,14 +1148,14 @@ class DestructorCall { public: DestructorCall() { invoked_ = false; -#if GTEST_OS_WINDOWS +#ifdef GTEST_OS_WINDOWS wait_event_.Reset(::CreateEvent(NULL, TRUE, FALSE, NULL)); GTEST_CHECK_(wait_event_.Get() != NULL); #endif } bool CheckDestroyed() const { -#if GTEST_OS_WINDOWS +#ifdef GTEST_OS_WINDOWS if (::WaitForSingleObject(wait_event_.Get(), 1000) != WAIT_OBJECT_0) return false; #endif @@ -1134,7 +1164,7 @@ class DestructorCall { void ReportDestroyed() { invoked_ = true; -#if GTEST_OS_WINDOWS +#ifdef GTEST_OS_WINDOWS ::SetEvent(wait_event_.Get()); #endif } @@ -1150,12 +1180,13 @@ class DestructorCall { private: bool invoked_; -#if GTEST_OS_WINDOWS +#ifdef GTEST_OS_WINDOWS AutoHandle wait_event_; #endif static std::vector<DestructorCall*>* const list_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(DestructorCall); + DestructorCall(const DestructorCall&) = delete; + DestructorCall& operator=(const DestructorCall&) = delete; }; std::vector<DestructorCall*>* const DestructorCall::list_ = @@ -1180,8 +1211,6 @@ class DestructorTracker { return DestructorCall::List().size() - 1; } const size_t index_; - - GTEST_DISALLOW_ASSIGN_(DestructorTracker); }; typedef ThreadLocal<DestructorTracker>* ThreadParam; @@ -1251,12 +1280,12 @@ TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) { #endif // GTEST_IS_THREADSAFE -#if GTEST_OS_WINDOWS +#ifdef GTEST_OS_WINDOWS TEST(WindowsTypesTest, HANDLEIsVoidStar) { StaticAssertTypeEq<HANDLE, void*>(); } -#if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR) +#if defined(GTEST_OS_WINDOWS_MINGW) && !defined(__MINGW64_VERSION_MAJOR) TEST(WindowsTypesTest, _CRITICAL_SECTIONIs_CRITICAL_SECTION) { StaticAssertTypeEq<CRITICAL_SECTION, _CRITICAL_SECTION>(); } |