/ src / processor / microdump_processor_unittest.cc
microdump_processor_unittest.cc
  1  // Copyright 2014 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  // Unit test for MicrodumpProcessor.
 30  
 31  #ifdef HAVE_CONFIG_H
 32  #include <config.h>  // Must come first
 33  #endif
 34  
 35  #include <fstream>
 36  #include <iostream>
 37  #include <string>
 38  #include <vector>
 39  
 40  #include "breakpad_googletest_includes.h"
 41  #include "google_breakpad/processor/basic_source_line_resolver.h"
 42  #include "google_breakpad/processor/call_stack.h"
 43  #include "google_breakpad/processor/microdump.h"
 44  #include "google_breakpad/processor/microdump_processor.h"
 45  #include "google_breakpad/processor/process_state.h"
 46  #include "google_breakpad/processor/stack_frame.h"
 47  #include "google_breakpad/processor/stack_frame_symbolizer.h"
 48  #include "processor/simple_symbol_supplier.h"
 49  #include "processor/stackwalker_unittest_utils.h"
 50  
 51  namespace {
 52  
 53  using google_breakpad::BasicSourceLineResolver;
 54  using google_breakpad::Microdump;
 55  using google_breakpad::MicrodumpProcessor;
 56  using google_breakpad::ProcessState;
 57  using google_breakpad::SimpleSymbolSupplier;
 58  using google_breakpad::StackFrameSymbolizer;
 59  
 60  class MicrodumpProcessorTest : public ::testing::Test {
 61   public:
 62    MicrodumpProcessorTest()
 63      : files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") +
 64                    "/src/processor/testdata/") {
 65    }
 66  
 67    void ReadFile(const string& file_name, string* file_contents) {
 68      assert(file_contents);
 69      std::ifstream file_stream(file_name.c_str(), std::ios::in);
 70      ASSERT_TRUE(file_stream.good());
 71      std::vector<char> bytes;
 72      file_stream.seekg(0, std::ios_base::end);
 73      ASSERT_TRUE(file_stream.good());
 74      bytes.resize(file_stream.tellg());
 75      file_stream.seekg(0, std::ios_base::beg);
 76      ASSERT_TRUE(file_stream.good());
 77      file_stream.read(&bytes[0], bytes.size());
 78      ASSERT_TRUE(file_stream.good());
 79      *file_contents = string(&bytes[0], bytes.size());
 80    }
 81  
 82    google_breakpad::ProcessResult ProcessMicrodump(
 83        const string& symbols_file,
 84        const string& microdump_contents,
 85        ProcessState* state) {
 86      SimpleSymbolSupplier supplier(symbols_file);
 87      BasicSourceLineResolver resolver;
 88      StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
 89      MicrodumpProcessor processor(&frame_symbolizer);
 90  
 91      Microdump microdump(microdump_contents);
 92      return processor.Process(&microdump, state);
 93    }
 94  
 95    void AnalyzeDump(const string& microdump_file_name, bool omit_symbols,
 96                     int expected_cpu_count, ProcessState* state) {
 97      string symbols_file = omit_symbols ? "" : files_path_ + "symbols/microdump";
 98      string microdump_file_path = files_path_ + microdump_file_name;
 99      string microdump_contents;
100      ReadFile(microdump_file_path, &microdump_contents);
101  
102      google_breakpad::ProcessResult result =
103          ProcessMicrodump(symbols_file, microdump_contents, state);
104  
105      ASSERT_EQ(google_breakpad::PROCESS_OK, result);
106      ASSERT_TRUE(state->crashed());
107      ASSERT_EQ(0, state->requesting_thread());
108      ASSERT_EQ(1U, state->threads()->size());
109  
110      ASSERT_EQ(expected_cpu_count, state->system_info()->cpu_count);
111      ASSERT_EQ("android", state->system_info()->os_short);
112      ASSERT_EQ("Android", state->system_info()->os);
113    }
114  
115    string files_path_;
116  };
117  
118  TEST_F(MicrodumpProcessorTest, TestProcess_Invalid) {
119    ProcessState state;
120    google_breakpad::ProcessResult result =
121        ProcessMicrodump("", "This is not a valid microdump", &state);
122    ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
123  }
124  
125  TEST_F(MicrodumpProcessorTest, TestProcess_WithoutCrashReason) {
126    ProcessState state;
127    AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */,
128                2 /* expected_cpu_count */, &state);
129    ASSERT_EQ(state.crash_reason(), "");
130    ASSERT_EQ(state.crash_address(), 0x0u);
131  }
132  
133  TEST_F(MicrodumpProcessorTest, TestProcess_WithCrashReason) {
134    ProcessState state;
135    AnalyzeDump("microdump-withcrashreason.dmp", true /* omit_symbols */,
136                8 /* expected_cpu_count */, &state);
137    ASSERT_EQ(state.crash_reason(), "SIGTRAP");
138    ASSERT_EQ(state.crash_address(), 0x4A7CB000u);
139  }
140  
141  TEST_F(MicrodumpProcessorTest, TestProcess_MissingSymbols) {
142    ProcessState state;
143    AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */,
144                2 /* expected_cpu_count */, &state);
145  
146    ASSERT_EQ(8U, state.modules()->module_count());
147    ASSERT_EQ("arm64", state.system_info()->cpu);
148    ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
149    ASSERT_EQ(1U, state.threads()->size());
150    ASSERT_EQ(11U, state.threads()->at(0)->frames()->size());
151  
152    ASSERT_EQ("",
153              state.threads()->at(0)->frames()->at(0)->function_name);
154    ASSERT_EQ("",
155              state.threads()->at(0)->frames()->at(3)->function_name);
156  }
157  
158  TEST_F(MicrodumpProcessorTest, TestProcess_UnsupportedArch) {
159    string microdump_contents =
160        "W/google-breakpad(26491): -----BEGIN BREAKPAD MICRODUMP-----\n"
161        "W/google-breakpad(26491): O A \"unsupported-arch\"\n"
162        "W/google-breakpad(26491): S 0 A48BD840 A48BD000 00002000\n";
163  
164    ProcessState state;
165  
166    google_breakpad::ProcessResult result =
167        ProcessMicrodump("", microdump_contents, &state);
168  
169    ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
170  }
171  
172  TEST_F(MicrodumpProcessorTest, TestProcessArm) {
173    ProcessState state;
174    AnalyzeDump("microdump-arm.dmp", false /* omit_symbols */,
175                2 /* expected_cpu_count*/, &state);
176  
177    ASSERT_EQ(6U, state.modules()->module_count());
178    ASSERT_EQ("arm", state.system_info()->cpu);
179    ASSERT_EQ("OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)",
180              state.system_info()->gl_version);
181    ASSERT_EQ("Qualcomm", state.system_info()->gl_vendor);
182    ASSERT_EQ("Adreno (TM) 330", state.system_info()->gl_renderer);
183    ASSERT_EQ("OS VERSION INFO", state.system_info()->os_version);
184    ASSERT_EQ(8U, state.threads()->at(0)->frames()->size());
185    ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
186              state.threads()->at(0)->frames()->at(0)->function_name);
187    ASSERT_EQ("testing::Test::Run",
188              state.threads()->at(0)->frames()->at(1)->function_name);
189    ASSERT_EQ("main",
190              state.threads()->at(0)->frames()->at(6)->function_name);
191    ASSERT_EQ("breakpad_unittests",
192              state.threads()->at(0)->frames()->at(6)->module->code_file());
193  }
194  
195  TEST_F(MicrodumpProcessorTest, TestProcessArm64) {
196    ProcessState state;
197    AnalyzeDump("microdump-arm64.dmp", false /* omit_symbols */,
198                2 /* expected_cpu_count*/, &state);
199  
200    ASSERT_EQ(8U, state.modules()->module_count());
201    ASSERT_EQ("arm64", state.system_info()->cpu);
202    ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
203    ASSERT_EQ(9U, state.threads()->at(0)->frames()->size());
204    ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
205              state.threads()->at(0)->frames()->at(0)->function_name);
206    ASSERT_EQ("testing::Test::Run",
207              state.threads()->at(0)->frames()->at(2)->function_name);
208    ASSERT_EQ("main",
209              state.threads()->at(0)->frames()->at(7)->function_name);
210    ASSERT_EQ("breakpad_unittests",
211              state.threads()->at(0)->frames()->at(7)->module->code_file());
212  }
213  
214  TEST_F(MicrodumpProcessorTest, TestProcessX86) {
215    ProcessState state;
216    AnalyzeDump("microdump-x86.dmp", false /* omit_symbols */,
217                4 /* expected_cpu_count */, &state);
218  
219    ASSERT_EQ(124U, state.modules()->module_count());
220    ASSERT_EQ("x86", state.system_info()->cpu);
221    ASSERT_EQ("asus/WW_Z00A/Z00A:5.0/LRX21V/2.19.40.22_20150627_5104_user:user/"
222        "release-keys", state.system_info()->os_version);
223    ASSERT_EQ(17U, state.threads()->at(0)->frames()->size());
224    ASSERT_EQ("libc.so",
225              state.threads()->at(0)->frames()->at(0)->module->debug_file());
226    // TODO(mmandlis): Get symbols for the test X86 microdump and test function
227    // names.
228  }
229  
230  TEST_F(MicrodumpProcessorTest, TestProcessMultiple) {
231    ProcessState state;
232    AnalyzeDump("microdump-multiple.dmp", false /* omit_symbols */,
233                6 /* expected_cpu_count */, &state);
234    ASSERT_EQ(156U, state.modules()->module_count());
235    ASSERT_EQ("arm", state.system_info()->cpu);
236    ASSERT_EQ("lge/p1_tmo_us/p1:6.0/MRA58K/1603210524c8d:user/release-keys",
237              state.system_info()->os_version);
238    ASSERT_EQ(5U, state.threads()->at(0)->frames()->size());
239  }
240  
241  TEST_F(MicrodumpProcessorTest, TestProcessMips) {
242    ProcessState state;
243    AnalyzeDump("microdump-mips32.dmp", false /* omit_symbols */,
244                2 /* expected_cpu_count */, &state);
245  
246    ASSERT_EQ(7U, state.modules()->module_count());
247    ASSERT_EQ("mips", state.system_info()->cpu);
248    ASSERT_EQ("3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015",
249        state.system_info()->os_version);
250    ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
251  
252    ASSERT_EQ("blaTest",
253              state.threads()->at(0)->frames()->at(0)->function_name);
254    ASSERT_EQ("Crash",
255              state.threads()->at(0)->frames()->at(1)->function_name);
256    ASSERT_EQ("main",
257              state.threads()->at(0)->frames()->at(2)->function_name);
258    ASSERT_EQ("crash_example",
259              state.threads()->at(0)->frames()->at(0)->module->debug_file());
260  }
261  
262  TEST_F(MicrodumpProcessorTest, TestProcessMips64) {
263    ProcessState state;
264    AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
265                1 /* expected_cpu_count */, &state);
266  
267    ASSERT_EQ(8U, state.modules()->module_count());
268    ASSERT_EQ("mips64", state.system_info()->cpu);
269    ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
270          state.system_info()->os_version);
271    ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
272  
273    ASSERT_EQ("blaTest",
274              state.threads()->at(0)->frames()->at(0)->function_name);
275    ASSERT_EQ("Crash",
276              state.threads()->at(0)->frames()->at(1)->function_name);
277    ASSERT_EQ("main",
278              state.threads()->at(0)->frames()->at(2)->function_name);
279    ASSERT_EQ("crash_example",
280              state.threads()->at(0)->frames()->at(0)->module->debug_file());
281  }
282  
283  }  // namespace
284  
285  int main(int argc, char* argv[]) {
286    ::testing::InitGoogleTest(&argc, argv);
287    return RUN_ALL_TESTS();
288  }