xref: /aosp_15_r20/external/cronet/base/threading/hang_watcher_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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