diff options
Diffstat (limited to 'src/processor/network_source_line_server_unittest.cc')
-rw-r--r-- | src/processor/network_source_line_server_unittest.cc | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/src/processor/network_source_line_server_unittest.cc b/src/processor/network_source_line_server_unittest.cc deleted file mode 100644 index c45f19cc..00000000 --- a/src/processor/network_source_line_server_unittest.cc +++ /dev/null @@ -1,963 +0,0 @@ -// 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)); - MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - char **symbol_data)); - MOCK_METHOD1(FreeSymbolData, void(const CodeModule *module)); -}; - -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_METHOD2(LoadModuleUsingMemoryBuffer, bool(const CodeModule *module, - char *memory_buffer)); - MOCK_METHOD0(ShouldDeleteMemoryBufferAfterLoadModule, bool()); - 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(); -} |