2015-06-03 89 views
2

我在理解爲什麼一個我認爲應該傳遞的測試用例大部分時間都失敗的問題。我已經將測試提取到條件變量並使用wait_for方法,特別是對其進行測試以確定它是否確實至少等待指定的持續時間。C++條件變量wait_for表現得不像預期的那樣

測試代碼片段如下:

TEST_CASE("Condition variable test") 
{ 
    std::mutex m; 
    std::unique_lock<std::mutex> lock(m); 
    std::condition_variable cv; 
    bool ex = false; 
    std::chrono::milliseconds rel_time(50); 

    auto start = std::chrono::steady_clock::now(); 

    cv.wait_for(lock, rel_time, [&ex] {return(ex);}); 

    auto end = std::chrono::steady_clock::now(); 

    REQUIRE(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() >= rel_time.count()); 
} 

我會從我的C++ 11標準的理解想到,這應該通過所有的時間。諷刺的是,如果我將時鐘類型更改爲系統時鐘,我無法使測試失敗。

對於condition_variable :: wait_for方法,摘自cplusplus.com指出「如果指定pred(2),函數只會在pred返回false時阻止,並且通知只能在線程變爲true時解除阻塞(尤其是用於檢查虛假的喚醒呼叫),其行爲如同實現爲: return wait_until(lck,chrono :: steady_clock :: now() + rel_time,std :: move(pred));「

這意味着使用穩定的時鐘來取我的參考時間戳是正確的時鐘。

我正在編譯使用MinGW環境與gcc 4.8.2編譯器。

+0

Collin,開始和結束都是time_points。我正在減去時間點來形成一個持續時間。我將測量的持續時間與期望的持續時間進行比較。我的系統上的分辨率對於此測量已足夠。我已經將期望的持續時間增加到了500ms和5s,並且測試仍然失敗。我仍然很想知道更多關於爲什麼你認爲這是一個糟糕的測試的細節。 –

回答

3

這聽起來像是供應商實施中的一個錯誤。我不明白這個測試可能會失敗。

FWIW,你REQUIRE語句可以大大簡化:中durations

REQUIRE(end - start >= rel_time); 

比較是總是準確。

您的測試有一種寫法可能會失敗:如果std::chrono::steady_clock::duration大於毫秒,則表達式duration_cast<milliseconds>(end - start)可能會導致0ms。爲了防止這種糟糕的實施,您可以添加:

static_assert(std::chrono::steady_clock::duration{1} <= std::chrono::milliseconds{1}, 
    "This steady_clock implementation has an outrageously coarse duration"); 
+0

如果'steady_clock'具有例如16毫秒的分辨率,那麼這很容易失敗。即使您請求了50毫秒,「wait_for」可能會延遲64毫秒。 –

+0

@CollinDauphinee那樣會失敗的測試如何? –

+0

@CollinDauphinee:如果'wait_for'延遲了64毫秒,那麼寫入的測試通過,假設'REQUIRE'是個好名字。 –

相關問題