1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/threading/hang_watcher.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <atomic>
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <optional>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/barrier_closure.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial_params.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/test/bind.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/test/metrics/histogram_tester.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/test/power_monitor_test.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/test/simple_test_tick_clock.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/test/test_timeouts.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/threading/threading_features.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/time/tick_clock.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
33*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
34*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
35*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker using testing::ElementsAre;
38*6777b538SAndroid Build Coastguard Worker using testing::IsEmpty;
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker namespace base {
41*6777b538SAndroid Build Coastguard Worker namespace {
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker // Use with a FeatureList to activate crash dumping for threads marked as
44*6777b538SAndroid Build Coastguard Worker // threadpool threads.
45*6777b538SAndroid Build Coastguard Worker const std::vector<base::test::FeatureRefAndParams> kFeatureAndParams{
46*6777b538SAndroid Build Coastguard Worker {base::kEnableHangWatcher, {{"ui_thread_log_level", "2"}}}};
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker // Use this value to mark things very far off in the future. Adding this
49*6777b538SAndroid Build Coastguard Worker // to TimeTicks::Now() gives a point that will never be reached during the
50*6777b538SAndroid Build Coastguard Worker // normal execution of a test.
51*6777b538SAndroid Build Coastguard Worker constexpr TimeDelta kVeryLongDelta{base::Days(365)};
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker // A relatively small time delta to ensure ordering of hung threads list.
54*6777b538SAndroid Build Coastguard Worker constexpr TimeDelta kSmallCPUQuantum{base::Milliseconds(1)};
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kArbitraryDeadline = 0x0000C0FFEEC0FFEEu;
57*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kAllOnes = 0xFFFFFFFFFFFFFFFFu;
58*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kAllZeros = 0x0000000000000000u;
59*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kOnesThenZeroes = 0xAAAAAAAAAAAAAAAAu;
60*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kZeroesThenOnes = 0x5555555555555555u;
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
63*6777b538SAndroid Build Coastguard Worker class HangWatcherEnabledInZygoteChildTest
64*6777b538SAndroid Build Coastguard Worker : public testing::TestWithParam<std::tuple<bool, bool>> {
65*6777b538SAndroid Build Coastguard Worker public:
HangWatcherEnabledInZygoteChildTest()66*6777b538SAndroid Build Coastguard Worker HangWatcherEnabledInZygoteChildTest() {
67*6777b538SAndroid Build Coastguard Worker std::vector<base::test::FeatureRefAndParams> enabled_features =
68*6777b538SAndroid Build Coastguard Worker kFeatureAndParams;
69*6777b538SAndroid Build Coastguard Worker std::vector<test::FeatureRef> disabled_features;
70*6777b538SAndroid Build Coastguard Worker if (std::get<0>(GetParam())) {
71*6777b538SAndroid Build Coastguard Worker enabled_features.push_back(test::FeatureRefAndParams(
72*6777b538SAndroid Build Coastguard Worker base::kEnableHangWatcherInZygoteChildren, {}));
73*6777b538SAndroid Build Coastguard Worker } else {
74*6777b538SAndroid Build Coastguard Worker disabled_features.push_back(base::kEnableHangWatcherInZygoteChildren);
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker feature_list_.InitWithFeaturesAndParameters(enabled_features,
77*6777b538SAndroid Build Coastguard Worker disabled_features);
78*6777b538SAndroid Build Coastguard Worker HangWatcher::InitializeOnMainThread(
79*6777b538SAndroid Build Coastguard Worker HangWatcher::ProcessType::kUtilityProcess,
80*6777b538SAndroid Build Coastguard Worker /*is_zygote_child=*/std::get<1>(GetParam()),
81*6777b538SAndroid Build Coastguard Worker /*emit_crashes=*/true);
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
TearDown()84*6777b538SAndroid Build Coastguard Worker void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker HangWatcherEnabledInZygoteChildTest(
87*6777b538SAndroid Build Coastguard Worker const HangWatcherEnabledInZygoteChildTest& other) = delete;
88*6777b538SAndroid Build Coastguard Worker HangWatcherEnabledInZygoteChildTest& operator=(
89*6777b538SAndroid Build Coastguard Worker const HangWatcherEnabledInZygoteChildTest& other) = delete;
90*6777b538SAndroid Build Coastguard Worker
91*6777b538SAndroid Build Coastguard Worker protected:
92*6777b538SAndroid Build Coastguard Worker base::test::ScopedFeatureList feature_list_;
93*6777b538SAndroid Build Coastguard Worker };
94*6777b538SAndroid Build Coastguard Worker
TEST_P(HangWatcherEnabledInZygoteChildTest,IsEnabled)95*6777b538SAndroid Build Coastguard Worker TEST_P(HangWatcherEnabledInZygoteChildTest, IsEnabled) {
96*6777b538SAndroid Build Coastguard Worker // If the kEnableHangWatcherInZygoteChildren feature is disabled and
97*6777b538SAndroid Build Coastguard Worker // InitializeOnMainThread is called with is_zygote_child==true, IsEnabled()
98*6777b538SAndroid Build Coastguard Worker // should return false. It should return true in all other situations.
99*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(std::get<0>(GetParam()) || !std::get<1>(GetParam()),
100*6777b538SAndroid Build Coastguard Worker HangWatcher::IsEnabled());
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(HangWatcherZygoteTest,
104*6777b538SAndroid Build Coastguard Worker HangWatcherEnabledInZygoteChildTest,
105*6777b538SAndroid Build Coastguard Worker testing::Combine(testing::Bool(), testing::Bool()));
106*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker // Waits on provided WaitableEvent before executing and signals when done.
109*6777b538SAndroid Build Coastguard Worker class BlockingThread : public DelegateSimpleThread::Delegate {
110*6777b538SAndroid Build Coastguard Worker public:
BlockingThread(base::WaitableEvent * unblock_thread,base::TimeDelta timeout)111*6777b538SAndroid Build Coastguard Worker explicit BlockingThread(base::WaitableEvent* unblock_thread,
112*6777b538SAndroid Build Coastguard Worker base::TimeDelta timeout)
113*6777b538SAndroid Build Coastguard Worker : thread_(this, "BlockingThread"),
114*6777b538SAndroid Build Coastguard Worker unblock_thread_(unblock_thread),
115*6777b538SAndroid Build Coastguard Worker timeout_(timeout) {}
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker ~BlockingThread() override = default;
118*6777b538SAndroid Build Coastguard Worker
Run()119*6777b538SAndroid Build Coastguard Worker void Run() override {
120*6777b538SAndroid Build Coastguard Worker // (Un)Register the thread here instead of in ctor/dtor so that the action
121*6777b538SAndroid Build Coastguard Worker // happens on the right thread.
122*6777b538SAndroid Build Coastguard Worker base::ScopedClosureRunner unregister_closure =
123*6777b538SAndroid Build Coastguard Worker base::HangWatcher::RegisterThread(
124*6777b538SAndroid Build Coastguard Worker base::HangWatcher::ThreadType::kMainThread);
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker WatchHangsInScope scope(timeout_);
127*6777b538SAndroid Build Coastguard Worker wait_until_entered_scope_.Signal();
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker unblock_thread_->Wait();
130*6777b538SAndroid Build Coastguard Worker run_event_.Signal();
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker
IsDone()133*6777b538SAndroid Build Coastguard Worker bool IsDone() { return run_event_.IsSignaled(); }
134*6777b538SAndroid Build Coastguard Worker
StartAndWaitForScopeEntered()135*6777b538SAndroid Build Coastguard Worker void StartAndWaitForScopeEntered() {
136*6777b538SAndroid Build Coastguard Worker thread_.Start();
137*6777b538SAndroid Build Coastguard Worker // Block until this thread registered itself for hang watching and has
138*6777b538SAndroid Build Coastguard Worker // entered a WatchHangsInScope.
139*6777b538SAndroid Build Coastguard Worker wait_until_entered_scope_.Wait();
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker
Join()142*6777b538SAndroid Build Coastguard Worker void Join() { thread_.Join(); }
143*6777b538SAndroid Build Coastguard Worker
GetId()144*6777b538SAndroid Build Coastguard Worker PlatformThreadId GetId() { return thread_.tid(); }
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker private:
147*6777b538SAndroid Build Coastguard Worker base::DelegateSimpleThread thread_;
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker // Will be signaled once the thread is properly registered for watching and
150*6777b538SAndroid Build Coastguard Worker // the WatchHangsInScope has been entered.
151*6777b538SAndroid Build Coastguard Worker WaitableEvent wait_until_entered_scope_;
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker // Will be signaled once ThreadMain has run.
154*6777b538SAndroid Build Coastguard Worker WaitableEvent run_event_;
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker const raw_ptr<base::WaitableEvent> unblock_thread_;
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker base::TimeDelta timeout_;
159*6777b538SAndroid Build Coastguard Worker };
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker class HangWatcherTest : public testing::Test {
162*6777b538SAndroid Build Coastguard Worker public:
163*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kTimeout = base::Seconds(10);
164*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kHangTime = kTimeout + base::Seconds(1);
165*6777b538SAndroid Build Coastguard Worker
HangWatcherTest()166*6777b538SAndroid Build Coastguard Worker HangWatcherTest() {
167*6777b538SAndroid Build Coastguard Worker feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
168*6777b538SAndroid Build Coastguard Worker HangWatcher::InitializeOnMainThread(
169*6777b538SAndroid Build Coastguard Worker HangWatcher::ProcessType::kBrowserProcess, false,
170*6777b538SAndroid Build Coastguard Worker /*emit_crashes=*/true);
171*6777b538SAndroid Build Coastguard Worker
172*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(base::BindRepeating(
173*6777b538SAndroid Build Coastguard Worker &WaitableEvent::Signal, base::Unretained(&monitor_event_)));
174*6777b538SAndroid Build Coastguard Worker
175*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetOnHangClosureForTesting(base::BindRepeating(
176*6777b538SAndroid Build Coastguard Worker &WaitableEvent::Signal, base::Unretained(&hang_event_)));
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker // We're not testing the monitoring loop behavior in this test so we want to
179*6777b538SAndroid Build Coastguard Worker // trigger monitoring manually.
180*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker // Start the monitoring loop.
183*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
TearDown()186*6777b538SAndroid Build Coastguard Worker void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker HangWatcherTest(const HangWatcherTest& other) = delete;
189*6777b538SAndroid Build Coastguard Worker HangWatcherTest& operator=(const HangWatcherTest& other) = delete;
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker protected:
192*6777b538SAndroid Build Coastguard Worker // Used to wait for monitoring. Will be signaled by the HangWatcher thread and
193*6777b538SAndroid Build Coastguard Worker // so needs to outlive it.
194*6777b538SAndroid Build Coastguard Worker WaitableEvent monitor_event_;
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker // Signaled from the HangWatcher thread when a hang is detected. Needs to
197*6777b538SAndroid Build Coastguard Worker // outlive the HangWatcher thread.
198*6777b538SAndroid Build Coastguard Worker WaitableEvent hang_event_;
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker base::test::ScopedFeatureList feature_list_;
201*6777b538SAndroid Build Coastguard Worker
202*6777b538SAndroid Build Coastguard Worker // Used exclusively for MOCK_TIME. No tasks will be run on the environment.
203*6777b538SAndroid Build Coastguard Worker // Single threaded to avoid ThreadPool WorkerThreads registering.
204*6777b538SAndroid Build Coastguard Worker test::SingleThreadTaskEnvironment task_environment_{
205*6777b538SAndroid Build Coastguard Worker test::TaskEnvironment::TimeSource::MOCK_TIME};
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker // This must be declared last (after task_environment_, for example) so that
208*6777b538SAndroid Build Coastguard Worker // the watcher thread is joined before objects like the mock timer are
209*6777b538SAndroid Build Coastguard Worker // destroyed, causing racy crashes.
210*6777b538SAndroid Build Coastguard Worker HangWatcher hang_watcher_;
211*6777b538SAndroid Build Coastguard Worker };
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker class HangWatcherBlockingThreadTest : public HangWatcherTest {
214*6777b538SAndroid Build Coastguard Worker public:
HangWatcherBlockingThreadTest()215*6777b538SAndroid Build Coastguard Worker HangWatcherBlockingThreadTest() : thread_(&unblock_thread_, kTimeout) {}
216*6777b538SAndroid Build Coastguard Worker
217*6777b538SAndroid Build Coastguard Worker HangWatcherBlockingThreadTest(const HangWatcherBlockingThreadTest& other) =
218*6777b538SAndroid Build Coastguard Worker delete;
219*6777b538SAndroid Build Coastguard Worker HangWatcherBlockingThreadTest& operator=(
220*6777b538SAndroid Build Coastguard Worker const HangWatcherBlockingThreadTest& other) = delete;
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker protected:
JoinThread()223*6777b538SAndroid Build Coastguard Worker void JoinThread() {
224*6777b538SAndroid Build Coastguard Worker unblock_thread_.Signal();
225*6777b538SAndroid Build Coastguard Worker
226*6777b538SAndroid Build Coastguard Worker // Thread is joinable since we signaled |unblock_thread_|.
227*6777b538SAndroid Build Coastguard Worker thread_.Join();
228*6777b538SAndroid Build Coastguard Worker
229*6777b538SAndroid Build Coastguard Worker // If thread is done then it signaled.
230*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(thread_.IsDone());
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker
StartBlockedThread()233*6777b538SAndroid Build Coastguard Worker void StartBlockedThread() {
234*6777b538SAndroid Build Coastguard Worker // Thread has not run yet.
235*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(thread_.IsDone());
236*6777b538SAndroid Build Coastguard Worker
237*6777b538SAndroid Build Coastguard Worker // Start the thread. It will block since |unblock_thread_| was not
238*6777b538SAndroid Build Coastguard Worker // signaled yet.
239*6777b538SAndroid Build Coastguard Worker thread_.StartAndWaitForScopeEntered();
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker // Thread registration triggered a call to HangWatcher::Monitor() which
242*6777b538SAndroid Build Coastguard Worker // signaled |monitor_event_|. Reset it so it's ready for waiting later on.
243*6777b538SAndroid Build Coastguard Worker monitor_event_.Reset();
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker
MonitorHangs()246*6777b538SAndroid Build Coastguard Worker void MonitorHangs() {
247*6777b538SAndroid Build Coastguard Worker // HangWatcher::Monitor() should not be set which would mean a call to
248*6777b538SAndroid Build Coastguard Worker // HangWatcher::Monitor() happened and was unacounted for.
249*6777b538SAndroid Build Coastguard Worker // ASSERT_FALSE(monitor_event_.IsSignaled());
250*6777b538SAndroid Build Coastguard Worker
251*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
252*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
253*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
254*6777b538SAndroid Build Coastguard Worker }
255*6777b538SAndroid Build Coastguard Worker
256*6777b538SAndroid Build Coastguard Worker // Used to unblock the monitored thread. Signaled from the test main thread.
257*6777b538SAndroid Build Coastguard Worker WaitableEvent unblock_thread_;
258*6777b538SAndroid Build Coastguard Worker
259*6777b538SAndroid Build Coastguard Worker BlockingThread thread_;
260*6777b538SAndroid Build Coastguard Worker };
261*6777b538SAndroid Build Coastguard Worker } // namespace
262*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherTest,InvalidatingExpectationsPreventsCapture)263*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest, InvalidatingExpectationsPreventsCapture) {
264*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
265*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
266*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker // Create a hang.
269*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
270*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
271*6777b538SAndroid Build Coastguard Worker
272*6777b538SAndroid Build Coastguard Worker // de-activate hang watching,
273*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
276*6777b538SAndroid Build Coastguard Worker // Hang is not detected.
277*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
278*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
279*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
280*6777b538SAndroid Build Coastguard Worker }
281*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherTest,MultipleInvalidateExpectationsDoNotCancelOut)282*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest, MultipleInvalidateExpectationsDoNotCancelOut) {
283*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
284*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
285*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker // Create a hang.
288*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
289*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
290*6777b538SAndroid Build Coastguard Worker
291*6777b538SAndroid Build Coastguard Worker // de-activate hang watching,
292*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
293*6777b538SAndroid Build Coastguard Worker
294*6777b538SAndroid Build Coastguard Worker // Redundently de-activate hang watching.
295*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
296*6777b538SAndroid Build Coastguard Worker
297*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
298*6777b538SAndroid Build Coastguard Worker // Hang is not detected.
299*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
300*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
301*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
302*6777b538SAndroid Build Coastguard Worker }
303*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherTest,NewInnerWatchHangsInScopeAfterInvalidationDetectsHang)304*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest, NewInnerWatchHangsInScopeAfterInvalidationDetectsHang) {
305*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
306*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
307*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
310*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker // De-activate hang watching.
313*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
314*6777b538SAndroid Build Coastguard Worker
315*6777b538SAndroid Build Coastguard Worker {
316*6777b538SAndroid Build Coastguard Worker WatchHangsInScope also_expires_instantly(base::TimeDelta{});
317*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
320*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
321*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
322*6777b538SAndroid Build Coastguard Worker
323*6777b538SAndroid Build Coastguard Worker // Hang is detected since the new WatchHangsInScope temporarily
324*6777b538SAndroid Build Coastguard Worker // re-activated hang_watching.
325*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
326*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(hang_event_.IsSignaled());
327*6777b538SAndroid Build Coastguard Worker }
328*6777b538SAndroid Build Coastguard Worker
329*6777b538SAndroid Build Coastguard Worker // Reset to attempt capture again.
330*6777b538SAndroid Build Coastguard Worker monitor_event_.Reset();
331*6777b538SAndroid Build Coastguard Worker hang_event_.Reset();
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
334*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
335*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
336*6777b538SAndroid Build Coastguard Worker
337*6777b538SAndroid Build Coastguard Worker // Hang is not detected since execution is back to being covered by
338*6777b538SAndroid Build Coastguard Worker // |expires_instantly| for which expectations were invalidated.
339*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
340*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherTest,NewSeparateWatchHangsInScopeAfterInvalidationDetectsHang)343*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest,
344*6777b538SAndroid Build Coastguard Worker NewSeparateWatchHangsInScopeAfterInvalidationDetectsHang) {
345*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
346*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
347*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker {
350*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
351*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Worker // De-activate hang watching.
354*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker WatchHangsInScope also_expires_instantly(base::TimeDelta{});
358*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
359*6777b538SAndroid Build Coastguard Worker
360*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
361*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
362*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker // Hang is detected since the new WatchHangsInScope did not have its
365*6777b538SAndroid Build Coastguard Worker // expectations invalidated.
366*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
367*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(hang_event_.IsSignaled());
368*6777b538SAndroid Build Coastguard Worker }
369*6777b538SAndroid Build Coastguard Worker
370*6777b538SAndroid Build Coastguard Worker // Test that invalidating expectations from inner WatchHangsInScope will also
371*6777b538SAndroid Build Coastguard Worker // prevent hang detection in outer scopes.
TEST_F(HangWatcherTest,ScopeDisabledObjectInnerScope)372*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
373*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
374*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
375*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
376*6777b538SAndroid Build Coastguard Worker
377*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires right away. Then advance
378*6777b538SAndroid Build Coastguard Worker // time to make sure no hang is detected.
379*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
380*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
381*6777b538SAndroid Build Coastguard Worker {
382*6777b538SAndroid Build Coastguard Worker WatchHangsInScope also_expires_instantly(base::TimeDelta{});
383*6777b538SAndroid Build Coastguard Worker
384*6777b538SAndroid Build Coastguard Worker // De-activate hang watching.
385*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
386*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker
389*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
390*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
391*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
392*6777b538SAndroid Build Coastguard Worker
393*6777b538SAndroid Build Coastguard Worker // Hang is ignored since it concerns a scope for which one of the inner scope
394*6777b538SAndroid Build Coastguard Worker // was ignored.
395*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
396*6777b538SAndroid Build Coastguard Worker }
397*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherTest,NewScopeAfterDisabling)398*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest, NewScopeAfterDisabling) {
399*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
400*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
401*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
402*6777b538SAndroid Build Coastguard Worker
403*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires right away. Then advance
404*6777b538SAndroid Build Coastguard Worker // time to make sure no hang is detected.
405*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
406*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
407*6777b538SAndroid Build Coastguard Worker {
408*6777b538SAndroid Build Coastguard Worker WatchHangsInScope also_expires_instantly(base::TimeDelta{});
409*6777b538SAndroid Build Coastguard Worker
410*6777b538SAndroid Build Coastguard Worker // De-activate hang watching.
411*6777b538SAndroid Build Coastguard Worker base::HangWatcher::InvalidateActiveExpectations();
412*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
413*6777b538SAndroid Build Coastguard Worker }
414*6777b538SAndroid Build Coastguard Worker
415*6777b538SAndroid Build Coastguard Worker // New scope for which expecations are never invalidated.
416*6777b538SAndroid Build Coastguard Worker WatchHangsInScope also_expires_instantly(base::TimeDelta{});
417*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
418*6777b538SAndroid Build Coastguard Worker
419*6777b538SAndroid Build Coastguard Worker // Trigger a monitoring on HangWatcher thread and verify results.
420*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
421*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
422*6777b538SAndroid Build Coastguard Worker
423*6777b538SAndroid Build Coastguard Worker // Hang is detected because it's unrelated to the hangs that were disabled.
424*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(hang_event_.IsSignaled());
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherTest,NestedScopes)427*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherTest, NestedScopes) {
428*6777b538SAndroid Build Coastguard Worker // Create a state object for the test thread since this test is single
429*6777b538SAndroid Build Coastguard Worker // threaded.
430*6777b538SAndroid Build Coastguard Worker auto current_hang_watch_state =
431*6777b538SAndroid Build Coastguard Worker base::internal::HangWatchState::CreateHangWatchStateForCurrentThread(
432*6777b538SAndroid Build Coastguard Worker HangWatcher::ThreadType::kMainThread);
433*6777b538SAndroid Build Coastguard Worker
434*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
435*6777b538SAndroid Build Coastguard Worker base::TimeTicks original_deadline = current_hang_watch_state->GetDeadline();
436*6777b538SAndroid Build Coastguard Worker
437*6777b538SAndroid Build Coastguard Worker constexpr base::TimeDelta kFirstTimeout(base::Milliseconds(500));
438*6777b538SAndroid Build Coastguard Worker base::TimeTicks first_deadline = base::TimeTicks::Now() + kFirstTimeout;
439*6777b538SAndroid Build Coastguard Worker
440*6777b538SAndroid Build Coastguard Worker constexpr base::TimeDelta kSecondTimeout(base::Milliseconds(250));
441*6777b538SAndroid Build Coastguard Worker base::TimeTicks second_deadline = base::TimeTicks::Now() + kSecondTimeout;
442*6777b538SAndroid Build Coastguard Worker
443*6777b538SAndroid Build Coastguard Worker // At this point we have not set any timeouts.
444*6777b538SAndroid Build Coastguard Worker {
445*6777b538SAndroid Build Coastguard Worker // Create a first timeout which is more restrictive than the default.
446*6777b538SAndroid Build Coastguard Worker WatchHangsInScope first_scope(kFirstTimeout);
447*6777b538SAndroid Build Coastguard Worker
448*6777b538SAndroid Build Coastguard Worker // We are on mock time. There is no time advancement and as such no hangs.
449*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
450*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(current_hang_watch_state->GetDeadline(), first_deadline);
451*6777b538SAndroid Build Coastguard Worker {
452*6777b538SAndroid Build Coastguard Worker // Set a yet more restrictive deadline. Still no hang.
453*6777b538SAndroid Build Coastguard Worker WatchHangsInScope second_scope(kSecondTimeout);
454*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
455*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(current_hang_watch_state->GetDeadline(), second_deadline);
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker // First deadline we set should be restored.
458*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
459*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(current_hang_watch_state->GetDeadline(), first_deadline);
460*6777b538SAndroid Build Coastguard Worker }
461*6777b538SAndroid Build Coastguard Worker
462*6777b538SAndroid Build Coastguard Worker // Original deadline should now be restored.
463*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
464*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(current_hang_watch_state->GetDeadline(), original_deadline);
465*6777b538SAndroid Build Coastguard Worker }
466*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherBlockingThreadTest,HistogramsLoggedOnHang)467*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedOnHang) {
468*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
469*6777b538SAndroid Build Coastguard Worker StartBlockedThread();
470*6777b538SAndroid Build Coastguard Worker
471*6777b538SAndroid Build Coastguard Worker // Simulate hang.
472*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
473*6777b538SAndroid Build Coastguard Worker
474*6777b538SAndroid Build Coastguard Worker // First monitoring catches the hang and emits the histogram.
475*6777b538SAndroid Build Coastguard Worker MonitorHangs();
476*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
477*6777b538SAndroid Build Coastguard Worker "BrowserProcess.UIThread"),
478*6777b538SAndroid Build Coastguard Worker ElementsAre(base::Bucket(true, /*count=*/1)));
479*6777b538SAndroid Build Coastguard Worker
480*6777b538SAndroid Build Coastguard Worker // Reset to attempt capture again.
481*6777b538SAndroid Build Coastguard Worker hang_event_.Reset();
482*6777b538SAndroid Build Coastguard Worker monitor_event_.Reset();
483*6777b538SAndroid Build Coastguard Worker
484*6777b538SAndroid Build Coastguard Worker // Hang is logged again even if it would not trigger a crash dump.
485*6777b538SAndroid Build Coastguard Worker MonitorHangs();
486*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
487*6777b538SAndroid Build Coastguard Worker "BrowserProcess.UIThread"),
488*6777b538SAndroid Build Coastguard Worker ElementsAre(base::Bucket(true, /*count=*/2)));
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker // Thread types that are not monitored should not get any samples.
491*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
492*6777b538SAndroid Build Coastguard Worker "BrowserProcess.IOThread"),
493*6777b538SAndroid Build Coastguard Worker IsEmpty());
494*6777b538SAndroid Build Coastguard Worker JoinThread();
495*6777b538SAndroid Build Coastguard Worker }
496*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherBlockingThreadTest,HistogramsLoggedWithoutHangs)497*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedWithoutHangs) {
498*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
499*6777b538SAndroid Build Coastguard Worker StartBlockedThread();
500*6777b538SAndroid Build Coastguard Worker
501*6777b538SAndroid Build Coastguard Worker // No hang to catch so nothing is recorded.
502*6777b538SAndroid Build Coastguard Worker MonitorHangs();
503*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
504*6777b538SAndroid Build Coastguard Worker
505*6777b538SAndroid Build Coastguard Worker // A thread of type ThreadForTesting was monitored but didn't hang. This is
506*6777b538SAndroid Build Coastguard Worker // logged.
507*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
508*6777b538SAndroid Build Coastguard Worker "BrowserProcess.UIThread"),
509*6777b538SAndroid Build Coastguard Worker ElementsAre(base::Bucket(false, /*count=*/1)));
510*6777b538SAndroid Build Coastguard Worker
511*6777b538SAndroid Build Coastguard Worker // Thread types that are not monitored should not get any samples.
512*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
513*6777b538SAndroid Build Coastguard Worker "BrowserProcess.IOThread"),
514*6777b538SAndroid Build Coastguard Worker IsEmpty());
515*6777b538SAndroid Build Coastguard Worker JoinThread();
516*6777b538SAndroid Build Coastguard Worker }
517*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherBlockingThreadTest,Hang)518*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherBlockingThreadTest, Hang) {
519*6777b538SAndroid Build Coastguard Worker StartBlockedThread();
520*6777b538SAndroid Build Coastguard Worker
521*6777b538SAndroid Build Coastguard Worker // Simulate hang.
522*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
523*6777b538SAndroid Build Coastguard Worker
524*6777b538SAndroid Build Coastguard Worker // First monitoring catches and records the hang.
525*6777b538SAndroid Build Coastguard Worker MonitorHangs();
526*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(hang_event_.IsSignaled());
527*6777b538SAndroid Build Coastguard Worker
528*6777b538SAndroid Build Coastguard Worker JoinThread();
529*6777b538SAndroid Build Coastguard Worker }
530*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherBlockingThreadTest,HangAlreadyRecorded)531*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherBlockingThreadTest, HangAlreadyRecorded) {
532*6777b538SAndroid Build Coastguard Worker StartBlockedThread();
533*6777b538SAndroid Build Coastguard Worker
534*6777b538SAndroid Build Coastguard Worker // Simulate hang.
535*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kHangTime);
536*6777b538SAndroid Build Coastguard Worker
537*6777b538SAndroid Build Coastguard Worker // First monitoring catches and records the hang.
538*6777b538SAndroid Build Coastguard Worker MonitorHangs();
539*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(hang_event_.IsSignaled());
540*6777b538SAndroid Build Coastguard Worker
541*6777b538SAndroid Build Coastguard Worker // Reset to attempt capture again.
542*6777b538SAndroid Build Coastguard Worker hang_event_.Reset();
543*6777b538SAndroid Build Coastguard Worker monitor_event_.Reset();
544*6777b538SAndroid Build Coastguard Worker
545*6777b538SAndroid Build Coastguard Worker // Second monitoring does not record because a hang that was already recorded
546*6777b538SAndroid Build Coastguard Worker // is still live.
547*6777b538SAndroid Build Coastguard Worker MonitorHangs();
548*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
549*6777b538SAndroid Build Coastguard Worker
550*6777b538SAndroid Build Coastguard Worker JoinThread();
551*6777b538SAndroid Build Coastguard Worker }
552*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherBlockingThreadTest,NoHang)553*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherBlockingThreadTest, NoHang) {
554*6777b538SAndroid Build Coastguard Worker StartBlockedThread();
555*6777b538SAndroid Build Coastguard Worker
556*6777b538SAndroid Build Coastguard Worker // No hang to catch so nothing is recorded.
557*6777b538SAndroid Build Coastguard Worker MonitorHangs();
558*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
559*6777b538SAndroid Build Coastguard Worker
560*6777b538SAndroid Build Coastguard Worker JoinThread();
561*6777b538SAndroid Build Coastguard Worker }
562*6777b538SAndroid Build Coastguard Worker
563*6777b538SAndroid Build Coastguard Worker namespace {
564*6777b538SAndroid Build Coastguard Worker class HangWatcherSnapshotTest : public testing::Test {
565*6777b538SAndroid Build Coastguard Worker public:
SetUp()566*6777b538SAndroid Build Coastguard Worker void SetUp() override {
567*6777b538SAndroid Build Coastguard Worker feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
568*6777b538SAndroid Build Coastguard Worker HangWatcher::InitializeOnMainThread(
569*6777b538SAndroid Build Coastguard Worker HangWatcher::ProcessType::kBrowserProcess, false,
570*6777b538SAndroid Build Coastguard Worker /*emit_crashes=*/true);
571*6777b538SAndroid Build Coastguard Worker
572*6777b538SAndroid Build Coastguard Worker // The monitoring loop behavior is not verified in this test so we want to
573*6777b538SAndroid Build Coastguard Worker // trigger monitoring manually.
574*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
575*6777b538SAndroid Build Coastguard Worker }
576*6777b538SAndroid Build Coastguard Worker
TearDown()577*6777b538SAndroid Build Coastguard Worker void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
578*6777b538SAndroid Build Coastguard Worker
579*6777b538SAndroid Build Coastguard Worker HangWatcherSnapshotTest() = default;
580*6777b538SAndroid Build Coastguard Worker HangWatcherSnapshotTest(const HangWatcherSnapshotTest& other) = delete;
581*6777b538SAndroid Build Coastguard Worker HangWatcherSnapshotTest& operator=(const HangWatcherSnapshotTest& other) =
582*6777b538SAndroid Build Coastguard Worker delete;
583*6777b538SAndroid Build Coastguard Worker
584*6777b538SAndroid Build Coastguard Worker protected:
TriggerMonitorAndWaitForCompletion()585*6777b538SAndroid Build Coastguard Worker void TriggerMonitorAndWaitForCompletion() {
586*6777b538SAndroid Build Coastguard Worker monitor_event_.Reset();
587*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
588*6777b538SAndroid Build Coastguard Worker monitor_event_.Wait();
589*6777b538SAndroid Build Coastguard Worker }
590*6777b538SAndroid Build Coastguard Worker
591*6777b538SAndroid Build Coastguard Worker // Verify that a capture takes place and that at the time of the capture the
592*6777b538SAndroid Build Coastguard Worker // list of hung thread ids is correct.
TestIDList(const std::string & id_list)593*6777b538SAndroid Build Coastguard Worker void TestIDList(const std::string& id_list) {
594*6777b538SAndroid Build Coastguard Worker list_of_hung_thread_ids_during_capture_ = id_list;
595*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kSmallCPUQuantum);
596*6777b538SAndroid Build Coastguard Worker TriggerMonitorAndWaitForCompletion();
597*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(++reference_capture_count_, hang_capture_count_);
598*6777b538SAndroid Build Coastguard Worker }
599*6777b538SAndroid Build Coastguard Worker
600*6777b538SAndroid Build Coastguard Worker // Verify that even if hang monitoring takes place no hangs are detected.
ExpectNoCapture()601*6777b538SAndroid Build Coastguard Worker void ExpectNoCapture() {
602*6777b538SAndroid Build Coastguard Worker int old_capture_count = hang_capture_count_;
603*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kSmallCPUQuantum);
604*6777b538SAndroid Build Coastguard Worker TriggerMonitorAndWaitForCompletion();
605*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(old_capture_count, hang_capture_count_);
606*6777b538SAndroid Build Coastguard Worker }
607*6777b538SAndroid Build Coastguard Worker
ConcatenateThreadIds(const std::vector<base::PlatformThreadId> & ids) const608*6777b538SAndroid Build Coastguard Worker std::string ConcatenateThreadIds(
609*6777b538SAndroid Build Coastguard Worker const std::vector<base::PlatformThreadId>& ids) const {
610*6777b538SAndroid Build Coastguard Worker std::string result;
611*6777b538SAndroid Build Coastguard Worker constexpr char kSeparator{'|'};
612*6777b538SAndroid Build Coastguard Worker
613*6777b538SAndroid Build Coastguard Worker for (PlatformThreadId id : ids) {
614*6777b538SAndroid Build Coastguard Worker result += base::NumberToString(id) + kSeparator;
615*6777b538SAndroid Build Coastguard Worker }
616*6777b538SAndroid Build Coastguard Worker
617*6777b538SAndroid Build Coastguard Worker return result;
618*6777b538SAndroid Build Coastguard Worker }
619*6777b538SAndroid Build Coastguard Worker
620*6777b538SAndroid Build Coastguard Worker // Will be signaled once monitoring took place. Marks the end of the test.
621*6777b538SAndroid Build Coastguard Worker WaitableEvent monitor_event_;
622*6777b538SAndroid Build Coastguard Worker
623*6777b538SAndroid Build Coastguard Worker const PlatformThreadId test_thread_id_ = PlatformThread::CurrentId();
624*6777b538SAndroid Build Coastguard Worker
625*6777b538SAndroid Build Coastguard Worker // This is written to by the test main thread and read from the hang watching
626*6777b538SAndroid Build Coastguard Worker // thread. It does not need to be protected because access to it is
627*6777b538SAndroid Build Coastguard Worker // synchronized by always setting before triggering the execution of the
628*6777b538SAndroid Build Coastguard Worker // reading code through HangWatcher::SignalMonitorEventForTesting().
629*6777b538SAndroid Build Coastguard Worker std::string list_of_hung_thread_ids_during_capture_;
630*6777b538SAndroid Build Coastguard Worker
631*6777b538SAndroid Build Coastguard Worker // This is written to by from the hang watching thread and read the test main
632*6777b538SAndroid Build Coastguard Worker // thread. It does not need to be protected because access to it is
633*6777b538SAndroid Build Coastguard Worker // synchronized by always reading after monitor_event_ has been signaled.
634*6777b538SAndroid Build Coastguard Worker int hang_capture_count_ = 0;
635*6777b538SAndroid Build Coastguard Worker
636*6777b538SAndroid Build Coastguard Worker // Increases at the same time as |hang_capture_count_| to test that capture
637*6777b538SAndroid Build Coastguard Worker // actually took place.
638*6777b538SAndroid Build Coastguard Worker int reference_capture_count_ = 0;
639*6777b538SAndroid Build Coastguard Worker
640*6777b538SAndroid Build Coastguard Worker std::string seconds_since_last_power_resume_crash_key_;
641*6777b538SAndroid Build Coastguard Worker
642*6777b538SAndroid Build Coastguard Worker base::test::ScopedFeatureList feature_list_;
643*6777b538SAndroid Build Coastguard Worker
644*6777b538SAndroid Build Coastguard Worker // Used exclusively for MOCK_TIME.
645*6777b538SAndroid Build Coastguard Worker test::SingleThreadTaskEnvironment task_environment_{
646*6777b538SAndroid Build Coastguard Worker test::TaskEnvironment::TimeSource::MOCK_TIME};
647*6777b538SAndroid Build Coastguard Worker
648*6777b538SAndroid Build Coastguard Worker HangWatcher hang_watcher_;
649*6777b538SAndroid Build Coastguard Worker };
650*6777b538SAndroid Build Coastguard Worker } // namespace
651*6777b538SAndroid Build Coastguard Worker
652*6777b538SAndroid Build Coastguard Worker // Verify that the hang capture fails when marking a thread for blocking fails.
653*6777b538SAndroid Build Coastguard Worker // This simulates a WatchHangsInScope completing between the time the hang
654*6777b538SAndroid Build Coastguard Worker // was dected and the time it is recorded which would create a non-actionable
655*6777b538SAndroid Build Coastguard Worker // report.
TEST_F(HangWatcherSnapshotTest,NonActionableReport)656*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherSnapshotTest, NonActionableReport) {
657*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetOnHangClosureForTesting(
658*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([this]() { ++hang_capture_count_; }));
659*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(
660*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([this]() { monitor_event_.Signal(); }));
661*6777b538SAndroid Build Coastguard Worker
662*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
663*6777b538SAndroid Build Coastguard Worker
664*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
665*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
666*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
667*6777b538SAndroid Build Coastguard Worker {
668*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires right away. Ensures that
669*6777b538SAndroid Build Coastguard Worker // the first monitor will detect a hang.
670*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
671*6777b538SAndroid Build Coastguard Worker
672*6777b538SAndroid Build Coastguard Worker internal::HangWatchState* current_hang_watch_state =
673*6777b538SAndroid Build Coastguard Worker internal::HangWatchState::GetHangWatchStateForCurrentThread();
674*6777b538SAndroid Build Coastguard Worker
675*6777b538SAndroid Build Coastguard Worker // Simulate the deadline changing concurrently during the capture. This
676*6777b538SAndroid Build Coastguard Worker // makes the capture fail since marking of the deadline fails.
677*6777b538SAndroid Build Coastguard Worker ASSERT_NE(current_hang_watch_state->GetDeadline(),
678*6777b538SAndroid Build Coastguard Worker base::TimeTicks::FromInternalValue(kArbitraryDeadline));
679*6777b538SAndroid Build Coastguard Worker current_hang_watch_state->GetHangWatchDeadlineForTesting()
680*6777b538SAndroid Build Coastguard Worker ->SetSwitchBitsClosureForTesting(
681*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([]() { return kArbitraryDeadline; }));
682*6777b538SAndroid Build Coastguard Worker
683*6777b538SAndroid Build Coastguard Worker ExpectNoCapture();
684*6777b538SAndroid Build Coastguard Worker
685*6777b538SAndroid Build Coastguard Worker // Marking failed.
686*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(current_hang_watch_state->IsFlagSet(
687*6777b538SAndroid Build Coastguard Worker internal::HangWatchDeadline::Flag::kShouldBlockOnHang));
688*6777b538SAndroid Build Coastguard Worker
689*6777b538SAndroid Build Coastguard Worker current_hang_watch_state->GetHangWatchDeadlineForTesting()
690*6777b538SAndroid Build Coastguard Worker ->ResetSwitchBitsClosureForTesting();
691*6777b538SAndroid Build Coastguard Worker }
692*6777b538SAndroid Build Coastguard Worker }
693*6777b538SAndroid Build Coastguard Worker
694*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1223033): On MAC, the base::PlatformThread::CurrentId(...)
695*6777b538SAndroid Build Coastguard Worker // should return the system wide IDs. The HungThreadIDs test fails because the
696*6777b538SAndroid Build Coastguard Worker // reported process ids do not match.
697*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC)
698*6777b538SAndroid Build Coastguard Worker #define MAYBE_HungThreadIDs DISABLED_HungThreadIDs
699*6777b538SAndroid Build Coastguard Worker #else
700*6777b538SAndroid Build Coastguard Worker #define MAYBE_HungThreadIDs HungThreadIDs
701*6777b538SAndroid Build Coastguard Worker #endif
702*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherSnapshotTest,MAYBE_HungThreadIDs)703*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherSnapshotTest, MAYBE_HungThreadIDs) {
704*6777b538SAndroid Build Coastguard Worker // During hang capture the list of hung threads should be populated.
705*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this]() {
706*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(hang_watcher_.GrabWatchStateSnapshotForTesting()
707*6777b538SAndroid Build Coastguard Worker .PrepareHungThreadListCrashKey(),
708*6777b538SAndroid Build Coastguard Worker list_of_hung_thread_ids_during_capture_);
709*6777b538SAndroid Build Coastguard Worker ++hang_capture_count_;
710*6777b538SAndroid Build Coastguard Worker }));
711*6777b538SAndroid Build Coastguard Worker
712*6777b538SAndroid Build Coastguard Worker // When hang capture is over the list should be empty.
713*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(
714*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([this]() {
715*6777b538SAndroid Build Coastguard Worker monitor_event_.Signal();
716*6777b538SAndroid Build Coastguard Worker }));
717*6777b538SAndroid Build Coastguard Worker
718*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
719*6777b538SAndroid Build Coastguard Worker
720*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
721*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
722*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
723*6777b538SAndroid Build Coastguard Worker
724*6777b538SAndroid Build Coastguard Worker BlockingThread blocking_thread(&monitor_event_, base::TimeDelta{});
725*6777b538SAndroid Build Coastguard Worker blocking_thread.StartAndWaitForScopeEntered();
726*6777b538SAndroid Build Coastguard Worker {
727*6777b538SAndroid Build Coastguard Worker // Ensure the blocking thread entered the scope before the main thread. This
728*6777b538SAndroid Build Coastguard Worker // will guarantee an ordering while reporting the list of hung threads.
729*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kSmallCPUQuantum);
730*6777b538SAndroid Build Coastguard Worker
731*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires right away. Ensures that
732*6777b538SAndroid Build Coastguard Worker // the first monitor will detect a hang. This scope will naturally have a
733*6777b538SAndroid Build Coastguard Worker // later deadline than the one in |blocking_thread_| since it was created
734*6777b538SAndroid Build Coastguard Worker // after.
735*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
736*6777b538SAndroid Build Coastguard Worker
737*6777b538SAndroid Build Coastguard Worker // Hung thread list should contain the id the blocking thread and then the
738*6777b538SAndroid Build Coastguard Worker // id of the test main thread since that is the order of increasing
739*6777b538SAndroid Build Coastguard Worker // deadline.
740*6777b538SAndroid Build Coastguard Worker TestIDList(
741*6777b538SAndroid Build Coastguard Worker ConcatenateThreadIds({blocking_thread.GetId(), test_thread_id_}));
742*6777b538SAndroid Build Coastguard Worker
743*6777b538SAndroid Build Coastguard Worker // |expires_instantly| and the scope from |blocking_thread| are still live
744*6777b538SAndroid Build Coastguard Worker // but already recorded so should be ignored.
745*6777b538SAndroid Build Coastguard Worker ExpectNoCapture();
746*6777b538SAndroid Build Coastguard Worker
747*6777b538SAndroid Build Coastguard Worker // Thread is joinable since we signaled |monitor_event_|. This closes the
748*6777b538SAndroid Build Coastguard Worker // scope in |blocking_thread|.
749*6777b538SAndroid Build Coastguard Worker blocking_thread.Join();
750*6777b538SAndroid Build Coastguard Worker
751*6777b538SAndroid Build Coastguard Worker // |expires_instantly| is still live but already recorded so should be
752*6777b538SAndroid Build Coastguard Worker // ignored.
753*6777b538SAndroid Build Coastguard Worker ExpectNoCapture();
754*6777b538SAndroid Build Coastguard Worker }
755*6777b538SAndroid Build Coastguard Worker
756*6777b538SAndroid Build Coastguard Worker // All HangWatchScopeEnables are over. There should be no capture.
757*6777b538SAndroid Build Coastguard Worker ExpectNoCapture();
758*6777b538SAndroid Build Coastguard Worker
759*6777b538SAndroid Build Coastguard Worker // Once all recorded scopes are over creating a new one and monitoring will
760*6777b538SAndroid Build Coastguard Worker // trigger a hang detection.
761*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
762*6777b538SAndroid Build Coastguard Worker TestIDList(ConcatenateThreadIds({test_thread_id_}));
763*6777b538SAndroid Build Coastguard Worker }
764*6777b538SAndroid Build Coastguard Worker
TEST_F(HangWatcherSnapshotTest,TimeSinceLastSystemPowerResumeCrashKey)765*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherSnapshotTest, TimeSinceLastSystemPowerResumeCrashKey) {
766*6777b538SAndroid Build Coastguard Worker // Override the capture of hangs. Simulate a crash key capture.
767*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this]() {
768*6777b538SAndroid Build Coastguard Worker ++hang_capture_count_;
769*6777b538SAndroid Build Coastguard Worker seconds_since_last_power_resume_crash_key_ =
770*6777b538SAndroid Build Coastguard Worker hang_watcher_.GetTimeSinceLastSystemPowerResumeCrashKeyValue();
771*6777b538SAndroid Build Coastguard Worker }));
772*6777b538SAndroid Build Coastguard Worker
773*6777b538SAndroid Build Coastguard Worker // When hang capture is over, unblock the main thread.
774*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(
775*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([this]() { monitor_event_.Signal(); }));
776*6777b538SAndroid Build Coastguard Worker
777*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
778*6777b538SAndroid Build Coastguard Worker
779*6777b538SAndroid Build Coastguard Worker // Register the main test thread for hang watching.
780*6777b538SAndroid Build Coastguard Worker auto unregister_thread_closure =
781*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
782*6777b538SAndroid Build Coastguard Worker
783*6777b538SAndroid Build Coastguard Worker {
784*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
785*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kSmallCPUQuantum);
786*6777b538SAndroid Build Coastguard Worker
787*6777b538SAndroid Build Coastguard Worker TriggerMonitorAndWaitForCompletion();
788*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, hang_capture_count_);
789*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Never suspended", seconds_since_last_power_resume_crash_key_);
790*6777b538SAndroid Build Coastguard Worker }
791*6777b538SAndroid Build Coastguard Worker
792*6777b538SAndroid Build Coastguard Worker {
793*6777b538SAndroid Build Coastguard Worker test::ScopedPowerMonitorTestSource power_monitor_source;
794*6777b538SAndroid Build Coastguard Worker power_monitor_source.Suspend();
795*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kSmallCPUQuantum);
796*6777b538SAndroid Build Coastguard Worker
797*6777b538SAndroid Build Coastguard Worker {
798*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
799*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kSmallCPUQuantum);
800*6777b538SAndroid Build Coastguard Worker TriggerMonitorAndWaitForCompletion();
801*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2, hang_capture_count_);
802*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Power suspended", seconds_since_last_power_resume_crash_key_);
803*6777b538SAndroid Build Coastguard Worker }
804*6777b538SAndroid Build Coastguard Worker
805*6777b538SAndroid Build Coastguard Worker power_monitor_source.Resume();
806*6777b538SAndroid Build Coastguard Worker constexpr TimeDelta kAfterResumeTime{base::Seconds(5)};
807*6777b538SAndroid Build Coastguard Worker task_environment_.AdvanceClock(kAfterResumeTime);
808*6777b538SAndroid Build Coastguard Worker
809*6777b538SAndroid Build Coastguard Worker {
810*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_instantly(base::TimeDelta{});
811*6777b538SAndroid Build Coastguard Worker TriggerMonitorAndWaitForCompletion();
812*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(3, hang_capture_count_);
813*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(base::NumberToString(kAfterResumeTime.InSeconds()),
814*6777b538SAndroid Build Coastguard Worker seconds_since_last_power_resume_crash_key_);
815*6777b538SAndroid Build Coastguard Worker }
816*6777b538SAndroid Build Coastguard Worker }
817*6777b538SAndroid Build Coastguard Worker }
818*6777b538SAndroid Build Coastguard Worker
819*6777b538SAndroid Build Coastguard Worker namespace {
820*6777b538SAndroid Build Coastguard Worker
821*6777b538SAndroid Build Coastguard Worker // Determines how long the HangWatcher will wait between calls to
822*6777b538SAndroid Build Coastguard Worker // Monitor(). Choose a low value so that that successive invocations happens
823*6777b538SAndroid Build Coastguard Worker // fast. This makes tests that wait for monitoring run fast and makes tests that
824*6777b538SAndroid Build Coastguard Worker // expect no monitoring fail fast.
825*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kMonitoringPeriod = base::Milliseconds(1);
826*6777b538SAndroid Build Coastguard Worker
827*6777b538SAndroid Build Coastguard Worker // Test if and how often the HangWatcher periodically monitors for hangs.
828*6777b538SAndroid Build Coastguard Worker class HangWatcherPeriodicMonitoringTest : public testing::Test {
829*6777b538SAndroid Build Coastguard Worker public:
HangWatcherPeriodicMonitoringTest()830*6777b538SAndroid Build Coastguard Worker HangWatcherPeriodicMonitoringTest() {
831*6777b538SAndroid Build Coastguard Worker hang_watcher_.InitializeOnMainThread(
832*6777b538SAndroid Build Coastguard Worker HangWatcher::ProcessType::kBrowserProcess, false,
833*6777b538SAndroid Build Coastguard Worker /*emit_crashes=*/true);
834*6777b538SAndroid Build Coastguard Worker
835*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetMonitoringPeriodForTesting(kMonitoringPeriod);
836*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetOnHangClosureForTesting(base::BindRepeating(
837*6777b538SAndroid Build Coastguard Worker &WaitableEvent::Signal, base::Unretained(&hang_event_)));
838*6777b538SAndroid Build Coastguard Worker
839*6777b538SAndroid Build Coastguard Worker // HangWatcher uses a TickClock to detect how long it slept in between calls
840*6777b538SAndroid Build Coastguard Worker // to Monitor(). Override that clock to control its subjective passage of
841*6777b538SAndroid Build Coastguard Worker // time.
842*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetTickClockForTesting(&test_clock_);
843*6777b538SAndroid Build Coastguard Worker }
844*6777b538SAndroid Build Coastguard Worker
845*6777b538SAndroid Build Coastguard Worker HangWatcherPeriodicMonitoringTest(
846*6777b538SAndroid Build Coastguard Worker const HangWatcherPeriodicMonitoringTest& other) = delete;
847*6777b538SAndroid Build Coastguard Worker HangWatcherPeriodicMonitoringTest& operator=(
848*6777b538SAndroid Build Coastguard Worker const HangWatcherPeriodicMonitoringTest& other) = delete;
849*6777b538SAndroid Build Coastguard Worker
TearDown()850*6777b538SAndroid Build Coastguard Worker void TearDown() override { hang_watcher_.UnitializeOnMainThreadForTesting(); }
851*6777b538SAndroid Build Coastguard Worker
852*6777b538SAndroid Build Coastguard Worker protected:
853*6777b538SAndroid Build Coastguard Worker // Setup the callback invoked after waiting in HangWatcher to advance the
854*6777b538SAndroid Build Coastguard Worker // tick clock by the desired time delta.
InstallAfterWaitCallback(base::TimeDelta time_delta)855*6777b538SAndroid Build Coastguard Worker void InstallAfterWaitCallback(base::TimeDelta time_delta) {
856*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterWaitCallbackForTesting(base::BindLambdaForTesting(
857*6777b538SAndroid Build Coastguard Worker [this, time_delta](base::TimeTicks time_before_wait) {
858*6777b538SAndroid Build Coastguard Worker test_clock_.Advance(time_delta);
859*6777b538SAndroid Build Coastguard Worker }));
860*6777b538SAndroid Build Coastguard Worker }
861*6777b538SAndroid Build Coastguard Worker
862*6777b538SAndroid Build Coastguard Worker base::SimpleTestTickClock test_clock_;
863*6777b538SAndroid Build Coastguard Worker
864*6777b538SAndroid Build Coastguard Worker // Single threaded to avoid ThreadPool WorkerThreads registering. Will run
865*6777b538SAndroid Build Coastguard Worker // delayed tasks created by the tests.
866*6777b538SAndroid Build Coastguard Worker test::SingleThreadTaskEnvironment task_environment_;
867*6777b538SAndroid Build Coastguard Worker
868*6777b538SAndroid Build Coastguard Worker std::unique_ptr<base::TickClock> fake_tick_clock_;
869*6777b538SAndroid Build Coastguard Worker HangWatcher hang_watcher_;
870*6777b538SAndroid Build Coastguard Worker
871*6777b538SAndroid Build Coastguard Worker // Signaled when a hang is detected.
872*6777b538SAndroid Build Coastguard Worker WaitableEvent hang_event_;
873*6777b538SAndroid Build Coastguard Worker
874*6777b538SAndroid Build Coastguard Worker base::ScopedClosureRunner unregister_thread_closure_;
875*6777b538SAndroid Build Coastguard Worker };
876*6777b538SAndroid Build Coastguard Worker } // namespace
877*6777b538SAndroid Build Coastguard Worker
878*6777b538SAndroid Build Coastguard Worker // Don't register any threads for hang watching. HangWatcher should not monitor.
TEST_F(HangWatcherPeriodicMonitoringTest,NoPeriodicMonitoringWithoutRegisteredThreads)879*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherPeriodicMonitoringTest,
880*6777b538SAndroid Build Coastguard Worker NoPeriodicMonitoringWithoutRegisteredThreads) {
881*6777b538SAndroid Build Coastguard Worker RunLoop run_loop;
882*6777b538SAndroid Build Coastguard Worker
883*6777b538SAndroid Build Coastguard Worker // If a call to HangWatcher::Monitor() takes place the test will instantly
884*6777b538SAndroid Build Coastguard Worker // fail.
885*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(
886*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([&run_loop]() {
887*6777b538SAndroid Build Coastguard Worker ADD_FAILURE() << "Monitoring took place!";
888*6777b538SAndroid Build Coastguard Worker run_loop.Quit();
889*6777b538SAndroid Build Coastguard Worker }));
890*6777b538SAndroid Build Coastguard Worker
891*6777b538SAndroid Build Coastguard Worker // Make the HangWatcher tick clock advance by exactly the monitoring period
892*6777b538SAndroid Build Coastguard Worker // after waiting so it will never detect oversleeping between attempts to call
893*6777b538SAndroid Build Coastguard Worker // Monitor(). This would inhibit monitoring and make the test pass for the
894*6777b538SAndroid Build Coastguard Worker // wrong reasons.
895*6777b538SAndroid Build Coastguard Worker InstallAfterWaitCallback(kMonitoringPeriod);
896*6777b538SAndroid Build Coastguard Worker
897*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
898*6777b538SAndroid Build Coastguard Worker
899*6777b538SAndroid Build Coastguard Worker // Unblock the test thread. No thread ever registered after the HangWatcher
900*6777b538SAndroid Build Coastguard Worker // was created in the test's constructor. No monitoring should have taken
901*6777b538SAndroid Build Coastguard Worker // place.
902*6777b538SAndroid Build Coastguard Worker task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
903*6777b538SAndroid Build Coastguard Worker FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
904*6777b538SAndroid Build Coastguard Worker run_loop.Run();
905*6777b538SAndroid Build Coastguard Worker
906*6777b538SAndroid Build Coastguard Worker // NOTE:
907*6777b538SAndroid Build Coastguard Worker // A lack of calls could technically also be caused by the HangWatcher thread
908*6777b538SAndroid Build Coastguard Worker // executing too slowly / being descheduled. This is a known limitation.
909*6777b538SAndroid Build Coastguard Worker // It's expected for |TestTimeouts::tiny_timeout()| to be large enough that
910*6777b538SAndroid Build Coastguard Worker // this is rare.
911*6777b538SAndroid Build Coastguard Worker }
912*6777b538SAndroid Build Coastguard Worker
913*6777b538SAndroid Build Coastguard Worker // During normal execution periodic monitorings should take place.
TEST_F(HangWatcherPeriodicMonitoringTest,PeriodicCallsTakePlace)914*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherPeriodicMonitoringTest, PeriodicCallsTakePlace) {
915*6777b538SAndroid Build Coastguard Worker // HangWatcher::Monitor() will run once right away on thread registration.
916*6777b538SAndroid Build Coastguard Worker // We want to make sure it runs at a couple more times from being scheduled.
917*6777b538SAndroid Build Coastguard Worker constexpr int kMinimumMonitorCount = 3;
918*6777b538SAndroid Build Coastguard Worker
919*6777b538SAndroid Build Coastguard Worker RunLoop run_loop;
920*6777b538SAndroid Build Coastguard Worker
921*6777b538SAndroid Build Coastguard Worker // Setup the HangWatcher to unblock run_loop when the Monitor() has been
922*6777b538SAndroid Build Coastguard Worker // invoked enough times.
923*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(BarrierClosure(
924*6777b538SAndroid Build Coastguard Worker kMinimumMonitorCount, base::BindLambdaForTesting([&run_loop]() {
925*6777b538SAndroid Build Coastguard Worker // Test condition are confirmed, stop monitoring.
926*6777b538SAndroid Build Coastguard Worker HangWatcher::StopMonitoringForTesting();
927*6777b538SAndroid Build Coastguard Worker
928*6777b538SAndroid Build Coastguard Worker // Unblock the test main thread.
929*6777b538SAndroid Build Coastguard Worker run_loop.Quit();
930*6777b538SAndroid Build Coastguard Worker })));
931*6777b538SAndroid Build Coastguard Worker
932*6777b538SAndroid Build Coastguard Worker // Make the HangWatcher tick clock advance by exactly the monitoring period
933*6777b538SAndroid Build Coastguard Worker // after waiting so it will never detect oversleeping between attempts to call
934*6777b538SAndroid Build Coastguard Worker // Monitor(). This would inhibit monitoring.
935*6777b538SAndroid Build Coastguard Worker InstallAfterWaitCallback(kMonitoringPeriod);
936*6777b538SAndroid Build Coastguard Worker
937*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
938*6777b538SAndroid Build Coastguard Worker
939*6777b538SAndroid Build Coastguard Worker // Register a thread,
940*6777b538SAndroid Build Coastguard Worker unregister_thread_closure_ =
941*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
942*6777b538SAndroid Build Coastguard Worker
943*6777b538SAndroid Build Coastguard Worker run_loop.Run();
944*6777b538SAndroid Build Coastguard Worker
945*6777b538SAndroid Build Coastguard Worker // No monitored scope means no possible hangs.
946*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(hang_event_.IsSignaled());
947*6777b538SAndroid Build Coastguard Worker }
948*6777b538SAndroid Build Coastguard Worker
949*6777b538SAndroid Build Coastguard Worker // If the HangWatcher detects it slept for longer than expected it will not
950*6777b538SAndroid Build Coastguard Worker // monitor.
TEST_F(HangWatcherPeriodicMonitoringTest,NoMonitorOnOverSleep)951*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) {
952*6777b538SAndroid Build Coastguard Worker RunLoop run_loop;
953*6777b538SAndroid Build Coastguard Worker
954*6777b538SAndroid Build Coastguard Worker // If a call to HangWatcher::Monitor() takes place the test will instantly
955*6777b538SAndroid Build Coastguard Worker // fail.
956*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(
957*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([&run_loop]() {
958*6777b538SAndroid Build Coastguard Worker ADD_FAILURE() << "Monitoring took place!";
959*6777b538SAndroid Build Coastguard Worker run_loop.Quit();
960*6777b538SAndroid Build Coastguard Worker }));
961*6777b538SAndroid Build Coastguard Worker
962*6777b538SAndroid Build Coastguard Worker // Make the HangWatcher tick clock advance so much after waiting that it will
963*6777b538SAndroid Build Coastguard Worker // detect oversleeping every time. This will keep it from monitoring.
964*6777b538SAndroid Build Coastguard Worker InstallAfterWaitCallback(base::Minutes(1));
965*6777b538SAndroid Build Coastguard Worker
966*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
967*6777b538SAndroid Build Coastguard Worker
968*6777b538SAndroid Build Coastguard Worker // Register a thread.
969*6777b538SAndroid Build Coastguard Worker unregister_thread_closure_ =
970*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
971*6777b538SAndroid Build Coastguard Worker
972*6777b538SAndroid Build Coastguard Worker // Unblock the test thread. All waits were perceived as oversleeping so all
973*6777b538SAndroid Build Coastguard Worker // monitoring was inhibited.
974*6777b538SAndroid Build Coastguard Worker task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
975*6777b538SAndroid Build Coastguard Worker FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
976*6777b538SAndroid Build Coastguard Worker run_loop.Run();
977*6777b538SAndroid Build Coastguard Worker
978*6777b538SAndroid Build Coastguard Worker // NOTE: A lack of calls could technically also be caused by the HangWatcher
979*6777b538SAndroid Build Coastguard Worker // thread executing too slowly / being descheduled. This is a known
980*6777b538SAndroid Build Coastguard Worker // limitation. It's expected for |TestTimeouts::tiny_timeout()| to be large
981*6777b538SAndroid Build Coastguard Worker // enough that this happens rarely.
982*6777b538SAndroid Build Coastguard Worker }
983*6777b538SAndroid Build Coastguard Worker
984*6777b538SAndroid Build Coastguard Worker namespace {
985*6777b538SAndroid Build Coastguard Worker class WatchHangsInScopeBlockingTest : public testing::Test {
986*6777b538SAndroid Build Coastguard Worker public:
WatchHangsInScopeBlockingTest()987*6777b538SAndroid Build Coastguard Worker WatchHangsInScopeBlockingTest() {
988*6777b538SAndroid Build Coastguard Worker feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
989*6777b538SAndroid Build Coastguard Worker HangWatcher::InitializeOnMainThread(
990*6777b538SAndroid Build Coastguard Worker HangWatcher::ProcessType::kBrowserProcess, false,
991*6777b538SAndroid Build Coastguard Worker /*emit_crashes=*/true);
992*6777b538SAndroid Build Coastguard Worker
993*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([&] {
994*6777b538SAndroid Build Coastguard Worker capture_started_.Signal();
995*6777b538SAndroid Build Coastguard Worker // Simulate capturing that takes a long time.
996*6777b538SAndroid Build Coastguard Worker PlatformThread::Sleep(base::Milliseconds(500));
997*6777b538SAndroid Build Coastguard Worker
998*6777b538SAndroid Build Coastguard Worker continue_capture_.Wait();
999*6777b538SAndroid Build Coastguard Worker completed_capture_ = true;
1000*6777b538SAndroid Build Coastguard Worker }));
1001*6777b538SAndroid Build Coastguard Worker
1002*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetAfterMonitorClosureForTesting(
1003*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([&] {
1004*6777b538SAndroid Build Coastguard Worker // Simulate monitoring that takes a long time.
1005*6777b538SAndroid Build Coastguard Worker PlatformThread::Sleep(base::Milliseconds(500));
1006*6777b538SAndroid Build Coastguard Worker completed_monitoring_.Signal();
1007*6777b538SAndroid Build Coastguard Worker }));
1008*6777b538SAndroid Build Coastguard Worker
1009*6777b538SAndroid Build Coastguard Worker // Make sure no periodic monitoring takes place.
1010*6777b538SAndroid Build Coastguard Worker hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
1011*6777b538SAndroid Build Coastguard Worker
1012*6777b538SAndroid Build Coastguard Worker hang_watcher_.Start();
1013*6777b538SAndroid Build Coastguard Worker
1014*6777b538SAndroid Build Coastguard Worker // Register the test main thread for hang watching.
1015*6777b538SAndroid Build Coastguard Worker unregister_thread_closure_ =
1016*6777b538SAndroid Build Coastguard Worker HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
1017*6777b538SAndroid Build Coastguard Worker }
1018*6777b538SAndroid Build Coastguard Worker
TearDown()1019*6777b538SAndroid Build Coastguard Worker void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
1020*6777b538SAndroid Build Coastguard Worker
1021*6777b538SAndroid Build Coastguard Worker WatchHangsInScopeBlockingTest(const WatchHangsInScopeBlockingTest& other) =
1022*6777b538SAndroid Build Coastguard Worker delete;
1023*6777b538SAndroid Build Coastguard Worker WatchHangsInScopeBlockingTest& operator=(
1024*6777b538SAndroid Build Coastguard Worker const WatchHangsInScopeBlockingTest& other) = delete;
1025*6777b538SAndroid Build Coastguard Worker
VerifyScopesDontBlock()1026*6777b538SAndroid Build Coastguard Worker void VerifyScopesDontBlock() {
1027*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that cannot possibly cause a hang to be
1028*6777b538SAndroid Build Coastguard Worker // detected.
1029*6777b538SAndroid Build Coastguard Worker {
1030*6777b538SAndroid Build Coastguard Worker WatchHangsInScope long_scope(kVeryLongDelta);
1031*6777b538SAndroid Build Coastguard Worker
1032*6777b538SAndroid Build Coastguard Worker // Manually trigger a monitoring.
1033*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
1034*6777b538SAndroid Build Coastguard Worker
1035*6777b538SAndroid Build Coastguard Worker // Execution has to continue freely here as no capture is in progress.
1036*6777b538SAndroid Build Coastguard Worker }
1037*6777b538SAndroid Build Coastguard Worker
1038*6777b538SAndroid Build Coastguard Worker // Monitoring should not be over yet because the test code should execute
1039*6777b538SAndroid Build Coastguard Worker // faster when not blocked.
1040*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(completed_monitoring_.IsSignaled());
1041*6777b538SAndroid Build Coastguard Worker
1042*6777b538SAndroid Build Coastguard Worker // Wait for the full monitoring process to be complete. This is to prove
1043*6777b538SAndroid Build Coastguard Worker // that monitoring truly executed and that we raced the signaling.
1044*6777b538SAndroid Build Coastguard Worker completed_monitoring_.Wait();
1045*6777b538SAndroid Build Coastguard Worker
1046*6777b538SAndroid Build Coastguard Worker // No hang means no capture.
1047*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(completed_capture_);
1048*6777b538SAndroid Build Coastguard Worker }
1049*6777b538SAndroid Build Coastguard Worker
1050*6777b538SAndroid Build Coastguard Worker protected:
1051*6777b538SAndroid Build Coastguard Worker base::WaitableEvent capture_started_;
1052*6777b538SAndroid Build Coastguard Worker base::WaitableEvent completed_monitoring_;
1053*6777b538SAndroid Build Coastguard Worker
1054*6777b538SAndroid Build Coastguard Worker // The HangWatcher waits on this event via the "on hang" closure when a hang
1055*6777b538SAndroid Build Coastguard Worker // is detected.
1056*6777b538SAndroid Build Coastguard Worker base::WaitableEvent continue_capture_;
1057*6777b538SAndroid Build Coastguard Worker bool completed_capture_{false};
1058*6777b538SAndroid Build Coastguard Worker
1059*6777b538SAndroid Build Coastguard Worker base::test::ScopedFeatureList feature_list_;
1060*6777b538SAndroid Build Coastguard Worker HangWatcher hang_watcher_;
1061*6777b538SAndroid Build Coastguard Worker base::ScopedClosureRunner unregister_thread_closure_;
1062*6777b538SAndroid Build Coastguard Worker };
1063*6777b538SAndroid Build Coastguard Worker } // namespace
1064*6777b538SAndroid Build Coastguard Worker
1065*6777b538SAndroid Build Coastguard Worker // Tests that execution is unimpeded by ~WatchHangsInScope() when no capture
1066*6777b538SAndroid Build Coastguard Worker // ever takes place.
TEST_F(WatchHangsInScopeBlockingTest,ScopeDoesNotBlocksWithoutCapture)1067*6777b538SAndroid Build Coastguard Worker TEST_F(WatchHangsInScopeBlockingTest, ScopeDoesNotBlocksWithoutCapture) {
1068*6777b538SAndroid Build Coastguard Worker // No capture should take place so |continue_capture_| is not signaled to
1069*6777b538SAndroid Build Coastguard Worker // create a test hang if one ever does.
1070*6777b538SAndroid Build Coastguard Worker VerifyScopesDontBlock();
1071*6777b538SAndroid Build Coastguard Worker }
1072*6777b538SAndroid Build Coastguard Worker
1073*6777b538SAndroid Build Coastguard Worker // Test that execution blocks in ~WatchHangsInScope() for a thread under
1074*6777b538SAndroid Build Coastguard Worker // watch during the capturing of a hang.
TEST_F(WatchHangsInScopeBlockingTest,ScopeBlocksDuringCapture)1075*6777b538SAndroid Build Coastguard Worker TEST_F(WatchHangsInScopeBlockingTest, ScopeBlocksDuringCapture) {
1076*6777b538SAndroid Build Coastguard Worker // The capture completing is not dependent on any test event. Signal to make
1077*6777b538SAndroid Build Coastguard Worker // sure the test is not blocked.
1078*6777b538SAndroid Build Coastguard Worker continue_capture_.Signal();
1079*6777b538SAndroid Build Coastguard Worker
1080*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires in the past already. Ensures
1081*6777b538SAndroid Build Coastguard Worker // that the first monitor will detect a hang.
1082*6777b538SAndroid Build Coastguard Worker {
1083*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires right away. Ensures that the
1084*6777b538SAndroid Build Coastguard Worker // first monitor will detect a hang.
1085*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_right_away(base::TimeDelta{});
1086*6777b538SAndroid Build Coastguard Worker
1087*6777b538SAndroid Build Coastguard Worker // Manually trigger a monitoring.
1088*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
1089*6777b538SAndroid Build Coastguard Worker
1090*6777b538SAndroid Build Coastguard Worker // Ensure that the hang capturing started.
1091*6777b538SAndroid Build Coastguard Worker capture_started_.Wait();
1092*6777b538SAndroid Build Coastguard Worker
1093*6777b538SAndroid Build Coastguard Worker // Execution will get stuck in the outer scope because it can't escape
1094*6777b538SAndroid Build Coastguard Worker // ~WatchHangsInScope() if a hang capture is under way.
1095*6777b538SAndroid Build Coastguard Worker }
1096*6777b538SAndroid Build Coastguard Worker
1097*6777b538SAndroid Build Coastguard Worker // A hang was in progress so execution should have been blocked in
1098*6777b538SAndroid Build Coastguard Worker // BlockWhileCaptureInProgress() until capture finishes.
1099*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(completed_capture_);
1100*6777b538SAndroid Build Coastguard Worker completed_monitoring_.Wait();
1101*6777b538SAndroid Build Coastguard Worker
1102*6777b538SAndroid Build Coastguard Worker // Reset expectations
1103*6777b538SAndroid Build Coastguard Worker completed_monitoring_.Reset();
1104*6777b538SAndroid Build Coastguard Worker capture_started_.Reset();
1105*6777b538SAndroid Build Coastguard Worker completed_capture_ = false;
1106*6777b538SAndroid Build Coastguard Worker
1107*6777b538SAndroid Build Coastguard Worker // Verify that scopes don't block just because a capture happened in the past.
1108*6777b538SAndroid Build Coastguard Worker VerifyScopesDontBlock();
1109*6777b538SAndroid Build Coastguard Worker }
1110*6777b538SAndroid Build Coastguard Worker
1111*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64)
1112*6777b538SAndroid Build Coastguard Worker // Flaky hangs on arm64 Macs: https://crbug.com/1140207
1113*6777b538SAndroid Build Coastguard Worker #define MAYBE_NewScopeDoesNotBlockDuringCapture \
1114*6777b538SAndroid Build Coastguard Worker DISABLED_NewScopeDoesNotBlockDuringCapture
1115*6777b538SAndroid Build Coastguard Worker #else
1116*6777b538SAndroid Build Coastguard Worker #define MAYBE_NewScopeDoesNotBlockDuringCapture \
1117*6777b538SAndroid Build Coastguard Worker NewScopeDoesNotBlockDuringCapture
1118*6777b538SAndroid Build Coastguard Worker #endif
1119*6777b538SAndroid Build Coastguard Worker
1120*6777b538SAndroid Build Coastguard Worker // Test that execution does not block in ~WatchHangsInScope() when the scope
1121*6777b538SAndroid Build Coastguard Worker // was created after the start of a capture.
TEST_F(WatchHangsInScopeBlockingTest,MAYBE_NewScopeDoesNotBlockDuringCapture)1122*6777b538SAndroid Build Coastguard Worker TEST_F(WatchHangsInScopeBlockingTest, MAYBE_NewScopeDoesNotBlockDuringCapture) {
1123*6777b538SAndroid Build Coastguard Worker // Start a WatchHangsInScope that expires right away. Ensures that the
1124*6777b538SAndroid Build Coastguard Worker // first monitor will detect a hang.
1125*6777b538SAndroid Build Coastguard Worker WatchHangsInScope expires_right_away(base::TimeDelta{});
1126*6777b538SAndroid Build Coastguard Worker
1127*6777b538SAndroid Build Coastguard Worker // Manually trigger a monitoring.
1128*6777b538SAndroid Build Coastguard Worker hang_watcher_.SignalMonitorEventForTesting();
1129*6777b538SAndroid Build Coastguard Worker
1130*6777b538SAndroid Build Coastguard Worker // Ensure that the hang capturing started.
1131*6777b538SAndroid Build Coastguard Worker capture_started_.Wait();
1132*6777b538SAndroid Build Coastguard Worker
1133*6777b538SAndroid Build Coastguard Worker // A scope started once a capture is already under way should not block
1134*6777b538SAndroid Build Coastguard Worker // execution.
1135*6777b538SAndroid Build Coastguard Worker { WatchHangsInScope also_expires_right_away(base::TimeDelta{}); }
1136*6777b538SAndroid Build Coastguard Worker
1137*6777b538SAndroid Build Coastguard Worker // Wait for the new WatchHangsInScope to be destroyed to let the capture
1138*6777b538SAndroid Build Coastguard Worker // finish. If the new scope block waiting for the capture to finish this would
1139*6777b538SAndroid Build Coastguard Worker // create a deadlock and the test would hang.
1140*6777b538SAndroid Build Coastguard Worker continue_capture_.Signal();
1141*6777b538SAndroid Build Coastguard Worker }
1142*6777b538SAndroid Build Coastguard Worker
1143*6777b538SAndroid Build Coastguard Worker namespace internal {
1144*6777b538SAndroid Build Coastguard Worker namespace {
1145*6777b538SAndroid Build Coastguard Worker
1146*6777b538SAndroid Build Coastguard Worker constexpr std::array<HangWatchDeadline::Flag, 3> kAllFlags{
1147*6777b538SAndroid Build Coastguard Worker {HangWatchDeadline::Flag::kMinValue,
1148*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope,
1149*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kShouldBlockOnHang}};
1150*6777b538SAndroid Build Coastguard Worker } // namespace
1151*6777b538SAndroid Build Coastguard Worker
1152*6777b538SAndroid Build Coastguard Worker class HangWatchDeadlineTest : public testing::Test {
1153*6777b538SAndroid Build Coastguard Worker protected:
AssertNoFlagsSet() const1154*6777b538SAndroid Build Coastguard Worker void AssertNoFlagsSet() const {
1155*6777b538SAndroid Build Coastguard Worker for (HangWatchDeadline::Flag flag : kAllFlags) {
1156*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(deadline_.IsFlagSet(flag));
1157*6777b538SAndroid Build Coastguard Worker }
1158*6777b538SAndroid Build Coastguard Worker }
1159*6777b538SAndroid Build Coastguard Worker
1160*6777b538SAndroid Build Coastguard Worker // Return a flag mask without one of the flags for test purposes. Use to
1161*6777b538SAndroid Build Coastguard Worker // ignore that effect of setting a flag that was just set.
FlagsMinus(uint64_t flags,HangWatchDeadline::Flag flag)1162*6777b538SAndroid Build Coastguard Worker uint64_t FlagsMinus(uint64_t flags, HangWatchDeadline::Flag flag) {
1163*6777b538SAndroid Build Coastguard Worker return flags & ~(static_cast<uint64_t>(flag));
1164*6777b538SAndroid Build Coastguard Worker }
1165*6777b538SAndroid Build Coastguard Worker
1166*6777b538SAndroid Build Coastguard Worker HangWatchDeadline deadline_;
1167*6777b538SAndroid Build Coastguard Worker };
1168*6777b538SAndroid Build Coastguard Worker
1169*6777b538SAndroid Build Coastguard Worker // Verify that the extract functions don't mangle any bits.
TEST_F(HangWatchDeadlineTest,BitsPreservedThroughExtract)1170*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest, BitsPreservedThroughExtract) {
1171*6777b538SAndroid Build Coastguard Worker for (auto bits : {kAllOnes, kAllZeros, kOnesThenZeroes, kZeroesThenOnes}) {
1172*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE((HangWatchDeadline::ExtractFlags(bits) |
1173*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::ExtractDeadline(bits)) == bits);
1174*6777b538SAndroid Build Coastguard Worker }
1175*6777b538SAndroid Build Coastguard Worker }
1176*6777b538SAndroid Build Coastguard Worker
1177*6777b538SAndroid Build Coastguard Worker // Verify that setting and clearing a persistent flag works and has no unwanted
1178*6777b538SAndroid Build Coastguard Worker // side-effects. Neither the flags nor the deadline change concurrently in this
1179*6777b538SAndroid Build Coastguard Worker // test.
TEST_F(HangWatchDeadlineTest,SetAndClearPersistentFlag)1180*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest, SetAndClearPersistentFlag) {
1181*6777b538SAndroid Build Coastguard Worker AssertNoFlagsSet();
1182*6777b538SAndroid Build Coastguard Worker
1183*6777b538SAndroid Build Coastguard Worker // Grab the original values for flags and deadline.
1184*6777b538SAndroid Build Coastguard Worker auto [old_flags, old_deadline] = deadline_.GetFlagsAndDeadline();
1185*6777b538SAndroid Build Coastguard Worker
1186*6777b538SAndroid Build Coastguard Worker // Set the flag. Operation cannot fail.
1187*6777b538SAndroid Build Coastguard Worker deadline_.SetIgnoreCurrentWatchHangsInScope();
1188*6777b538SAndroid Build Coastguard Worker
1189*6777b538SAndroid Build Coastguard Worker // Get new flags and deadline.
1190*6777b538SAndroid Build Coastguard Worker auto [new_flags, new_deadline] = deadline_.GetFlagsAndDeadline();
1191*6777b538SAndroid Build Coastguard Worker
1192*6777b538SAndroid Build Coastguard Worker // Flag was set properly.
1193*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(HangWatchDeadline::IsFlagSet(
1194*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope, new_flags));
1195*6777b538SAndroid Build Coastguard Worker
1196*6777b538SAndroid Build Coastguard Worker // No side-effect on deadline.
1197*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(new_deadline, old_deadline);
1198*6777b538SAndroid Build Coastguard Worker
1199*6777b538SAndroid Build Coastguard Worker // No side-effect on other flags.
1200*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(
1201*6777b538SAndroid Build Coastguard Worker FlagsMinus(new_flags,
1202*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope),
1203*6777b538SAndroid Build Coastguard Worker old_flags);
1204*6777b538SAndroid Build Coastguard Worker
1205*6777b538SAndroid Build Coastguard Worker // Clear the flag, operation cannot fail.
1206*6777b538SAndroid Build Coastguard Worker deadline_.UnsetIgnoreCurrentWatchHangsInScope();
1207*6777b538SAndroid Build Coastguard Worker
1208*6777b538SAndroid Build Coastguard Worker // Update new values.
1209*6777b538SAndroid Build Coastguard Worker std::tie(new_flags, new_deadline) = deadline_.GetFlagsAndDeadline();
1210*6777b538SAndroid Build Coastguard Worker
1211*6777b538SAndroid Build Coastguard Worker // All flags back to original state.
1212*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(new_flags, old_flags);
1213*6777b538SAndroid Build Coastguard Worker
1214*6777b538SAndroid Build Coastguard Worker // Deadline still unnafected.
1215*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(new_deadline, old_deadline);
1216*6777b538SAndroid Build Coastguard Worker }
1217*6777b538SAndroid Build Coastguard Worker
1218*6777b538SAndroid Build Coastguard Worker // Verify setting the TimeTicks value works and has no unwanted side-effects.
TEST_F(HangWatchDeadlineTest,SetDeadline)1219*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest, SetDeadline) {
1220*6777b538SAndroid Build Coastguard Worker TimeTicks ticks;
1221*6777b538SAndroid Build Coastguard Worker
1222*6777b538SAndroid Build Coastguard Worker AssertNoFlagsSet();
1223*6777b538SAndroid Build Coastguard Worker ASSERT_NE(deadline_.GetDeadline(), ticks);
1224*6777b538SAndroid Build Coastguard Worker
1225*6777b538SAndroid Build Coastguard Worker // Set the deadline and verify it stuck.
1226*6777b538SAndroid Build Coastguard Worker deadline_.SetDeadline(ticks);
1227*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(deadline_.GetDeadline(), ticks);
1228*6777b538SAndroid Build Coastguard Worker
1229*6777b538SAndroid Build Coastguard Worker // Only the value was modified, no flags should be set.
1230*6777b538SAndroid Build Coastguard Worker AssertNoFlagsSet();
1231*6777b538SAndroid Build Coastguard Worker }
1232*6777b538SAndroid Build Coastguard Worker
1233*6777b538SAndroid Build Coastguard Worker // Verify that setting a non-persistent flag (kShouldBlockOnHang)
1234*6777b538SAndroid Build Coastguard Worker // when the TimeTicks value changed since calling the flag setting
1235*6777b538SAndroid Build Coastguard Worker // function fails and has no side-effects.
TEST_F(HangWatchDeadlineTest,SetShouldBlockOnHangDeadlineChanged)1236*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest, SetShouldBlockOnHangDeadlineChanged) {
1237*6777b538SAndroid Build Coastguard Worker AssertNoFlagsSet();
1238*6777b538SAndroid Build Coastguard Worker
1239*6777b538SAndroid Build Coastguard Worker auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1240*6777b538SAndroid Build Coastguard Worker
1241*6777b538SAndroid Build Coastguard Worker // Simulate value change. Flags are constant.
1242*6777b538SAndroid Build Coastguard Worker const base::TimeTicks new_deadline =
1243*6777b538SAndroid Build Coastguard Worker base::TimeTicks::FromInternalValue(kArbitraryDeadline);
1244*6777b538SAndroid Build Coastguard Worker ASSERT_NE(deadline, new_deadline);
1245*6777b538SAndroid Build Coastguard Worker deadline_.SetSwitchBitsClosureForTesting(
1246*6777b538SAndroid Build Coastguard Worker base::BindLambdaForTesting([]() { return kArbitraryDeadline; }));
1247*6777b538SAndroid Build Coastguard Worker
1248*6777b538SAndroid Build Coastguard Worker // kShouldBlockOnHangs does not persist through value change.
1249*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(deadline_.SetShouldBlockOnHang(flags, deadline));
1250*6777b538SAndroid Build Coastguard Worker
1251*6777b538SAndroid Build Coastguard Worker // Flag was not applied.
1252*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(
1253*6777b538SAndroid Build Coastguard Worker deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1254*6777b538SAndroid Build Coastguard Worker
1255*6777b538SAndroid Build Coastguard Worker // New value that was changed concurrently is preserved.
1256*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
1257*6777b538SAndroid Build Coastguard Worker }
1258*6777b538SAndroid Build Coastguard Worker
1259*6777b538SAndroid Build Coastguard Worker // Verify that clearing a persistent (kIgnoreCurrentWatchHangsInScope) when
1260*6777b538SAndroid Build Coastguard Worker // the value changed succeeds and has non side-effects.
TEST_F(HangWatchDeadlineTest,ClearIgnoreHangsDeadlineChanged)1261*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest, ClearIgnoreHangsDeadlineChanged) {
1262*6777b538SAndroid Build Coastguard Worker AssertNoFlagsSet();
1263*6777b538SAndroid Build Coastguard Worker
1264*6777b538SAndroid Build Coastguard Worker auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1265*6777b538SAndroid Build Coastguard Worker
1266*6777b538SAndroid Build Coastguard Worker deadline_.SetIgnoreCurrentWatchHangsInScope();
1267*6777b538SAndroid Build Coastguard Worker std::tie(flags, deadline) = deadline_.GetFlagsAndDeadline();
1268*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(HangWatchDeadline::IsFlagSet(
1269*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope, flags));
1270*6777b538SAndroid Build Coastguard Worker
1271*6777b538SAndroid Build Coastguard Worker // Simulate deadline change. Flags are constant.
1272*6777b538SAndroid Build Coastguard Worker const base::TimeTicks new_deadline =
1273*6777b538SAndroid Build Coastguard Worker base::TimeTicks::FromInternalValue(kArbitraryDeadline);
1274*6777b538SAndroid Build Coastguard Worker ASSERT_NE(deadline, new_deadline);
1275*6777b538SAndroid Build Coastguard Worker deadline_.SetSwitchBitsClosureForTesting(base::BindLambdaForTesting([]() {
1276*6777b538SAndroid Build Coastguard Worker return static_cast<uint64_t>(HangWatchDeadline::Flag::kShouldBlockOnHang) |
1277*6777b538SAndroid Build Coastguard Worker kArbitraryDeadline;
1278*6777b538SAndroid Build Coastguard Worker }));
1279*6777b538SAndroid Build Coastguard Worker
1280*6777b538SAndroid Build Coastguard Worker // Clearing kIgnoreHang is unaffected by deadline or flags change.
1281*6777b538SAndroid Build Coastguard Worker deadline_.UnsetIgnoreCurrentWatchHangsInScope();
1282*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(deadline_.IsFlagSet(
1283*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1284*6777b538SAndroid Build Coastguard Worker
1285*6777b538SAndroid Build Coastguard Worker // New deadline that was changed concurrently is preserved.
1286*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1287*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
1288*6777b538SAndroid Build Coastguard Worker }
1289*6777b538SAndroid Build Coastguard Worker
1290*6777b538SAndroid Build Coastguard Worker // Verify that setting a persistent (kIgnoreCurrentWatchHangsInScope) when
1291*6777b538SAndroid Build Coastguard Worker // the deadline or flags changed succeeds and has non side-effects.
TEST_F(HangWatchDeadlineTest,SetIgnoreCurrentHangWatchScopeEnableDeadlineChangedd)1292*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest,
1293*6777b538SAndroid Build Coastguard Worker SetIgnoreCurrentHangWatchScopeEnableDeadlineChangedd) {
1294*6777b538SAndroid Build Coastguard Worker AssertNoFlagsSet();
1295*6777b538SAndroid Build Coastguard Worker
1296*6777b538SAndroid Build Coastguard Worker auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1297*6777b538SAndroid Build Coastguard Worker
1298*6777b538SAndroid Build Coastguard Worker // Simulate deadline change. Flags are constant.
1299*6777b538SAndroid Build Coastguard Worker const base::TimeTicks new_deadline =
1300*6777b538SAndroid Build Coastguard Worker base::TimeTicks::FromInternalValue(kArbitraryDeadline);
1301*6777b538SAndroid Build Coastguard Worker
1302*6777b538SAndroid Build Coastguard Worker ASSERT_NE(deadline, new_deadline);
1303*6777b538SAndroid Build Coastguard Worker deadline_.SetSwitchBitsClosureForTesting(base::BindLambdaForTesting([]() {
1304*6777b538SAndroid Build Coastguard Worker return static_cast<uint64_t>(HangWatchDeadline::Flag::kShouldBlockOnHang) |
1305*6777b538SAndroid Build Coastguard Worker kArbitraryDeadline;
1306*6777b538SAndroid Build Coastguard Worker }));
1307*6777b538SAndroid Build Coastguard Worker
1308*6777b538SAndroid Build Coastguard Worker // kIgnoreHang persists through value change.
1309*6777b538SAndroid Build Coastguard Worker deadline_.SetIgnoreCurrentWatchHangsInScope();
1310*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.IsFlagSet(
1311*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1312*6777b538SAndroid Build Coastguard Worker
1313*6777b538SAndroid Build Coastguard Worker // New deadline and flags that changed concurrently are preserved.
1314*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1315*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
1316*6777b538SAndroid Build Coastguard Worker }
1317*6777b538SAndroid Build Coastguard Worker
1318*6777b538SAndroid Build Coastguard Worker // Setting a new deadline should wipe flags that a not persistent.
1319*6777b538SAndroid Build Coastguard Worker // Persistent flags should not be disturbed.
TEST_F(HangWatchDeadlineTest,SetDeadlineWipesFlags)1320*6777b538SAndroid Build Coastguard Worker TEST_F(HangWatchDeadlineTest, SetDeadlineWipesFlags) {
1321*6777b538SAndroid Build Coastguard Worker auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1322*6777b538SAndroid Build Coastguard Worker
1323*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.SetShouldBlockOnHang(flags, deadline));
1324*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1325*6777b538SAndroid Build Coastguard Worker
1326*6777b538SAndroid Build Coastguard Worker std::tie(flags, deadline) = deadline_.GetFlagsAndDeadline();
1327*6777b538SAndroid Build Coastguard Worker
1328*6777b538SAndroid Build Coastguard Worker deadline_.SetIgnoreCurrentWatchHangsInScope();
1329*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.IsFlagSet(
1330*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1331*6777b538SAndroid Build Coastguard Worker
1332*6777b538SAndroid Build Coastguard Worker // Change the deadline.
1333*6777b538SAndroid Build Coastguard Worker deadline_.SetDeadline(TimeTicks{});
1334*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(deadline_.GetDeadline(), TimeTicks{});
1335*6777b538SAndroid Build Coastguard Worker
1336*6777b538SAndroid Build Coastguard Worker // Verify the persistent flag stuck and the non-persistent one was unset.
1337*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(
1338*6777b538SAndroid Build Coastguard Worker deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1339*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(deadline_.IsFlagSet(
1340*6777b538SAndroid Build Coastguard Worker HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1341*6777b538SAndroid Build Coastguard Worker }
1342*6777b538SAndroid Build Coastguard Worker
1343*6777b538SAndroid Build Coastguard Worker } // namespace internal
1344*6777b538SAndroid Build Coastguard Worker
1345*6777b538SAndroid Build Coastguard Worker } // namespace base
1346