diff options
Diffstat (limited to 'src/processor/network_source_line_resolver_unittest.cc')
-rw-r--r-- | src/processor/network_source_line_resolver_unittest.cc | 535 |
1 files changed, 0 insertions, 535 deletions
diff --git a/src/processor/network_source_line_resolver_unittest.cc b/src/processor/network_source_line_resolver_unittest.cc deleted file mode 100644 index bf0aae78..00000000 --- a/src/processor/network_source_line_resolver_unittest.cc +++ /dev/null @@ -1,535 +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 NetworkSourceLineResolver. - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "google_breakpad/processor/network_source_line_resolver.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/symbol_supplier.h" -#include "processor/basic_code_module.h" -#include "processor/binarystream.h" -#include "processor/cfi_frame_info.h" -#include "processor/network_interface.h" -#include "processor/network_source_line_protocol.h" -#include "processor/windows_frame_info.h" - -namespace google_breakpad { -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)); -}; -} - -namespace { -using std::string; -using google_breakpad::binarystream; -using google_breakpad::BasicCodeModule; -using google_breakpad::CFIFrameInfo; -using google_breakpad::MockNetwork; -using google_breakpad::NetworkSourceLineResolver; -using google_breakpad::StackFrame; -using google_breakpad::SymbolSupplier; -using google_breakpad::WindowsFrameInfo; -using ::testing::_; -using ::testing::Invoke; -using ::testing::Return; -using namespace google_breakpad::source_line_protocol; - -class TestNetworkSourceLineResolver : public ::testing::Test { -public: - TestNetworkSourceLineResolver() : resolver(NULL) {} - - void SetUp() { - EXPECT_CALL(net, Init(false)).WillOnce(Return(true)); - resolver = new NetworkSourceLineResolver(&net, 0); - } - - NetworkSourceLineResolver *resolver; - MockNetwork net; -}; - -bool GeneratePositiveHasResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << u_int16_t(0) << OK << MODULE_LOADED; - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - return true; -} - -bool GenerateNegativeHasResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << u_int16_t(1) << OK << MODULE_NOT_LOADED; - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - return true; -} - -TEST_F(TestNetworkSourceLineResolver, TestHasMessages) { - EXPECT_CALL(net, Send(_,_)) - .WillOnce(Return(true)) - .WillOnce(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .WillOnce(Return(true)) - .WillOnce(Return(true)); - EXPECT_CALL(net, Receive(_,_,_)) - .WillOnce(Invoke(GeneratePositiveHasResponse)) - .WillOnce(Invoke(GenerateNegativeHasResponse)); - ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL); - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - EXPECT_TRUE(resolver->HasModule(&module)); - BasicCodeModule module2(0x0, 0x0, "test2.dll", "test2.pdb", "FFFF", "", ""); - EXPECT_FALSE(resolver->HasModule(&module2)); - // calling again should hit the cache, and not the network - EXPECT_TRUE(resolver->HasModule(&module)); -} - -bool GenerateErrorResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << u_int16_t(0) << ERROR; - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - return true; -} - -TEST_F(TestNetworkSourceLineResolver, TestHasErrorResponse) { - EXPECT_CALL(net, Send(_,_)) - .WillOnce(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .WillOnce(Return(true)); - EXPECT_CALL(net, Receive(_,_,_)) - .WillOnce(Invoke(GenerateErrorResponse)); - ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL); - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - // error packet should function as a not found - EXPECT_FALSE(resolver->HasModule(&module)); -} - -// GenerateLoadResponse will generate (LOAD_NOT_FOUND, LOAD_INTERRUPT, -// LOAD_FAIL, LOAD_OK) in order. -class LoadHelper { - public: - LoadHelper() : response(LOAD_NOT_FOUND), sequence(0) {} - bool GenerateLoadResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << sequence << OK << response; - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - ++sequence; - ++response; - return true; - } - u_int8_t response; - u_int16_t sequence; -}; - -TEST_F(TestNetworkSourceLineResolver, TestLoadMessages) { - EXPECT_CALL(net, Send(_,_)) - .Times(4) - .WillRepeatedly(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .Times(4) - .WillRepeatedly(Return(true)); - LoadHelper helper; - EXPECT_CALL(net, Receive(_,_,_)) - .Times(4) - .WillRepeatedly(Invoke(&helper, &LoadHelper::GenerateLoadResponse)); - ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL); - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - string s; - EXPECT_EQ(SymbolSupplier::NOT_FOUND, - resolver->GetSymbolFile(&module, NULL, &s)); - BasicCodeModule module2(0x0, 0x0, "test2.dll", "test2.pdb", "FFFF", "", ""); - EXPECT_EQ(SymbolSupplier::INTERRUPT, - resolver->GetSymbolFile(&module2, NULL, &s)); - BasicCodeModule module3(0x0, 0x0, "test3.dll", "test3.pdb", "0000", "", ""); - // a FAIL result from the network should come back as NOT_FOUND - EXPECT_EQ(SymbolSupplier::NOT_FOUND, - resolver->GetSymbolFile(&module3, NULL, &s)); - BasicCodeModule module4(0x0, 0x0, "test4.dll", "test4.pdb", "1010", "", ""); - EXPECT_EQ(SymbolSupplier::FOUND, - resolver->GetSymbolFile(&module4, NULL, &s)); - // calling this should hit the cache, and not the network - EXPECT_TRUE(resolver->HasModule(&module4)); -} - -TEST_F(TestNetworkSourceLineResolver, TestLoadErrorResponse) { - EXPECT_CALL(net, Send(_,_)) - .WillOnce(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .WillOnce(Return(true)); - EXPECT_CALL(net, Receive(_,_,_)) - .WillOnce(Invoke(GenerateErrorResponse)); - ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL); - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - string s; - // error packet should function as NOT_FOUND response - EXPECT_EQ(SymbolSupplier::NOT_FOUND, - resolver->GetSymbolFile(&module, NULL, &s)); -} - -class GetHelper { - public: - GetHelper() : sequence(1) {} - bool GenerateGetResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << sequence << OK; - switch(sequence) { - case 1: - // return full info - stream << string("test()") << u_int64_t(0x1000) << string("test.c") - << u_int32_t(1) << u_int64_t(0x1010); - break; - case 2: - // return full info - stream << string("test2()") << u_int64_t(0x2000) << string("test2.c") - << u_int32_t(2) << u_int64_t(0x2020); - break; - case 3: - // return just function name - stream << string("test3()") << u_int64_t(0x4000) << string("") - << u_int32_t(0) << u_int64_t(0); - break; - } - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - ++sequence; - return true; - } - u_int16_t sequence; -}; - -TEST_F(TestNetworkSourceLineResolver, TestGetMessages) { - EXPECT_CALL(net, Send(_,_)) - .Times(4) - .WillRepeatedly(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .Times(4) - .WillRepeatedly(Return(true)); - GetHelper helper; - EXPECT_CALL(net, Receive(_,_,_)) - .Times(4) - .WillOnce(Invoke(GeneratePositiveHasResponse)) - .WillRepeatedly(Invoke(&helper, &GetHelper::GenerateGetResponse)); - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - // The resolver has to think the module is loaded before it will respond - // to GET requests for that module. - EXPECT_TRUE(resolver->HasModule(&module)); - StackFrame frame; - frame.module = &module; - frame.instruction = 0x1010; - resolver->FillSourceLineInfo(&frame); - EXPECT_EQ("test()", frame.function_name); - EXPECT_EQ(0x1000, frame.function_base); - EXPECT_EQ("test.c", frame.source_file_name); - EXPECT_EQ(1, frame.source_line); - EXPECT_EQ(0x1010, frame.source_line_base); - - StackFrame frame2; - frame2.module = &module; - frame2.instruction = 0x2020; - resolver->FillSourceLineInfo(&frame2); - EXPECT_EQ("test2()", frame2.function_name); - EXPECT_EQ(0x2000, frame2.function_base); - EXPECT_EQ("test2.c", frame2.source_file_name); - EXPECT_EQ(2, frame2.source_line); - EXPECT_EQ(0x2020, frame2.source_line_base); - - StackFrame frame3; - frame3.module = &module; - frame3.instruction = 0x4040; - resolver->FillSourceLineInfo(&frame3); - EXPECT_EQ("test3()", frame3.function_name); - EXPECT_EQ(0x4000, frame3.function_base); - EXPECT_EQ("", frame3.source_file_name); - EXPECT_EQ(0, frame3.source_line); - EXPECT_EQ(0, frame3.source_line_base); - - // this should come from the cache and not hit the network - StackFrame frame4; - frame4.module = &module; - frame4.instruction = 0x1010; - resolver->FillSourceLineInfo(&frame4); - EXPECT_EQ("test()", frame4.function_name); - EXPECT_EQ(0x1000, frame4.function_base); - EXPECT_EQ("test.c", frame4.source_file_name); - EXPECT_EQ(1, frame4.source_line); - EXPECT_EQ(0x1010, frame4.source_line_base); - - // this should also be cached - StackFrame frame5; - frame5.module = &module; - frame5.instruction = 0x4040; - resolver->FillSourceLineInfo(&frame5); - EXPECT_EQ("test3()", frame5.function_name); - EXPECT_EQ(0x4000, frame5.function_base); - EXPECT_EQ("", frame5.source_file_name); - EXPECT_EQ(0, frame5.source_line); - EXPECT_EQ(0, frame5.source_line_base); -} - -class GetStackWinHelper { - public: - GetStackWinHelper() : sequence(1) {} - bool GenerateGetStackWinResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << sequence << OK; - switch(sequence) { - case 1: - // return full info including program string - stream << string("0 0 0 1 2 3 a ff f00 1 x y ="); - break; - case 2: - // return full info, no program string - stream << string("0 0 0 1 2 3 a ff f00 0 1"); - break; - case 3: - // return empty string - stream << string(""); - break; - } - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - ++sequence; - return true; - } - u_int16_t sequence; -}; - -TEST_F(TestNetworkSourceLineResolver, TestGetStackWinMessages) { - EXPECT_CALL(net, Send(_,_)) - .Times(4) - .WillRepeatedly(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .Times(4) - .WillRepeatedly(Return(true)); - GetStackWinHelper helper; - EXPECT_CALL(net, Receive(_,_,_)) - .Times(4) - .WillOnce(Invoke(GeneratePositiveHasResponse)) - .WillRepeatedly(Invoke(&helper, - &GetStackWinHelper::GenerateGetStackWinResponse)); - - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - // The resolver has to think the module is loaded before it will respond - // to GETSTACKWIN requests for that module. - EXPECT_TRUE(resolver->HasModule(&module)); - StackFrame frame; - frame.module = &module; - frame.instruction = 0x1010; - WindowsFrameInfo *info = resolver->FindWindowsFrameInfo(&frame); - ASSERT_NE((WindowsFrameInfo*)NULL, info); - EXPECT_EQ(0x1, info->prolog_size); - EXPECT_EQ(0x2, info->epilog_size); - EXPECT_EQ(0x3, info->parameter_size); - EXPECT_EQ(0xa, info->saved_register_size); - EXPECT_EQ(0xff, info->local_size); - EXPECT_EQ(0xf00, info->max_stack_size); - EXPECT_EQ("x y =", info->program_string); - delete info; - - StackFrame frame2; - frame2.module = &module; - frame2.instruction = 0x2020; - info = resolver->FindWindowsFrameInfo(&frame2); - ASSERT_NE((WindowsFrameInfo*)NULL, info); - EXPECT_EQ(0x1, info->prolog_size); - EXPECT_EQ(0x2, info->epilog_size); - EXPECT_EQ(0x3, info->parameter_size); - EXPECT_EQ(0xa, info->saved_register_size); - EXPECT_EQ(0xff, info->local_size); - EXPECT_EQ(0xf00, info->max_stack_size); - EXPECT_EQ("", info->program_string); - EXPECT_EQ(true, info->allocates_base_pointer); - delete info; - - StackFrame frame3; - frame3.module = &module; - frame3.instruction = 0x4040; - info = resolver->FindWindowsFrameInfo(&frame3); - EXPECT_EQ((WindowsFrameInfo*)NULL, info); - - // this should come from the cache and not hit the network - StackFrame frame4; - frame4.module = &module; - frame4.instruction = 0x1010; - info = resolver->FindWindowsFrameInfo(&frame4); - ASSERT_NE((WindowsFrameInfo*)NULL, info); - EXPECT_EQ(0x1, info->prolog_size); - EXPECT_EQ(0x2, info->epilog_size); - EXPECT_EQ(0x3, info->parameter_size); - EXPECT_EQ(0xa, info->saved_register_size); - EXPECT_EQ(0xff, info->local_size); - EXPECT_EQ(0xf00, info->max_stack_size); - EXPECT_EQ("x y =", info->program_string); - delete info; - - // this should also be cached - StackFrame frame5; - frame5.module = &module; - frame5.instruction = 0x4040; - info = resolver->FindWindowsFrameInfo(&frame5); - EXPECT_EQ((WindowsFrameInfo*)NULL, info); -} - -class GetStackCFIHelper { - public: - GetStackCFIHelper() : sequence(1) {} - bool GenerateGetStackCFIResponse(char *buffer, size_t buffer_size, - ssize_t &received) { - binarystream stream; - stream << sequence << OK; - switch(sequence) { - case 1: - // return .cfa, .ra, registers - stream << string(".cfa: 1234 .ra: .cfa 5 + r0: abc xyz r2: 10 10"); - break; - case 2: - // return just .cfa - stream << string(".cfa: xyz"); - break; - case 3: - // return empty string - stream << string(""); - break; - } - string s = stream.str(); - received = s.length(); - memcpy(buffer, s.c_str(), s.length()); - ++sequence; - return true; - } - u_int16_t sequence; -}; - -TEST_F(TestNetworkSourceLineResolver, TestGetStackCFIMessages) { - EXPECT_CALL(net, Send(_,_)) - .Times(4) - .WillRepeatedly(Return(true)); - EXPECT_CALL(net, WaitToReceive(0)) - .Times(4) - .WillRepeatedly(Return(true)); - GetStackCFIHelper helper; - EXPECT_CALL(net, Receive(_,_,_)) - .Times(4) - .WillOnce(Invoke(GeneratePositiveHasResponse)) - .WillRepeatedly(Invoke(&helper, - &GetStackCFIHelper::GenerateGetStackCFIResponse)); - - BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", ""); - // The resolver has to think the module is loaded before it will respond - // to GETSTACKCFI requests for that module. - EXPECT_TRUE(resolver->HasModule(&module)); - StackFrame frame; - frame.module = &module; - frame.instruction = 0x1010; - CFIFrameInfo *info = resolver->FindCFIFrameInfo(&frame); - ASSERT_NE((CFIFrameInfo*)NULL, info); - // Ostensibly we would check the internal data structure, but - // we'd have to either mock out some other classes or get internal access, - // so this is easier. - EXPECT_EQ(".cfa: 1234 .ra: .cfa 5 + r0: abc xyz r2: 10 10", - info->Serialize()); - delete info; - - StackFrame frame2; - frame2.module = &module; - frame2.instruction = 0x2020; - info = resolver->FindCFIFrameInfo(&frame2); - ASSERT_NE((CFIFrameInfo*)NULL, info); - EXPECT_EQ(".cfa: xyz", info->Serialize()); - delete info; - - StackFrame frame3; - frame3.module = &module; - frame3.instruction = 0x4040; - info = resolver->FindCFIFrameInfo(&frame3); - EXPECT_EQ((CFIFrameInfo*)NULL, info); - - // this should come from the cache and not hit the network - StackFrame frame4; - frame4.module = &module; - frame4.instruction = 0x1010; - info = resolver->FindCFIFrameInfo(&frame4); - ASSERT_NE((CFIFrameInfo*)NULL, info); - EXPECT_EQ(".cfa: 1234 .ra: .cfa 5 + r0: abc xyz r2: 10 10", - info->Serialize()); - delete info; - - // this should also be cached - StackFrame frame5; - frame5.module = &module; - frame5.instruction = 0x4040; - info = resolver->FindCFIFrameInfo(&frame5); - EXPECT_EQ((CFIFrameInfo*)NULL, info); -} - -TEST_F(TestNetworkSourceLineResolver, TestBogusData) { - EXPECT_FALSE(resolver->HasModule(NULL)); - - StackFrame frame; - frame.module = NULL; - frame.instruction = 0x1000; - resolver->FillSourceLineInfo(&frame); - EXPECT_EQ("", frame.function_name); - EXPECT_EQ(0x0, frame.function_base); - EXPECT_EQ("", frame.source_file_name); - EXPECT_EQ(0, frame.source_line); - EXPECT_EQ(0x0, frame.source_line_base); - - EXPECT_EQ((WindowsFrameInfo*)NULL, resolver->FindWindowsFrameInfo(&frame)); -} - -} // namespace - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} |