mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-07-06 15:50:49 +00:00
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@569 4c0a9323-5329-0410-9bdc-e9ce6186880e
536 lines
18 KiB
C++
536 lines
18 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 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();
|
|
}
|