// Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Tests for Watchdog class. #include "base/logging.h" #include "base/watchdog.h" #include "base/spin_wait.h" #include "base/time.h" #include "testing/gtest/include/gtest/gtest.h" namespace { //------------------------------------------------------------------------------ // Provide a derived class to facilitate testing. // TODO(JAR): Remove default argument from constructor, and make mandatory. class WatchdogCounter : public Watchdog { public: WatchdogCounter(const TimeDelta& duration, const std::wstring& thread_watched_name, bool enabled = true) : Watchdog(duration, thread_watched_name, enabled), alarm_counter_(0) { } virtual ~WatchdogCounter() {} virtual void Alarm() { alarm_counter_++; Watchdog::Alarm(); } int alarm_counter() { return alarm_counter_; } private: int alarm_counter_; DISALLOW_EVIL_CONSTRUCTORS(WatchdogCounter); }; class WatchdogTest : public testing::Test { }; //------------------------------------------------------------------------------ // Actual tests // Minimal constructor/destructor test. TEST(WatchdogTest, StartupShutdownTest) { Watchdog watchdog1(TimeDelta::FromMilliseconds(300), L"Disabled", false); Watchdog watchdog2(TimeDelta::FromMilliseconds(300), L"Enabled", true); // The following test is depricated, and should be removed when the // default argument constructor is no longer accepted. Watchdog watchdog3(TimeDelta::FromMilliseconds(300), L"Default"); } // Test ability to call Arm and Disarm repeatedly. TEST(WatchdogTest, ArmDisarmTest) { Watchdog watchdog1(TimeDelta::FromMilliseconds(300), L"Disabled", false); watchdog1.Arm(); watchdog1.Disarm(); watchdog1.Arm(); watchdog1.Disarm(); Watchdog watchdog2(TimeDelta::FromMilliseconds(300), L"Enabled", true); watchdog2.Arm(); watchdog2.Disarm(); watchdog2.Arm(); watchdog2.Disarm(); // The following test is depricated, and should be removed when the // default argument constructor is no longer accepted. Watchdog watchdog3(TimeDelta::FromMilliseconds(300), L"Default"); watchdog3.Arm(); watchdog3.Disarm(); watchdog3.Arm(); watchdog3.Disarm(); } // Make sure a basic alarm fires when the time has expired. TEST(WatchdogTest, AlarmTest) { WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), L"Enabled", true); watchdog.Arm(); SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromSeconds(1), watchdog.alarm_counter() > 0); EXPECT_EQ(1, watchdog.alarm_counter()); // Set a time greater than the timeout into the past. watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2)); // It should instantly go off, but certainly in less than a second. SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromSeconds(1), watchdog.alarm_counter() > 1); EXPECT_EQ(2, watchdog.alarm_counter()); } // Make sure a disable alarm does nothing, even if we arm it. TEST(WatchdogTest, ConstructorDisabledTest) { WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), L"Disabled", false); watchdog.Arm(); // Alarm should not fire, as it was disabled. Sleep(500); EXPECT_EQ(0, watchdog.alarm_counter()); } // Make sure Disarming will prevent firing, even after Arming. TEST(WatchdogTest, DisarmTest) { WatchdogCounter watchdog(TimeDelta::FromSeconds(1), L"Enabled", true); watchdog.Arm(); Sleep(100); // Don't sleep too long watchdog.Disarm(); // Alarm should not fire. Sleep(1500); EXPECT_EQ(0, watchdog.alarm_counter()); // ...but even after disarming, we can still use the alarm... // Set a time greater than the timeout into the past. watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2)); // It should almost instantly go off, but certainly in less than a second. SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromSeconds(1), watchdog.alarm_counter() > 0); EXPECT_EQ(1, watchdog.alarm_counter()); } } // namespace