1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/crash/core/app/fallback_crash_handling_win.h"
6
7 #include "base/base_switches.h"
8 #include "base/check.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/test/multiprocess_test.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "testing/multiprocess_func_list.h"
15 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
16
17 namespace crash_reporter {
18
19 namespace {
20
21 const DWORD kExceptionCode = 0xCAFEBABE;
22
23 // This main function runs in two modes, first as a faux-crashpad handler,
24 // and then with --type=fallback-handler to handle the crash in the first
25 // instance.
MULTIPROCESS_TEST_MAIN(FallbackCrashHandlingWinRunHandler)26 MULTIPROCESS_TEST_MAIN(FallbackCrashHandlingWinRunHandler) {
27 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
28 if (cmd_line->GetSwitchValueASCII("type") ==
29 switches::kFallbackCrashHandler) {
30 return RunAsFallbackCrashHandler(*cmd_line,
31 "FallbackCrashHandlingWinRunHandler",
32 "1.2.3.4", "FakeChannel");
33 }
34
35 CHECK(SetupFallbackCrashHandling(*cmd_line));
36
37 // Provoke a crash with a well-defined exception code.
38 // The process shouldn't terminate with this exception code.
39 RaiseException(kExceptionCode, 0, 0, nullptr);
40
41 // This process should never return from the exception.
42 CHECK(false) << "Unexpected return from RaiseException";
43
44 // Should never get here.
45 return 0;
46 }
47
48 class FallbackCrashHandlingTest : public base::MultiProcessTest {
49 public:
SetUp()50 void SetUp() override { ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); }
51
52 protected:
53 base::ScopedTempDir database_dir_;
54 };
55
56 } // namespace
57
TEST_F(FallbackCrashHandlingTest,SetupAndRunAsFallbackCrashHandler)58 TEST_F(FallbackCrashHandlingTest, SetupAndRunAsFallbackCrashHandler) {
59 // Launch a subprocess to test the fallback handling implementation.
60 base::CommandLine cmd_line = base::GetMultiProcessTestChildBaseCommandLine();
61 cmd_line.AppendSwitchPath("database", database_dir_.GetPath());
62
63 base::LaunchOptions options;
64 options.start_hidden = true;
65 base::Process test_child = base::SpawnMultiProcessTestChild(
66 "FallbackCrashHandlingWinRunHandler", cmd_line, options);
67
68 ASSERT_TRUE(test_child.IsValid());
69 int exit_code = -1;
70 ASSERT_TRUE(test_child.WaitForExit(&exit_code));
71 ASSERT_EQ(kFallbackCrashTerminationCode, static_cast<uint32_t>(exit_code));
72
73 // Validate that the database contains one valid crash dump.
74 std::unique_ptr<crashpad::CrashReportDatabase> database =
75 crashpad::CrashReportDatabase::InitializeWithoutCreating(
76 database_dir_.GetPath());
77
78 std::vector<crashpad::CrashReportDatabase::Report> reports;
79 ASSERT_EQ(crashpad::CrashReportDatabase::kNoError,
80 database->GetPendingReports(&reports));
81
82 EXPECT_EQ(1U, reports.size());
83 }
84
85 } // namespace crash_reporter
86