diff options
Diffstat (limited to 'src/processor')
-rw-r--r-- | src/processor/minidump_processor_unittest.cc | 57 | ||||
-rw-r--r-- | src/processor/stackwalker.cc | 3 |
2 files changed, 60 insertions, 0 deletions
diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc index 7df12172..dd4f633e 100644 --- a/src/processor/minidump_processor_unittest.cc +++ b/src/processor/minidump_processor_unittest.cc @@ -34,6 +34,7 @@ #include <string> #include <iostream> #include <fstream> +#include <map> #include "breakpad_googletest_includes.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" @@ -47,6 +48,8 @@ #include "processor/logging.h" #include "processor/scoped_ptr.h" +using std::map; + namespace google_breakpad { class MockMinidump : public Minidump { public: @@ -74,6 +77,10 @@ using google_breakpad::scoped_ptr; using google_breakpad::SymbolSupplier; using google_breakpad::SystemInfo; using std::string; +using ::testing::_; +using ::testing::Mock; +using ::testing::Ne; +using ::testing::Property; using ::testing::Return; static const char *kSystemInfoOS = "Windows NT"; @@ -155,6 +162,19 @@ SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( return s; } +// A mock symbol supplier that always returns NOT_FOUND; one current +// use for testing the processor's caching of symbol lookups. +class MockSymbolSupplier : public SymbolSupplier { + public: + MockSymbolSupplier() { } + MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule*, + const SystemInfo*, + string*)); + MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule*, + const SystemInfo*, + string*, + string*)); +}; class MinidumpProcessorTest : public ::testing::Test { @@ -186,6 +206,43 @@ TEST_F(MinidumpProcessorTest, TestCorruptMinidumps) { google_breakpad::PROCESS_ERROR_NO_THREAD_LIST); } +// This test case verifies that the symbol supplier is only consulted +// once per minidump per module. +TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) { + MockSymbolSupplier supplier; + BasicSourceLineResolver resolver; + MinidumpProcessor processor(&supplier, &resolver); + + string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/processor/testdata/minidump2.dmp"; + ProcessState state; + EXPECT_CALL(supplier, GetSymbolFile( + Property(&google_breakpad::CodeModule::code_file, + "c:\\test_app.exe"), + _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND)); + EXPECT_CALL(supplier, GetSymbolFile( + Property(&google_breakpad::CodeModule::code_file, + Ne("c:\\test_app.exe")), + _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND)); + ASSERT_EQ(processor.Process(minidump_file, &state), + google_breakpad::PROCESS_OK); + + ASSERT_TRUE(Mock::VerifyAndClearExpectations(&supplier)); + + // We need to verify that across minidumps, the processor will refetch + // symbol files, even with the same symbol supplier. + EXPECT_CALL(supplier, GetSymbolFile( + Property(&google_breakpad::CodeModule::code_file, + "c:\\test_app.exe"), + _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND)); + EXPECT_CALL(supplier, GetSymbolFile( + Property(&google_breakpad::CodeModule::code_file, + Ne("c:\\test_app.exe")), + _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND)); + ASSERT_EQ(processor.Process(minidump_file, &state), + google_breakpad::PROCESS_OK); +} + TEST_F(MinidumpProcessorTest, TestBasicProcessing) { TestSymbolSupplier supplier; BasicSourceLineResolver resolver; diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index 3a3725fa..3b9a313a 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -93,6 +93,8 @@ bool Stackwalker::Walk(CallStack *stack) { frame->module = module; if (resolver_ && !resolver_->HasModule(frame->module->code_file()) && + no_symbol_modules_.find( + module->code_file()) == no_symbol_modules_.end() && supplier_) { string symbol_data, symbol_file; SymbolSupplier::SymbolResult symbol_result = @@ -105,6 +107,7 @@ bool Stackwalker::Walk(CallStack *stack) { symbol_data); break; case SymbolSupplier::NOT_FOUND: + no_symbol_modules_.insert(module->code_file()); break; // nothing to do case SymbolSupplier::INTERRUPT: return false; |