mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-02-06 13:33:36 +00:00
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@569 4c0a9323-5329-0410-9bdc-e9ce6186880e
956 lines
37 KiB
C++
956 lines
37 KiB
C++
// Copyright (c) 2010, Google Inc.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following disclaimer
|
|
// in the documentation and/or other materials provided with the
|
|
// distribution.
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
// contributors may be used to endorse or promote products derived from
|
|
// this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
// Unit tests for NetworkSourceLineServer.
|
|
|
|
#include <ios>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
#include "breakpad_googletest_includes.h"
|
|
#include "google_breakpad/processor/code_module.h"
|
|
#include "google_breakpad/processor/source_line_resolver_interface.h"
|
|
#include "google_breakpad/processor/stack_frame.h"
|
|
#include "google_breakpad/processor/symbol_supplier.h"
|
|
#include "processor/binarystream.h"
|
|
#include "processor/cfi_frame_info.h"
|
|
#include "processor/network_source_line_server.h"
|
|
#include "processor/network_source_line_protocol.h"
|
|
#include "processor/windows_frame_info.h"
|
|
|
|
namespace {
|
|
using std::ios_base;
|
|
using std::set;
|
|
using std::string;
|
|
using google_breakpad::CFIFrameInfo;
|
|
using google_breakpad::CodeModule;
|
|
using google_breakpad::binarystream;
|
|
using google_breakpad::NetworkInterface;
|
|
using google_breakpad::NetworkSourceLineServer;
|
|
using google_breakpad::SourceLineResolverInterface;
|
|
using google_breakpad::StackFrame;
|
|
using google_breakpad::SymbolSupplier;
|
|
using google_breakpad::SystemInfo;
|
|
using google_breakpad::WindowsFrameInfo;
|
|
using ::testing::_;
|
|
using ::testing::DoAll;
|
|
using ::testing::Invoke;
|
|
using ::testing::Property;
|
|
using ::testing::Return;
|
|
using ::testing::SetArgumentPointee;
|
|
// Style guide forbids "using namespace", so at least shorten it.
|
|
namespace P = google_breakpad::source_line_protocol;
|
|
|
|
class MockNetwork : public NetworkInterface {
|
|
public:
|
|
MockNetwork() {}
|
|
|
|
MOCK_METHOD1(Init, bool(bool listen));
|
|
MOCK_METHOD2(Send, bool(const char *data, size_t length));
|
|
MOCK_METHOD1(WaitToReceive, bool(int timeout));
|
|
MOCK_METHOD3(Receive, bool(char *buffer, size_t buffer_size,
|
|
ssize_t &received));
|
|
};
|
|
|
|
class MockSymbolSupplier : public SymbolSupplier {
|
|
public:
|
|
MockSymbolSupplier() {}
|
|
|
|
MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule *module,
|
|
const SystemInfo *system_info,
|
|
string *symbol_file));
|
|
MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule *module,
|
|
const SystemInfo *system_info,
|
|
string *symbol_file,
|
|
string *symbol_data));
|
|
};
|
|
|
|
class MockSourceLineResolver : public SourceLineResolverInterface {
|
|
public:
|
|
MockSourceLineResolver() {}
|
|
virtual ~MockSourceLineResolver() {}
|
|
|
|
MOCK_METHOD2(LoadModule, bool(const CodeModule *module,
|
|
const string &map_file));
|
|
MOCK_METHOD2(LoadModuleUsingMapBuffer, bool(const CodeModule *module,
|
|
const string &map_buffer));
|
|
MOCK_METHOD1(UnloadModule, void(const CodeModule *module));
|
|
MOCK_METHOD1(HasModule, bool(const CodeModule *module));
|
|
MOCK_METHOD1(FillSourceLineInfo, void(StackFrame *frame));
|
|
MOCK_METHOD1(FindWindowsFrameInfo,
|
|
WindowsFrameInfo*(const StackFrame *frame));
|
|
MOCK_METHOD1(FindCFIFrameInfo,
|
|
CFIFrameInfo*(const StackFrame *frame));
|
|
};
|
|
|
|
class TestNetworkSourceLineServer : public NetworkSourceLineServer {
|
|
public:
|
|
// Override visibility for testing. It's a lot easier to just
|
|
// call into this method and verify the result than it would be
|
|
// to mock out the calls to the NetworkInterface, even though
|
|
// that would ostensibly be more correct and test the code more
|
|
// thoroughly. Perhaps if someone has time and figures out a
|
|
// clean way to do it this could be changed.
|
|
using NetworkSourceLineServer::HandleRequest;
|
|
|
|
TestNetworkSourceLineServer(SymbolSupplier *supplier,
|
|
SourceLineResolverInterface *resolver,
|
|
NetworkInterface *net,
|
|
u_int64_t max_symbol_lines = 0)
|
|
: NetworkSourceLineServer(supplier, resolver, net, max_symbol_lines)
|
|
|
|
{}
|
|
};
|
|
|
|
class NetworkSourceLineServerTest : public ::testing::Test {
|
|
public:
|
|
MockSymbolSupplier supplier;
|
|
MockSourceLineResolver resolver;
|
|
MockNetwork net;
|
|
TestNetworkSourceLineServer *server;
|
|
|
|
NetworkSourceLineServerTest() : server(NULL) {}
|
|
|
|
void SetUp() {
|
|
server = new TestNetworkSourceLineServer(&supplier, &resolver, &net);
|
|
}
|
|
};
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestInit) {
|
|
EXPECT_CALL(net, Init(true)).WillOnce(Return(true));
|
|
EXPECT_CALL(net, WaitToReceive(0)).WillOnce(Return(false));
|
|
ASSERT_TRUE(server->Initialize());
|
|
EXPECT_FALSE(server->RunOnce(0));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestMalformedRequest) {
|
|
binarystream request;
|
|
// send a request without a full sequence number
|
|
request << u_int8_t(1);
|
|
binarystream response;
|
|
EXPECT_FALSE(server->HandleRequest(request, response));
|
|
request.rewind();
|
|
// send a request without a command
|
|
request << u_int16_t(1);
|
|
EXPECT_FALSE(server->HandleRequest(request, response));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestUnknownCommand) {
|
|
binarystream request;
|
|
// send a request with an unknown command
|
|
request << u_int16_t(1) << u_int8_t(100);
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(u_int16_t(1), response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestHasBasic) {
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true));
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
// first request should come back as not loaded
|
|
request << sequence << P::HAS << string("test.dll") << string("test.pdb")
|
|
<< string("ABCD1234");
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(P::MODULE_NOT_LOADED, int(response_data));
|
|
// second request should come back as loaded
|
|
binarystream request2;
|
|
request2 << sequence << P::HAS << string("loaded.dll") << string("loaded.pdb")
|
|
<< string("ABCD1234");
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(P::MODULE_LOADED, int(response_data));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestMalformedHasRequest) {
|
|
binarystream request;
|
|
// send request with just command, missing all data
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::HAS;
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
// send request with just module name
|
|
binarystream request2;
|
|
request2 << sequence << P::HAS << string("test.dll");
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
// send request with module name, debug file, missing debug id
|
|
binarystream request3;
|
|
request3 << sequence << P::HAS << string("test.dll") << string("test.pdb");
|
|
ASSERT_TRUE(server->HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestHasLoad) {
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.WillOnce(Return(SymbolSupplier::FOUND));
|
|
|
|
// verify that the module is not loaded, with a HAS request
|
|
binarystream request;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::HAS << string("found.dll") << string("found.pdb")
|
|
<< string("ABCD1234");
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(P::MODULE_NOT_LOADED, int(response_data));
|
|
// now send a load request for this module
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0xB0B0;
|
|
request2 << sequence2 << P::LOAD << string("found.dll") << string("found.pdb")
|
|
<< string("ABCD1234");
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
// sending another HAS message should now show it as loaded
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0xC0C0;
|
|
request3 << sequence3 << P::HAS << string("found.dll") << string("found.pdb")
|
|
<< string("ABCD1234");
|
|
ASSERT_TRUE(server->HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(P::MODULE_LOADED, int(response_data));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestLoad) {
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(false));
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.WillOnce(Return(SymbolSupplier::NOT_FOUND))
|
|
.WillOnce(Return(SymbolSupplier::INTERRUPT))
|
|
.WillOnce(Return(SymbolSupplier::FOUND));
|
|
|
|
// notfound.dll should return LOAD_NOT_FOUND
|
|
binarystream request;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::LOAD << string("notfound.dll")
|
|
<< string("notfound.pdb") << string("ABCD1234");
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(int(P::LOAD_NOT_FOUND), int(response_data));
|
|
// interrupt.dll should return LOAD_INTERRUPT
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0xB0B0;
|
|
request2 << sequence2 << P::LOAD << string("interrupt.dll")
|
|
<< string("interrupt.pdb") << string("0000");
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(int(P::LOAD_INTERRUPT), int(response_data));
|
|
// fail.dll should return LOAD_FAIL
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0xC0C0;
|
|
request3 << sequence3 << P::LOAD << string("fail.dll") << string("fail.pdb")
|
|
<< string("FFFFFFFF");
|
|
ASSERT_TRUE(server->HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(int(P::LOAD_FAIL), int(response_data));
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestMalformedLoadRequest) {
|
|
binarystream request;
|
|
// send request with just command, missing all data
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::LOAD;
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
// send request with just module name
|
|
binarystream request2;
|
|
request2 << sequence << P::LOAD << string("test.dll");
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
// send request with module name, debug file, missing debug id
|
|
binarystream request3;
|
|
request3 << sequence << P::LOAD << string("test.dll") << string("test.pdb");
|
|
ASSERT_TRUE(server->HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::ERROR, int(response_status));
|
|
}
|
|
|
|
void FillFullSourceLineInfo(StackFrame *frame) {
|
|
frame->function_name = "function1";
|
|
frame->function_base = 0x1200;
|
|
frame->source_file_name = "function1.cc";
|
|
frame->source_line = 1;
|
|
frame->source_line_base = 0x1230;
|
|
}
|
|
|
|
void FillPartialSourceLineInfo(StackFrame *frame) {
|
|
frame->function_name = "function2";
|
|
frame->function_base = 0xFFF0;
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestGet) {
|
|
EXPECT_CALL(resolver, FillSourceLineInfo(_))
|
|
.WillOnce(Invoke(FillFullSourceLineInfo))
|
|
.WillOnce(Invoke(FillPartialSourceLineInfo));
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::GET << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
string function, source_file;
|
|
u_int32_t source_line;
|
|
u_int64_t function_base, source_line_base;
|
|
response >> response_sequence >> response_status >> function
|
|
>> function_base >> source_file >> source_line >> source_line_base;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("function1", function);
|
|
EXPECT_EQ(0x1200, function_base);
|
|
EXPECT_EQ("function1.cc", source_file);
|
|
EXPECT_EQ(1, source_line);
|
|
EXPECT_EQ(0x1230, source_line_base);
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0xC0C0;
|
|
request2 << sequence2 << P::GET << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0xFFFF);
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> function
|
|
>> function_base >> source_file >> source_line >> source_line_base;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("function2", function);
|
|
EXPECT_EQ(0xFFF0, function_base);
|
|
EXPECT_EQ("", source_file);
|
|
EXPECT_EQ(0, source_line);
|
|
EXPECT_EQ(0, source_line_base);
|
|
}
|
|
|
|
WindowsFrameInfo* GetFullWindowsFrameInfo(const StackFrame *frame) {
|
|
// return frame info with program string
|
|
return new WindowsFrameInfo(1, 2, 3, 0xA, 0xFF, 0xF00,
|
|
true,
|
|
"x y =");
|
|
}
|
|
|
|
WindowsFrameInfo* GetPartialWindowsFrameInfo(const StackFrame *frame) {
|
|
// return frame info, no program string
|
|
return new WindowsFrameInfo(1, 2, 3, 4, 5, 6, true, "");
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestGetStackWin) {
|
|
EXPECT_CALL(resolver, FindWindowsFrameInfo(_))
|
|
.WillOnce(Invoke(GetFullWindowsFrameInfo))
|
|
.WillOnce(Invoke(GetPartialWindowsFrameInfo))
|
|
.WillOnce(Return((WindowsFrameInfo*)NULL));
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::GETSTACKWIN << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
string stack_info;
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("0 0 0 1 2 3 a ff f00 1 x y =", stack_info);
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0xB0B0;
|
|
request2 << sequence2 << P::GETSTACKWIN << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0xABCD);
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("0 0 0 1 2 3 4 5 6 0 1", stack_info);
|
|
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0xC0C0;
|
|
request3 << sequence3 << P::GETSTACKWIN << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0xFFFF);
|
|
ASSERT_TRUE(server->HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("", stack_info);
|
|
}
|
|
|
|
|
|
CFIFrameInfo* GetCFIFrameInfoJustCFA(const StackFrame *frame) {
|
|
CFIFrameInfo* cfi = new CFIFrameInfo();
|
|
cfi->SetCFARule("12345678");
|
|
return cfi;
|
|
}
|
|
|
|
CFIFrameInfo* GetCFIFrameInfoCFARA(const StackFrame *frame) {
|
|
CFIFrameInfo* cfi = new CFIFrameInfo();
|
|
cfi->SetCFARule("12345678");
|
|
cfi->SetRARule("abcdefgh");
|
|
return cfi;
|
|
}
|
|
|
|
CFIFrameInfo* GetCFIFrameInfoLots(const StackFrame *frame) {
|
|
CFIFrameInfo* cfi = new CFIFrameInfo();
|
|
cfi->SetCFARule("12345678");
|
|
cfi->SetRARule("abcdefgh");
|
|
cfi->SetRegisterRule("r0", "foo bar");
|
|
cfi->SetRegisterRule("b0", "123 abc +");
|
|
return cfi;
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestGetStackCFI) {
|
|
EXPECT_CALL(resolver, FindCFIFrameInfo(_))
|
|
.WillOnce(Return((CFIFrameInfo*)NULL))
|
|
.WillOnce(Invoke(GetCFIFrameInfoJustCFA))
|
|
.WillOnce(Invoke(GetCFIFrameInfoCFARA))
|
|
.WillOnce(Invoke(GetCFIFrameInfoLots));
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
request << sequence << P::GETSTACKCFI << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
binarystream response;
|
|
ASSERT_TRUE(server->HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
string stack_info;
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("", stack_info);
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0xB0B0;
|
|
request2 << sequence2 << P::GETSTACKCFI << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0xABCD);
|
|
ASSERT_TRUE(server->HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(".cfa: 12345678", stack_info);
|
|
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0xC0C0;
|
|
request3 << sequence3 << P::GETSTACKCFI << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0xFFFF);
|
|
ASSERT_TRUE(server->HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(".cfa: 12345678 .ra: abcdefgh", stack_info);
|
|
|
|
binarystream request4;
|
|
const u_int16_t sequence4 = 0xD0D0;
|
|
request4 << sequence4 << P::GETSTACKCFI << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0xFFFF);
|
|
ASSERT_TRUE(server->HandleRequest(request4, response));
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence4, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ(".cfa: 12345678 .ra: abcdefgh b0: 123 abc + r0: foo bar",
|
|
stack_info);
|
|
}
|
|
|
|
TEST_F(NetworkSourceLineServerTest, TestMalformedGetRequest) {
|
|
//TODO
|
|
}
|
|
|
|
TEST(TestMissingMembers, TestServerWithoutSymbolSupplier) {
|
|
// Should provide reasonable responses without a SymbolSupplier
|
|
MockSourceLineResolver resolver;
|
|
MockNetwork net;
|
|
TestNetworkSourceLineServer server(NULL, &resolver, &net);
|
|
|
|
// All LOAD requests should return LOAD_NOT_FOUND
|
|
binarystream request;
|
|
binarystream response;
|
|
const u_int16_t sequence = 0xB0B0;
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
request << sequence << P::LOAD << string("found.dll") << string("found.pdb")
|
|
<< string("ABCD1234");
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_NOT_FOUND), int(response_data));
|
|
}
|
|
|
|
TEST(TestMissingMembers, TestServerWithoutResolver) {
|
|
// Should provide reasonable responses without a SourceLineResolver
|
|
MockSymbolSupplier supplier;
|
|
MockNetwork net;
|
|
TestNetworkSourceLineServer server(&supplier, NULL, &net);
|
|
|
|
// GET requests should return empty info
|
|
binarystream request;
|
|
binarystream response;
|
|
const u_int16_t sequence = 0xA0A0;
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status;
|
|
request << sequence << P::GET << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
string function, source_file;
|
|
u_int32_t source_line;
|
|
u_int64_t function_base, source_line_base;
|
|
response >> response_sequence >> response_status >> function
|
|
>> function_base >> source_file >> source_line >> source_line_base;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("", function);
|
|
EXPECT_EQ(0x0, function_base);
|
|
EXPECT_EQ("", source_file);
|
|
EXPECT_EQ(0, source_line);
|
|
EXPECT_EQ(0x0, source_line_base);
|
|
|
|
// GETSTACKWIN requests should return an empty string
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0xB0B0;
|
|
request << sequence2 << P::GETSTACKWIN << string("loaded.dll")
|
|
<< string("loaded.pdb") << string("ABCD1234")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
string response_string;
|
|
response >> response_sequence >> response_status >> response_string;
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
EXPECT_EQ("", response_string);
|
|
}
|
|
|
|
class TestModuleManagement : public ::testing::Test {
|
|
public:
|
|
MockSymbolSupplier supplier;
|
|
MockSourceLineResolver resolver;
|
|
MockNetwork net;
|
|
TestNetworkSourceLineServer server;
|
|
|
|
// Init server with symbol line limit of 25
|
|
TestModuleManagement() : server(&supplier, &resolver, &net, 25) {}
|
|
};
|
|
|
|
TEST_F(TestModuleManagement, TestModuleUnloading) {
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
|
|
Return(SymbolSupplier::FOUND)));
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(false));
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
|
|
string("one.dll|one.pdb|1111"))))
|
|
.Times(1);
|
|
|
|
// load three modules, each with 10 lines of symbols.
|
|
// the third module will overflow the server's symbol line limit,
|
|
// and should cause the first module to be unloaded.
|
|
binarystream request;
|
|
const u_int16_t sequence = 0x1010;
|
|
request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
|
|
<< string("1111");
|
|
binarystream response;
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0x2020;
|
|
request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
|
|
<< string("2222");
|
|
ASSERT_TRUE(server.HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0x3030;
|
|
request3 << sequence3 << P::LOAD << string("three.dll") << string("three.pdb")
|
|
<< string("3333");
|
|
ASSERT_TRUE(server.HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
}
|
|
|
|
TEST_F(TestModuleManagement, TestSymbolLimitTooLow) {
|
|
// load module with symbol count > limit,
|
|
// ensure that it doesn't get unloaded even though it's the only module
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.WillOnce(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n")),
|
|
Return(SymbolSupplier::FOUND)));
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(resolver, UnloadModule(_))
|
|
.Times(0);
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0x1010;
|
|
request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
|
|
<< string("1111");
|
|
binarystream response;
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
}
|
|
|
|
TEST_F(TestModuleManagement, TestModuleLoadLRU) {
|
|
// load 2 modules, then re-load the first one,
|
|
// then load a third one, causing the second one to be unloaded
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
|
|
Return(SymbolSupplier::FOUND)));
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.WillOnce(Return(false)) // load module 1
|
|
.WillOnce(Return(false)) // load module 2
|
|
.WillOnce(Return(true)) // module 1 already loaded
|
|
.WillOnce(Return(false)); // load module 3
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
|
|
string("two.dll|two.pdb|2222"))))
|
|
.Times(1);
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0x1010;
|
|
request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
|
|
<< string("1111");
|
|
binarystream response;
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0x2020;
|
|
request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
|
|
<< string("2222");
|
|
ASSERT_TRUE(server.HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0x3030;
|
|
request3 << sequence3 << P::LOAD << string("one.dll") << string("one.pdb")
|
|
<< string("1111");
|
|
ASSERT_TRUE(server.HandleRequest(request3, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request4;
|
|
const u_int16_t sequence4 = 0x4040;
|
|
request4 << sequence4 << P::LOAD << string("three.dll") << string("three.pdb")
|
|
<< string("3333");
|
|
ASSERT_TRUE(server.HandleRequest(request4, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence4, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
}
|
|
|
|
TEST_F(TestModuleManagement, TestModuleGetLRU) {
|
|
// load 2 modules, then issue a GET for the first one,
|
|
// then load a third one, causing the second one to be unloaded
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
|
|
Return(SymbolSupplier::FOUND)));
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(false));
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(resolver, FillSourceLineInfo(_))
|
|
.Times(1);
|
|
EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
|
|
string("two.dll|two.pdb|2222"))))
|
|
.Times(1);
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0x1010;
|
|
request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
|
|
<< string("1111");
|
|
binarystream response;
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0x2020;
|
|
request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
|
|
<< string("2222");
|
|
ASSERT_TRUE(server.HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0x3030;
|
|
request3 << sequence3 << P::GET << string("one.dll")
|
|
<< string("one.pdb") << string("1111")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
ASSERT_TRUE(server.HandleRequest(request3, response));
|
|
string function, source_file;
|
|
u_int32_t source_line;
|
|
u_int64_t function_base, source_line_base;
|
|
response >> response_sequence >> response_status >> function
|
|
>> function_base >> source_file >> source_line >> source_line_base;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
// Don't care about the rest of the response, really.
|
|
|
|
binarystream request4;
|
|
const u_int16_t sequence4 = 0x4040;
|
|
request4 << sequence4 << P::LOAD << string("three.dll") << string("three.pdb")
|
|
<< string("3333");
|
|
ASSERT_TRUE(server.HandleRequest(request4, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence4, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
}
|
|
|
|
TEST_F(TestModuleManagement, TestModuleGetStackWinLRU) {
|
|
// load 2 modules, then issue a GETSTACKWIN for the first one,
|
|
// then load a third one, causing the second one to be unloaded
|
|
EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
|
|
Return(SymbolSupplier::FOUND)));
|
|
EXPECT_CALL(resolver, HasModule(_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(false));
|
|
EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
|
|
.Times(3)
|
|
.WillRepeatedly(Return(true));
|
|
EXPECT_CALL(resolver, FindWindowsFrameInfo(_))
|
|
.WillOnce(Return((WindowsFrameInfo*)NULL));
|
|
EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
|
|
string("two.dll|two.pdb|2222"))))
|
|
.Times(1);
|
|
|
|
binarystream request;
|
|
const u_int16_t sequence = 0x1010;
|
|
request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
|
|
<< string("1111");
|
|
binarystream response;
|
|
ASSERT_TRUE(server.HandleRequest(request, response));
|
|
u_int16_t response_sequence;
|
|
u_int8_t response_status, response_data;
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request2;
|
|
const u_int16_t sequence2 = 0x2020;
|
|
request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
|
|
<< string("2222");
|
|
ASSERT_TRUE(server.HandleRequest(request2, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence2, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
|
|
binarystream request3;
|
|
const u_int16_t sequence3 = 0x3030;
|
|
request3 << sequence3 << P::GETSTACKWIN << string("one.dll")
|
|
<< string("one.pdb") << string("1111")
|
|
<< u_int64_t(0x1000) << u_int64_t(0x1234);
|
|
ASSERT_TRUE(server.HandleRequest(request3, response));
|
|
string stack_info;
|
|
response >> response_sequence >> response_status
|
|
>> stack_info;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence3, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
// Don't care about the rest of the response, really.
|
|
|
|
binarystream request4;
|
|
const u_int16_t sequence4 = 0x4040;
|
|
request4 << sequence4 << P::LOAD << string("three.dll") << string("three.pdb")
|
|
<< string("3333");
|
|
ASSERT_TRUE(server.HandleRequest(request4, response));
|
|
response >> response_sequence >> response_status >> response_data;
|
|
ASSERT_FALSE(response.eof());
|
|
EXPECT_EQ(sequence4, response_sequence);
|
|
EXPECT_EQ(P::OK, int(response_status));
|
|
ASSERT_EQ(int(P::LOAD_OK), int(response_data));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char *argv[]) {
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|