| Index: goopdate/crash_unittest.cc
|
| diff --git a/goopdate/crash_unittest.cc b/goopdate/crash_unittest.cc
|
| deleted file mode 100644
|
| index 93f2f346f7e7830451f01044413ecb47b937a191..0000000000000000000000000000000000000000
|
| --- a/goopdate/crash_unittest.cc
|
| +++ /dev/null
|
| @@ -1,400 +0,0 @@
|
| -// Copyright 2007-2010 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -
|
| -#include <string>
|
| -#include "omaha/base/app_util.h"
|
| -#include "omaha/base/atl_regexp.h"
|
| -#include "omaha/base/constants.h"
|
| -#include "omaha/base/const_addresses.h"
|
| -#include "omaha/base/const_object_names.h"
|
| -#include "omaha/base/error.h"
|
| -#include "omaha/base/file.h"
|
| -#include "omaha/base/scoped_any.h"
|
| -#include "omaha/base/time.h"
|
| -#include "omaha/base/user_info.h"
|
| -#include "omaha/base/utils.h"
|
| -#include "omaha/base/vistautil.h"
|
| -#include "omaha/common/config_manager.h"
|
| -#include "omaha/common/event_logger.h"
|
| -#include "omaha/common/goopdate_utils.h"
|
| -#include "omaha/goopdate/crash.h"
|
| -#include "omaha/testing/unit_test.h"
|
| -
|
| -// TODO(omaha): Modify the tests to avoid writing files to the staging
|
| -// directory, which should not be modified after building.
|
| -
|
| -using google_breakpad::ClientInfo;
|
| -using google_breakpad::CustomClientInfo;
|
| -using google_breakpad::CustomInfoEntry;
|
| -using google_breakpad::ExceptionHandler;
|
| -
|
| -namespace omaha {
|
| -
|
| -namespace {
|
| -
|
| -const TCHAR kMiniDumpFilename[] = _T("minidump.dmp");
|
| -const TCHAR kCustomInfoFilename[] = _T("minidump.txt");
|
| -const TCHAR kTestFilenamePattern[] = _T("minidump.*");
|
| -
|
| -} // namespace
|
| -
|
| -class CrashTest : public testing::Test {
|
| - protected:
|
| - // Initialize the crash reporting for the machine case. The user case is
|
| - // simpler and specific tests can reinitialize for the user case if needed.
|
| - virtual void SetUp() {
|
| - module_dir_ = app_util::GetModuleDirectory(NULL);
|
| - EXPECT_HRESULT_SUCCEEDED(Crash::Initialize(true));
|
| - }
|
| -
|
| - virtual void TearDown() {
|
| - EXPECT_HRESULT_SUCCEEDED(DeleteDirectory(Crash::crash_dir_));
|
| - }
|
| -
|
| - static void CallbackHelper(const wchar_t* dump_path,
|
| - const wchar_t* minidump_id) {
|
| - CString postfix_string(kCrashVersionPostfixString);
|
| - postfix_string.Append(_T(".ut"));
|
| - CString crash_filename;
|
| - crash_filename.Format(_T("%s\\%s.dmp"), dump_path, minidump_id);
|
| - Crash::set_max_reports_per_day(kMaxReportsPerDayFromUnittests);
|
| - Crash::set_version_postfix(postfix_string);
|
| - Crash::set_crash_report_url(kUrlCrashReport);
|
| - EXPECT_SUCCEEDED(Crash::Report(true, crash_filename, CString(), false));
|
| - }
|
| -
|
| - static bool MinidumpCallback(const wchar_t* dump_path,
|
| - const wchar_t* minidump_id,
|
| - void* context,
|
| - EXCEPTION_POINTERS*,
|
| - MDRawAssertionInfo*,
|
| - bool succeeded) {
|
| - EXPECT_TRUE(dump_path);
|
| - EXPECT_TRUE(minidump_id);
|
| - EXPECT_TRUE(!context);
|
| - EXPECT_SUCCEEDED(succeeded);
|
| -
|
| - CallbackHelper(dump_path, minidump_id);
|
| - return true;
|
| - }
|
| -
|
| - static void BuildPipeSecurityAttributesTest(bool is_machine) {
|
| - CSecurityAttributes pipe_sec_attrs;
|
| - EXPECT_TRUE(
|
| - Crash::BuildPipeSecurityAttributes(is_machine, &pipe_sec_attrs));
|
| - LPVOID sec_desc(pipe_sec_attrs.lpSecurityDescriptor);
|
| - CSecurityDesc sd1(*reinterpret_cast<SECURITY_DESCRIPTOR*>(sec_desc));
|
| - CString sddl1;
|
| -
|
| - sd1.ToString(&sddl1, OWNER_SECURITY_INFORMATION |
|
| - GROUP_SECURITY_INFORMATION |
|
| - DACL_SECURITY_INFORMATION |
|
| - SACL_SECURITY_INFORMATION |
|
| - LABEL_SECURITY_INFORMATION);
|
| -
|
| - CSecurityDesc sd2;
|
| - EXPECT_TRUE(Crash::AddPipeSecurityDaclToDesc(is_machine, &sd2));
|
| - EXPECT_HRESULT_SUCCEEDED(
|
| - vista_util::AddLowIntegritySaclToExistingDesc(&sd2));
|
| -
|
| - CString sddl2;
|
| - sd2.ToString(&sddl2, OWNER_SECURITY_INFORMATION |
|
| - GROUP_SECURITY_INFORMATION |
|
| - DACL_SECURITY_INFORMATION |
|
| - SACL_SECURITY_INFORMATION |
|
| - LABEL_SECURITY_INFORMATION);
|
| -
|
| - EXPECT_STREQ(sddl2, sddl1);
|
| -
|
| - if (vista_util::IsVistaOrLater()) {
|
| - // The low integrity SACL is at the end of the SDDL string.
|
| - EXPECT_STREQ(LOW_INTEGRITY_SDDL_SACL,
|
| - sddl1.Right(arraysize(LOW_INTEGRITY_SDDL_SACL) - 1));
|
| - }
|
| - }
|
| -
|
| - static HRESULT StartSenderWithCommandLine(CString* cmd_line) {
|
| - return Crash::StartSenderWithCommandLine(cmd_line);
|
| - }
|
| -
|
| - // Returns the strings of the last Update2 event in the event log.
|
| - static CString GetLastCrashEventStrings() {
|
| - const size_t kBufferSize = 1024;
|
| - uint8 buffer[kBufferSize] = {0};
|
| - EVENTLOGRECORD* rec = reinterpret_cast<EVENTLOGRECORD*>(buffer);
|
| -
|
| - rec->Length = kBufferSize;
|
| - EXPECT_SUCCEEDED(EventLogger::ReadLastEvent(_T("Update2"), rec));
|
| - EXPECT_EQ(kCrashUploadEventId, rec->EventID);
|
| -
|
| - const TCHAR* strings = reinterpret_cast<const TCHAR*>(
|
| - (reinterpret_cast<uint8*>(buffer + rec->StringOffset)));
|
| -
|
| - return CString(strings);
|
| - }
|
| -
|
| - CString module_dir_;
|
| -
|
| - static const int kMaxReportsPerDayFromUnittests = INT_MAX;
|
| -};
|
| -
|
| -TEST_F(CrashTest, CreateCustomInfoFile) {
|
| - CString expected_custom_info_file_path;
|
| - expected_custom_info_file_path.Format(_T("%s\\%s"),
|
| - module_dir_, kCustomInfoFilename);
|
| -
|
| - CString crash_filename;
|
| - crash_filename.Format(_T("%s\\%s"), module_dir_, kMiniDumpFilename);
|
| - CustomInfoEntry info_entry(_T("foo"), _T("bar"));
|
| - CustomClientInfo custom_client_info = {&info_entry, 1};
|
| -
|
| - CString actual_custom_info_filepath;
|
| - EXPECT_SUCCEEDED(Crash::CreateCustomInfoFile(crash_filename,
|
| - custom_client_info,
|
| - &actual_custom_info_filepath));
|
| - EXPECT_STREQ(expected_custom_info_file_path, actual_custom_info_filepath);
|
| - EXPECT_TRUE(File::Exists(actual_custom_info_filepath));
|
| - EXPECT_TRUE(::DeleteFile(actual_custom_info_filepath));
|
| -
|
| - // Tests an invalid file name.
|
| - EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
|
| - Crash::CreateCustomInfoFile(_T("C:\\\"minidump.dmp"),
|
| - custom_client_info,
|
| - &actual_custom_info_filepath));
|
| -}
|
| -
|
| -// Tests sending an Omaha crash.
|
| -TEST_F(CrashTest, Report_OmahaCrash) {
|
| - CString crash_filename;
|
| - crash_filename.Format(_T("%s\\%s"), module_dir_, kMiniDumpFilename);
|
| -
|
| - ::DeleteFile(crash_filename);
|
| -
|
| - EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
|
| - Crash::Report(true, crash_filename, _T(""), _T("")));
|
| -
|
| - // Copy the minidump and the corresponding info file.
|
| - CString test_dir;
|
| - test_dir.Format(_T("%s\\unittest_support"), module_dir_);
|
| - ASSERT_SUCCEEDED(File::CopyWildcards(test_dir, // From.
|
| - module_dir_, // To.
|
| - kTestFilenamePattern,
|
| - true));
|
| -
|
| - ASSERT_TRUE(File::Exists(crash_filename));
|
| -
|
| - ASSERT_SUCCEEDED(Crash::Report(true, crash_filename, _T(""), _T("")));
|
| -
|
| - // The crash artifacts should be deleted after the crash is reported.
|
| - EXPECT_FALSE(File::Exists(crash_filename));
|
| -}
|
| -
|
| -// Tests sending an out-of-process crash.
|
| -// This test will write an entry with the source "Update2" in the Event Log.
|
| -TEST_F(CrashTest, Report_ProductCrash) {
|
| - CString crash_filename;
|
| - CString custom_info_filename;
|
| - crash_filename.Format(_T("%s\\%s"), module_dir_, kMiniDumpFilename);
|
| - custom_info_filename.Format(_T("%s\\%s"), module_dir_, kCustomInfoFilename);
|
| -
|
| - ::DeleteFile(crash_filename);
|
| - ::DeleteFile(custom_info_filename);
|
| -
|
| - EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
|
| - Crash::Report(true, crash_filename, custom_info_filename, _T("")));
|
| -
|
| - // Copy the minidump and the corresponding info file.
|
| - CString test_dir;
|
| - test_dir.Format(_T("%s\\unittest_support"), module_dir_);
|
| - ASSERT_SUCCEEDED(File::CopyWildcards(test_dir, // From.
|
| - module_dir_, // To.
|
| - kTestFilenamePattern,
|
| - true));
|
| -
|
| - ASSERT_TRUE(File::Exists(crash_filename));
|
| - ASSERT_TRUE(File::Exists(custom_info_filename));
|
| -
|
| - ASSERT_SUCCEEDED(Crash::Report(true, crash_filename,
|
| - custom_info_filename, _T("")));
|
| -
|
| - // Check the 'crash uploaded' event log.
|
| - const CString strings = GetLastCrashEventStrings();
|
| -
|
| - // Verify that the strings include the Id token.
|
| - AtlRE crash_id_regex(_T("Id={\\h+}."));
|
| - CString crash_id;
|
| - EXPECT_TRUE(AtlRE::PartialMatch(strings, crash_id_regex, &crash_id));
|
| -
|
| - // The crash artifacts should be deleted after the crash is reported.
|
| - EXPECT_FALSE(File::Exists(crash_filename));
|
| - EXPECT_FALSE(File::Exists(custom_info_filename));
|
| -}
|
| -
|
| -// Tests generation of a minidump and uploading it to the staging server.
|
| -TEST_F(CrashTest, WriteMinidump) {
|
| - ASSERT_TRUE(!Crash::crash_dir_.IsEmpty());
|
| -
|
| - MINIDUMP_TYPE dump_type = MiniDumpNormal;
|
| - ExceptionHandler handler(Crash::crash_dir_.GetString(), NULL,
|
| - &MinidumpCallback, NULL,
|
| - ExceptionHandler::HANDLER_NONE,
|
| - dump_type, NULL, NULL);
|
| - ASSERT_TRUE(handler.WriteMinidump());
|
| -}
|
| -
|
| -// Tests the retrieval of the exception information from an existing mini dump.
|
| -TEST_F(CrashTest, GetExceptionInfo) {
|
| - const uint32 kExceptionAddress = 0x12345670;
|
| - const uint32 kExceptionCode = 0xc0000005;
|
| -
|
| - CString filename;
|
| - filename.AppendFormat(_T("%s\\unittest_support\\%s"),
|
| - module_dir_, kMiniDumpFilename);
|
| - MINIDUMP_EXCEPTION ex_info = {0};
|
| - ASSERT_SUCCEEDED(Crash::GetExceptionInfo(filename, &ex_info));
|
| - EXPECT_EQ(kExceptionAddress, ex_info.ExceptionAddress);
|
| - EXPECT_EQ(kExceptionCode, ex_info.ExceptionCode);
|
| -}
|
| -
|
| -TEST_F(CrashTest, IsCrashReportProcess) {
|
| - // Clear the environment variable.
|
| - ::SetEnvironmentVariable(kNoCrashHandlerEnvVariableName, NULL);
|
| -
|
| - bool is_crash_report_process = false;
|
| - EXPECT_SUCCEEDED(Crash::IsCrashReportProcess(&is_crash_report_process));
|
| - EXPECT_FALSE(is_crash_report_process);
|
| -
|
| - EXPECT_TRUE(::SetEnvironmentVariable(kNoCrashHandlerEnvVariableName,
|
| - _T("1")));
|
| - is_crash_report_process = false;
|
| - EXPECT_SUCCEEDED(Crash::IsCrashReportProcess(&is_crash_report_process));
|
| - EXPECT_TRUE(is_crash_report_process);
|
| -
|
| - // Clear the environment variable.
|
| - EXPECT_TRUE(::SetEnvironmentVariable(kNoCrashHandlerEnvVariableName, NULL));
|
| -}
|
| -
|
| -TEST_F(CrashTest, GetProductName) {
|
| - Crash::ParameterMap parameters;
|
| - EXPECT_STREQ(SHORT_COMPANY_NAME _T(" Error Reporting"),
|
| - Crash::GetProductName(parameters));
|
| -
|
| - parameters[_T("prod")] = _T("Update2");
|
| - EXPECT_STREQ(_T("Update2"), Crash::GetProductName(parameters));
|
| -}
|
| -
|
| -TEST_F(CrashTest, SaveLastCrash) {
|
| - // Copy a test file into the module directory to use as a crash file.
|
| - CString test_file; // The unit test support file.
|
| - CString crash_file; // The crash file to be backed up.
|
| - test_file.AppendFormat(_T("%s\\unittest_support\\%s"),
|
| - module_dir_, kMiniDumpFilename);
|
| - crash_file.AppendFormat(_T("%s\\%s"), Crash::crash_dir_, kMiniDumpFilename);
|
| - EXPECT_TRUE(File::Exists(test_file));
|
| - EXPECT_TRUE(::CopyFile(test_file, crash_file, false));
|
| - EXPECT_TRUE(File::Exists(crash_file));
|
| -
|
| - EXPECT_HRESULT_SUCCEEDED(Crash::SaveLastCrash(crash_file, _T("test")));
|
| -
|
| - CString saved_crash_file; // The name of backup crash file.
|
| - saved_crash_file.AppendFormat(_T("%s\\test-last.dmp"), Crash::crash_dir_);
|
| - EXPECT_TRUE(File::Exists(saved_crash_file));
|
| -
|
| - EXPECT_TRUE(::DeleteFile(saved_crash_file));
|
| -}
|
| -
|
| -TEST_F(CrashTest, StartServer) {
|
| - // Terminate all processes to avoid conflicts on the crash services pipe.
|
| - TerminateAllGoogleUpdateProcesses();
|
| -
|
| - EXPECT_HRESULT_SUCCEEDED(Crash::StartServer());
|
| -
|
| - // Try opening the crash services pipe.
|
| - CString user_sid;
|
| - EXPECT_HRESULT_SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid));
|
| - CString pipe_name;
|
| - pipe_name.AppendFormat(_T("\\\\.\\pipe\\%sCrashServices\\%s"),
|
| - SHORT_COMPANY_NAME, user_sid);
|
| - scoped_pipe pipe_handle(::CreateFile(pipe_name,
|
| - GENERIC_READ | GENERIC_WRITE,
|
| - FILE_SHARE_READ | FILE_SHARE_WRITE,
|
| - NULL,
|
| - OPEN_EXISTING,
|
| - 0,
|
| - NULL));
|
| - EXPECT_TRUE(pipe_handle);
|
| -
|
| - Crash::StopServer();
|
| -}
|
| -
|
| -TEST_F(CrashTest, CleanStaleCrashes) {
|
| - // Copy a test file into the module directory to use as a crash file.
|
| - CString test_file; // The unit test support file.
|
| - CString crash_file; // The crash file to be backed up.
|
| - test_file.AppendFormat(_T("%s\\unittest_support\\%s"),
|
| - module_dir_, kMiniDumpFilename);
|
| - crash_file.AppendFormat(_T("%s\\%s.dmp"),
|
| - Crash::crash_dir_,
|
| - _T("5695F1E0-95BD-4bc2-99C0-E9DCC0AC5274"));
|
| - EXPECT_TRUE(File::Exists(test_file));
|
| - EXPECT_TRUE(::CopyFile(test_file, crash_file, false));
|
| - EXPECT_TRUE(File::Exists(crash_file));
|
| -
|
| - FILETIME time_created = {0};
|
| - time64 now = GetCurrent100NSTime();
|
| -
|
| - // Create a time value 23 hours in the past. Expect the crash file remains.
|
| - Time64ToFileTime(now - 23 * kHoursTo100ns, &time_created);
|
| - EXPECT_HRESULT_SUCCEEDED(File::SetFileTime(crash_file, &time_created,
|
| - NULL, NULL));
|
| - Crash::CleanStaleCrashes();
|
| - EXPECT_TRUE(File::Exists(crash_file));
|
| -
|
| - // Create a time value 25 hours in the past. Expect the crash file is deleted.
|
| - Time64ToFileTime(now - 25 * kHoursTo100ns, &time_created);
|
| - EXPECT_HRESULT_SUCCEEDED(File::SetFileTime(crash_file, &time_created,
|
| - NULL, NULL));
|
| - Crash::CleanStaleCrashes();
|
| - EXPECT_FALSE(File::Exists(crash_file));
|
| -}
|
| -
|
| -// Installs and uninstalls the crash handler in the user case.
|
| -TEST_F(CrashTest, InstallCrashHandler) {
|
| - EXPECT_HRESULT_SUCCEEDED(Crash::InstallCrashHandler(false));
|
| - Crash::UninstallCrashHandler();
|
| -}
|
| -
|
| -// Makes sure that the security descriptor that BuildPipeSecurityAttributes
|
| -// creates matches the security descriptor built by adding the DACL first, and
|
| -// then using AddLowIntegritySaclToExistingDesc(). The latter method uses an
|
| -// approach similar to what is documented in MSDN:
|
| -// http://msdn.microsoft.com/en-us/library/bb625960.aspx
|
| -//
|
| -// Also, makes sure that the security descriptor that
|
| -// BuildPipeSecurityAttributes creates has the low integrity SACL within it.
|
| -TEST_F(CrashTest, BuildPipeSecurityAttributes) {
|
| - BuildPipeSecurityAttributesTest(true);
|
| - BuildPipeSecurityAttributesTest(false);
|
| -}
|
| -
|
| -TEST_F(CrashTest, StartSenderWithCommandLine) {
|
| - // Negative test.
|
| - CString filename(_T("DoesNotExist.exe"));
|
| - EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
|
| - StartSenderWithCommandLine(&filename));
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
|
|