blob: 1641a920126764ca0978ceeda20ca9711d336a47 [file] [log] [blame]
#include "aos/common/util/phased_loop.h"
#include "gtest/gtest.h"
#include "aos/testing/test_logging.h"
namespace aos {
namespace time {
namespace testing {
class PhasedLoopTest : public ::testing::Test {
protected:
PhasedLoopTest() {
::aos::testing::EnableTestLogging();
}
};
typedef PhasedLoopTest PhasedLoopDeathTest;
TEST_F(PhasedLoopTest, Reset) {
{
PhasedLoop loop(Time::InMS(100), Time::kZero);
loop.Reset(Time::kZero);
EXPECT_EQ(Time::InMS(0), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::kZero));
EXPECT_EQ(Time::InMS(100), loop.sleep_time());
loop.Reset(Time::InMS(99));
EXPECT_EQ(Time::InMS(0), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(99)));
EXPECT_EQ(Time::InMS(100), loop.sleep_time());
loop.Reset(Time::InMS(100));
EXPECT_EQ(Time::InMS(100), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(199)));
EXPECT_EQ(Time::InMS(200), loop.sleep_time());
loop.Reset(Time::InMS(101));
EXPECT_EQ(Time::InMS(100), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(101)));
EXPECT_EQ(Time::InMS(200), loop.sleep_time());
}
{
PhasedLoop loop(Time::InMS(100), Time::InMS(1));
loop.Reset(Time::kZero);
EXPECT_EQ(Time::InMS(-99), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::kZero));
EXPECT_EQ(Time::InMS(1), loop.sleep_time());
}
{
PhasedLoop loop(Time::InMS(100), Time::InMS(99));
loop.Reset(Time::kZero);
EXPECT_EQ(Time::InMS(-1), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::kZero));
EXPECT_EQ(Time::InMS(99), loop.sleep_time());
loop.Reset(Time::InMS(98));
EXPECT_EQ(Time::InMS(-1), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(98)));
EXPECT_EQ(Time::InMS(99), loop.sleep_time());
loop.Reset(Time::InMS(99));
EXPECT_EQ(Time::InMS(99), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(99)));
EXPECT_EQ(Time::InMS(199), loop.sleep_time());
loop.Reset(Time::InMS(100));
EXPECT_EQ(Time::InMS(99), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(100)));
EXPECT_EQ(Time::InMS(199), loop.sleep_time());
}
}
TEST_F(PhasedLoopTest, Iterate) {
{
PhasedLoop loop(Time::InMS(100), Time::InMS(99));
loop.Reset(Time::kZero);
EXPECT_EQ(1, loop.Iterate(Time::kZero));
EXPECT_EQ(Time::InMS(99), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(100)));
EXPECT_EQ(Time::InMS(199), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(100)));
EXPECT_EQ(Time::InMS(199), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(101)));
EXPECT_EQ(Time::InMS(199), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(198)));
EXPECT_EQ(Time::InMS(199), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(199)));
EXPECT_EQ(Time::InMS(299), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(300)));
EXPECT_EQ(Time::InMS(399), loop.sleep_time());
EXPECT_EQ(3, loop.Iterate(Time::InMS(600)));
EXPECT_EQ(Time::InMS(699), loop.sleep_time());
}
{
PhasedLoop loop(Time::InMS(100), Time::InMS(1));
loop.Reset(Time::kZero);
EXPECT_EQ(1, loop.Iterate(Time::kZero));
EXPECT_EQ(Time::InMS(1), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(100)));
EXPECT_EQ(Time::InMS(101), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(100)));
EXPECT_EQ(Time::InMS(101), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(103)));
EXPECT_EQ(Time::InMS(201), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(198)));
EXPECT_EQ(Time::InMS(201), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(200)));
EXPECT_EQ(Time::InMS(201), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(201)));
EXPECT_EQ(Time::InMS(301), loop.sleep_time());
EXPECT_EQ(3, loop.Iterate(Time::InMS(600)));
EXPECT_EQ(Time::InMS(601), loop.sleep_time());
}
}
// Makes sure that everything works correctly when crossing zero.
// This seems like a rare case at first, but starting from zero needs to
// work, which means negatives should too.
TEST_F(PhasedLoopTest, CrossingZero) {
PhasedLoop loop(Time::InMS(100), Time::InMS(1));
loop.Reset(Time::InMS(-1000));
EXPECT_EQ(Time::InMS(-1099), loop.sleep_time());
EXPECT_EQ(9, loop.Iterate(Time::InMS(-250)));
EXPECT_EQ(Time::InMS(-199), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(-199)));
EXPECT_EQ(Time::InMS(-99), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(-90)));
EXPECT_EQ(Time::InMS(1), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(0)));
EXPECT_EQ(Time::InMS(1), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(1)));
EXPECT_EQ(Time::InMS(101), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(2)));
EXPECT_EQ(Time::InMS(101), loop.sleep_time());
EXPECT_EQ(-2, loop.Iterate(Time::InMS(-101)));
EXPECT_EQ(Time::InMS(-99), loop.sleep_time());
EXPECT_EQ(1, loop.Iterate(Time::InMS(-99)));
EXPECT_EQ(Time::InMS(1), loop.sleep_time());
EXPECT_EQ(0, loop.Iterate(Time::InMS(-99)));
EXPECT_EQ(Time::InMS(1), loop.sleep_time());
}
// Tests that passing invalid values to the constructor dies correctly.
TEST_F(PhasedLoopDeathTest, InvalidValues) {
EXPECT_DEATH(PhasedLoop(Time::InMS(1), Time::InMS(2)), ".*offset<interval.*");
EXPECT_DEATH(PhasedLoop(Time::InMS(1), Time::InMS(1)), ".*offset<interval.*");
EXPECT_DEATH(PhasedLoop(Time::InMS(1), Time::InMS(-1)),
".*offset>=Time::kZero.*");
EXPECT_DEATH(PhasedLoop(Time::InMS(0), Time::InMS(0)),
".*interval>Time::kZero.*");
}
} // namespace testing
} // namespace time
} // namespace aos