blob: 3f569afdb5f363921183fe915ac7a831a8dbc8bf [file] [log] [blame]
// 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