xref: /aosp_15_r20/external/cronet/base/threading/watchdog_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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/watchdog.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <atomic>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/test/spin_wait.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
13*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker namespace {
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
20*6777b538SAndroid Build Coastguard Worker // Provide a derived class to facilitate testing.
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker class WatchdogCounter : public Watchdog::Delegate {
23*6777b538SAndroid Build Coastguard Worker  public:
WatchdogCounter(const TimeDelta & duration,const std::string & thread_watched_name,bool enabled)24*6777b538SAndroid Build Coastguard Worker   WatchdogCounter(const TimeDelta& duration,
25*6777b538SAndroid Build Coastguard Worker                   const std::string& thread_watched_name,
26*6777b538SAndroid Build Coastguard Worker                   bool enabled)
27*6777b538SAndroid Build Coastguard Worker       : watchdog_(duration, thread_watched_name, enabled, this) {}
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker   WatchdogCounter(const WatchdogCounter&) = delete;
30*6777b538SAndroid Build Coastguard Worker   WatchdogCounter& operator=(const WatchdogCounter&) = delete;
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker   ~WatchdogCounter() override = default;
33*6777b538SAndroid Build Coastguard Worker 
Alarm()34*6777b538SAndroid Build Coastguard Worker   void Alarm() override {
35*6777b538SAndroid Build Coastguard Worker     alarm_counter_++;
36*6777b538SAndroid Build Coastguard Worker     watchdog_.DefaultAlarm();
37*6777b538SAndroid Build Coastguard Worker   }
38*6777b538SAndroid Build Coastguard Worker 
watchdog()39*6777b538SAndroid Build Coastguard Worker   Watchdog& watchdog() { return watchdog_; }
alarm_counter()40*6777b538SAndroid Build Coastguard Worker   int alarm_counter() { return alarm_counter_.load(); }
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker  private:
43*6777b538SAndroid Build Coastguard Worker   std::atomic<int> alarm_counter_{0};
44*6777b538SAndroid Build Coastguard Worker   Watchdog watchdog_;
45*6777b538SAndroid Build Coastguard Worker };
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker class WatchdogTest : public testing::Test {
48*6777b538SAndroid Build Coastguard Worker  public:
SetUp()49*6777b538SAndroid Build Coastguard Worker   void SetUp() override { Watchdog::ResetStaticData(); }
50*6777b538SAndroid Build Coastguard Worker };
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker }  // namespace
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
55*6777b538SAndroid Build Coastguard Worker // Actual tests
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker // Minimal constructor/destructor test.
TEST_F(WatchdogTest,StartupShutdownTest)58*6777b538SAndroid Build Coastguard Worker TEST_F(WatchdogTest, StartupShutdownTest) {
59*6777b538SAndroid Build Coastguard Worker   Watchdog watchdog1(Milliseconds(300), "Disabled", false);
60*6777b538SAndroid Build Coastguard Worker   Watchdog watchdog2(Milliseconds(300), "Enabled", true);
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker // Test ability to call Arm and Disarm repeatedly.
TEST_F(WatchdogTest,ArmDisarmTest)64*6777b538SAndroid Build Coastguard Worker TEST_F(WatchdogTest, ArmDisarmTest) {
65*6777b538SAndroid Build Coastguard Worker   Watchdog watchdog1(Milliseconds(300), "Disabled", false);
66*6777b538SAndroid Build Coastguard Worker   watchdog1.Arm();
67*6777b538SAndroid Build Coastguard Worker   watchdog1.Disarm();
68*6777b538SAndroid Build Coastguard Worker   watchdog1.Arm();
69*6777b538SAndroid Build Coastguard Worker   watchdog1.Disarm();
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker   Watchdog watchdog2(Milliseconds(300), "Enabled", true);
72*6777b538SAndroid Build Coastguard Worker   watchdog2.Arm();
73*6777b538SAndroid Build Coastguard Worker   watchdog2.Disarm();
74*6777b538SAndroid Build Coastguard Worker   watchdog2.Arm();
75*6777b538SAndroid Build Coastguard Worker   watchdog2.Disarm();
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker // Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest,AlarmTest)79*6777b538SAndroid Build Coastguard Worker TEST_F(WatchdogTest, AlarmTest) {
80*6777b538SAndroid Build Coastguard Worker   WatchdogCounter watchdog(Milliseconds(10), "Enabled", true);
81*6777b538SAndroid Build Coastguard Worker   watchdog.watchdog().Arm();
82*6777b538SAndroid Build Coastguard Worker   SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(Minutes(5), watchdog.alarm_counter() > 0);
83*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, watchdog.alarm_counter());
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker // Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest,AlarmPriorTimeTest)87*6777b538SAndroid Build Coastguard Worker TEST_F(WatchdogTest, AlarmPriorTimeTest) {
88*6777b538SAndroid Build Coastguard Worker   WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
89*6777b538SAndroid Build Coastguard Worker   // Set a time in the past.
90*6777b538SAndroid Build Coastguard Worker   watchdog.watchdog().ArmSomeTimeDeltaAgo(Seconds(2));
91*6777b538SAndroid Build Coastguard Worker   // It should instantly go off, but certainly in less than 5 minutes.
92*6777b538SAndroid Build Coastguard Worker   SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(Minutes(5), watchdog.alarm_counter() > 0);
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, watchdog.alarm_counter());
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker 
97*6777b538SAndroid Build Coastguard Worker // Make sure a disable alarm does nothing, even if we arm it.
TEST_F(WatchdogTest,ConstructorDisabledTest)98*6777b538SAndroid Build Coastguard Worker TEST_F(WatchdogTest, ConstructorDisabledTest) {
99*6777b538SAndroid Build Coastguard Worker   WatchdogCounter watchdog(Milliseconds(10), "Disabled", false);
100*6777b538SAndroid Build Coastguard Worker   watchdog.watchdog().Arm();
101*6777b538SAndroid Build Coastguard Worker   // Alarm should not fire, as it was disabled.
102*6777b538SAndroid Build Coastguard Worker   PlatformThread::Sleep(Milliseconds(500));
103*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, watchdog.alarm_counter());
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker // Make sure Disarming will prevent firing, even after Arming.
TEST_F(WatchdogTest,DisarmTest)107*6777b538SAndroid Build Coastguard Worker TEST_F(WatchdogTest, DisarmTest) {
108*6777b538SAndroid Build Coastguard Worker   WatchdogCounter watchdog(Seconds(1), "Enabled3", true);
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   TimeTicks start = TimeTicks::Now();
111*6777b538SAndroid Build Coastguard Worker   watchdog.watchdog().Arm();
112*6777b538SAndroid Build Coastguard Worker   // Sleep a bit, but not past the alarm point.
113*6777b538SAndroid Build Coastguard Worker   PlatformThread::Sleep(Milliseconds(100));
114*6777b538SAndroid Build Coastguard Worker   watchdog.watchdog().Disarm();
115*6777b538SAndroid Build Coastguard Worker   TimeTicks end = TimeTicks::Now();
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker   if (end - start > Milliseconds(500)) {
118*6777b538SAndroid Build Coastguard Worker     LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
119*6777b538SAndroid Build Coastguard Worker                  << "timing-sensitive test suspicious.  Aborting now.";
120*6777b538SAndroid Build Coastguard Worker     return;
121*6777b538SAndroid Build Coastguard Worker   }
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker   // Alarm should not have fired before it was disarmed.
124*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, watchdog.alarm_counter());
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker   // Sleep past the point where it would have fired if it wasn't disarmed,
127*6777b538SAndroid Build Coastguard Worker   // and verify that it didn't fire.
128*6777b538SAndroid Build Coastguard Worker   PlatformThread::Sleep(Seconds(1));
129*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, watchdog.alarm_counter());
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   // ...but even after disarming, we can still use the alarm...
132*6777b538SAndroid Build Coastguard Worker   // Set a time greater than the timeout into the past.
133*6777b538SAndroid Build Coastguard Worker   watchdog.watchdog().ArmSomeTimeDeltaAgo(Seconds(10));
134*6777b538SAndroid Build Coastguard Worker   // It should almost instantly go off, but certainly in less than 5 minutes.
135*6777b538SAndroid Build Coastguard Worker   SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(Minutes(5), watchdog.alarm_counter() > 0);
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, watchdog.alarm_counter());
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker }  // namespace base
141