13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/watchdog.h"
63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/logging.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/spin_wait.h"
93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace base {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Provide a derived class to facilitate testing.
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass WatchdogCounter : public Watchdog {
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WatchdogCounter(const TimeDelta& duration,
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  const std::string& thread_watched_name,
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                  bool enabled)
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : Watchdog(duration, thread_watched_name, enabled), alarm_counter_(0) {
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~WatchdogCounter() {}
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Alarm() {
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    alarm_counter_++;
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Watchdog::Alarm();
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int alarm_counter() { return alarm_counter_; }
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int alarm_counter_;
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(WatchdogCounter);
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass WatchdogTest : public testing::Test {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SetUp() {
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Watchdog::ResetStaticData();
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}  // namespace
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Actual tests
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Minimal constructor/destructor test.
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(WatchdogTest, StartupShutdownTest) {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Test ability to call Arm and Disarm repeatedly.
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(WatchdogTest, ArmDisarmTest) {
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog1.Arm();
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog1.Disarm();
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog1.Arm();
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog1.Disarm();
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog2.Arm();
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog2.Disarm();
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog2.Arm();
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog2.Disarm();
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Make sure a basic alarm fires when the time has expired.
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(WatchdogTest, AlarmTest) {
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog.Arm();
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   watchdog.alarm_counter() > 0);
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, watchdog.alarm_counter());
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Make sure a basic alarm fires when the time has expired.
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(WatchdogTest, AlarmPriorTimeTest) {
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Set a time in the past.
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // It should instantly go off, but certainly in less than 5 minutes.
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   watchdog.alarm_counter() > 0);
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, watchdog.alarm_counter());
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Make sure a disable alarm does nothing, even if we arm it.
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(WatchdogTest, ConstructorDisabledTest) {
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false);
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog.Arm();
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Alarm should not fire, as it was disabled.
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PlatformThread::Sleep(500);
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, watchdog.alarm_counter());
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Make sure Disarming will prevent firing, even after Arming.
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(WatchdogTest, DisarmTest) {
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  WatchdogCounter watchdog(TimeDelta::FromSeconds(1), "Enabled3", true);
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TimeTicks start = TimeTicks::Now();
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog.Arm();
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  PlatformThread::Sleep(100);  // Sleep a bit, but not past the alarm point.
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog.Disarm();
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TimeTicks end = TimeTicks::Now();
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (end - start > TimeDelta::FromMilliseconds(500)) {
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                 << "timing-sensitive test suspicious.  Aborting now.";
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Alarm should not have fired before it was disarmed.
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, watchdog.alarm_counter());
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Sleep past the point where it would have fired if it wasn't disarmed,
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // and verify that it didn't fire.
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  PlatformThread::Sleep(1000);
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, watchdog.alarm_counter());
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ...but even after disarming, we can still use the alarm...
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Set a time greater than the timeout into the past.
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(10));
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // It should almost instantly go off, but certainly in less than 5 minutes.
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   watchdog.alarm_counter() > 0);
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, watchdog.alarm_counter());
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}  // namespace base
141