blob: b013c2e9db7f7e85abbc12fefedad06f9548b157 [file] [log] [blame]
Brian Silvermandcaa3f72015-11-29 05:32:08 +00001#include "aos/common/util/phased_loop.h"
2
3#include "gtest/gtest.h"
4
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05005#include "aos/testing/test_logging.h"
Brian Silvermandcaa3f72015-11-29 05:32:08 +00006
7namespace aos {
8namespace time {
9namespace testing {
10
Austin Schuh8aec1ed2016-05-01 13:29:20 -070011using ::std::chrono::milliseconds;
12
Brian Silvermandcaa3f72015-11-29 05:32:08 +000013class PhasedLoopTest : public ::testing::Test {
14 protected:
Austin Schuh8aec1ed2016-05-01 13:29:20 -070015 PhasedLoopTest() { ::aos::testing::EnableTestLogging(); }
Brian Silvermandcaa3f72015-11-29 05:32:08 +000016};
17
18typedef PhasedLoopTest PhasedLoopDeathTest;
19
Austin Schuh8aec1ed2016-05-01 13:29:20 -070020monotonic_clock::time_point InMs(int ms) {
21 return monotonic_clock::time_point(::std::chrono::milliseconds(ms));
22}
23
Brian Silvermandcaa3f72015-11-29 05:32:08 +000024TEST_F(PhasedLoopTest, Reset) {
25 {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070026 PhasedLoop loop(milliseconds(100), milliseconds(0));
Brian Silvermandcaa3f72015-11-29 05:32:08 +000027
Austin Schuh8aec1ed2016-05-01 13:29:20 -070028 loop.Reset(monotonic_clock::epoch());
29 EXPECT_EQ(InMs(0), loop.sleep_time());
30 EXPECT_EQ(1, loop.Iterate(monotonic_clock::epoch()));
31 EXPECT_EQ(InMs(100), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000032
Austin Schuh8aec1ed2016-05-01 13:29:20 -070033 loop.Reset(InMs(99));
34 EXPECT_EQ(InMs(0), loop.sleep_time());
35 EXPECT_EQ(1, loop.Iterate(InMs(99)));
36 EXPECT_EQ(InMs(100), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000037
Austin Schuh8aec1ed2016-05-01 13:29:20 -070038 loop.Reset(InMs(100));
39 EXPECT_EQ(InMs(100), loop.sleep_time());
40 EXPECT_EQ(1, loop.Iterate(InMs(199)));
41 EXPECT_EQ(InMs(200), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000042
Austin Schuh8aec1ed2016-05-01 13:29:20 -070043 loop.Reset(InMs(101));
44 EXPECT_EQ(InMs(100), loop.sleep_time());
45 EXPECT_EQ(1, loop.Iterate(InMs(101)));
46 EXPECT_EQ(InMs(200), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000047 }
48 {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070049 PhasedLoop loop(milliseconds(100), milliseconds(1));
50 loop.Reset(monotonic_clock::epoch());
51 EXPECT_EQ(InMs(-99), loop.sleep_time());
52 EXPECT_EQ(1, loop.Iterate(monotonic_clock::epoch()));
53 EXPECT_EQ(InMs(1), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000054 }
55 {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070056 PhasedLoop loop(milliseconds(100), milliseconds(99));
Brian Silvermandcaa3f72015-11-29 05:32:08 +000057
Austin Schuh8aec1ed2016-05-01 13:29:20 -070058 loop.Reset(monotonic_clock::epoch());
59 EXPECT_EQ(InMs(-1), loop.sleep_time());
60 EXPECT_EQ(1, loop.Iterate(monotonic_clock::epoch()));
61 EXPECT_EQ(InMs(99), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000062
Austin Schuh8aec1ed2016-05-01 13:29:20 -070063 loop.Reset(InMs(98));
64 EXPECT_EQ(InMs(-1), loop.sleep_time());
65 EXPECT_EQ(1, loop.Iterate(InMs(98)));
66 EXPECT_EQ(InMs(99), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000067
Austin Schuh8aec1ed2016-05-01 13:29:20 -070068 loop.Reset(InMs(99));
69 EXPECT_EQ(InMs(99), loop.sleep_time());
70 EXPECT_EQ(1, loop.Iterate(InMs(99)));
71 EXPECT_EQ(InMs(199), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000072
Austin Schuh8aec1ed2016-05-01 13:29:20 -070073 loop.Reset(InMs(100));
74 EXPECT_EQ(InMs(99), loop.sleep_time());
75 EXPECT_EQ(1, loop.Iterate(InMs(100)));
76 EXPECT_EQ(InMs(199), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000077 }
78}
79
80TEST_F(PhasedLoopTest, Iterate) {
81 {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070082 PhasedLoop loop(milliseconds(100), milliseconds(99));
83 loop.Reset(monotonic_clock::epoch());
84 EXPECT_EQ(1, loop.Iterate(monotonic_clock::epoch()));
85 EXPECT_EQ(InMs(99), loop.sleep_time());
86 EXPECT_EQ(1, loop.Iterate(InMs(100)));
87 EXPECT_EQ(InMs(199), loop.sleep_time());
88 EXPECT_EQ(0, loop.Iterate(InMs(100)));
89 EXPECT_EQ(InMs(199), loop.sleep_time());
90 EXPECT_EQ(0, loop.Iterate(InMs(101)));
91 EXPECT_EQ(InMs(199), loop.sleep_time());
92 EXPECT_EQ(0, loop.Iterate(InMs(198)));
93 EXPECT_EQ(InMs(199), loop.sleep_time());
94 EXPECT_EQ(1, loop.Iterate(InMs(199)));
95 EXPECT_EQ(InMs(299), loop.sleep_time());
96 EXPECT_EQ(1, loop.Iterate(InMs(300)));
97 EXPECT_EQ(InMs(399), loop.sleep_time());
98 EXPECT_EQ(3, loop.Iterate(InMs(600)));
99 EXPECT_EQ(InMs(699), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000100 }
101 {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700102 PhasedLoop loop(milliseconds(100), milliseconds(1));
103 loop.Reset(monotonic_clock::epoch());
104 EXPECT_EQ(1, loop.Iterate(monotonic_clock::epoch()));
105 EXPECT_EQ(InMs(1), loop.sleep_time());
106 EXPECT_EQ(1, loop.Iterate(InMs(100)));
107 EXPECT_EQ(InMs(101), loop.sleep_time());
108 EXPECT_EQ(0, loop.Iterate(InMs(100)));
109 EXPECT_EQ(InMs(101), loop.sleep_time());
110 EXPECT_EQ(1, loop.Iterate(InMs(103)));
111 EXPECT_EQ(InMs(201), loop.sleep_time());
112 EXPECT_EQ(0, loop.Iterate(InMs(198)));
113 EXPECT_EQ(InMs(201), loop.sleep_time());
114 EXPECT_EQ(0, loop.Iterate(InMs(200)));
115 EXPECT_EQ(InMs(201), loop.sleep_time());
116 EXPECT_EQ(1, loop.Iterate(InMs(201)));
117 EXPECT_EQ(InMs(301), loop.sleep_time());
118 EXPECT_EQ(3, loop.Iterate(InMs(600)));
119 EXPECT_EQ(InMs(601), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000120 }
121}
122
123// Makes sure that everything works correctly when crossing zero.
124// This seems like a rare case at first, but starting from zero needs to
125// work, which means negatives should too.
126TEST_F(PhasedLoopTest, CrossingZero) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700127 PhasedLoop loop(milliseconds(100), milliseconds(1));
128 loop.Reset(InMs(-1000));
129 EXPECT_EQ(InMs(-1099), loop.sleep_time());
130 EXPECT_EQ(9, loop.Iterate(InMs(-250)));
131 EXPECT_EQ(InMs(-199), loop.sleep_time());
132 EXPECT_EQ(1, loop.Iterate(InMs(-199)));
133 EXPECT_EQ(InMs(-99), loop.sleep_time());
134 EXPECT_EQ(1, loop.Iterate(InMs(-90)));
135 EXPECT_EQ(InMs(1), loop.sleep_time());
136 EXPECT_EQ(0, loop.Iterate(InMs(0)));
137 EXPECT_EQ(InMs(1), loop.sleep_time());
138 EXPECT_EQ(1, loop.Iterate(InMs(1)));
139 EXPECT_EQ(InMs(101), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000140
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700141 EXPECT_EQ(0, loop.Iterate(InMs(2)));
142 EXPECT_EQ(InMs(101), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000143
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700144 EXPECT_EQ(-2, loop.Iterate(InMs(-101)));
145 EXPECT_EQ(InMs(-99), loop.sleep_time());
146 EXPECT_EQ(1, loop.Iterate(InMs(-99)));
147 EXPECT_EQ(InMs(1), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000148
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700149 EXPECT_EQ(0, loop.Iterate(InMs(-99)));
150 EXPECT_EQ(InMs(1), loop.sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000151}
152
153// Tests that passing invalid values to the constructor dies correctly.
154TEST_F(PhasedLoopDeathTest, InvalidValues) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -0700155 EXPECT_DEATH(PhasedLoop(milliseconds(1), milliseconds(2)),
156 ".*offset<interval.*");
157 EXPECT_DEATH(PhasedLoop(milliseconds(1), milliseconds(1)),
158 ".*offset<interval.*");
159 EXPECT_DEATH(PhasedLoop(milliseconds(1), milliseconds(-1)),
160 ".*offset>=monotonic_clock::duration\\(0\\).*");
161 EXPECT_DEATH(PhasedLoop(milliseconds(0), milliseconds(0)),
162 ".*interval>monotonic_clock::duration\\(0\\).*");
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000163}
164
165} // namespace testing
166} // namespace time
167} // namespace aos