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
This commit is contained in:
Abseil Team 2021-06-28 17:52:38 -04:00 committed by Andy Soffer
parent 255323cf09
commit 22e6055c75

View File

@ -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) {