Googletest export

Make multiple attempts to verify GetThreadCount()

Testing GetThreadCount() is inheritently noisy, as other threads can be started
or destroyed between two calls to GetThreadCount(). This is especially true
under certain analyzer configurations, such as TSAN.

PiperOrigin-RevId: 381951799
pull/3481/merge
Abseil Team 3 years ago committed by Andy Soffer
parent 255323cf09
commit 22e6055c75
  1. 73
      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;
// 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;
}
SleepMilliseconds(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) {

Loading…
Cancel
Save