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