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

Side by Side Diff: goopdate/crash_unittest.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 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
« no previous file with comments | « goopdate/crash.cc ('k') | goopdate/cred_dialog.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2010 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 #include <string>
17 #include "omaha/base/app_util.h"
18 #include "omaha/base/atl_regexp.h"
19 #include "omaha/base/constants.h"
20 #include "omaha/base/const_addresses.h"
21 #include "omaha/base/const_object_names.h"
22 #include "omaha/base/error.h"
23 #include "omaha/base/file.h"
24 #include "omaha/base/scoped_any.h"
25 #include "omaha/base/time.h"
26 #include "omaha/base/user_info.h"
27 #include "omaha/base/utils.h"
28 #include "omaha/base/vistautil.h"
29 #include "omaha/common/config_manager.h"
30 #include "omaha/common/event_logger.h"
31 #include "omaha/common/goopdate_utils.h"
32 #include "omaha/goopdate/crash.h"
33 #include "omaha/testing/unit_test.h"
34
35 // TODO(omaha): Modify the tests to avoid writing files to the staging
36 // directory, which should not be modified after building.
37
38 using google_breakpad::ClientInfo;
39 using google_breakpad::CustomClientInfo;
40 using google_breakpad::CustomInfoEntry;
41 using google_breakpad::ExceptionHandler;
42
43 namespace omaha {
44
45 namespace {
46
47 const TCHAR kMiniDumpFilename[] = _T("minidump.dmp");
48 const TCHAR kCustomInfoFilename[] = _T("minidump.txt");
49 const TCHAR kTestFilenamePattern[] = _T("minidump.*");
50
51 } // namespace
52
53 class CrashTest : public testing::Test {
54 protected:
55 // Initialize the crash reporting for the machine case. The user case is
56 // simpler and specific tests can reinitialize for the user case if needed.
57 virtual void SetUp() {
58 module_dir_ = app_util::GetModuleDirectory(NULL);
59 EXPECT_HRESULT_SUCCEEDED(Crash::Initialize(true));
60 }
61
62 virtual void TearDown() {
63 EXPECT_HRESULT_SUCCEEDED(DeleteDirectory(Crash::crash_dir_));
64 }
65
66 static void CallbackHelper(const wchar_t* dump_path,
67 const wchar_t* minidump_id) {
68 CString postfix_string(kCrashVersionPostfixString);
69 postfix_string.Append(_T(".ut"));
70 CString crash_filename;
71 crash_filename.Format(_T("%s\\%s.dmp"), dump_path, minidump_id);
72 Crash::set_max_reports_per_day(kMaxReportsPerDayFromUnittests);
73 Crash::set_version_postfix(postfix_string);
74 Crash::set_crash_report_url(kUrlCrashReport);
75 EXPECT_SUCCEEDED(Crash::Report(true, crash_filename, CString(), false));
76 }
77
78 static bool MinidumpCallback(const wchar_t* dump_path,
79 const wchar_t* minidump_id,
80 void* context,
81 EXCEPTION_POINTERS*,
82 MDRawAssertionInfo*,
83 bool succeeded) {
84 EXPECT_TRUE(dump_path);
85 EXPECT_TRUE(minidump_id);
86 EXPECT_TRUE(!context);
87 EXPECT_SUCCEEDED(succeeded);
88
89 CallbackHelper(dump_path, minidump_id);
90 return true;
91 }
92
93 static void BuildPipeSecurityAttributesTest(bool is_machine) {
94 CSecurityAttributes pipe_sec_attrs;
95 EXPECT_TRUE(
96 Crash::BuildPipeSecurityAttributes(is_machine, &pipe_sec_attrs));
97 LPVOID sec_desc(pipe_sec_attrs.lpSecurityDescriptor);
98 CSecurityDesc sd1(*reinterpret_cast<SECURITY_DESCRIPTOR*>(sec_desc));
99 CString sddl1;
100
101 sd1.ToString(&sddl1, OWNER_SECURITY_INFORMATION |
102 GROUP_SECURITY_INFORMATION |
103 DACL_SECURITY_INFORMATION |
104 SACL_SECURITY_INFORMATION |
105 LABEL_SECURITY_INFORMATION);
106
107 CSecurityDesc sd2;
108 EXPECT_TRUE(Crash::AddPipeSecurityDaclToDesc(is_machine, &sd2));
109 EXPECT_HRESULT_SUCCEEDED(
110 vista_util::AddLowIntegritySaclToExistingDesc(&sd2));
111
112 CString sddl2;
113 sd2.ToString(&sddl2, OWNER_SECURITY_INFORMATION |
114 GROUP_SECURITY_INFORMATION |
115 DACL_SECURITY_INFORMATION |
116 SACL_SECURITY_INFORMATION |
117 LABEL_SECURITY_INFORMATION);
118
119 EXPECT_STREQ(sddl2, sddl1);
120
121 if (vista_util::IsVistaOrLater()) {
122 // The low integrity SACL is at the end of the SDDL string.
123 EXPECT_STREQ(LOW_INTEGRITY_SDDL_SACL,
124 sddl1.Right(arraysize(LOW_INTEGRITY_SDDL_SACL) - 1));
125 }
126 }
127
128 static HRESULT StartSenderWithCommandLine(CString* cmd_line) {
129 return Crash::StartSenderWithCommandLine(cmd_line);
130 }
131
132 // Returns the strings of the last Update2 event in the event log.
133 static CString GetLastCrashEventStrings() {
134 const size_t kBufferSize = 1024;
135 uint8 buffer[kBufferSize] = {0};
136 EVENTLOGRECORD* rec = reinterpret_cast<EVENTLOGRECORD*>(buffer);
137
138 rec->Length = kBufferSize;
139 EXPECT_SUCCEEDED(EventLogger::ReadLastEvent(_T("Update2"), rec));
140 EXPECT_EQ(kCrashUploadEventId, rec->EventID);
141
142 const TCHAR* strings = reinterpret_cast<const TCHAR*>(
143 (reinterpret_cast<uint8*>(buffer + rec->StringOffset)));
144
145 return CString(strings);
146 }
147
148 CString module_dir_;
149
150 static const int kMaxReportsPerDayFromUnittests = INT_MAX;
151 };
152
153 TEST_F(CrashTest, CreateCustomInfoFile) {
154 CString expected_custom_info_file_path;
155 expected_custom_info_file_path.Format(_T("%s\\%s"),
156 module_dir_, kCustomInfoFilename);
157
158 CString crash_filename;
159 crash_filename.Format(_T("%s\\%s"), module_dir_, kMiniDumpFilename);
160 CustomInfoEntry info_entry(_T("foo"), _T("bar"));
161 CustomClientInfo custom_client_info = {&info_entry, 1};
162
163 CString actual_custom_info_filepath;
164 EXPECT_SUCCEEDED(Crash::CreateCustomInfoFile(crash_filename,
165 custom_client_info,
166 &actual_custom_info_filepath));
167 EXPECT_STREQ(expected_custom_info_file_path, actual_custom_info_filepath);
168 EXPECT_TRUE(File::Exists(actual_custom_info_filepath));
169 EXPECT_TRUE(::DeleteFile(actual_custom_info_filepath));
170
171 // Tests an invalid file name.
172 EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
173 Crash::CreateCustomInfoFile(_T("C:\\\"minidump.dmp"),
174 custom_client_info,
175 &actual_custom_info_filepath));
176 }
177
178 // Tests sending an Omaha crash.
179 TEST_F(CrashTest, Report_OmahaCrash) {
180 CString crash_filename;
181 crash_filename.Format(_T("%s\\%s"), module_dir_, kMiniDumpFilename);
182
183 ::DeleteFile(crash_filename);
184
185 EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
186 Crash::Report(true, crash_filename, _T(""), _T("")));
187
188 // Copy the minidump and the corresponding info file.
189 CString test_dir;
190 test_dir.Format(_T("%s\\unittest_support"), module_dir_);
191 ASSERT_SUCCEEDED(File::CopyWildcards(test_dir, // From.
192 module_dir_, // To.
193 kTestFilenamePattern,
194 true));
195
196 ASSERT_TRUE(File::Exists(crash_filename));
197
198 ASSERT_SUCCEEDED(Crash::Report(true, crash_filename, _T(""), _T("")));
199
200 // The crash artifacts should be deleted after the crash is reported.
201 EXPECT_FALSE(File::Exists(crash_filename));
202 }
203
204 // Tests sending an out-of-process crash.
205 // This test will write an entry with the source "Update2" in the Event Log.
206 TEST_F(CrashTest, Report_ProductCrash) {
207 CString crash_filename;
208 CString custom_info_filename;
209 crash_filename.Format(_T("%s\\%s"), module_dir_, kMiniDumpFilename);
210 custom_info_filename.Format(_T("%s\\%s"), module_dir_, kCustomInfoFilename);
211
212 ::DeleteFile(crash_filename);
213 ::DeleteFile(custom_info_filename);
214
215 EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
216 Crash::Report(true, crash_filename, custom_info_filename, _T("")));
217
218 // Copy the minidump and the corresponding info file.
219 CString test_dir;
220 test_dir.Format(_T("%s\\unittest_support"), module_dir_);
221 ASSERT_SUCCEEDED(File::CopyWildcards(test_dir, // From.
222 module_dir_, // To.
223 kTestFilenamePattern,
224 true));
225
226 ASSERT_TRUE(File::Exists(crash_filename));
227 ASSERT_TRUE(File::Exists(custom_info_filename));
228
229 ASSERT_SUCCEEDED(Crash::Report(true, crash_filename,
230 custom_info_filename, _T("")));
231
232 // Check the 'crash uploaded' event log.
233 const CString strings = GetLastCrashEventStrings();
234
235 // Verify that the strings include the Id token.
236 AtlRE crash_id_regex(_T("Id={\\h+}."));
237 CString crash_id;
238 EXPECT_TRUE(AtlRE::PartialMatch(strings, crash_id_regex, &crash_id));
239
240 // The crash artifacts should be deleted after the crash is reported.
241 EXPECT_FALSE(File::Exists(crash_filename));
242 EXPECT_FALSE(File::Exists(custom_info_filename));
243 }
244
245 // Tests generation of a minidump and uploading it to the staging server.
246 TEST_F(CrashTest, WriteMinidump) {
247 ASSERT_TRUE(!Crash::crash_dir_.IsEmpty());
248
249 MINIDUMP_TYPE dump_type = MiniDumpNormal;
250 ExceptionHandler handler(Crash::crash_dir_.GetString(), NULL,
251 &MinidumpCallback, NULL,
252 ExceptionHandler::HANDLER_NONE,
253 dump_type, NULL, NULL);
254 ASSERT_TRUE(handler.WriteMinidump());
255 }
256
257 // Tests the retrieval of the exception information from an existing mini dump.
258 TEST_F(CrashTest, GetExceptionInfo) {
259 const uint32 kExceptionAddress = 0x12345670;
260 const uint32 kExceptionCode = 0xc0000005;
261
262 CString filename;
263 filename.AppendFormat(_T("%s\\unittest_support\\%s"),
264 module_dir_, kMiniDumpFilename);
265 MINIDUMP_EXCEPTION ex_info = {0};
266 ASSERT_SUCCEEDED(Crash::GetExceptionInfo(filename, &ex_info));
267 EXPECT_EQ(kExceptionAddress, ex_info.ExceptionAddress);
268 EXPECT_EQ(kExceptionCode, ex_info.ExceptionCode);
269 }
270
271 TEST_F(CrashTest, IsCrashReportProcess) {
272 // Clear the environment variable.
273 ::SetEnvironmentVariable(kNoCrashHandlerEnvVariableName, NULL);
274
275 bool is_crash_report_process = false;
276 EXPECT_SUCCEEDED(Crash::IsCrashReportProcess(&is_crash_report_process));
277 EXPECT_FALSE(is_crash_report_process);
278
279 EXPECT_TRUE(::SetEnvironmentVariable(kNoCrashHandlerEnvVariableName,
280 _T("1")));
281 is_crash_report_process = false;
282 EXPECT_SUCCEEDED(Crash::IsCrashReportProcess(&is_crash_report_process));
283 EXPECT_TRUE(is_crash_report_process);
284
285 // Clear the environment variable.
286 EXPECT_TRUE(::SetEnvironmentVariable(kNoCrashHandlerEnvVariableName, NULL));
287 }
288
289 TEST_F(CrashTest, GetProductName) {
290 Crash::ParameterMap parameters;
291 EXPECT_STREQ(SHORT_COMPANY_NAME _T(" Error Reporting"),
292 Crash::GetProductName(parameters));
293
294 parameters[_T("prod")] = _T("Update2");
295 EXPECT_STREQ(_T("Update2"), Crash::GetProductName(parameters));
296 }
297
298 TEST_F(CrashTest, SaveLastCrash) {
299 // Copy a test file into the module directory to use as a crash file.
300 CString test_file; // The unit test support file.
301 CString crash_file; // The crash file to be backed up.
302 test_file.AppendFormat(_T("%s\\unittest_support\\%s"),
303 module_dir_, kMiniDumpFilename);
304 crash_file.AppendFormat(_T("%s\\%s"), Crash::crash_dir_, kMiniDumpFilename);
305 EXPECT_TRUE(File::Exists(test_file));
306 EXPECT_TRUE(::CopyFile(test_file, crash_file, false));
307 EXPECT_TRUE(File::Exists(crash_file));
308
309 EXPECT_HRESULT_SUCCEEDED(Crash::SaveLastCrash(crash_file, _T("test")));
310
311 CString saved_crash_file; // The name of backup crash file.
312 saved_crash_file.AppendFormat(_T("%s\\test-last.dmp"), Crash::crash_dir_);
313 EXPECT_TRUE(File::Exists(saved_crash_file));
314
315 EXPECT_TRUE(::DeleteFile(saved_crash_file));
316 }
317
318 TEST_F(CrashTest, StartServer) {
319 // Terminate all processes to avoid conflicts on the crash services pipe.
320 TerminateAllGoogleUpdateProcesses();
321
322 EXPECT_HRESULT_SUCCEEDED(Crash::StartServer());
323
324 // Try opening the crash services pipe.
325 CString user_sid;
326 EXPECT_HRESULT_SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid));
327 CString pipe_name;
328 pipe_name.AppendFormat(_T("\\\\.\\pipe\\%sCrashServices\\%s"),
329 SHORT_COMPANY_NAME, user_sid);
330 scoped_pipe pipe_handle(::CreateFile(pipe_name,
331 GENERIC_READ | GENERIC_WRITE,
332 FILE_SHARE_READ | FILE_SHARE_WRITE,
333 NULL,
334 OPEN_EXISTING,
335 0,
336 NULL));
337 EXPECT_TRUE(pipe_handle);
338
339 Crash::StopServer();
340 }
341
342 TEST_F(CrashTest, CleanStaleCrashes) {
343 // Copy a test file into the module directory to use as a crash file.
344 CString test_file; // The unit test support file.
345 CString crash_file; // The crash file to be backed up.
346 test_file.AppendFormat(_T("%s\\unittest_support\\%s"),
347 module_dir_, kMiniDumpFilename);
348 crash_file.AppendFormat(_T("%s\\%s.dmp"),
349 Crash::crash_dir_,
350 _T("5695F1E0-95BD-4bc2-99C0-E9DCC0AC5274"));
351 EXPECT_TRUE(File::Exists(test_file));
352 EXPECT_TRUE(::CopyFile(test_file, crash_file, false));
353 EXPECT_TRUE(File::Exists(crash_file));
354
355 FILETIME time_created = {0};
356 time64 now = GetCurrent100NSTime();
357
358 // Create a time value 23 hours in the past. Expect the crash file remains.
359 Time64ToFileTime(now - 23 * kHoursTo100ns, &time_created);
360 EXPECT_HRESULT_SUCCEEDED(File::SetFileTime(crash_file, &time_created,
361 NULL, NULL));
362 Crash::CleanStaleCrashes();
363 EXPECT_TRUE(File::Exists(crash_file));
364
365 // Create a time value 25 hours in the past. Expect the crash file is deleted.
366 Time64ToFileTime(now - 25 * kHoursTo100ns, &time_created);
367 EXPECT_HRESULT_SUCCEEDED(File::SetFileTime(crash_file, &time_created,
368 NULL, NULL));
369 Crash::CleanStaleCrashes();
370 EXPECT_FALSE(File::Exists(crash_file));
371 }
372
373 // Installs and uninstalls the crash handler in the user case.
374 TEST_F(CrashTest, InstallCrashHandler) {
375 EXPECT_HRESULT_SUCCEEDED(Crash::InstallCrashHandler(false));
376 Crash::UninstallCrashHandler();
377 }
378
379 // Makes sure that the security descriptor that BuildPipeSecurityAttributes
380 // creates matches the security descriptor built by adding the DACL first, and
381 // then using AddLowIntegritySaclToExistingDesc(). The latter method uses an
382 // approach similar to what is documented in MSDN:
383 // http://msdn.microsoft.com/en-us/library/bb625960.aspx
384 //
385 // Also, makes sure that the security descriptor that
386 // BuildPipeSecurityAttributes creates has the low integrity SACL within it.
387 TEST_F(CrashTest, BuildPipeSecurityAttributes) {
388 BuildPipeSecurityAttributesTest(true);
389 BuildPipeSecurityAttributesTest(false);
390 }
391
392 TEST_F(CrashTest, StartSenderWithCommandLine) {
393 // Negative test.
394 CString filename(_T("DoesNotExist.exe"));
395 EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
396 StartSenderWithCommandLine(&filename));
397 }
398
399 } // namespace omaha
400
OLDNEW
« no previous file with comments | « goopdate/crash.cc ('k') | goopdate/cred_dialog.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698