• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
41 #include "google_breakpad/processor/microdump_processor.h"
42 #include "google_breakpad/processor/process_state.h"
43 #include "google_breakpad/processor/stack_frame.h"
44 #include "google_breakpad/processor/stack_frame_symbolizer.h"
45 #include "processor/simple_symbol_supplier.h"
46 #include "processor/stackwalker_unittest_utils.h"
47 
48 namespace {
49 
50 using google_breakpad::BasicSourceLineResolver;
51 using google_breakpad::Microdump;
52 using google_breakpad::MicrodumpProcessor;
53 using google_breakpad::ProcessState;
54 using google_breakpad::SimpleSymbolSupplier;
55 using google_breakpad::StackFrameSymbolizer;
56 
57 class MicrodumpProcessorTest : public ::testing::Test {
58  public:
MicrodumpProcessorTest()59   MicrodumpProcessorTest()
60     : files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") +
61                   "/src/processor/testdata/") {
62   }
63 
ReadFile(const string & file_name,string * file_contents)64   void ReadFile(const string& file_name, string* file_contents) {
65     assert(file_contents);
66     std::ifstream file_stream(file_name.c_str(), std::ios::in);
67     ASSERT_TRUE(file_stream.good());
68     std::vector<char> bytes;
69     file_stream.seekg(0, std::ios_base::end);
70     ASSERT_TRUE(file_stream.good());
71     bytes.resize(file_stream.tellg());
72     file_stream.seekg(0, std::ios_base::beg);
73     ASSERT_TRUE(file_stream.good());
74     file_stream.read(&bytes[0], bytes.size());
75     ASSERT_TRUE(file_stream.good());
76     *file_contents = string(&bytes[0], bytes.size());
77   }
78 
ProcessMicrodump(const string & symbols_file,const string & microdump_contents,ProcessState * state)79   google_breakpad::ProcessResult ProcessMicrodump(
80       const string& symbols_file,
81       const string& microdump_contents,
82       ProcessState* state) {
83     SimpleSymbolSupplier supplier(symbols_file);
84     BasicSourceLineResolver resolver;
85     StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
86     MicrodumpProcessor processor(&frame_symbolizer);
87 
88     Microdump microdump(microdump_contents);
89     return processor.Process(&microdump, state);
90   }
91 
AnalyzeDump(const string & microdump_file_name,bool omit_symbols,int expected_cpu_count,ProcessState * state)92   void AnalyzeDump(const string& microdump_file_name, bool omit_symbols,
93                    int expected_cpu_count, ProcessState* state) {
94     string symbols_file = omit_symbols ? "" : files_path_ + "symbols/microdump";
95     string microdump_file_path = files_path_ + microdump_file_name;
96     string microdump_contents;
97     ReadFile(microdump_file_path, &microdump_contents);
98 
99     google_breakpad::ProcessResult result =
100         ProcessMicrodump(symbols_file, microdump_contents, state);
101 
102     ASSERT_EQ(google_breakpad::PROCESS_OK, result);
103     ASSERT_TRUE(state->crashed());
104     ASSERT_EQ(0, state->requesting_thread());
105     ASSERT_EQ(1U, state->threads()->size());
106 
107     ASSERT_EQ(expected_cpu_count, state->system_info()->cpu_count);
108     ASSERT_EQ("android", state->system_info()->os_short);
109     ASSERT_EQ("Android", state->system_info()->os);
110   }
111 
112   string files_path_;
113 };
114 
TEST_F(MicrodumpProcessorTest,TestProcess_Invalid)115 TEST_F(MicrodumpProcessorTest, TestProcess_Invalid) {
116   ProcessState state;
117   google_breakpad::ProcessResult result =
118       ProcessMicrodump("", "This is not a valid microdump", &state);
119   ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
120 }
121 
TEST_F(MicrodumpProcessorTest,TestProcess_WithoutCrashReason)122 TEST_F(MicrodumpProcessorTest, TestProcess_WithoutCrashReason) {
123   ProcessState state;
124   AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */,
125               2 /* expected_cpu_count */, &state);
126   ASSERT_EQ(state.crash_reason(), "");
127   ASSERT_EQ(state.crash_address(), 0x0u);
128 }
129 
TEST_F(MicrodumpProcessorTest,TestProcess_WithCrashReason)130 TEST_F(MicrodumpProcessorTest, TestProcess_WithCrashReason) {
131   ProcessState state;
132   AnalyzeDump("microdump-withcrashreason.dmp", true /* omit_symbols */,
133               8 /* expected_cpu_count */, &state);
134   ASSERT_EQ(state.crash_reason(), "SIGTRAP");
135   ASSERT_EQ(state.crash_address(), 0x4A7CB000u);
136 }
137 
TEST_F(MicrodumpProcessorTest,TestProcess_MissingSymbols)138 TEST_F(MicrodumpProcessorTest, TestProcess_MissingSymbols) {
139   ProcessState state;
140   AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */,
141               2 /* expected_cpu_count */, &state);
142 
143   ASSERT_EQ(8U, state.modules()->module_count());
144   ASSERT_EQ("arm64", state.system_info()->cpu);
145   ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
146   ASSERT_EQ(1U, state.threads()->size());
147   ASSERT_EQ(11U, state.threads()->at(0)->frames()->size());
148 
149   ASSERT_EQ("",
150             state.threads()->at(0)->frames()->at(0)->function_name);
151   ASSERT_EQ("",
152             state.threads()->at(0)->frames()->at(3)->function_name);
153 }
154 
TEST_F(MicrodumpProcessorTest,TestProcess_UnsupportedArch)155 TEST_F(MicrodumpProcessorTest, TestProcess_UnsupportedArch) {
156   string microdump_contents =
157       "W/google-breakpad(26491): -----BEGIN BREAKPAD MICRODUMP-----\n"
158       "W/google-breakpad(26491): O A \"unsupported-arch\"\n"
159       "W/google-breakpad(26491): S 0 A48BD840 A48BD000 00002000\n";
160 
161   ProcessState state;
162 
163   google_breakpad::ProcessResult result =
164       ProcessMicrodump("", microdump_contents, &state);
165 
166   ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
167 }
168 
TEST_F(MicrodumpProcessorTest,TestProcessArm)169 TEST_F(MicrodumpProcessorTest, TestProcessArm) {
170   ProcessState state;
171   AnalyzeDump("microdump-arm.dmp", false /* omit_symbols */,
172               2 /* expected_cpu_count*/, &state);
173 
174   ASSERT_EQ(6U, state.modules()->module_count());
175   ASSERT_EQ("arm", state.system_info()->cpu);
176   ASSERT_EQ("OpenGL ES 3.0 V@104.0 AU@  (GIT@Id3510ff6dc)",
177             state.system_info()->gl_version);
178   ASSERT_EQ("Qualcomm", state.system_info()->gl_vendor);
179   ASSERT_EQ("Adreno (TM) 330", state.system_info()->gl_renderer);
180   ASSERT_EQ("OS VERSION INFO", state.system_info()->os_version);
181   ASSERT_EQ(8U, 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(1)->function_name);
186   ASSERT_EQ("main",
187             state.threads()->at(0)->frames()->at(6)->function_name);
188   ASSERT_EQ("breakpad_unittests",
189             state.threads()->at(0)->frames()->at(6)->module->code_file());
190 }
191 
TEST_F(MicrodumpProcessorTest,TestProcessArm64)192 TEST_F(MicrodumpProcessorTest, TestProcessArm64) {
193   ProcessState state;
194   AnalyzeDump("microdump-arm64.dmp", false /* omit_symbols */,
195               2 /* expected_cpu_count*/, &state);
196 
197   ASSERT_EQ(8U, state.modules()->module_count());
198   ASSERT_EQ("arm64", state.system_info()->cpu);
199   ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
200   ASSERT_EQ(9U, state.threads()->at(0)->frames()->size());
201   ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
202             state.threads()->at(0)->frames()->at(0)->function_name);
203   ASSERT_EQ("testing::Test::Run",
204             state.threads()->at(0)->frames()->at(2)->function_name);
205   ASSERT_EQ("main",
206             state.threads()->at(0)->frames()->at(7)->function_name);
207   ASSERT_EQ("breakpad_unittests",
208             state.threads()->at(0)->frames()->at(7)->module->code_file());
209 }
210 
TEST_F(MicrodumpProcessorTest,TestProcessX86)211 TEST_F(MicrodumpProcessorTest, TestProcessX86) {
212   ProcessState state;
213   AnalyzeDump("microdump-x86.dmp", false /* omit_symbols */,
214               4 /* expected_cpu_count */, &state);
215 
216   ASSERT_EQ(124U, state.modules()->module_count());
217   ASSERT_EQ("x86", state.system_info()->cpu);
218   ASSERT_EQ("asus/WW_Z00A/Z00A:5.0/LRX21V/2.19.40.22_20150627_5104_user:user/"
219       "release-keys", state.system_info()->os_version);
220   ASSERT_EQ(17U, state.threads()->at(0)->frames()->size());
221   ASSERT_EQ("libc.so",
222             state.threads()->at(0)->frames()->at(0)->module->debug_file());
223   // TODO(mmandlis): Get symbols for the test X86 microdump and test function
224   // names.
225 }
226 
TEST_F(MicrodumpProcessorTest,TestProcessMultiple)227 TEST_F(MicrodumpProcessorTest, TestProcessMultiple) {
228   ProcessState state;
229   AnalyzeDump("microdump-multiple.dmp", false /* omit_symbols */,
230               6 /* expected_cpu_count */, &state);
231   ASSERT_EQ(156U, state.modules()->module_count());
232   ASSERT_EQ("arm", state.system_info()->cpu);
233   ASSERT_EQ("lge/p1_tmo_us/p1:6.0/MRA58K/1603210524c8d:user/release-keys",
234             state.system_info()->os_version);
235   ASSERT_EQ(5U, state.threads()->at(0)->frames()->size());
236 }
237 
TEST_F(MicrodumpProcessorTest,TestProcessMips)238 TEST_F(MicrodumpProcessorTest, TestProcessMips) {
239   ProcessState state;
240   AnalyzeDump("microdump-mips32.dmp", false /* omit_symbols */,
241               2 /* expected_cpu_count */, &state);
242 
243   ASSERT_EQ(7U, state.modules()->module_count());
244   ASSERT_EQ("mips", state.system_info()->cpu);
245   ASSERT_EQ("3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015",
246       state.system_info()->os_version);
247   ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
248 
249   ASSERT_EQ("blaTest",
250             state.threads()->at(0)->frames()->at(0)->function_name);
251   ASSERT_EQ("Crash",
252             state.threads()->at(0)->frames()->at(1)->function_name);
253   ASSERT_EQ("main",
254             state.threads()->at(0)->frames()->at(2)->function_name);
255   ASSERT_EQ("crash_example",
256             state.threads()->at(0)->frames()->at(0)->module->debug_file());
257 }
258 
TEST_F(MicrodumpProcessorTest,TestProcessMips64)259 TEST_F(MicrodumpProcessorTest, TestProcessMips64) {
260   ProcessState state;
261   AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
262               1 /* expected_cpu_count */, &state);
263 
264   ASSERT_EQ(8U, state.modules()->module_count());
265   ASSERT_EQ("mips64", state.system_info()->cpu);
266   ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
267         state.system_info()->os_version);
268   ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
269 
270   ASSERT_EQ("blaTest",
271             state.threads()->at(0)->frames()->at(0)->function_name);
272   ASSERT_EQ("Crash",
273             state.threads()->at(0)->frames()->at(1)->function_name);
274   ASSERT_EQ("main",
275             state.threads()->at(0)->frames()->at(2)->function_name);
276   ASSERT_EQ("crash_example",
277             state.threads()->at(0)->frames()->at(0)->module->debug_file());
278 }
279 
280 }  // namespace
281 
main(int argc,char * argv[])282 int main(int argc, char* argv[]) {
283   ::testing::InitGoogleTest(&argc, argv);
284   return RUN_ALL_TESTS();
285 }
286