Chromium Code Reviews| Index: components/browser_watcher/stability_debugging_win_unittest.cc |
| diff --git a/components/browser_watcher/stability_debugging_win_unittest.cc b/components/browser_watcher/stability_debugging_win_unittest.cc |
| index 785ab22be786ae76ef070fc2edefc51a53ea74d0..345072122aa7d2cc68a5062bb274399b7aef19bc 100644 |
| --- a/components/browser_watcher/stability_debugging_win_unittest.cc |
| +++ b/components/browser_watcher/stability_debugging_win_unittest.cc |
| @@ -4,84 +4,88 @@ |
| #include "components/browser_watcher/stability_debugging.h" |
| -#include "base/files/file_enumerator.h" |
| +#include <windows.h> |
| + |
| +#include "base/command_line.h" |
| +#include "base/debug/activity_tracker.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/process/process.h" |
| #include "base/test/multiprocess_test.h" |
| -#include "components/browser_watcher/stability_paths.h" |
| +#include "base/test/test_timeouts.h" |
| +#include "components/browser_watcher/stability_report.pb.h" |
| +#include "components/browser_watcher/stability_report_extractor.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/multiprocess_func_list.h" |
| namespace browser_watcher { |
| -class StabilityDebuggingWinMultiProcTest : public base::MultiProcessTest {}; |
| +using base::debug::GlobalActivityTracker; |
| -MULTIPROCESS_TEST_MAIN(DummyProcess) { |
| - return 0; |
| -} |
| +const int kMemorySize = 1 << 20; // 1MiB |
| +const char* kDebugFileSwitch = "stability_debugging_test_debug_file_switch"; |
| -TEST_F(StabilityDebuggingWinMultiProcTest, GetStabilityFileForProcessTest) { |
| - const base::FilePath empty_path; |
| - |
| - // Get the path for the current process. |
| - base::FilePath stability_path; |
| - ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path, |
| - &stability_path)); |
| - |
| - // Ensure requesting a second time produces the same. |
| - base::FilePath stability_path_two; |
| - ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path, |
| - &stability_path_two)); |
| - EXPECT_EQ(stability_path, stability_path_two); |
| - |
| - // Ensure a different process has a different stability path. |
| - base::SpawnChildResult spawn_result = SpawnChild("DummyProcess"); |
| - base::FilePath stability_path_other; |
| - ASSERT_TRUE(GetStabilityFileForProcess(spawn_result.process, empty_path, |
| - &stability_path_other)); |
| - EXPECT_NE(stability_path, stability_path_other); |
| -} |
| +class StabilityDebuggingTest : public base::MultiProcessTest { |
| + public: |
| + StabilityDebuggingTest() {} |
| + ~StabilityDebuggingTest() override = default; |
| + |
| + void SetUp() override { |
| + testing::Test::SetUp(); |
| -TEST(StabilityDebuggingWinTest, |
| - GetStabilityFilePatternMatchesGetStabilityFileForProcessResult) { |
| - // GetStabilityFileForProcess file names must match GetStabilityFilePattern |
| - // according to |
| - // FileEnumerator's algorithm. We test this by writing out some files and |
| - // validating what is matched. |
| - |
| - base::ScopedTempDir temp_dir; |
| - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| - base::FilePath user_data_dir = temp_dir.GetPath(); |
| - |
| - // Create the stability directory. |
| - base::FilePath stability_dir = GetStabilityDir(user_data_dir); |
| - ASSERT_TRUE(base::CreateDirectory(stability_dir)); |
| - |
| - // Write a stability file. |
| - base::FilePath stability_file; |
| - ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), |
| - user_data_dir, &stability_file)); |
| - { |
| - base::ScopedFILE file(base::OpenFile(stability_file, "w")); |
| - ASSERT_TRUE(file.get()); |
| + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| + debug_file_path_ = temp_dir_.GetPath().AppendASCII("debug.pma"); |
| } |
| - // Write a file that shouldn't match. |
| - base::FilePath non_matching_file = |
| - stability_dir.AppendASCII("non_matching.foo"); |
| - { |
| - base::ScopedFILE file(base::OpenFile(non_matching_file, "w")); |
| - ASSERT_TRUE(file.get()); |
| + const base::FilePath& debug_file_path() { return debug_file_path_; } |
| + |
| + protected: |
| + base::CommandLine MakeCmdLine(const std::string& procname) override { |
| + base::CommandLine cmd = base::MultiProcessTest::MakeCmdLine(procname); |
| + cmd.AppendSwitchPath(kDebugFileSwitch, debug_file_path_); |
| + return cmd; |
| } |
| - // Validate only the stability file matches. |
| - base::FileEnumerator enumerator(stability_dir, false /* recursive */, |
| - base::FileEnumerator::FILES, |
| - GetStabilityFilePattern()); |
| - ASSERT_EQ(stability_file, enumerator.Next()); |
| - ASSERT_TRUE(enumerator.Next().empty()); |
| + base::ScopedTempDir temp_dir_; |
| + base::FilePath debug_file_path_; |
| +}; |
| + |
| +// Creates a global tracker, registers a vectored exception handler, then |
| +// crashes. |
| +MULTIPROCESS_TEST_MAIN(CrashingProcess) { |
| + base::FilePath debug_path = |
| + base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( |
| + kDebugFileSwitch); |
| + GlobalActivityTracker::CreateWithFile(debug_path, kMemorySize, 0ULL, "", 3); |
| + RegisterStabilityVEH(); |
| + |
| + // Crash! |
| + char* invalid = nullptr; |
|
Sigurður Ásgeirsson
2017/06/09 13:55:15
I'm not sure the compiler is obliged to honor your
manzagop (departed)
2017/06/09 21:27:35
Switched to a single process test, as that's simpl
|
| + *invalid = 42; |
| + |
| + return 0; |
| +} |
| + |
| +TEST_F(StabilityDebuggingTest, CrashingTest) { |
| + base::SpawnChildResult spawn_result = SpawnChild("CrashingProcess"); |
| + int exit_code; |
| + EXPECT_TRUE(spawn_result.process.WaitForExitWithTimeout( |
| + TestTimeouts::action_max_timeout(), &exit_code)); |
| + |
| + // Collect the report. |
| + StabilityReport report; |
| + ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report)); |
| + |
| + // Validate expectations: 1 process with 1 thread that has an exception. |
|
Sigurður Ásgeirsson
2017/06/09 13:55:15
My bet is that this is going to flake a bit, as yo
manzagop (departed)
2017/06/09 21:27:35
Sgtm! Actually, I'm in the same thread it's easy t
|
| + ASSERT_EQ(1, report.process_states_size()); |
| + const ProcessState& process_state = report.process_states(0); |
| + EXPECT_EQ(spawn_result.process.Pid(), process_state.process_id()); |
| + ASSERT_EQ(1, process_state.threads_size()); |
| + const ThreadState& thread_state = process_state.threads(0); |
| + ASSERT_TRUE(thread_state.has_exception()); |
| + const Exception& exception = thread_state.exception(); |
| + EXPECT_EQ(EXCEPTION_ACCESS_VIOLATION, exception.code()); |
| } |
| } // namespace browser_watcher |