[C++] 用 Google Test 裡使用多執行緒作測試,不能使用 ASSERT_EQ()?

[C++] 用 Google Test 裡使用多執行緒作測試,不能使用 ASSERT_EQ()?

最近在查一個 C++ 程式當掉的問題,懷疑是多執行緒 (multi-thread) 造成的,

因此在 Google Test 的 unit-testing 程式裡,加了下面的程式碼:

TEST(MyLib, ScanMultiThread)
{
// Initialize and set thread joinable
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_t threadData;
std::vector<pthread_t> vecThreads;
int rc = 0;
// Create threads
for (unsigned int i = 0; i < 1000; i++)
{
rc = pthread_create(&threadData, NULL, ThreadFuncScan, (void*)i);
if (rc == 0)
{
printf("Created worker thread %d\n", i+1);
vecThreads.push_back(threadData);
}
else
{
printf("Failed to create worker thread");
}
}
// Free attribute and wait for the other threads
pthread_attr_destroy(&attr);
void* pThreadStatus = NULL;
for (std::vector<pthread_t>::const_iterator it = vecThreads.begin(); it != vecThreads.end(); ++it)
{
rc = pthread_join(*it, &pThreadStatus);
if (rc != 0)
{
printf("Failed to join thread: rc=%d\n", rc);
}
}
}

 

這個測試裡,會建立 1000 根 thread 來跑 ThreadFuncScan(),

然後我在 ThreadFuncScan() 裡寫一些測試,例如:

void* ThreadFuncScan(void* pParam)
{
size_t iThread = reinterpret_cast<size_t>(pParam);
ASSERT_EQ(4, iThread);
// Other operations...
return NULL;
}

 

看似簡單的測試,在編譯時卻遇到了看不太懂的錯誤訊息: 

In file included from ../3rd_party/googletest/googletest/include/gtest/gtest.h:58:0,
from Test.cpp:2:
Test.cpp: In function 'void* ThreadFuncScan(void*)':
Test.cpp:163:5: error: void value not ignored as it ought to be
ASSERT_EQ(4, iThread);

 

嗯… 看了半天就是看不懂那個 void value not ignored as it ought to be 是啥意思…

找了一下,總算在 Google Test 的 FAQ 裡找到了解答:

My compiler complains “void value not ignored as it ought to be.” What does this mean?

原來是 ASSERT_*() 只能在回傳值是 void 的函式內使用~

在本例中,因為我們是在 ThreadFuncScan() 函式中使用 ASSERT_EQ(),

但 ThreadFuncScan() 會回傳一個 void* 指標,因此是不符合規定的…

 

但是 thread 的函式定義是有規範的,我也不能自己把回傳值改掉,怎麼辦呢?

想了一下,決定多呼叫一層函式來變通,

將要使用 ASSERT_*() 的部分放到另一個沒有傳回值的函式去:

void* ThreadFuncScan(void* pParam)
{
size_t iThread = reinterpret_cast<size_t>(pParam);
ThreadFuncScanImpl(iThread);
return NULL;
}
void ThreadFuncScanImpl(size_t iThread)
{
ASSERT_EQ(4, iThread);
// Other operations...
}

 

果然這樣子就可以成功編譯,ASSERT_*() 也還是可以正常運作囉~^^

 

(本頁面已被瀏覽過 1,079 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料