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

Side by Side Diff: components/crash/content/app/fallback_crash_handler_win_unittest.cc

Issue 2637433002: Change the GenerateCrashDump test to use the launcher for end-to-end testing. (Closed)
Patch Set: Address Scott's naming nit. Created 3 years, 11 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 | « components/crash/content/app/fallback_crash_handler_win.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/crash/content/app/fallback_crash_handler_win.h" 5 #include "components/crash/content/app/fallback_crash_handler_win.h"
6 6
7 #include "base/base_switches.h"
7 #include "base/command_line.h" 8 #include "base/command_line.h"
8 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h" 10 #include "base/files/scoped_temp_dir.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
10 #include "base/process/process_handle.h" 13 #include "base/process/process_handle.h"
11 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/test/multiprocess_test.h"
12 #include "base/threading/platform_thread.h" 16 #include "base/threading/platform_thread.h"
13 #include "base/win/scoped_handle.h" 17 #include "base/win/scoped_handle.h"
14 #include "base/win/win_util.h" 18 #include "base/win/win_util.h"
19 #include "components/crash/content/app/fallback_crash_handler_launcher_win.h"
15 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "testing/multiprocess_func_list.h"
16 #include "third_party/crashpad/crashpad/client/crash_report_database.h" 22 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
17 #include "third_party/crashpad/crashpad/client/settings.h" 23 #include "third_party/crashpad/crashpad/client/settings.h"
18 #include "third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minid ump.h" 24 #include "third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minid ump.h"
19 #include "third_party/crashpad/crashpad/util/file/file_reader.h" 25 #include "third_party/crashpad/crashpad/util/file/file_reader.h"
20 #include "third_party/crashpad/crashpad/util/misc/uuid.h" 26 #include "third_party/crashpad/crashpad/util/misc/uuid.h"
21 27
22 namespace crash_reporter { 28 namespace crash_reporter {
23 29
24 namespace { 30 namespace {
25 31
26 class FallbackCrashHandlerWinTest : public testing::Test { 32 class ExceptionPointers {
27 public: 33 public:
28 FallbackCrashHandlerWinTest() : self_handle_(base::kNullProcessHandle) { 34 ExceptionPointers() {
29 RtlCaptureContext(&context_); 35 RtlCaptureContext(&context_);
30 memset(&exception_, 0, sizeof(exception_)); 36 memset(&exception_, 0, sizeof(exception_));
31 exception_.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; 37 exception_.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
32 38
33 exception_ptrs_.ExceptionRecord = &exception_; 39 exception_ptrs_.ExceptionRecord = &exception_;
34 exception_ptrs_.ContextRecord = &context_; 40 exception_ptrs_.ContextRecord = &context_;
35 } 41 }
36 42
43 EXCEPTION_POINTERS* exception_ptrs() { return &exception_ptrs_; }
44 std::string AsString() {
45 return base::Uint64ToString(reinterpret_cast<uintptr_t>(exception_ptrs()));
46 }
47
48 private:
49 CONTEXT context_;
50 EXCEPTION_RECORD exception_;
51 EXCEPTION_POINTERS exception_ptrs_;
52
53 DISALLOW_COPY_AND_ASSIGN(ExceptionPointers);
54 };
55
56 const char kProduct[] = "SomeProduct";
57 const char kVersion[] = "1.2.3.6";
58 const char kChannel[] = "canary";
59 const char kProcessType[] = "Test";
60
61 // This main function runs the handler to test.
62 MULTIPROCESS_TEST_MAIN(FallbackCrashHandlerWinRunHandler) {
63 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
64
65 FallbackCrashHandler handler;
66 CHECK(handler.ParseCommandLine(*cmd_line));
67 CHECK(handler.GenerateCrashDump(kProduct, kVersion, kChannel, kProcessType));
68
69 return 0;
70 }
71
72 // This main function runs the setup and generates the simulated crash.
73 MULTIPROCESS_TEST_MAIN(FallbackCrashHandlerWinMain) {
74 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
75
76 base::FilePath directory = cmd_line->GetSwitchValuePath("directory");
77 CHECK(!directory.empty());
78
79 base::CommandLine base_cmdline =
80 base::GetMultiProcessTestChildBaseCommandLine();
81 base_cmdline.AppendSwitchASCII(switches::kTestChildProcess,
82 "FallbackCrashHandlerWinRunHandler");
83
84 FallbackCrashHandlerLauncher launcher;
85 CHECK(launcher.Initialize(base_cmdline, directory));
86
87 ExceptionPointers exception_ptrs;
88 CHECK_EQ(0U,
89 launcher.LaunchAndWaitForHandler(exception_ptrs.exception_ptrs()));
90
91 return 0;
92 }
93
94 class FallbackCrashHandlerWinTest : public testing::Test {
95 public:
96 FallbackCrashHandlerWinTest() : self_handle_(base::kNullProcessHandle) {}
97
37 void SetUp() override { 98 void SetUp() override {
38 ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); 99 ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
39 100
40 // Open a handle to our own process. 101 // Open a handle to our own process.
41 const DWORD kAccessMask = 102 const DWORD kAccessMask =
42 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE; 103 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE;
43 self_handle_ = OpenProcess(kAccessMask, FALSE, base::GetCurrentProcId()); 104 self_handle_ = OpenProcess(kAccessMask, FALSE, base::GetCurrentProcId());
44 DWORD err = GetLastError(); 105 DWORD err = GetLastError();
45 EXPECT_NE(base::kNullProcessHandle, self_handle_) << "GetLastError: " 106 EXPECT_NE(base::kNullProcessHandle, self_handle_) << "GetLastError: "
46 << err; 107 << err;
47 } 108 }
48 109
49 void TearDown() override { 110 void TearDown() override {
50 if (self_handle_ != base::kNullProcessHandle) { 111 if (self_handle_ != base::kNullProcessHandle) {
51 CloseHandle(self_handle_); 112 CloseHandle(self_handle_);
52 self_handle_ = base::kNullProcessHandle; 113 self_handle_ = base::kNullProcessHandle;
53 } 114 }
54 } 115 }
55 116
56 std::string ExcPtrsAsString() const {
57 return base::Uint64ToString(reinterpret_cast<uintptr_t>(&exception_ptrs_));
58 };
59
60 std::string SelfHandleAsString() const { 117 std::string SelfHandleAsString() const {
61 return base::UintToString(base::win::HandleToUint32(self_handle_)); 118 return base::UintToString(base::win::HandleToUint32(self_handle_));
62 }; 119 };
63 120
64 void CreateDatabase() { 121 void CreateDatabase() {
65 std::unique_ptr<crashpad::CrashReportDatabase> database = 122 std::unique_ptr<crashpad::CrashReportDatabase> database =
66 crashpad::CrashReportDatabase::InitializeWithoutCreating( 123 crashpad::CrashReportDatabase::InitializeWithoutCreating(
67 database_dir_.GetPath()); 124 database_dir_.GetPath());
68 } 125 }
69 126
70 protected: 127 protected:
71 CONTEXT context_;
72 EXCEPTION_RECORD exception_;
73 EXCEPTION_POINTERS exception_ptrs_;
74
75 base::ProcessHandle self_handle_; 128 base::ProcessHandle self_handle_;
76 base::ScopedTempDir database_dir_; 129 base::ScopedTempDir database_dir_;
77 130
78 DISALLOW_COPY_AND_ASSIGN(FallbackCrashHandlerWinTest); 131 DISALLOW_COPY_AND_ASSIGN(FallbackCrashHandlerWinTest);
79 }; 132 };
80 133
81 } // namespace 134 } // namespace
82 135
83 TEST_F(FallbackCrashHandlerWinTest, ParseCommandLine) { 136 TEST_F(FallbackCrashHandlerWinTest, ParseCommandLine) {
84 FallbackCrashHandler handler; 137 FallbackCrashHandler handler;
85 138
86 // An empty command line shouldn't work. 139 // An empty command line shouldn't work.
87 base::CommandLine cmd_line(base::FilePath(L"empty")); 140 base::CommandLine cmd_line(base::FilePath(L"empty"));
88 ASSERT_FALSE(handler.ParseCommandLine(cmd_line)); 141 ASSERT_FALSE(handler.ParseCommandLine(cmd_line));
89 142
143 ExceptionPointers exception_ptrs;
90 cmd_line.AppendSwitchPath("database", database_dir_.GetPath()); 144 cmd_line.AppendSwitchPath("database", database_dir_.GetPath());
91 cmd_line.AppendSwitchASCII("exception-pointers", ExcPtrsAsString()); 145 cmd_line.AppendSwitchASCII("exception-pointers", exception_ptrs.AsString());
92 cmd_line.AppendSwitchASCII("process", SelfHandleAsString()); 146 cmd_line.AppendSwitchASCII("process", SelfHandleAsString());
93 147
94 // Thread missing, still should fail. 148 // Thread missing, still should fail.
95 ASSERT_FALSE(handler.ParseCommandLine(cmd_line)); 149 ASSERT_FALSE(handler.ParseCommandLine(cmd_line));
96 150
97 cmd_line.AppendSwitchASCII( 151 cmd_line.AppendSwitchASCII(
98 "thread", base::UintToString(base::PlatformThread::CurrentId())); 152 "thread", base::UintToString(base::PlatformThread::CurrentId()));
99 153
100 // Should succeed with a fully populated command line. 154 // Should succeed with a fully populated command line.
101 // Because of how handle ownership is guarded, we have to "disown" it before 155 // Because of how handle ownership is guarded, we have to "disown" it before
102 // the handler takes it over. 156 // the handler takes it over.
103 EXPECT_TRUE(handler.ParseCommandLine(cmd_line)); 157 EXPECT_TRUE(handler.ParseCommandLine(cmd_line));
104 self_handle_ = base::kNullProcessHandle; 158 self_handle_ = base::kNullProcessHandle;
105 } 159 }
106 160
107 TEST_F(FallbackCrashHandlerWinTest, GenerateCrashDump) { 161 TEST_F(FallbackCrashHandlerWinTest, GenerateCrashDump) {
108 FallbackCrashHandler handler; 162 base::CommandLine cmd_line = base::GetMultiProcessTestChildBaseCommandLine();
163 cmd_line.AppendSwitchPath("directory", database_dir_.GetPath());
164 base::LaunchOptions options;
165 options.start_hidden = true;
166 base::Process test_child = base::SpawnMultiProcessTestChild(
167 "FallbackCrashHandlerWinMain", cmd_line, options);
109 168
110 base::CommandLine cmd_line(base::FilePath(L"empty")); 169 ASSERT_TRUE(test_child.IsValid());
111 cmd_line.AppendSwitchPath("database", database_dir_.GetPath()); 170 int exit_code = -1;
112 cmd_line.AppendSwitchASCII("exception-pointers", ExcPtrsAsString()); 171 ASSERT_TRUE(test_child.WaitForExit(&exit_code));
113 172 ASSERT_EQ(0, exit_code);
114 cmd_line.AppendSwitchASCII("process", SelfHandleAsString());
115 cmd_line.AppendSwitchASCII(
116 "thread", base::UintToString(base::PlatformThread::CurrentId()));
117
118 // Because how handle ownership is guarded, we have to "disown" this before
119 // the handler takes it over.
120 ASSERT_TRUE(handler.ParseCommandLine(cmd_line));
121 self_handle_ = base::kNullProcessHandle;
122
123 const char kProduct[] = "SomeProduct";
124 const char kVersion[] = "1.2.3.6";
125 const char kChannel[] = "canary";
126 const char kProcessType[] = "Test";
127
128 // TODO(siggi): If this ends up being flakey, spin the testing out to a
129 // a separate process, which can in turn use the
130 // FallbackCrashHandlerLauncher class to spin a third process to grab
131 // a dump.
132 EXPECT_TRUE(
133 handler.GenerateCrashDump(kProduct, kVersion, kChannel, kProcessType));
134 173
135 // Validate that the database contains one valid crash dump. 174 // Validate that the database contains one valid crash dump.
136 std::unique_ptr<crashpad::CrashReportDatabase> database = 175 std::unique_ptr<crashpad::CrashReportDatabase> database =
137 crashpad::CrashReportDatabase::InitializeWithoutCreating( 176 crashpad::CrashReportDatabase::InitializeWithoutCreating(
138 database_dir_.GetPath()); 177 database_dir_.GetPath());
139 178
140 std::vector<crashpad::CrashReportDatabase::Report> reports; 179 std::vector<crashpad::CrashReportDatabase::Report> reports;
141 ASSERT_EQ(crashpad::CrashReportDatabase::kNoError, 180 ASSERT_EQ(crashpad::CrashReportDatabase::kNoError,
142 database->GetPendingReports(&reports)); 181 database->GetPendingReports(&reports));
143 182
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 #else 223 #else
185 EXPECT_EQ("Win32", it->second); 224 EXPECT_EQ("Win32", it->second);
186 #endif 225 #endif
187 226
188 it = parameters.find("ptype"); 227 it = parameters.find("ptype");
189 EXPECT_NE(parameters.end(), it); 228 EXPECT_NE(parameters.end(), it);
190 EXPECT_EQ(kProcessType, it->second); 229 EXPECT_EQ(kProcessType, it->second);
191 } 230 }
192 231
193 } // namespace crash_reporter 232 } // namespace crash_reporter
OLDNEW
« no previous file with comments | « components/crash/content/app/fallback_crash_handler_win.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698