GoogleMock在Linux上不是线程安全吗?

时间:2017-06-25 19:51:38

标签: c++ linux multithreading visual-studio googlemock

我开始在Windows上测试GoogleMock(1.8.0版)。我想展示一个不是线程安全的例子。在证明成功后,我想表明在Linux上运行相同的测试。但那失败了。这与我的期望不符。 由于GoogleMock文档说它在或应该是具有pthread的系统上的线程安全,因此它应该在Linux上是线程安全的。我必须将-pthread添加到链接器命令行以构建可执行文件。这意味着GoogleMock或GoogleTest确实使用了pthread。

这是我用于测试的代码:

#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!的{​​{1}}消息。

在Linux,Ubuntu 17.04上,当我从命令行运行Debug构建时,我得到Expression: vector iterator not decrementable

当在Linux上的调试器中运行时,程序(经常)在gtest-port.h第1100行被中断,这是该callstack中的第2行:

[ FATAL ] ../googletest-release-1.8.0/googletest/include/gtest/internal/gtest-port.h:1928:: pthread_mutex_lock(&mutex_)failed with error 22

因为它应该是线程安全的,我怀疑我做错了什么。但我不知道是什么。 或者我是否在GoogleTest或GoogleMock中遇到了错误?

1 个答案:

答案 0 :(得分:4)

来自精细的手册:

  

重要说明:Google Mock要求在调用模拟函数之前设置期望,否则行为未定义。特别是,您不能交错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] ...