Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: src/client/linux/microdump_writer/microdump_writer_unittest.cc

Issue 1334473003: Add GPU fingerprint information to breakpad microdumps. (Closed) Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@master
Patch Set: Remove unnecessary code, add unittest, update comments. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 &microdump_extra_info,
Lei Zhang 2015/09/10 18:38:19 & ditto
Tobias Sargeant 2015/09/11 09:07:50 Done.
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
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 &microdum_content, 110 void CheckMicrodumpContents(const string& microdump_content,
111 const string &expected_fingerprint, 111 const MicrodumpExtraInfo &expected_info) {
Lei Zhang 2015/09/10 18:38:19 & ditto ditto
Tobias Sargeant 2015/09/11 09:07:50 Done.
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";
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);
230 }
231
232 TEST(MicrodumpWriterTest, NoGPUInfo) {
233 const char kProductInfo[] = "bazqux";
234 const char kBuildFingerprint[] = "foobar";
235 scoped_array<char> buf;
236 MappingList no_mappings;
237
238 const MicrodumpExtraInfo kMicrodumpExtraInfoNoGPUInfo(
239 kBuildFingerprint, kProductInfo, NULL);
240
241 CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoGPUInfo, &buf);
242 CheckMicrodumpContents(string(buf.get()), kBuildFingerprint,
243 kProductInfo, "UNKNOWN");
204 } 244 }
205 } // namespace 245 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698