xref: /aosp_15_r20/external/google-breakpad/src/processor/microdump_processor_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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:
MicrodumpProcessorTest()62   MicrodumpProcessorTest()
63     : files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") +
64                   "/src/processor/testdata/") {
65   }
66 
ReadFile(const string & file_name,string * file_contents)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 
ProcessMicrodump(const string & symbols_file,const string & microdump_contents,ProcessState * state)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 
AnalyzeDump(const string & microdump_file_name,bool omit_symbols,int expected_cpu_count,ProcessState * state)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 
TEST_F(MicrodumpProcessorTest,TestProcess_Invalid)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 
TEST_F(MicrodumpProcessorTest,TestProcess_WithoutCrashReason)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 
TEST_F(MicrodumpProcessorTest,TestProcess_WithCrashReason)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 
TEST_F(MicrodumpProcessorTest,TestProcess_MissingSymbols)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 
TEST_F(MicrodumpProcessorTest,TestProcess_UnsupportedArch)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 
TEST_F(MicrodumpProcessorTest,TestProcessArm)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 [email protected] 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 
TEST_F(MicrodumpProcessorTest,TestProcessArm64)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 
TEST_F(MicrodumpProcessorTest,TestProcessX86)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 
TEST_F(MicrodumpProcessorTest,TestProcessMultiple)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 
TEST_F(MicrodumpProcessorTest,TestProcessMips)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 
TEST_F(MicrodumpProcessorTest,TestProcessMips64)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 
main(int argc,char * argv[])285 int main(int argc, char* argv[]) {
286   ::testing::InitGoogleTest(&argc, argv);
287   return RUN_ALL_TESTS();
288 }
289