[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,082 次)