blob: 8defcb5707ea441fd7b873eaf68114cb1e27d90c [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/event_loop_param_test.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08002
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
4
Alex Perrycb7da4b2019-08-28 19:35:56 -07005#include "glog/logging.h"
Austin Schuh3578a2e2019-05-25 18:17:59 -07006#include "gmock/gmock.h"
7#include "gtest/gtest.h"
8
Alex Perrycb7da4b2019-08-28 19:35:56 -07009#include "aos/events/test_message_generated.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -080010#include "aos/flatbuffer_merge.h"
11#include "glog/logging.h"
Austin Schuh9fe68f72019-08-10 19:32:03 -070012
Parker Schuhe4a70d62017-12-27 20:10:20 -080013namespace aos {
14namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070015namespace {
16namespace chrono = ::std::chrono;
17} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080018
Austin Schuh6b6dfa52019-06-12 20:16:20 -070019// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080020// Also tests that OnRun() works.
21TEST_P(AbstractEventLoopTest, Basic) {
22 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070023 auto loop2 = MakePrimary();
24
Alex Perrycb7da4b2019-08-28 19:35:56 -070025 aos::Sender<TestMessage> sender = loop1->MakeSender<TestMessage>("/test");
Austin Schuh6b6dfa52019-06-12 20:16:20 -070026
27 bool happened = false;
28
29 loop2->OnRun([&]() {
30 happened = true;
31
Alex Perrycb7da4b2019-08-28 19:35:56 -070032 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
33 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
34 builder.add_value(200);
35 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070036 });
37
38 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070039 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -070040 this->Exit();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070041 });
42
43 EXPECT_FALSE(happened);
44 Run();
45 EXPECT_TRUE(happened);
46}
47
48// Tests that a fetcher can fetch from a sender.
49// Also tests that OnRun() works.
50TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
51 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -080052 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -070053 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -080054
55 auto sender = loop1->MakeSender<TestMessage>("/test");
56
57 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
58
Austin Schuhbbce72d2019-05-26 15:11:46 -070059 EXPECT_FALSE(fetcher.Fetch());
60
Alex Perrycb7da4b2019-08-28 19:35:56 -070061 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
62 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
63 builder.add_value(200);
64 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -070065
66 EXPECT_TRUE(fetcher.Fetch());
67 ASSERT_FALSE(fetcher.get() == nullptr);
Alex Perrycb7da4b2019-08-28 19:35:56 -070068 EXPECT_EQ(fetcher.get()->value(), 200);
Parker Schuhe4a70d62017-12-27 20:10:20 -080069}
70
Austin Schuh3578a2e2019-05-25 18:17:59 -070071// Tests that watcher will receive all messages sent if they are sent after
72// initialization and before running.
73TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
74 auto loop1 = Make();
75 auto loop2 = MakePrimary();
76
77 auto sender = loop1->MakeSender<TestMessage>("/test");
78
79 ::std::vector<int> values;
80
81 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -070083 if (values.size() == 2) {
Austin Schuh9fe68f72019-08-10 19:32:03 -070084 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -070085 }
86 });
87
Austin Schuh6b6dfa52019-06-12 20:16:20 -070088 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -070089 {
Alex Perrycb7da4b2019-08-28 19:35:56 -070090 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
91 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
92 builder.add_value(199);
93 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -070094 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -070095
96 loop2->OnRun([&]() {
97 {
Alex Perrycb7da4b2019-08-28 19:35:56 -070098 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
99 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
100 builder.add_value(200);
101 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700102 }
103 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700104 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
105 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
106 builder.add_value(201);
107 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700108 }
109 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700110
111 Run();
112
113 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
114}
115
116// Tests that watcher will not receive messages sent before the watcher is
117// created.
118TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
119 auto loop1 = Make();
120 auto loop2 = MakePrimary();
121
122 auto sender = loop1->MakeSender<TestMessage>("/test");
123
124 ::std::vector<int> values;
125
126 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700127 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
128 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
129 builder.add_value(200);
130 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700131 }
132 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700133 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
134 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
135 builder.add_value(201);
136 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3578a2e2019-05-25 18:17:59 -0700137 }
138
139 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700140 values.push_back(message.value());
Austin Schuh3578a2e2019-05-25 18:17:59 -0700141 });
142
143 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700144 auto test_timer = loop2->AddTimer([this]() { this->Exit(); });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700145 loop2->OnRun([&test_timer, &loop2]() {
146 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
147 });
148
149 Run();
150 EXPECT_EQ(0, values.size());
151}
152
Austin Schuhbbce72d2019-05-26 15:11:46 -0700153// Tests that FetchNext gets all the messages sent after it is constructed.
154TEST_P(AbstractEventLoopTest, FetchNext) {
155 auto loop1 = Make();
156 auto loop2 = MakePrimary();
157
158 auto sender = loop1->MakeSender<TestMessage>("/test");
159 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
160
161 ::std::vector<int> values;
162
163 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700164 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
165 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
166 builder.add_value(200);
167 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700168 }
169 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700170 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
171 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
172 builder.add_value(201);
173 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700174 }
175
176 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700177 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700178 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700179 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700180 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700181 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700182 });
183
184 loop2->OnRun([&test_timer, &loop2]() {
185 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
186 });
187
188 Run();
189 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
190}
191
192// Tests that FetchNext gets no messages sent before it is constructed.
193TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
194 auto loop1 = Make();
195 auto loop2 = MakePrimary();
196
197 auto sender = loop1->MakeSender<TestMessage>("/test");
198
199 ::std::vector<int> values;
200
201 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700202 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
203 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
204 builder.add_value(200);
205 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700206 }
207 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700208 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
209 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
210 builder.add_value(201);
211 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700212 }
213
214 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
215
216 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700217 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700218 while (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700219 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700220 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700221 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700222 });
223
224 loop2->OnRun([&test_timer, &loop2]() {
225 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
226 });
227
228 Run();
229 EXPECT_THAT(0, values.size());
230}
231
232// Tests that Fetch returns the last message created before the loop was
233// started.
234TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
235 auto loop1 = Make();
236 auto loop2 = MakePrimary();
237
238 auto sender = loop1->MakeSender<TestMessage>("/test");
239
240 ::std::vector<int> values;
241
242 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700243 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
244 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
245 builder.add_value(200);
246 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700247 }
248 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700249 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
250 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
251 builder.add_value(201);
252 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700253 }
254
255 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
256
257 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700258 auto test_timer = loop2->AddTimer([&fetcher, &values, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700259 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700260 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700261 }
262 // Do it again to make sure we don't double fetch.
263 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700264 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700265 }
Austin Schuh9fe68f72019-08-10 19:32:03 -0700266 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700267 });
268
269 loop2->OnRun([&test_timer, &loop2]() {
270 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
271 });
272
273 Run();
274 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
275}
276
277// Tests that Fetch and FetchNext interleave as expected.
278TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
279 auto loop1 = Make();
280 auto loop2 = MakePrimary();
281
282 auto sender = loop1->MakeSender<TestMessage>("/test");
283
284 ::std::vector<int> values;
285
286 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700287 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
288 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
289 builder.add_value(200);
290 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700291 }
292 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700293 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
294 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
295 builder.add_value(201);
296 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700297 }
298
299 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
300
301 // Add a timer to actually quit.
Austin Schuh9fe68f72019-08-10 19:32:03 -0700302 auto test_timer = loop2->AddTimer([&fetcher, &values, &sender, this]() {
Austin Schuhbbce72d2019-05-26 15:11:46 -0700303 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700304 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700305 }
306
307 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700308 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
309 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
310 builder.add_value(202);
311 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700312 }
313 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700314 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
315 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
316 builder.add_value(203);
317 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700318 }
319 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700320 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
321 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
322 builder.add_value(204);
323 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuhbbce72d2019-05-26 15:11:46 -0700324 }
325
326 if (fetcher.FetchNext()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700327 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700328 }
329
330 if (fetcher.Fetch()) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700331 values.push_back(fetcher.get()->value());
Austin Schuhbbce72d2019-05-26 15:11:46 -0700332 }
333
Austin Schuh9fe68f72019-08-10 19:32:03 -0700334 this->Exit();
Austin Schuhbbce72d2019-05-26 15:11:46 -0700335 });
336
337 loop2->OnRun([&test_timer, &loop2]() {
338 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
339 });
340
341 Run();
342 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
343}
344
Austin Schuh3115a202019-05-27 21:02:14 -0700345
346// Tests that FetchNext behaves correctly when we get two messages in the queue
347// but don't consume the first until after the second has been sent.
348TEST_P(AbstractEventLoopTest, FetchNextTest) {
349
350 auto send_loop = Make();
351 auto fetch_loop = Make();
352 auto sender = send_loop->MakeSender<TestMessage>("/test");
353 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
354
355 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700356 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
357 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
358 builder.add_value(100);
359 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700360 }
361
362 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700363 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
364 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
365 builder.add_value(200);
366 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh3115a202019-05-27 21:02:14 -0700367 }
368
369 ASSERT_TRUE(fetcher.FetchNext());
370 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700371 EXPECT_EQ(100, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700372
373 ASSERT_TRUE(fetcher.FetchNext());
374 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700375 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700376
377 // When we run off the end of the queue, expect to still have the old message:
378 ASSERT_FALSE(fetcher.FetchNext());
379 ASSERT_NE(nullptr, fetcher.get());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700380 EXPECT_EQ(200, fetcher.get()->value());
Austin Schuh3115a202019-05-27 21:02:14 -0700381}
382
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800383// Verify that making a fetcher and watcher for "/test" succeeds.
384TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800385 auto loop = Make();
386 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800387 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800388}
389
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800390// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800391TEST_P(AbstractEventLoopTest, TwoFetcher) {
392 auto loop = Make();
393 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800394 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800395}
396
Alex Perrycb7da4b2019-08-28 19:35:56 -0700397// Verify that registering a watcher for an invalid channel name dies.
398TEST_P(AbstractEventLoopDeathTest, InvalidChannelName) {
399 auto loop = Make();
400 EXPECT_DEATH(
401 { loop->MakeWatcher("/test/invalid", [&](const TestMessage &) {}); },
402 "/test/invalid");
403}
404
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800405// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700406TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800407 auto loop = Make();
408 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800409 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
410 "/test");
411}
412
Austin Schuh3115a202019-05-27 21:02:14 -0700413// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700414TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700415 auto loop = MakePrimary();
416 // Confirm that runtime priority calls work when not realtime.
417 loop->SetRuntimeRealtimePriority(5);
418
419 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
420
421 EXPECT_DEATH(Run(), "realtime");
422}
423
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800424// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700425TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800426 auto loop = Make();
427 auto sender = loop->MakeSender<TestMessage>("/test");
428 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
429 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800430}
431
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700432// Verify that we can't create a sender inside OnRun.
433TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
434 auto loop1 = MakePrimary();
435
436 loop1->OnRun(
437 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
438
439 EXPECT_DEATH(Run(), "running");
440}
441
442// Verify that we can't create a watcher inside OnRun.
443TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
444 auto loop1 = MakePrimary();
445
446 loop1->OnRun(
447 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
448
449 EXPECT_DEATH(Run(), "running");
450}
451
Parker Schuhe4a70d62017-12-27 20:10:20 -0800452// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800453TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
454 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700455 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800456
Austin Schuh3578a2e2019-05-25 18:17:59 -0700457 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
458 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700459 EXPECT_EQ(message.value(), 200);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700460 this->Exit();
Austin Schuh3578a2e2019-05-25 18:17:59 -0700461 });
462
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800463 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700464
465 loop2->OnRun([&]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700466 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
467 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
468 builder.add_value(200);
469 ASSERT_TRUE(msg.Send(builder.Finish()));
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700470 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800471
Austin Schuh44019f92019-05-19 19:58:27 -0700472 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800473}
474
Neil Balch229001a2018-01-07 18:22:52 -0800475// Verify that timer intervals and duration function properly.
476TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800477 const int kCount = 5;
Neil Balch229001a2018-01-07 18:22:52 -0800478
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800479 auto loop = MakePrimary();
480 ::std::vector<::aos::monotonic_clock::time_point> times;
481 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
482
483 auto test_timer = loop->AddTimer([this, &times, &expected_times, &loop]() {
484 times.push_back(loop->monotonic_now());
485 expected_times.push_back(loop->context().monotonic_sent_time);
486 if (times.size() == kCount) {
487 this->Exit();
488 }
Neil Balch229001a2018-01-07 18:22:52 -0800489 });
490
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800491 monotonic_clock::time_point start_time = loop->monotonic_now();
Austin Schuh52d325c2019-06-23 18:59:06 -0700492 // TODO(austin): This should be an error... Should be done in OnRun only.
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800493 test_timer->Setup(start_time + chrono::seconds(1), chrono::seconds(1));
494
Austin Schuh44019f92019-05-19 19:58:27 -0700495 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800496
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800497 // Confirm that we got both the right number of samples, and it's odd.
498 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
499 EXPECT_EQ(times.size(), expected_times.size());
500 EXPECT_EQ((times.size() % 2), 1);
501
502 // Grab the middle sample.
503 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
504
505 // Add up all the delays of all the times.
506 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
507 for (const ::aos::monotonic_clock::time_point time : times) {
508 sum += time - average_time;
509 }
510
511 // Average and add to the middle to find the average time.
512 sum /= times.size();
513 average_time += sum;
514
515 // Compute the offset from the average and the expected average. It
516 // should be pretty close to 0.
517 const ::aos::monotonic_clock::duration remainder =
518 average_time - start_time - chrono::seconds(times.size() / 2 + 1);
519
520 const chrono::milliseconds kEpsilon(100);
521 EXPECT_LT(remainder, +kEpsilon);
522 EXPECT_GT(remainder, -kEpsilon);
523
524 // Make sure that the average duration is close to 1 second.
525 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
526 times.front())
527 .count() /
528 static_cast<double>(times.size() - 1),
529 1.0, 0.1);
530
531 // Confirm that the ideal wakeup times increment correctly.
532 for (size_t i = 1; i < expected_times.size(); ++i) {
533 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
534 }
535
536 for (size_t i = 0; i < expected_times.size(); ++i) {
537 EXPECT_EQ((expected_times[i] - start_time) % chrono::seconds(1),
538 chrono::seconds(0));
539 }
540
541 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
542 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Neil Balch229001a2018-01-07 18:22:52 -0800543}
544
545// Verify that we can change a timer's parameters during execution.
546TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -0700547 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800548 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
549
550 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
551 iteration_list.push_back(loop->monotonic_now());
552 });
553
554 auto modifier_timer = loop->AddTimer([&loop, &test_timer]() {
555 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(30));
556 });
557
Neil Balch229001a2018-01-07 18:22:52 -0800558 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
559 modifier_timer->Setup(loop->monotonic_now() +
560 ::std::chrono::milliseconds(45));
561 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700562 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800563
564 EXPECT_EQ(iteration_list.size(), 7);
565}
566
567// Verify that we can disable a timer during execution.
568TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -0700569 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800570 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
571
572 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
573 iteration_list.push_back(loop->monotonic_now());
574 });
575
576 auto ender_timer = loop->AddTimer([&test_timer]() {
577 test_timer->Disable();
578 });
579
580 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
581 ender_timer->Setup(loop->monotonic_now() +
582 ::std::chrono::milliseconds(45));
583 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700584 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800585
586 EXPECT_EQ(iteration_list.size(), 3);
587}
Austin Schuh7267c532019-05-19 19:55:53 -0700588
Austin Schuh54cf95f2019-11-29 13:14:18 -0800589// Verifies that the event loop implementations detect when Channel is not a
590// pointer into confguration()
591TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
592 auto loop = MakePrimary();
593
594 const Channel *channel = loop->configuration()->channels()->Get(0);
595
596 FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
597
598 EXPECT_DEATH(
599 { loop->MakeRawSender(&channel_copy.message()); },
600 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
601
602 EXPECT_DEATH(
603 { loop->MakeRawFetcher(&channel_copy.message()); },
604 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
605
606 EXPECT_DEATH(
607 {
608 loop->MakeRawWatcher(&channel_copy.message(),
609 [](const Context, const void *) {});
610 },
611 "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
612}
613
Austin Schuh7267c532019-05-19 19:55:53 -0700614// Verify that the send time on a message is roughly right.
615TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -0700616 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -0700617 auto loop2 = Make();
618 auto sender = loop1->MakeSender<TestMessage>("/test");
619 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
620
621 auto test_timer = loop1->AddTimer([&sender]() {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700622 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
623 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
624 builder.add_value(200);
625 ASSERT_TRUE(msg.Send(builder.Finish()));
626 });
627
628 loop2->MakeWatcher("/test", [&loop2](const TestMessage &msg) {
629 // Confirm that the data pointer makes sense from a watcher.
630 EXPECT_GT(&msg, loop2->context().data);
631 EXPECT_LT(&msg, reinterpret_cast<void *>(
632 reinterpret_cast<char *>(loop2->context().data) +
633 loop2->context().size));
Austin Schuh7267c532019-05-19 19:55:53 -0700634 });
635
636 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
637
638 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -0700639 Run();
Austin Schuh7267c532019-05-19 19:55:53 -0700640
641 EXPECT_TRUE(fetcher.Fetch());
642
Alex Perrycb7da4b2019-08-28 19:35:56 -0700643 monotonic_clock::duration monotonic_time_offset =
644 fetcher.context().monotonic_sent_time -
645 (loop1->monotonic_now() - ::std::chrono::seconds(1));
646 realtime_clock::duration realtime_time_offset =
647 fetcher.context().realtime_sent_time -
648 (loop1->realtime_now() - ::std::chrono::seconds(1));
Austin Schuh7267c532019-05-19 19:55:53 -0700649
Alex Perrycb7da4b2019-08-28 19:35:56 -0700650 EXPECT_TRUE(monotonic_time_offset > ::std::chrono::milliseconds(-500))
651 << ": Got "
652 << fetcher.context().monotonic_sent_time.time_since_epoch().count()
Austin Schuh52d325c2019-06-23 18:59:06 -0700653 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700654 // Confirm that the data pointer makes sense.
655 EXPECT_GT(fetcher.get(), fetcher.context().data);
656 EXPECT_LT(fetcher.get(),
657 reinterpret_cast<void *>(
658 reinterpret_cast<char *>(fetcher.context().data) +
659 fetcher.context().size));
660 EXPECT_TRUE(monotonic_time_offset < ::std::chrono::milliseconds(500))
661 << ": Got "
662 << fetcher.context().monotonic_sent_time.time_since_epoch().count()
Austin Schuh7267c532019-05-19 19:55:53 -0700663 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700664
665 EXPECT_TRUE(realtime_time_offset > ::std::chrono::milliseconds(-500))
666 << ": Got "
667 << fetcher.context().realtime_sent_time.time_since_epoch().count()
668 << " expected " << loop1->realtime_now().time_since_epoch().count();
669 EXPECT_TRUE(realtime_time_offset < ::std::chrono::milliseconds(500))
670 << ": Got "
671 << fetcher.context().realtime_sent_time.time_since_epoch().count()
672 << " expected " << loop1->realtime_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -0700673}
674
Austin Schuh52d325c2019-06-23 18:59:06 -0700675// Tests that a couple phased loops run in a row result in the correct offset
676// and period.
677TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
678 const chrono::milliseconds kOffset = chrono::milliseconds(400);
679 const int kCount = 5;
680
681 auto loop1 = MakePrimary();
682
683 // Collect up a couple of samples.
684 ::std::vector<::aos::monotonic_clock::time_point> times;
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800685 ::std::vector<::aos::monotonic_clock::time_point> expected_times;
Austin Schuh52d325c2019-06-23 18:59:06 -0700686
687 // Run kCount iterations.
688 loop1->AddPhasedLoop(
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800689 [&times, &expected_times, &loop1, this](int count) {
Austin Schuh52d325c2019-06-23 18:59:06 -0700690 EXPECT_EQ(count, 1);
691 times.push_back(loop1->monotonic_now());
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800692 expected_times.push_back(loop1->context().monotonic_sent_time);
Austin Schuh52d325c2019-06-23 18:59:06 -0700693 if (times.size() == kCount) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700694 this->Exit();
Austin Schuh52d325c2019-06-23 18:59:06 -0700695 }
696 },
697 chrono::seconds(1), kOffset);
698
699 // Add a delay to make sure that delay during startup doesn't result in a
700 // "missed cycle".
701 SleepFor(chrono::seconds(2));
702
703 Run();
704
705 // Confirm that we got both the right number of samples, and it's odd.
706 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800707 EXPECT_EQ(times.size(), expected_times.size());
Austin Schuh52d325c2019-06-23 18:59:06 -0700708 EXPECT_EQ((times.size() % 2), 1);
709
710 // Grab the middle sample.
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800711 ::aos::monotonic_clock::time_point average_time = times[times.size() / 2];
Austin Schuh52d325c2019-06-23 18:59:06 -0700712
713 // Add up all the delays of all the times.
714 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
715 for (const ::aos::monotonic_clock::time_point time : times) {
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800716 sum += time - average_time;
Austin Schuh52d325c2019-06-23 18:59:06 -0700717 }
718
719 // Average and add to the middle to find the average time.
720 sum /= times.size();
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800721 average_time += sum;
Austin Schuh52d325c2019-06-23 18:59:06 -0700722
723 // Compute the offset from the start of the second of the average time. This
724 // should be pretty close to the offset.
725 const ::aos::monotonic_clock::duration remainder =
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800726 average_time.time_since_epoch() -
727 chrono::duration_cast<chrono::seconds>(average_time.time_since_epoch());
Austin Schuh52d325c2019-06-23 18:59:06 -0700728
729 const chrono::milliseconds kEpsilon(100);
730 EXPECT_LT(remainder, kOffset + kEpsilon);
731 EXPECT_GT(remainder, kOffset - kEpsilon);
732
733 // Make sure that the average duration is close to 1 second.
734 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
735 times.front())
736 .count() /
737 static_cast<double>(times.size() - 1),
738 1.0, 0.1);
Austin Schuhde8a8ff2019-11-30 15:25:36 -0800739
740 // Confirm that the ideal wakeup times increment correctly.
741 for (size_t i = 1; i < expected_times.size(); ++i) {
742 EXPECT_EQ(expected_times[i], expected_times[i - 1] + chrono::seconds(1));
743 }
744
745 for (size_t i = 0; i < expected_times.size(); ++i) {
746 EXPECT_EQ(expected_times[i].time_since_epoch() % chrono::seconds(1),
747 kOffset);
748 }
749
750 EXPECT_LT(expected_times[expected_times.size() / 2], average_time + kEpsilon);
751 EXPECT_GT(expected_times[expected_times.size() / 2], average_time - kEpsilon);
Austin Schuh52d325c2019-06-23 18:59:06 -0700752}
753
Parker Schuhe4a70d62017-12-27 20:10:20 -0800754} // namespace testing
755} // namespace aos