1 // Copyright (c) 2014, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // Unit test for MicrodumpProcessor. 31 32 #include <fstream> 33 #include <iostream> 34 #include <string> 35 #include <vector> 36 37 #include "breakpad_googletest_includes.h" 38 #include "google_breakpad/processor/basic_source_line_resolver.h" 39 #include "google_breakpad/processor/call_stack.h" 40 #include "google_breakpad/processor/microdump_processor.h" 41 #include "google_breakpad/processor/process_state.h" 42 #include "google_breakpad/processor/stack_frame.h" 43 #include "google_breakpad/processor/stack_frame_symbolizer.h" 44 #include "processor/simple_symbol_supplier.h" 45 #include "processor/stackwalker_unittest_utils.h" 46 47 namespace { 48 49 using google_breakpad::BasicSourceLineResolver; 50 using google_breakpad::MicrodumpProcessor; 51 using google_breakpad::ProcessState; 52 using google_breakpad::SimpleSymbolSupplier; 53 using google_breakpad::StackFrameSymbolizer; 54 55 class MicrodumpProcessorTest : public ::testing::Test { 56 public: 57 MicrodumpProcessorTest() 58 : files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") + 59 "/src/processor/testdata/") { 60 } 61 62 void ReadFile(const string& file_name, string* file_contents) { 63 assert(file_contents); 64 std::ifstream file_stream(file_name.c_str(), std::ios::in); 65 ASSERT_TRUE(file_stream.good()); 66 std::vector<char> bytes; 67 file_stream.seekg(0, std::ios_base::end); 68 ASSERT_TRUE(file_stream.good()); 69 bytes.resize(file_stream.tellg()); 70 file_stream.seekg(0, std::ios_base::beg); 71 ASSERT_TRUE(file_stream.good()); 72 file_stream.read(&bytes[0], bytes.size()); 73 ASSERT_TRUE(file_stream.good()); 74 *file_contents = string(&bytes[0], bytes.size()); 75 } 76 77 google_breakpad::ProcessResult ProcessMicrodump( 78 const string& symbols_file, 79 const string& microdump_contents, 80 ProcessState* state) { 81 SimpleSymbolSupplier supplier(symbols_file); 82 BasicSourceLineResolver resolver; 83 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); 84 MicrodumpProcessor processor(&frame_symbolizer); 85 86 return processor.Process(microdump_contents, state); 87 } 88 89 void AnalyzeDump(const string& microdump_file_name, ProcessState* state, 90 bool omit_symbols) { 91 string symbols_file = omit_symbols ? "" : files_path_ + "symbols/microdump"; 92 string microdump_file_path = files_path_ + microdump_file_name; 93 string microdump_contents; 94 ReadFile(microdump_file_path, µdump_contents); 95 96 google_breakpad::ProcessResult result = 97 ProcessMicrodump(symbols_file, microdump_contents, state); 98 99 ASSERT_EQ(google_breakpad::PROCESS_OK, result); 100 ASSERT_TRUE(state->crashed()); 101 ASSERT_EQ(0, state->requesting_thread()); 102 ASSERT_EQ(1U, state->threads()->size()); 103 104 ASSERT_EQ(2, state->system_info()->cpu_count); 105 ASSERT_EQ("android", state->system_info()->os_short); 106 ASSERT_EQ("Android", state->system_info()->os); 107 } 108 109 string files_path_; 110 }; 111 112 TEST_F(MicrodumpProcessorTest, TestProcess_Empty) { 113 ProcessState state; 114 google_breakpad::ProcessResult result = 115 ProcessMicrodump("", "", &state); 116 ASSERT_EQ(google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND, result); 117 } 118 119 TEST_F(MicrodumpProcessorTest, TestProcess_Invalid) { 120 ProcessState state; 121 google_breakpad::ProcessResult result = 122 ProcessMicrodump("", "This is not a valid microdump", &state); 123 ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result); 124 } 125 126 TEST_F(MicrodumpProcessorTest, TestProcess_MissingSymbols) { 127 ProcessState state; 128 AnalyzeDump("microdump-arm64.dmp", &state, true /* omit_symbols */); 129 130 ASSERT_EQ(8U, state.modules()->module_count()); 131 ASSERT_EQ("aarch64", state.system_info()->cpu); 132 ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version); 133 ASSERT_EQ(1U, state.threads()->size()); 134 ASSERT_EQ(12U, state.threads()->at(0)->frames()->size()); 135 136 ASSERT_EQ("", 137 state.threads()->at(0)->frames()->at(0)->function_name); 138 ASSERT_EQ("", 139 state.threads()->at(0)->frames()->at(3)->function_name); 140 } 141 142 TEST_F(MicrodumpProcessorTest, TestProcess_UnsupportedArch) { 143 string microdump_contents = 144 "W/google-breakpad(26491): -----BEGIN BREAKPAD MICRODUMP-----\n" 145 "W/google-breakpad(26491): O A \"unsupported-arch\"\n" 146 "W/google-breakpad(26491): S 0 A48BD840 A48BD000 00002000\n"; 147 148 ProcessState state; 149 150 google_breakpad::ProcessResult result = 151 ProcessMicrodump("", microdump_contents, &state); 152 153 ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result); 154 } 155 156 TEST_F(MicrodumpProcessorTest, TestProcessArm) { 157 ProcessState state; 158 AnalyzeDump("microdump-arm.dmp", &state, false /* omit_symbols */); 159 160 ASSERT_EQ(6U, state.modules()->module_count()); 161 ASSERT_EQ("armv7l", state.system_info()->cpu); 162 ASSERT_EQ("OS VERSION INFO", state.system_info()->os_version); 163 ASSERT_EQ(8U, state.threads()->at(0)->frames()->size()); 164 ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody", 165 state.threads()->at(0)->frames()->at(0)->function_name); 166 ASSERT_EQ("testing::Test::Run", 167 state.threads()->at(0)->frames()->at(1)->function_name); 168 ASSERT_EQ("main", 169 state.threads()->at(0)->frames()->at(6)->function_name); 170 ASSERT_EQ("breakpad_unittests", 171 state.threads()->at(0)->frames()->at(6)->module->code_file()); 172 } 173 174 TEST_F(MicrodumpProcessorTest, TestProcessArm64) { 175 ProcessState state; 176 AnalyzeDump("microdump-arm64.dmp", &state, false /* omit_symbols */); 177 178 ASSERT_EQ(8U, state.modules()->module_count()); 179 ASSERT_EQ("aarch64", state.system_info()->cpu); 180 ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version); 181 ASSERT_EQ(9U, state.threads()->at(0)->frames()->size()); 182 ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody", 183 state.threads()->at(0)->frames()->at(0)->function_name); 184 ASSERT_EQ("testing::Test::Run", 185 state.threads()->at(0)->frames()->at(2)->function_name); 186 ASSERT_EQ("main", 187 state.threads()->at(0)->frames()->at(7)->function_name); 188 ASSERT_EQ("breakpad_unittests", 189 state.threads()->at(0)->frames()->at(7)->module->code_file()); 190 } 191 192 } // namespace 193 194 int main(int argc, char* argv[]) { 195 ::testing::InitGoogleTest(&argc, argv); 196 return RUN_ALL_TESTS(); 197 } 198