#include "base/threading/watchdog.h"
#include <atomic>
#include "base/logging.h"
#include "base/test/spin_wait.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace {
class WatchdogCounter : public Watchdog::Delegate {
public:
WatchdogCounter(const TimeDelta& duration,
const std::string& thread_watched_name,
bool enabled)
: watchdog_(duration, thread_watched_name, enabled, this) {}
WatchdogCounter(const WatchdogCounter&) = delete;
WatchdogCounter& operator=(const WatchdogCounter&) = delete;
~WatchdogCounter() override = default;
void Alarm() override {
alarm_counter_++;
watchdog_.DefaultAlarm();
}
Watchdog& watchdog() { return watchdog_; }
int alarm_counter() { return alarm_counter_.load(); }
private:
std::atomic<int> alarm_counter_{0};
Watchdog watchdog_;
};
class WatchdogTest : public testing::Test {
public:
void SetUp() override { Watchdog::ResetStaticData(); }
};
}
TEST_F(WatchdogTest, StartupShutdownTest) {
Watchdog watchdog1(Milliseconds(300), "Disabled", false);
Watchdog watchdog2(Milliseconds(300), "Enabled", true);
}
TEST_F(WatchdogTest, ArmDisarmTest) {
Watchdog watchdog1(Milliseconds(300), "Disabled", false);
watchdog1.Arm();
watchdog1.Disarm();
watchdog1.Arm();
watchdog1.Disarm();
Watchdog watchdog2(Milliseconds(300), "Enabled", true);
watchdog2.Arm();
watchdog2.Disarm();
watchdog2.Arm();
watchdog2.Disarm();
}
TEST_F(WatchdogTest, AlarmTest) {
WatchdogCounter watchdog(Milliseconds(10), "Enabled", true);
watchdog.watchdog().Arm();
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(Minutes(5), watchdog.alarm_counter() > 0);
EXPECT_EQ(1, watchdog.alarm_counter());
}
TEST_F(WatchdogTest, AlarmPriorTimeTest) {
WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
watchdog.watchdog().ArmSomeTimeDeltaAgo(Seconds(2));
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(Minutes(5), watchdog.alarm_counter() > 0);
EXPECT_EQ(1, watchdog.alarm_counter());
}
TEST_F(WatchdogTest, ConstructorDisabledTest) {
WatchdogCounter watchdog(Milliseconds(10), "Disabled", false);
watchdog.watchdog().Arm();
PlatformThread::Sleep(Milliseconds(500));
EXPECT_EQ(0, watchdog.alarm_counter());
}
TEST_F(WatchdogTest, DisarmTest) {
WatchdogCounter watchdog(Seconds(1), "Enabled3", true);
TimeTicks start = TimeTicks::Now();
watchdog.watchdog().Arm();
PlatformThread::Sleep(Milliseconds(100));
watchdog.watchdog().Disarm();
TimeTicks end = TimeTicks::Now();
if (end - start > Milliseconds(500)) {
LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
<< "timing-sensitive test suspicious. Aborting now.";
return;
}
EXPECT_EQ(0, watchdog.alarm_counter());
PlatformThread::Sleep(Seconds(1));
EXPECT_EQ(0, watchdog.alarm_counter());
watchdog.watchdog().ArmSomeTimeDeltaAgo(Seconds(10));
SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(Minutes(5), watchdog.alarm_counter() > 0);
EXPECT_EQ(1, watchdog.alarm_counter());
}
}