2017-06-25 12 views
1

私はWindowsでGoogleMock(1.8.0リリース)をテストし始めました。スレッドセーフではないという例を示したかったのです。成功したことを証明した後、同じテストがLinux上で正常に動作することを示したいと考えました。それはしかし失敗しました。それは私の期待と一致しませんでした。 GoogleMockのドキュメントでは、pthreadがあるシステムでスレッドセーフであることが示されているので、スレッドセーフである必要があります。実行可能ファイルをビルドするには、-pthreadをリンカのコマンドラインに追加する必要がありました。つまり、GoogleMockまたはGoogleTestはpthreadを使用します。GoogleMockはLinuxでスレッドセーフではありませんか?

これは、私がテストに使用コードです:

#include <thread> 
#include <vector> 

#include "gmock/gmock.h" 

class Dummy 
{ 
public: 
    virtual void SomeMethod(int) {} 
}; 

class DummyMock : public Dummy 
{ 
public: 
    MOCK_METHOD1(SomeMethod, void(int)); 
}; 

using ::testing::Exactly; 

constexpr static int nrCallsPerThread = 100 * 1000; 
constexpr static int nrThreads = 10; 

TEST(SomeTest, Test100) 
{ 
    DummyMock dummy; 

    std::vector<std::thread> threads; 
    for (int i = 0; i < nrThreads; i++) 
    { 
     EXPECT_CALL(dummy, SomeMethod(i)).Times(Exactly(nrCallsPerThread)); 
     threads.emplace_back([&dummy, i] 
     { 
      for (int j = 0; j < nrCallsPerThread; j++) 
      { 
       dummy.SomeMethod(i); 
      } 
     }); 
    } 

    for (auto& t: threads) 
    { 
     t.join(); 
    } 
} 

int main(int argc, char** argv) 
{ 
    testing::InitGoogleMock(&argc, argv); 
    return RUN_ALL_TESTS(); 
} 

問題は、Linux上で、すべての実行を露出していません。しかし、--gtest_repeat=100で実行ファイルを実行すると、ほぼ100%のヒット率が得られます。

Windowsの場合、Visual Studio 2015を使用してのDebug Assertion Failed!というメッセージが表示される場合。

Linuxでは、Ubuntu 17.04、コマンドラインからデバッグビルドを実行すると、[ FATAL ] ../googletest-release-1.8.0/googletest/include/gtest/internal/gtest-port.h:1928:: pthread_mutex_lock(&mutex_)failed with error 22が得られます。

Linux上のデバッガで実行している場合、プログラムは、(多くの場合)、このコールスタックにライン2であるGTEST-port.hライン1100で中断されています。それは、スレッドセーフである必要がありますので、

