blob: f8eb5da4747fe7f992470f841ad41522f62a518d [file] [log] [blame]
Parker Schuhe4a70d62017-12-27 20:10:20 -08001#include "aos/events/event-loop_param_test.h"
2
Austin Schuh3578a2e2019-05-25 18:17:59 -07003#include "gmock/gmock.h"
4#include "gtest/gtest.h"
5
Parker Schuhe4a70d62017-12-27 20:10:20 -08006namespace aos {
7namespace testing {
8
9struct TestMessage : public ::aos::Message {
10 enum { kQueueLength = 100, kHash = 0x696c0cdc };
11 int msg_value;
12
Austin Schuh7267c532019-05-19 19:55:53 -070013 void Zero() {
14 ::aos::Message::Zero();
15 msg_value = 0;
16 }
Parker Schuhe4a70d62017-12-27 20:10:20 -080017 static size_t Size() { return 1 + ::aos::Message::Size(); }
18 size_t Print(char *buffer, size_t length) const;
19 TestMessage() { Zero(); }
20};
21
Neil Balch229001a2018-01-07 18:22:52 -080022// Ends the given event loop at the given time from now.
23void EndEventLoop(EventLoop *loop, ::std::chrono::milliseconds duration) {
24 auto end_timer = loop->AddTimer([loop]() { loop->Exit(); });
25 end_timer->Setup(loop->monotonic_now() +
26 ::std::chrono::milliseconds(duration));
27}
28
Parker Schuhe4a70d62017-12-27 20:10:20 -080029// Tests that watcher and fetcher can fetch from a sender.
30// Also tests that OnRun() works.
31TEST_P(AbstractEventLoopTest, Basic) {
32 auto loop1 = Make();
33 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -070034 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -080035
36 auto sender = loop1->MakeSender<TestMessage>("/test");
37
38 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
39
Parker Schuhe4a70d62017-12-27 20:10:20 -080040 bool happened = false;
41
42 loop3->OnRun([&]() { happened = true; });
43
44 loop3->MakeWatcher("/test", [&](const TestMessage &message) {
45 EXPECT_EQ(message.msg_value, 200);
46 loop3->Exit();
47 });
48
Austin Schuh3578a2e2019-05-25 18:17:59 -070049 auto msg = sender.MakeMessage();
50 msg->msg_value = 200;
51 msg.Send();
52
53 EXPECT_TRUE(fetcher.Fetch());
54 ASSERT_FALSE(fetcher.get() == nullptr);
55 EXPECT_EQ(fetcher->msg_value, 200);
56
Parker Schuhe4a70d62017-12-27 20:10:20 -080057 EXPECT_FALSE(happened);
Austin Schuh44019f92019-05-19 19:58:27 -070058 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -080059 EXPECT_TRUE(happened);
60}
61
Austin Schuh3578a2e2019-05-25 18:17:59 -070062// Tests that watcher will receive all messages sent if they are sent after
63// initialization and before running.
64TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
65 auto loop1 = Make();
66 auto loop2 = MakePrimary();
67
68 auto sender = loop1->MakeSender<TestMessage>("/test");
69
70 ::std::vector<int> values;
71
72 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
73 fprintf(stderr, "Got a message\n");
74 values.push_back(message.msg_value);
75 if (values.size() == 2) {
76 loop2->Exit();
77 }
78 });
79
80 {
81 auto msg = sender.MakeMessage();
82 msg->msg_value = 200;
83 msg.Send();
84 }
85 {
86 auto msg = sender.MakeMessage();
87 msg->msg_value = 201;
88 msg.Send();
89 }
90
91 Run();
92
93 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
94}
95
96// Tests that watcher will not receive messages sent before the watcher is
97// created.
98TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
99 auto loop1 = Make();
100 auto loop2 = MakePrimary();
101
102 auto sender = loop1->MakeSender<TestMessage>("/test");
103
104 ::std::vector<int> values;
105
106 {
107 auto msg = sender.MakeMessage();
108 msg->msg_value = 200;
109 msg.Send();
110 }
111 {
112 auto msg = sender.MakeMessage();
113 msg->msg_value = 201;
114 msg.Send();
115 }
116
117 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
118 values.push_back(message.msg_value);
119 });
120
121 // Add a timer to actually quit.
122 auto test_timer = loop2->AddTimer([&loop2]() { loop2->Exit(); });
123 loop2->OnRun([&test_timer, &loop2]() {
124 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
125 });
126
127 Run();
128 EXPECT_EQ(0, values.size());
129}
130
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800131// Verify that making a fetcher and watcher for "/test" succeeds.
132TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800133 auto loop = Make();
134 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800135 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800136}
137
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800138// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800139TEST_P(AbstractEventLoopTest, TwoFetcher) {
140 auto loop = Make();
141 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800142 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800143}
144
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800145// Verify that registering a watcher twice for "/test" fails.
146TEST_P(AbstractEventLoopTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800147 auto loop = Make();
148 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800149 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
150 "/test");
151}
152
153// Verify that registering a watcher and a sender for "/test" fails.
154TEST_P(AbstractEventLoopTest, WatcherAndSender) {
155 auto loop = Make();
156 auto sender = loop->MakeSender<TestMessage>("/test");
157 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
158 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800159}
160
161// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800162TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
163 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700164 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800165
Austin Schuh3578a2e2019-05-25 18:17:59 -0700166 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
167 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
168 EXPECT_EQ(message.msg_value, 200);
169 loop2->Exit();
170 });
171
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800172 auto sender = loop1->MakeSender<TestMessage>("/test2");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800173 {
174 auto msg = sender.MakeMessage();
175 msg->msg_value = 200;
176 msg.Send();
177 }
178
Austin Schuh44019f92019-05-19 19:58:27 -0700179 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800180}
181
Neil Balch229001a2018-01-07 18:22:52 -0800182// Verify that timer intervals and duration function properly.
183TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Austin Schuh44019f92019-05-19 19:58:27 -0700184 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800185 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
186
187 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
188 iteration_list.push_back(loop->monotonic_now());
189 });
190
191 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
192 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
193 // Testing that the timer thread waits for the event loop to start before
194 // running
195 ::std::this_thread::sleep_for(std::chrono::milliseconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -0700196 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800197
198 EXPECT_EQ(iteration_list.size(), 8);
199}
200
201// Verify that we can change a timer's parameters during execution.
202TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -0700203 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800204 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
205
206 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
207 iteration_list.push_back(loop->monotonic_now());
208 });
209
210 auto modifier_timer = loop->AddTimer([&loop, &test_timer]() {
211 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(30));
212 });
213
214
215 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
216 modifier_timer->Setup(loop->monotonic_now() +
217 ::std::chrono::milliseconds(45));
218 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700219 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800220
221 EXPECT_EQ(iteration_list.size(), 7);
222}
223
224// Verify that we can disable a timer during execution.
225TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -0700226 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800227 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
228
229 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
230 iteration_list.push_back(loop->monotonic_now());
231 });
232
233 auto ender_timer = loop->AddTimer([&test_timer]() {
234 test_timer->Disable();
235 });
236
237 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
238 ender_timer->Setup(loop->monotonic_now() +
239 ::std::chrono::milliseconds(45));
240 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700241 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800242
243 EXPECT_EQ(iteration_list.size(), 3);
244}
Austin Schuh7267c532019-05-19 19:55:53 -0700245
246// Verify that the send time on a message is roughly right.
247TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -0700248 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -0700249 auto loop2 = Make();
250 auto sender = loop1->MakeSender<TestMessage>("/test");
251 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
252
253 auto test_timer = loop1->AddTimer([&sender]() {
254 auto msg = sender.MakeMessage();
255 msg->msg_value = 200;
256 msg.Send();
257 });
258
259 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
260
261 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -0700262 Run();
Austin Schuh7267c532019-05-19 19:55:53 -0700263
264 EXPECT_TRUE(fetcher.Fetch());
265
266 monotonic_clock::duration time_offset =
267 fetcher->sent_time - (loop1->monotonic_now() - ::std::chrono::seconds(1));
268
269 EXPECT_TRUE(time_offset > ::std::chrono::milliseconds(-500))
270 << ": Got " << fetcher->sent_time.time_since_epoch().count() << " expected "
271 << loop1->monotonic_now().time_since_epoch().count();
272 EXPECT_TRUE(time_offset < ::std::chrono::milliseconds(500))
273 << ": Got " << fetcher->sent_time.time_since_epoch().count()
274 << " expected " << loop1->monotonic_now().time_since_epoch().count();
275}
276
Parker Schuhe4a70d62017-12-27 20:10:20 -0800277} // namespace testing
278} // namespace aos