2

在 cygwin 上,EXPECT_CALL 给出分段错误。回溯显示:

Program received signal SIGSEGV, Segmentation fault.
0x004538e2 in join (ptr=0x61230494 <vtable for pthread_key+12>,
    this=0x8003aedc) at ./gtest/include/gtest/internal/gtest-linked_ptr.h:113
113         while (p->next_ != ptr) p = p->next_;
(gdb) bt
#0  0x004538e2 in join (ptr=0x61230494 <vtable for pthread_key+12>,
    this=0x8003aedc) at ./gtest/include/gtest/internal/gtest-linked_ptr.h:113
#1  copy<testing::internal::ExpectationBase> (
    ptr=0x61230490 <vtable for pthread_key+8>, this=0x8003aed8)
    at ./gtest/include/gtest/internal/gtest-linked_ptr.h:206
#2  linked_ptr (ptr=..., this=0x8003aed8)
    at ./gtest/include/gtest/internal/gtest-linked_ptr.h:149
#3  Expectation (this=0x8003aed8) at ./include/gmock/gmock-spec-builders.h:487
...
(gdb) p ptr
$1 = (const testing::internal::linked_ptr_internal *) 0x61230494 <vtable for pthread_key+12>
(gdb) p p
$2 = (const testing::internal::linked_ptr_internal *) 0x18ec8353
(gdb) p p->next_
Cannot access memory at address 0x18ec8353

看起来像一些 gmock 内部链接列表损坏,但由于我的测试并不复杂,所以连接了:

模拟类:

class NSEBase {
public:
    NSEBase(const std::string& ip, const std::string& port)
        : ip_(ip), port_(port) { } ;

    void setRequestHandler(RequestHandler& req_hdl) {
        request_handler_ = &req_hdl;
    };

    virtual void send(Response& rsp) { };
    virtual void run() { };

    virtual ~NSEBase() { };

private:
    RequestHandler * request_handler_;
    const std::string & ip_, port_;
};

模拟类标题:

class NSEBaseMock : public NSEBase {
public:
  NSEBaseMock(const char* ip, const char* port) : NSEBase(ip, port) {};
  MOCK_METHOD0(run, void());
  MOCK_METHOD1(send, void(Response& rsp));
};

模拟类主体:

class NSEBaseMockTest : public ::testing::Test {
protected:
    static const std::string retrieve_json;
    Request * req_;
    Response * rsp_;
    CSEBase * cse_;
    NSEBaseMock * nse_;
    CSEHandler * hdl_;
    CSEServer * server_;

public:
    virtual void SetUp()
    {
        ....
        nse_ = new NiceMock<NSEBaseMock>("127.0.0.1", "1234");
        ....  
        // cout shows it got here correctly
    }

    virtual void TearDown()
    {
        ....
        delete nse_;
        ....
    }

    void handleRequest() {
        req_ = new Request(retrieve_json);
        hdl_->handleRequest(*req_);
    }

};

const string NSEBaseMockTest::retrieve_json(....);

TEST_F(NSEBaseMockTest, RetrieveCSE) {

  EXPECT_CALL(*nse_, run()) **<--- crash here. no matter with .WillOnce or w/o.**
      .WillOnce(Invoke(this, &NSEBaseMockTest::handleRequest));

  std::cout << "EXPECT_CALL() done" << std::endl;

  ON_CALL(*nse_, send(Property(&Response::getResponseStatusCode, Eq(RSC_OK))));

  std::cout << "ON_CALL() done" << std::endl;


  server_->run();

}

通过 gmock 论坛和这里搜索,还没有任何线索。直到今天我都在使用最新的。

请给我一些想法:)谢谢。

射线


抱歉,伊恩回复晚了。这是我的编译日志,所有 cc 文件的标志相同:

*g++ utest/gmock/NSEBase_mock.cc -Wall -D_WIN32_WINNT=0x0501 -D__USE_W32_SOCKETS -std=gnu++11 -Iinclude -Isrc -Istore -Isrc-gen -Icse -Iutest/gtest -I/cygdrive/c/Workspace/gmock-1.7.0/gtest/include -Iutest/gmock -I/cygdrive/c/Workspace/gmock-1.7.0/include -I/cygdrive/c/Workspace/gmock-1.7.0/gtest/include -g -c  -o build/utest/gmock/NSEBase_mock.o*

链接命令:

