OLD | NEW |
---|---|
1 // Copyright (c) 2014 Google Inc. | 1 // Copyright (c) 2014 Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 19 matching lines...) Expand all Loading... | |
30 #include <ctype.h> | 30 #include <ctype.h> |
31 #include <sys/syscall.h> | 31 #include <sys/syscall.h> |
32 #include <sys/types.h> | 32 #include <sys/types.h> |
33 #include <unistd.h> | 33 #include <unistd.h> |
34 | 34 |
35 #include <sstream> | 35 #include <sstream> |
36 #include <string> | 36 #include <string> |
37 | 37 |
38 #include "breakpad_googletest_includes.h" | 38 #include "breakpad_googletest_includes.h" |
39 #include "client/linux/handler/exception_handler.h" | 39 #include "client/linux/handler/exception_handler.h" |
40 #include "client/linux/handler/microdump_extra_info.h" | |
40 #include "client/linux/microdump_writer/microdump_writer.h" | 41 #include "client/linux/microdump_writer/microdump_writer.h" |
41 #include "common/linux/eintr_wrapper.h" | 42 #include "common/linux/eintr_wrapper.h" |
42 #include "common/linux/ignore_ret.h" | 43 #include "common/linux/ignore_ret.h" |
43 #include "common/scoped_ptr.h" | 44 #include "common/scoped_ptr.h" |
44 #include "common/tests/auto_tempdir.h" | 45 #include "common/tests/auto_tempdir.h" |
45 #include "common/using_std_string.h" | 46 #include "common/using_std_string.h" |
46 | 47 |
47 using namespace google_breakpad; | 48 using namespace google_breakpad; |
48 | 49 |
49 namespace { | 50 namespace { |
50 | 51 |
51 typedef testing::Test MicrodumpWriterTest; | 52 typedef testing::Test MicrodumpWriterTest; |
52 | 53 |
53 void CrashAndGetMicrodump( | 54 void CrashAndGetMicrodump( |
54 const MappingList& mappings, | 55 const MappingList& mappings, |
55 const char* build_fingerprint, | 56 const MicrodumpExtraInfo µdump_extra_info, |
56 const char* product_info, | |
57 scoped_array<char>* buf) { | 57 scoped_array<char>* buf) { |
58 int fds[2]; | 58 int fds[2]; |
59 ASSERT_NE(-1, pipe(fds)); | 59 ASSERT_NE(-1, pipe(fds)); |
60 | 60 |
61 AutoTempDir temp_dir; | 61 AutoTempDir temp_dir; |
62 string stderr_file = temp_dir.path() + "/stderr.log"; | 62 string stderr_file = temp_dir.path() + "/stderr.log"; |
63 int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); | 63 int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); |
64 ASSERT_NE(-1, err_fd); | 64 ASSERT_NE(-1, err_fd); |
65 | 65 |
66 const pid_t child = fork(); | 66 const pid_t child = fork(); |
(...skipping 11 matching lines...) Expand all Loading... | |
78 | 78 |
79 // Set a non-zero tid to avoid tripping asserts. | 79 // Set a non-zero tid to avoid tripping asserts. |
80 context.tid = child; | 80 context.tid = child; |
81 | 81 |
82 // Redirect temporarily stderr to the stderr.log file. | 82 // Redirect temporarily stderr to the stderr.log file. |
83 int save_err = dup(STDERR_FILENO); | 83 int save_err = dup(STDERR_FILENO); |
84 ASSERT_NE(-1, save_err); | 84 ASSERT_NE(-1, save_err); |
85 ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO)); | 85 ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO)); |
86 | 86 |
87 ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings, | 87 ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings, |
88 build_fingerprint, product_info)); | 88 microdump_extra_info)); |
89 | 89 |
90 // Revert stderr back to the console. | 90 // Revert stderr back to the console. |
91 dup2(save_err, STDERR_FILENO); | 91 dup2(save_err, STDERR_FILENO); |
92 close(save_err); | 92 close(save_err); |
93 | 93 |
94 // Read back the stderr file and check for the microdump marker. | 94 // Read back the stderr file and check for the microdump marker. |
95 fsync(err_fd); | 95 fsync(err_fd); |
96 lseek(err_fd, 0, SEEK_SET); | 96 lseek(err_fd, 0, SEEK_SET); |
97 const size_t kBufSize = 64 * 1024; | 97 const size_t kBufSize = 64 * 1024; |
98 buf->reset(new char[kBufSize]); | 98 buf->reset(new char[kBufSize]); |
99 ASSERT_GT(read(err_fd, buf->get(), kBufSize), 0); | 99 ASSERT_GT(read(err_fd, buf->get(), kBufSize), 0); |
100 | 100 |
101 close(err_fd); | 101 close(err_fd); |
102 close(fds[1]); | 102 close(fds[1]); |
103 | 103 |
104 ASSERT_NE(static_cast<char*>(0), strstr( | 104 ASSERT_NE(static_cast<char*>(0), strstr( |
105 buf->get(), "-----BEGIN BREAKPAD MICRODUMP-----")); | 105 buf->get(), "-----BEGIN BREAKPAD MICRODUMP-----")); |
106 ASSERT_NE(static_cast<char*>(0), strstr( | 106 ASSERT_NE(static_cast<char*>(0), strstr( |
107 buf->get(), "-----END BREAKPAD MICRODUMP-----")); | 107 buf->get(), "-----END BREAKPAD MICRODUMP-----")); |
108 } | 108 } |
109 | 109 |
110 void CheckMicrodumpContents(const string µdum_content, | 110 void CheckMicrodumpContents(const string& microdump_content, |
111 const string &expected_fingerprint, | 111 const MicrodumpExtraInfo &expected_info) { |
112 const string &expected_product_info) { | 112 std::istringstream iss(microdump_content); |
113 std::istringstream iss(microdum_content); | |
114 bool did_find_os_info = false; | 113 bool did_find_os_info = false; |
115 bool did_find_product_info = false; | 114 bool did_find_product_info = false; |
115 bool did_find_gpu_info = false; | |
116 for (string line; std::getline(iss, line);) { | 116 for (string line; std::getline(iss, line);) { |
117 if (line.find("O ") == 0) { | 117 if (line.find("O ") == 0) { |
118 std::istringstream os_info_tokens(line); | 118 std::istringstream os_info_tokens(line); |
119 string token; | 119 string token; |
120 os_info_tokens.ignore(2); // Ignore the "O " preamble. | 120 os_info_tokens.ignore(2); // Ignore the "O " preamble. |
121 // Check the OS descriptor char (L=Linux, A=Android). | 121 // Check the OS descriptor char (L=Linux, A=Android). |
122 os_info_tokens >> token; | 122 os_info_tokens >> token; |
123 ASSERT_TRUE(token == "L" || token == "A"); | 123 ASSERT_TRUE(token == "L" || token == "A"); |
124 | 124 |
125 os_info_tokens >> token; // HW architecture. | 125 os_info_tokens >> token; // HW architecture. |
126 os_info_tokens >> token; // Number of cpus. | 126 os_info_tokens >> token; // Number of cpus. |
127 for (size_t i = 0; i < token.size(); ++i) | 127 for (size_t i = 0; i < token.size(); ++i) |
128 ASSERT_TRUE(isxdigit(token[i])); | 128 ASSERT_TRUE(isxdigit(token[i])); |
129 os_info_tokens >> token; // SW architecture. | 129 os_info_tokens >> token; // SW architecture. |
130 | 130 |
131 // Check that the build fingerprint is in the right place. | 131 // Check that the build fingerprint is in the right place. |
132 os_info_tokens >> token; | 132 os_info_tokens >> token; |
133 ASSERT_EQ(expected_fingerprint, token); | 133 if (expected_info.build_fingerprint) |
134 ASSERT_EQ(expected_info.build_fingerprint, token); | |
134 did_find_os_info = true; | 135 did_find_os_info = true; |
135 } else if (line.find("V ") == 0) { | 136 } else if (line.find("V ") == 0) { |
136 ASSERT_EQ("V " + expected_product_info, line); | 137 if (expected_info.product_info) |
138 ASSERT_EQ(string("V ") + expected_info.product_info, line); | |
137 did_find_product_info = true; | 139 did_find_product_info = true; |
140 } else if (line.find("G ") == 0) { | |
141 if (expected_info.gpu_fingerprint) | |
142 ASSERT_EQ(string("G ") + expected_info.gpu_fingerprint, line); | |
143 did_find_gpu_info = true; | |
138 } | 144 } |
139 } | 145 } |
140 ASSERT_TRUE(did_find_os_info); | 146 ASSERT_TRUE(did_find_os_info); |
141 ASSERT_TRUE(did_find_product_info); | 147 ASSERT_TRUE(did_find_product_info); |
148 ASSERT_TRUE(did_find_gpu_info); | |
149 } | |
150 | |
151 void CheckMicrodumpContents(const string& microdump_content, | |
152 const string& expected_fingerprint, | |
153 const string& expected_product_info, | |
154 const string& expected_gpu_fingerprint) { | |
155 CheckMicrodumpContents(microdump_content, | |
156 MicrodumpExtraInfo(expected_fingerprint.c_str(), | |
157 expected_product_info.c_str(), | |
158 expected_gpu_fingerprint.c_str())); | |
142 } | 159 } |
143 | 160 |
144 TEST(MicrodumpWriterTest, BasicWithMappings) { | 161 TEST(MicrodumpWriterTest, BasicWithMappings) { |
145 // Push some extra mapping to check the MappingList logic. | 162 // Push some extra mapping to check the MappingList logic. |
146 const uint32_t memory_size = sysconf(_SC_PAGESIZE); | 163 const uint32_t memory_size = sysconf(_SC_PAGESIZE); |
147 const char* kMemoryName = "libfoo.so"; | 164 const char* kMemoryName = "libfoo.so"; |
148 const uint8_t kModuleGUID[sizeof(MDGUID)] = { | 165 const uint8_t kModuleGUID[sizeof(MDGUID)] = { |
149 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | 166 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
150 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF | 167 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF |
151 }; | 168 }; |
152 | 169 |
153 MappingInfo info; | 170 MappingInfo info; |
154 info.start_addr = memory_size; | 171 info.start_addr = memory_size; |
155 info.size = memory_size; | 172 info.size = memory_size; |
156 info.offset = 42; | 173 info.offset = 42; |
157 strcpy(info.name, kMemoryName); | 174 strcpy(info.name, kMemoryName); |
158 | 175 |
159 MappingList mappings; | 176 MappingList mappings; |
160 MappingEntry mapping; | 177 MappingEntry mapping; |
161 mapping.first = info; | 178 mapping.first = info; |
162 memcpy(mapping.second, kModuleGUID, sizeof(MDGUID)); | 179 memcpy(mapping.second, kModuleGUID, sizeof(MDGUID)); |
163 mappings.push_back(mapping); | 180 mappings.push_back(mapping); |
164 | 181 |
165 scoped_array<char> buf; | 182 scoped_array<char> buf; |
166 CrashAndGetMicrodump(mappings, NULL, NULL, &buf); | 183 CrashAndGetMicrodump(mappings, MicrodumpExtraInfo(), &buf); |
167 | 184 |
168 #ifdef __LP64__ | 185 #ifdef __LP64__ |
169 ASSERT_NE(static_cast<char*>(0), strstr( | 186 ASSERT_NE(static_cast<char*>(0), strstr( |
170 buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 " | 187 buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 " |
171 "33221100554477668899AABBCCDDEEFF0 libfoo.so")); | 188 "33221100554477668899AABBCCDDEEFF0 libfoo.so")); |
172 #else | 189 #else |
173 ASSERT_NE(static_cast<char*>(0), strstr( | 190 ASSERT_NE(static_cast<char*>(0), strstr( |
174 buf.get(), "M 00001000 0000002A 00001000 " | 191 buf.get(), "M 00001000 0000002A 00001000 " |
175 "33221100554477668899AABBCCDDEEFF0 libfoo.so")); | 192 "33221100554477668899AABBCCDDEEFF0 libfoo.so")); |
176 #endif | 193 #endif |
177 | 194 |
178 // In absence of a product info in the minidump, the writer should just write | 195 // In absence of a product info in the minidump, the writer should just write |
179 // an unknown marker. | 196 // an unknown marker. |
180 ASSERT_NE(static_cast<char*>(0), strstr( | 197 ASSERT_NE(static_cast<char*>(0), strstr( |
181 buf.get(), "V UNKNOWN:0.0.0.0")); | 198 buf.get(), "V UNKNOWN:0.0.0.0")); |
182 } | 199 } |
183 | 200 |
184 // Ensure that the product info and build fingerprint metadata show up in the | 201 // Ensure that the product info and build fingerprint metadata show up in the |
185 // final microdump if present. | 202 // final microdump if present. |
186 TEST(MicrodumpWriterTest, BuildFingerprintAndProductInfo) { | 203 TEST(MicrodumpWriterTest, BuildFingerprintAndProductInfo) { |
187 const char kProductInfo[] = "MockProduct:42.0.2311.99"; | 204 const char kProductInfo[] = "MockProduct:42.0.2311.99"; |
188 const char kBuildFingerprint[] = | 205 const char kBuildFingerprint[] = |
189 "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys"; | 206 "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys"; |
207 const char kGPUFingerprint[] = | |
208 "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)"; | |
209 const MicrodumpExtraInfo kMicrodumpExtraInfo( | |
210 kBuildFingerprint, kProductInfo, kGPUFingerprint); | |
190 scoped_array<char> buf; | 211 scoped_array<char> buf; |
191 MappingList no_mappings; | 212 MappingList no_mappings; |
192 | 213 |
193 CrashAndGetMicrodump(no_mappings, kBuildFingerprint, kProductInfo, &buf); | 214 CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf); |
194 CheckMicrodumpContents(string(buf.get()), kBuildFingerprint, kProductInfo); | 215 CheckMicrodumpContents(string(buf.get()), kMicrodumpExtraInfo); |
195 } | 216 } |
196 | 217 |
197 TEST(MicrodumpWriterTest, NoProductInfo) { | 218 TEST(MicrodumpWriterTest, NoProductInfo) { |
198 const char kBuildFingerprint[] = "foobar"; | 219 const char kBuildFingerprint[] = "foobar"; |
220 const char kGPUFingerprint[] = "bazqux"; | |
Primiano Tucci (use gerrit)
2015/09/10 12:38:58
you probably want to check here that GPUfinerprint
Tobias Sargeant
2015/09/10 13:18:39
Done.
| |
199 scoped_array<char> buf; | 221 scoped_array<char> buf; |
200 MappingList no_mappings; | 222 MappingList no_mappings; |
201 | 223 |
202 CrashAndGetMicrodump(no_mappings, kBuildFingerprint, NULL, &buf); | 224 const MicrodumpExtraInfo kMicrodumpExtraInfoNoProductInfo( |
203 CheckMicrodumpContents(string(buf.get()), kBuildFingerprint, "UNKNOWN:0.0.0.0" ); | 225 kBuildFingerprint, NULL, kGPUFingerprint); |
226 | |
227 CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoProductInfo, &buf); | |
228 CheckMicrodumpContents(string(buf.get()), kBuildFingerprint, | |
229 "UNKNOWN:0.0.0.0", kGPUFingerprint); | |
204 } | 230 } |
205 } // namespace | 231 } // namespace |
OLD | NEW |