blob: 831cad660a818da2f76e158c589fab3125c13033 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/browser_watcher/stability_debugging.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 "base/test/test_timeouts.h"
#include "build/build_config.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 {
using base::debug::GlobalActivityTracker;
const int kMemorySize = 1 << 20; // 1MiB
const uint32_t exception_code = 42U;
const uint32_t exception_flag_continuable = 0U;
class StabilityDebuggingTest : public testing::Test {
public:
StabilityDebuggingTest() {}
~StabilityDebuggingTest() override {
GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
if (global_tracker) {
global_tracker->ReleaseTrackerForCurrentThreadForTesting();
delete global_tracker;
}
}
void SetUp() override {
testing::Test::SetUp();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
debug_path_ = temp_dir_.GetPath().AppendASCII("debug.pma");
GlobalActivityTracker::CreateWithFile(debug_path_, kMemorySize, 0ULL, "",
3);
}
const base::FilePath& debug_path() { return debug_path_; }
private:
base::ScopedTempDir temp_dir_;
base::FilePath debug_path_;
};
#if defined(ADDRESS_SANITIZER) && defined(OS_WIN)
// The test does not pass under WinASan. See crbug.com/809524.
#define MAYBE_CrashingTest DISABLED_CrashingTest
#else
#define MAYBE_CrashingTest CrashingTest
#endif
TEST_F(StabilityDebuggingTest, MAYBE_CrashingTest) {
RegisterStabilityVEH();
// Raise an exception, then continue.
__try {
::RaiseException(exception_code, exception_flag_continuable, 0U, nullptr);
} __except (EXCEPTION_CONTINUE_EXECUTION) {
}
// Collect the report.
StabilityReport report;
ASSERT_EQ(SUCCESS, Extract(debug_path(), &report));
// Validate expectations.
ASSERT_EQ(1, report.process_states_size());
const ProcessState& process_state = report.process_states(0);
ASSERT_EQ(1, process_state.threads_size());
bool thread_found = false;
for (const ThreadState& thread : process_state.threads()) {
if (thread.thread_id() == ::GetCurrentThreadId()) {
thread_found = true;
ASSERT_TRUE(thread.has_exception());
const Exception& exception = thread.exception();
EXPECT_EQ(exception_code, exception.code());
EXPECT_NE(0ULL, exception.program_counter());
EXPECT_NE(0ULL, exception.exception_address());
EXPECT_NE(0LL, exception.time());
}
}
ASSERT_TRUE(thread_found);
}
} // namespace browser_watcher