*`g++ build/src/Request.o build/src/RequestHandler.o build/src/Response.o build/src/CSEBase.o build/store/FakeStore.o build/src-gen/Response.pb.o build/src-gen/CSEBase.pb.o build/src-gen/CommonTypes.pb.o build/src-gen/Request.pb.o build/cse/CSEServer.o build/cse/CSEHandler.o build/utest/gmock/NSEBase_mock.o build/utest/gmock/gmock_main.o -ljson2pb -ljansson -lprotobuf -lpthread  -lboost_iostreams -lboost_filesystem -lboost_system -L/usr/local/lib  -lgtest -L/cygdrive/c/Workspace/gmock-1.7.0/gtest/lib/.libs -lgmock  -lgtest -L/cygdrive/c/Workspace/gmock-1.7.0/lib/.libs -L/cygdrive/c/Workspace/gmock-1.7.0/gtest/lib/.libs -lws2_32 -o build/gmock.exe`*

关于 NSEBase 中的 ip_, port_ 字符串引用,你是对的,但它还没有相关性,NSEBase 现在是一个存根,它仍然崩溃。

完整的崩溃调用跟踪:

Program received signal SIGSEGV, Segmentation fault.
0x00465002 in join (ptr=0x61230494 <vtable for pthread_key+12>,
    this=0x8003e844) at ./gtest/include/gtest/internal/gtest-linked_ptr.h:113
113         while (p->next_ != ptr) p = p->next_;
(gdb) bt
#0  0x00465002 in join (ptr=0x61230494 <vtable for pthread_key+12>,
    this=0x8003e844) at ./gtest/include/gtest/internal/gtest-linked_ptr.h:113
#1  copy<testing::internal::ExpectationBase> (
    ptr=0x61230490 <vtable for pthread_key+8>, this=0x8003e840)
    at ./gtest/include/gtest/internal/gtest-linked_ptr.h:206
#2  linked_ptr (ptr=..., this=0x8003e840)
    at ./gtest/include/gtest/internal/gtest-linked_ptr.h:149
#3  Expectation (this=0x8003e840) at ./include/gmock/gmock-spec-builders.h:487
#4  construct (this=<optimized out>, __val=..., __p=0x8003e840)
    at /usr/lib/gcc/i686-pc-cygwin/4.9.3/include/c++/ext/new_allocator.h:130
#5  _M_create_node (this=<optimized out>, __x=...)
    at /usr/lib/gcc/i686-pc-cygwin/4.9.3/include/c++/bits/stl_tree.h:397
#6  _M_insert_ (__v=..., __p=0x8003e498, __x=0x0, this=0x8003e494)
    at /usr/lib/gcc/i686-pc-cygwin/4.9.3/include/c++/bits/stl_tree.h:1143
#7  std::_Rb_tree<testing::Expectation, testing::Expectation, std::_Identity<testing::Expectation>, testing::Expectation::Less, std::allocator<testing::Expectation> >::_M_insert_unique (this=0x8003e494, __v=...)
    at /usr/lib/gcc/i686-pc-cygwin/4.9.3/include/c++/bits/stl_tree.h:1503
#8  0x00437bd0 in insert (__x=..., this=<optimized out>)
    at /usr/lib/gcc/i686-pc-cygwin/4.9.3/include/c++/bits/stl_set.h:502
#9  operator+= (e=..., this=<optimized out>)
    at ./include/gmock/gmock-spec-builders.h:602
#10 testing::Sequence::AddExpectation (this=0x8003af20, expectation=...)
    at ./src/gmock-spec-builders.cc:788
#11 0x00449511 in testing::internal::FunctionMockerBase<void ()>::AddNewExpectation(char const*, int, std::string const&, std::tuple<> const&) (
    this=0x8003e188,
    file=0x481bba <testing::_+104> "utest/gmock/NSEBase_mock.cc", line=74,
    source_text=..., m=...)
    at /cygdrive/c/Workspace/gmock-1.7.0/include/gmock/../../../gmock/include/gmock/../../../gmock/include/gmock/gmock-spec-builders.h:1560
#12 0x0044cf12 in testing::internal::MockSpec<void ()>::InternalExpectedAt(char const*, int, char const*, char const*) (this=0x8003e1ac,
    file=0x481bba <testing::_+104> "utest/gmock/NSEBase_mock.cc", line=74,
    obj=0x481bb4 <testing::_+98> "*nse_",
    call=0x481bae <testing::_+92> "run()")
    at /cygdrive/c/Workspace/gmock-1.7.0/include/gmock/../../../gmock/include/gmock/../../../gmock/include/gmock/gmock-spec-builders.h:1273
#13 0x0041432a in NSEBaseMockTest_RetrieveCSE_Test::TestBody (this=0x8003dd70)
    at utest/gmock/NSEBase_mock.cc:74
#14 0x0044c45c in HandleSehExceptionsInMethodIfSupported<testing::Test, void> (
    location=0x484c00 <(anonymous namespace)::b64_decode(std::string const&)::lookup+8000> "the test body",
    method=&virtual table offset 16, this adjustment -2147230352,
