diff --git a/googletest/test/googletest-port-test.cc b/googletest/test/googletest-port-test.cc index 2697355d..16d30c46 100644 --- a/googletest/test/googletest-port-test.cc +++ b/googletest/test/googletest-port-test.cc @@ -289,36 +289,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; - 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)); + // 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; - 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()); + 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); + } + + thread_count_after_create = GetThreadCount(); + + void* dummy; + ASSERT_EQ(0, pthread_join(thread_id, &dummy)); + + // 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; + } + + SleepMilliseconds(100); + } + + // Retry if an arbitrary other thread was created or destroyed. + if (!thread_count_matches) continue; + + break; } - 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; - - SleepMilliseconds(100); - } - - 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) {