0 0x5555555a6633 testing::Cardinality::ConservativeUpperBound() const() (??:??) 
1 0x5555555a1a13 testing::internal::ExpectationBase::CheckActionCountIfNotDone() const() (??:??) 
2 0x555555563f98 testing::internal::TypedExpectation<void (int)>::ShouldHandleArguments(std::tuple<int> const&) const(this=0x5555557f58a0, args=std::tuple containing = {...}) (../googletest-release-1.8.0/googlemock/include/gmock/gmock-spec-builders.h:1100) 
3 0x55555556397d testing::internal::FunctionMockerBase<void (int)>::FindMatchingExpectationLocked(std::tuple<int> const&) const(this=0x7fffffffde38, args=std::tuple containing = {...}) (../googletest-release-1.8.0/googlemock/include/gmock/gmock-spec-builders.h:1723) 
4 0x555555563578 testing::internal::FunctionMockerBase<void (int)>::UntypedFindMatchingExpectation(void const*, void const**, bool*, std::ostream*, std::ostream*)(this=0x7fffffffde38, untyped_args=0x7fffde7fbe14, untyped_action=0x7fffde7fb7d0, is_excessive=0x7fffde7fb7c7, what=0x7fffde7fb900, why=0x7fffde7fba90) (../googletest-release-1.8.0/googlemock/include/gmock/gmock-spec-builders.h:1687) 
5 0x5555555a265e testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith(void const*)() (??:??) 
6 0x55555555fcba testing::internal::FunctionMockerBase<void (int)>::InvokeWith(std::tuple<int> const&)(this=0x7fffffffde38, args=std::tuple containing = {...}) (../googletest-release-1.8.0/googlemock/include/gmock/gmock-spec-builders.h:1585) 
7 0x55555555f16c testing::internal::FunctionMocker<void (int)>::Invoke(int)(this=0x7fffffffde38, a1=1) (../googletest-release-1.8.0/googlemock/include/gmock/gmock-generated-function-mockers.h:101) 
8 0x55555555ecb6 DummyMock::SomeMethod(this=0x7fffffffde30, gmock_a1=1) (/home/jos/Programming/ThreadSafeGMock/main.cpp:16) 
9 0x55555555d31e SomeTest_Test100_Test::<lambda()>::operator()(void) const(__closure=0x5555557f5478) (/home/jos/Programming/ThreadSafeGMock/main.cpp:36) 
10 0x55555555de98 std::_Bind_simple<SomeTest_Test100_Test::TestBody()::<lambda()>()>::_M_invoke<>(std::_Index_tuple<>)(this=0x5555557f5478) (/usr/include/c++/6/functional:1391) 
11 0x55555555de22 std::_Bind_simple<SomeTest_Test100_Test::TestBody()::<lambda()>()>::operator()(void)(this=0x5555557f5478) (/usr/include/c++/6/functional:1380) 
12 0x55555555ddf2 std::thread::_State_impl<std::_Bind_simple<SomeTest_Test100_Test::TestBody()::<lambda()>()> >::_M_run(void)(this=0x5555557f5470) (/usr/include/c++/6/thread:197) 
13 0x7ffff7b0a83f ??() (/usr/lib/x86_64-linux-gnu/libstdc++.so.6:??) 
14 0x7ffff76216da start_thread(arg=0x7fffde7fc700) (pthread_create.c:456) 
15 0x7ffff735b17f clone() (../sysdeps/unix/sysv/linux/x86_64/clone.S:105) 

私は何か間違っていると思う。しかし、私は何が見えないのですか? GoogleTestまたはGoogleMockでバグを起こしましたか?

+0

* compiler *コマンドラインにも-pthreadを追加する必要があります。 –

+0

@ n.m。どうして?コンパイラ、またはより具体的には、pre-processorは、googlemockヘッダーとgoogletestヘッダーに条件付きコンパイルに基づいてpthreadのヘッダーを含めるようになります。 – jokr

+0

これは[動作方法](https://stackoverflow.com/questions/2127797/gcc-significance-of-pthread-flag-when-compiling)です。 –

答えて

2

細かいマニュアルから:

重要な注意: Googleのモックは、そうでない場合の動作は未定義で、モック関数が呼び出される前に設定する期待を必要とします。特に、EXPECT_CALL()とモック関数の呼び出しをインターリーブしてはいけません。

私のシステム(cygwin)でエラー22で断続的に元のコードが失敗したり、メッセージ/エラーコードがまったくないことがあります。この変更は完全に機能します。

for (int i = 0; i < nrThreads; i++) 
{ 
    EXPECT_CALL(dummy, SomeMethod(i)).Times(Exactly(nrCallsPerThread)); 
} 

std::vector<std::thread> threads; 
for (int i = 0; i < nrThreads; i++) 
{ 
    threads.emplace_back([&dummy, i] ... 
+0

固定していただきありがとうございます。 私が達成しようとしたのは、GoogleMockがWindows上でスレッドセーフではなく、Linux上にあることを示すいくつかの例を作成することです。あなたは@ n.m。これを示す例を知っていますか? – jokr

+0

@ jokr no、なぜスレッドセーフではないでしょうか? –

+0

CookBook [link](https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md)はこう言っています: 'Google Mockとスレッドの使用 重要なお知らせ:レシピは、Google Mockがスレッドセーフであるプラットフォームでのみ有効です。現在、これらはpthreadsライブラリ(LinuxとMacを含む)をサポートするプラットフォームです。他のプラットフォームでスレッドセーフなものにするために、 "gtest/internal/gtest-port.h"にいくつかの同期操作を実装する必要があります。 – jokr