---Type <return> to continue, or q <return> to quit---
    object=0x8003dd70) at ./src/gtest.cc:2078
#15 testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>
    (object=object@entry=0x8003dd70,
    method=(void (testing::Test::*)(testing::Test * const)) 0x4142c8 <NSEBaseMockTest_RetrieveCSE_Test::TestBody()>, this adjustment -2147230352,
    location=location@entry=0x484c00 <(anonymous namespace)::b64_decode(std::string const&)::lookup+8000> "the test body") at ./src/gtest.cc:2114
#16 0x0042fb59 in testing::Test::Run (this=0x8003dd70) at ./src/gtest.cc:2151
#17 0x0042fd18 in testing::TestInfo::Run (this=0x8003ac78)
    at ./src/gtest.cc:2326
#18 0x0042fe57 in Run (this=<optimized out>) at ./src/gtest.cc:2301
#19 testing::TestCase::Run (this=0x8003b508) at ./src/gtest.cc:2444
#20 0x00430325 in Run (this=<optimized out>) at ./src/gtest.cc:2430
#21 testing::internal::UnitTestImpl::RunAllTests (this=0x8003b330)
    at ./src/gtest.cc:4315
#22 0x0044c15c in HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (
    location=0x484d60 <(anonymous namespace)::b64_decode(std::string const&)::lookup+8352> "auxiliary test code (environments or event listeners)",
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x42ff60 <testing::internal::UnitTestImpl::RunAllTests()>, this adjustment -2147241168, object=0x8003b330) at ./src/gtest.cc:2078
#23 testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x8003b330,
    method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x42ff60 <testing::internal::UnitTestImpl::RunAllTests()>, this adjustment -2147241168,
    location=location@entry=0x484d60 <(anonymous namespace)::b64_decode(std::string const&)::lookup+8352> "auxiliary test code (environments or event listeners)") at ./src/gtest.cc:2114
#24 0x00430597 in testing::UnitTest::Run (
    this=0x4c81c8 <testing::UnitTest::GetInstance()::instance>)
    at ./src/gtest.cc:3929
#25 0x0043d793 in RUN_ALL_TESTS ()
    at /cygdrive/c/Workspace/gmock-1.7.0/include/gmock/../../../gmock/include/gmock/../../../gmock/include/gmock/internal/../../../../gmock/fused-src/gtest/gtest.h:20058
#26 0x004145c1 in main (argc=1, argv=0x28cc6c) at utest/gmock/gmock_main.cc:60

11 到 #13 似乎增加了对 gmock 内部结构的期望,其中链接列表出现问题。


现在简化为一个源文件以使事情变得清晰。

gmtest.cc

#include "gmock/gmock.h"
#include "gtest/gtest.h"

class Base {
public:
    virtual void f1() { };
    virtual void f2() { };
};

class BaseMock : public Base {
public:
    MOCK_METHOD0(f1, void());
    MOCK_METHOD0(f2, void());
};

class BaseMockTest : public ::testing::Test {
};

TEST_F(BaseMockTest, Test1) {
    BaseMock bm;

    EXPECT_CALL(bm, f1()).Times(1);

    std::cout << "EXPECT_CALL done.\n";
}

GTEST_API_ int main(int argc, char** argv) {
  std::cout << "Running main() from gmock_main.cc\n";
  testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}

并编译链接:

$ g++ -I/mnt/Workspace/gmock/include -I/mnt/Workspace/gmock/gtest/include -g -c gmtest.cc

$ g++ gmtest.o -L/mnt/Workspace/gmock/lib/.libs/ -lgmock -L/mnt/Workspace/gmock/gtest/lib/.libs -lgtest -o gmtest

砰!还是崩溃!任何人都可以验证这一点吗?

射线

4

2 回答 2

3

得到了解决方案。也许 Ian 是对的,仍然编译我的代码和 Gmock 之间的标志不一致问题。所以使用融合的gmock源代码代替libs,问题就没有了。生成融合的 gmock 代码:

scripts/python fuse_gmock_files.py OUTPUT_DIR

并将其拉入您的项目,然后不要忘记修改构建设置以删除 gmock/gtest 库。

于 2015-08-02T17:11:44.540 回答
0

我遇到了完全相同的问题,而且确实是编译器标志不兼容。我有一个 cmake 2.8 / CentOS 6.8 项目,我需要在 cmake 3.6 / Cygwin 2.9 下编译以执行 Windows 10。我在打开 VERBOSE 的情况下编译了 gtest 和我的项目,并比较了使用中的标志。然后我添加add_definitions( -DGTEST_HAS_PTHREAD=1 )到我的 cmake 项目中,并且使用 gtest 和 gmock 的单元测试没有问题。

于 2017-09-25T15:27:06.240 回答