Home | History | Annotate | Download | only in processor
      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, &microdump_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