watchdog_unittest.cc 4.4 KB

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