1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/threading/watchdog.h"
7 #include "base/logging.h"
8 #include "base/synchronization/spin_wait.h"
9 #include "base/threading/platform_thread.h"
10 #include "base/time/time.h"
11 #include "testing/gtest/include/gtest/gtest.h"
17 //------------------------------------------------------------------------------
18 // Provide a derived class to facilitate testing.
20 class WatchdogCounter
: public Watchdog
{
22 WatchdogCounter(const TimeDelta
& duration
,
23 const std::string
& thread_watched_name
,
25 : Watchdog(duration
, thread_watched_name
, enabled
),
29 ~WatchdogCounter() override
{}
31 void Alarm() override
{
36 int alarm_counter() { return alarm_counter_
; }
41 DISALLOW_COPY_AND_ASSIGN(WatchdogCounter
);
44 class WatchdogTest
: public testing::Test
{
46 void SetUp() override
{ Watchdog::ResetStaticData(); }
51 //------------------------------------------------------------------------------
54 // Minimal constructor/destructor test.
55 TEST_F(WatchdogTest
, StartupShutdownTest
) {
56 Watchdog
watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
57 Watchdog
watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
60 // Test ability to call Arm and Disarm repeatedly.
61 TEST_F(WatchdogTest
, ArmDisarmTest
) {
62 Watchdog
watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
68 Watchdog
watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
75 // Make sure a basic alarm fires when the time has expired.
76 TEST_F(WatchdogTest
, AlarmTest
) {
77 WatchdogCounter
watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true);
79 SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
80 watchdog
.alarm_counter() > 0);
81 EXPECT_EQ(1, watchdog
.alarm_counter());
84 // Make sure a basic alarm fires when the time has expired.
85 TEST_F(WatchdogTest
, AlarmPriorTimeTest
) {
86 WatchdogCounter
watchdog(TimeDelta(), "Enabled2", true);
87 // Set a time in the past.
88 watchdog
.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
89 // It should instantly go off, but certainly in less than 5 minutes.
90 SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
91 watchdog
.alarm_counter() > 0);
93 EXPECT_EQ(1, watchdog
.alarm_counter());
96 // Make sure a disable alarm does nothing, even if we arm it.
97 TEST_F(WatchdogTest
, ConstructorDisabledTest
) {
98 WatchdogCounter
watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false);
100 // Alarm should not fire, as it was disabled.
101 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500));
102 EXPECT_EQ(0, watchdog
.alarm_counter());
105 // Make sure Disarming will prevent firing, even after Arming.
106 TEST_F(WatchdogTest
, DisarmTest
) {
107 WatchdogCounter
watchdog(TimeDelta::FromSeconds(1), "Enabled3", true);
109 TimeTicks start
= TimeTicks::Now();
111 // Sleep a bit, but not past the alarm point.
112 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
114 TimeTicks end
= TimeTicks::Now();
116 if (end
- start
> TimeDelta::FromMilliseconds(500)) {
117 LOG(WARNING
) << "100ms sleep took over 500ms, making the results of this "
118 << "timing-sensitive test suspicious. Aborting now.";
122 // Alarm should not have fired before it was disarmed.
123 EXPECT_EQ(0, watchdog
.alarm_counter());
125 // Sleep past the point where it would have fired if it wasn't disarmed,
126 // and verify that it didn't fire.
127 PlatformThread::Sleep(TimeDelta::FromSeconds(1));
128 EXPECT_EQ(0, watchdog
.alarm_counter());
130 // ...but even after disarming, we can still use the alarm...
131 // Set a time greater than the timeout into the past.
132 watchdog
.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(10));
133 // It should almost instantly go off, but certainly in less than 5 minutes.
134 SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
135 watchdog
.alarm_counter() > 0);
137 EXPECT_EQ(1, watchdog
.alarm_counter());