blob: 0a10ecbfdb2fc01c71dc6cefff7a194ecb0697f4 [file] [log] [blame]
Parker Schuhe4a70d62017-12-27 20:10:20 -08001#include "aos/events/event-loop_param_test.h"
2
Austin Schuh52d325c2019-06-23 18:59:06 -07003#include <chrono>
4
Austin Schuh3578a2e2019-05-25 18:17:59 -07005#include "gmock/gmock.h"
6#include "gtest/gtest.h"
7
Parker Schuhe4a70d62017-12-27 20:10:20 -08008namespace aos {
9namespace testing {
Austin Schuh52d325c2019-06-23 18:59:06 -070010namespace {
11namespace chrono = ::std::chrono;
12} // namespace
Parker Schuhe4a70d62017-12-27 20:10:20 -080013
14struct TestMessage : public ::aos::Message {
15 enum { kQueueLength = 100, kHash = 0x696c0cdc };
16 int msg_value;
17
Austin Schuh7267c532019-05-19 19:55:53 -070018 void Zero() {
19 ::aos::Message::Zero();
20 msg_value = 0;
21 }
Parker Schuhe4a70d62017-12-27 20:10:20 -080022 static size_t Size() { return 1 + ::aos::Message::Size(); }
23 size_t Print(char *buffer, size_t length) const;
24 TestMessage() { Zero(); }
25};
26
Neil Balch229001a2018-01-07 18:22:52 -080027// Ends the given event loop at the given time from now.
28void EndEventLoop(EventLoop *loop, ::std::chrono::milliseconds duration) {
29 auto end_timer = loop->AddTimer([loop]() { loop->Exit(); });
30 end_timer->Setup(loop->monotonic_now() +
31 ::std::chrono::milliseconds(duration));
32}
33
Austin Schuh6b6dfa52019-06-12 20:16:20 -070034// Tests that watcher can receive messages from a sender.
Parker Schuhe4a70d62017-12-27 20:10:20 -080035// Also tests that OnRun() works.
36TEST_P(AbstractEventLoopTest, Basic) {
37 auto loop1 = Make();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070038 auto loop2 = MakePrimary();
39
40 auto sender = loop1->MakeSender<TestMessage>("/test");
41
42 bool happened = false;
43
44 loop2->OnRun([&]() {
45 happened = true;
46
47 auto msg = sender.MakeMessage();
48 msg->msg_value = 200;
49 msg.Send();
50 });
51
52 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
53 EXPECT_EQ(message.msg_value, 200);
54 loop2->Exit();
55 });
56
57 EXPECT_FALSE(happened);
58 Run();
59 EXPECT_TRUE(happened);
60}
61
62// Tests that a fetcher can fetch from a sender.
63// Also tests that OnRun() works.
64TEST_P(AbstractEventLoopTest, FetchWithoutRun) {
65 auto loop1 = Make();
Parker Schuhe4a70d62017-12-27 20:10:20 -080066 auto loop2 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -070067 auto loop3 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -080068
69 auto sender = loop1->MakeSender<TestMessage>("/test");
70
71 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
72
Austin Schuhbbce72d2019-05-26 15:11:46 -070073 EXPECT_FALSE(fetcher.Fetch());
74
Austin Schuh3578a2e2019-05-25 18:17:59 -070075 auto msg = sender.MakeMessage();
76 msg->msg_value = 200;
77 msg.Send();
78
79 EXPECT_TRUE(fetcher.Fetch());
80 ASSERT_FALSE(fetcher.get() == nullptr);
81 EXPECT_EQ(fetcher->msg_value, 200);
Parker Schuhe4a70d62017-12-27 20:10:20 -080082}
83
Austin Schuh3578a2e2019-05-25 18:17:59 -070084// Tests that watcher will receive all messages sent if they are sent after
85// initialization and before running.
86TEST_P(AbstractEventLoopTest, DoubleSendAtStartup) {
87 auto loop1 = Make();
88 auto loop2 = MakePrimary();
89
90 auto sender = loop1->MakeSender<TestMessage>("/test");
91
92 ::std::vector<int> values;
93
94 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
Austin Schuh3578a2e2019-05-25 18:17:59 -070095 values.push_back(message.msg_value);
96 if (values.size() == 2) {
97 loop2->Exit();
98 }
99 });
100
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700101 // Before Run, should be ignored.
Austin Schuh3578a2e2019-05-25 18:17:59 -0700102 {
103 auto msg = sender.MakeMessage();
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700104 msg->msg_value = 199;
Austin Schuh3578a2e2019-05-25 18:17:59 -0700105 msg.Send();
106 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700107
108 loop2->OnRun([&]() {
109 {
110 auto msg = sender.MakeMessage();
111 msg->msg_value = 200;
112 msg.Send();
113 }
114 {
115 auto msg = sender.MakeMessage();
116 msg->msg_value = 201;
117 msg.Send();
118 }
119 });
Austin Schuh3578a2e2019-05-25 18:17:59 -0700120
121 Run();
122
123 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
124}
125
126// Tests that watcher will not receive messages sent before the watcher is
127// created.
128TEST_P(AbstractEventLoopTest, DoubleSendAfterStartup) {
129 auto loop1 = Make();
130 auto loop2 = MakePrimary();
131
132 auto sender = loop1->MakeSender<TestMessage>("/test");
133
134 ::std::vector<int> values;
135
136 {
137 auto msg = sender.MakeMessage();
138 msg->msg_value = 200;
139 msg.Send();
140 }
141 {
142 auto msg = sender.MakeMessage();
143 msg->msg_value = 201;
144 msg.Send();
145 }
146
147 loop2->MakeWatcher("/test", [&](const TestMessage &message) {
148 values.push_back(message.msg_value);
149 });
150
151 // Add a timer to actually quit.
152 auto test_timer = loop2->AddTimer([&loop2]() { loop2->Exit(); });
153 loop2->OnRun([&test_timer, &loop2]() {
154 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
155 });
156
157 Run();
158 EXPECT_EQ(0, values.size());
159}
160
Austin Schuhbbce72d2019-05-26 15:11:46 -0700161// Tests that FetchNext gets all the messages sent after it is constructed.
162TEST_P(AbstractEventLoopTest, FetchNext) {
163 auto loop1 = Make();
164 auto loop2 = MakePrimary();
165
166 auto sender = loop1->MakeSender<TestMessage>("/test");
167 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
168
169 ::std::vector<int> values;
170
171 {
172 auto msg = sender.MakeMessage();
173 msg->msg_value = 200;
174 msg.Send();
175 }
176 {
177 auto msg = sender.MakeMessage();
178 msg->msg_value = 201;
179 msg.Send();
180 }
181
182 // Add a timer to actually quit.
183 auto test_timer = loop2->AddTimer([&loop2, &fetcher, &values]() {
184 while (fetcher.FetchNext()) {
185 values.push_back(fetcher->msg_value);
186 }
187 loop2->Exit();
188 });
189
190 loop2->OnRun([&test_timer, &loop2]() {
191 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
192 });
193
194 Run();
195 EXPECT_THAT(values, ::testing::ElementsAreArray({200, 201}));
196}
197
198// Tests that FetchNext gets no messages sent before it is constructed.
199TEST_P(AbstractEventLoopTest, FetchNextAfterSend) {
200 auto loop1 = Make();
201 auto loop2 = MakePrimary();
202
203 auto sender = loop1->MakeSender<TestMessage>("/test");
204
205 ::std::vector<int> values;
206
207 {
208 auto msg = sender.MakeMessage();
209 msg->msg_value = 200;
210 msg.Send();
211 }
212 {
213 auto msg = sender.MakeMessage();
214 msg->msg_value = 201;
215 msg.Send();
216 }
217
218 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
219
220 // Add a timer to actually quit.
221 auto test_timer = loop2->AddTimer([&loop2, &fetcher, &values]() {
222 while (fetcher.FetchNext()) {
223 values.push_back(fetcher->msg_value);
224 }
225 loop2->Exit();
226 });
227
228 loop2->OnRun([&test_timer, &loop2]() {
229 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
230 });
231
232 Run();
233 EXPECT_THAT(0, values.size());
234}
235
236// Tests that Fetch returns the last message created before the loop was
237// started.
238TEST_P(AbstractEventLoopTest, FetchDataFromBeforeCreation) {
239 auto loop1 = Make();
240 auto loop2 = MakePrimary();
241
242 auto sender = loop1->MakeSender<TestMessage>("/test");
243
244 ::std::vector<int> values;
245
246 {
247 auto msg = sender.MakeMessage();
248 msg->msg_value = 200;
249 msg.Send();
250 }
251 {
252 auto msg = sender.MakeMessage();
253 msg->msg_value = 201;
254 msg.Send();
255 }
256
257 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
258
259 // Add a timer to actually quit.
260 auto test_timer = loop2->AddTimer([&loop2, &fetcher, &values]() {
261 if (fetcher.Fetch()) {
262 values.push_back(fetcher->msg_value);
263 }
264 // Do it again to make sure we don't double fetch.
265 if (fetcher.Fetch()) {
266 values.push_back(fetcher->msg_value);
267 }
268 loop2->Exit();
269 });
270
271 loop2->OnRun([&test_timer, &loop2]() {
272 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
273 });
274
275 Run();
276 EXPECT_THAT(values, ::testing::ElementsAreArray({201}));
277}
278
279// Tests that Fetch and FetchNext interleave as expected.
280TEST_P(AbstractEventLoopTest, FetchAndFetchNextTogether) {
281 auto loop1 = Make();
282 auto loop2 = MakePrimary();
283
284 auto sender = loop1->MakeSender<TestMessage>("/test");
285
286 ::std::vector<int> values;
287
288 {
289 auto msg = sender.MakeMessage();
290 msg->msg_value = 200;
291 msg.Send();
292 }
293 {
294 auto msg = sender.MakeMessage();
295 msg->msg_value = 201;
296 msg.Send();
297 }
298
299 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
300
301 // Add a timer to actually quit.
302 auto test_timer = loop2->AddTimer([&loop2, &fetcher, &values, &sender]() {
303 if (fetcher.Fetch()) {
304 values.push_back(fetcher->msg_value);
305 }
306
307 {
308 auto msg = sender.MakeMessage();
309 msg->msg_value = 202;
310 msg.Send();
311 }
312 {
313 auto msg = sender.MakeMessage();
314 msg->msg_value = 203;
315 msg.Send();
316 }
317 {
318 auto msg = sender.MakeMessage();
319 msg->msg_value = 204;
320 msg.Send();
321 }
322
323 if (fetcher.FetchNext()) {
324 values.push_back(fetcher->msg_value);
325 }
326
327 if (fetcher.Fetch()) {
328 values.push_back(fetcher->msg_value);
329 }
330
331 loop2->Exit();
332 });
333
334 loop2->OnRun([&test_timer, &loop2]() {
335 test_timer->Setup(loop2->monotonic_now(), ::std::chrono::milliseconds(100));
336 });
337
338 Run();
339 EXPECT_THAT(values, ::testing::ElementsAreArray({201, 202, 204}));
340}
341
Austin Schuh3115a202019-05-27 21:02:14 -0700342
343// Tests that FetchNext behaves correctly when we get two messages in the queue
344// but don't consume the first until after the second has been sent.
345TEST_P(AbstractEventLoopTest, FetchNextTest) {
346
347 auto send_loop = Make();
348 auto fetch_loop = Make();
349 auto sender = send_loop->MakeSender<TestMessage>("/test");
350 Fetcher<TestMessage> fetcher = fetch_loop->MakeFetcher<TestMessage>("/test");
351
352 {
353 auto msg = sender.MakeMessage();
354 msg->msg_value = 100;
355 ASSERT_TRUE(msg.Send());
356 }
357
358 {
359 auto msg = sender.MakeMessage();
360 msg->msg_value = 200;
361 ASSERT_TRUE(msg.Send());
362 }
363
364 ASSERT_TRUE(fetcher.FetchNext());
365 ASSERT_NE(nullptr, fetcher.get());
366 EXPECT_EQ(100, fetcher->msg_value);
367
368 ASSERT_TRUE(fetcher.FetchNext());
369 ASSERT_NE(nullptr, fetcher.get());
370 EXPECT_EQ(200, fetcher->msg_value);
371
372 // When we run off the end of the queue, expect to still have the old message:
373 ASSERT_FALSE(fetcher.FetchNext());
374 ASSERT_NE(nullptr, fetcher.get());
375 EXPECT_EQ(200, fetcher->msg_value);
376}
377
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800378// Verify that making a fetcher and watcher for "/test" succeeds.
379TEST_P(AbstractEventLoopTest, FetcherAndWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800380 auto loop = Make();
381 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800382 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Parker Schuhe4a70d62017-12-27 20:10:20 -0800383}
384
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800385// Verify that making 2 fetchers for "/test" succeeds.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800386TEST_P(AbstractEventLoopTest, TwoFetcher) {
387 auto loop = Make();
388 auto fetcher = loop->MakeFetcher<TestMessage>("/test");
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800389 auto fetcher2 = loop->MakeFetcher<TestMessage>("/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800390}
391
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800392// Verify that registering a watcher twice for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700393TEST_P(AbstractEventLoopDeathTest, TwoWatcher) {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800394 auto loop = Make();
395 loop->MakeWatcher("/test", [&](const TestMessage &) {});
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800396 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
397 "/test");
398}
399
Austin Schuh3115a202019-05-27 21:02:14 -0700400// Verify that SetRuntimeRealtimePriority fails while running.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700401TEST_P(AbstractEventLoopDeathTest, SetRuntimeRealtimePriority) {
Austin Schuh3115a202019-05-27 21:02:14 -0700402 auto loop = MakePrimary();
403 // Confirm that runtime priority calls work when not realtime.
404 loop->SetRuntimeRealtimePriority(5);
405
406 loop->OnRun([&]() { loop->SetRuntimeRealtimePriority(5); });
407
408 EXPECT_DEATH(Run(), "realtime");
409}
410
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800411// Verify that registering a watcher and a sender for "/test" fails.
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700412TEST_P(AbstractEventLoopDeathTest, WatcherAndSender) {
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800413 auto loop = Make();
414 auto sender = loop->MakeSender<TestMessage>("/test");
415 EXPECT_DEATH(loop->MakeWatcher("/test", [&](const TestMessage &) {}),
416 "/test");
Parker Schuhe4a70d62017-12-27 20:10:20 -0800417}
418
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700419// Verify that we can't create a sender inside OnRun.
420TEST_P(AbstractEventLoopDeathTest, SenderInOnRun) {
421 auto loop1 = MakePrimary();
422
423 loop1->OnRun(
424 [&]() { auto sender = loop1->MakeSender<TestMessage>("/test2"); });
425
426 EXPECT_DEATH(Run(), "running");
427}
428
429// Verify that we can't create a watcher inside OnRun.
430TEST_P(AbstractEventLoopDeathTest, WatcherInOnRun) {
431 auto loop1 = MakePrimary();
432
433 loop1->OnRun(
434 [&]() { loop1->MakeWatcher("/test", [&](const TestMessage &) {}); });
435
436 EXPECT_DEATH(Run(), "running");
437}
438
Parker Schuhe4a70d62017-12-27 20:10:20 -0800439// Verify that Quit() works when there are multiple watchers.
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800440TEST_P(AbstractEventLoopTest, MultipleWatcherQuit) {
441 auto loop1 = Make();
Austin Schuh44019f92019-05-19 19:58:27 -0700442 auto loop2 = MakePrimary();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800443
Austin Schuh3578a2e2019-05-25 18:17:59 -0700444 loop2->MakeWatcher("/test1", [&](const TestMessage &) {});
445 loop2->MakeWatcher("/test2", [&](const TestMessage &message) {
446 EXPECT_EQ(message.msg_value, 200);
447 loop2->Exit();
448 });
449
Austin Schuh81fc9cc2019-02-02 23:25:47 -0800450 auto sender = loop1->MakeSender<TestMessage>("/test2");
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700451
452 loop2->OnRun([&]() {
Parker Schuhe4a70d62017-12-27 20:10:20 -0800453 auto msg = sender.MakeMessage();
454 msg->msg_value = 200;
455 msg.Send();
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700456 });
Parker Schuhe4a70d62017-12-27 20:10:20 -0800457
Austin Schuh44019f92019-05-19 19:58:27 -0700458 Run();
Parker Schuhe4a70d62017-12-27 20:10:20 -0800459}
460
Neil Balch229001a2018-01-07 18:22:52 -0800461// Verify that timer intervals and duration function properly.
462TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
Austin Schuh44019f92019-05-19 19:58:27 -0700463 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800464 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
465
466 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
467 iteration_list.push_back(loop->monotonic_now());
468 });
469
Austin Schuh52d325c2019-06-23 18:59:06 -0700470 // TODO(austin): This should be an error... Should be done in OnRun only.
Neil Balch229001a2018-01-07 18:22:52 -0800471 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
472 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
473 // Testing that the timer thread waits for the event loop to start before
474 // running
475 ::std::this_thread::sleep_for(std::chrono::milliseconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -0700476 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800477
478 EXPECT_EQ(iteration_list.size(), 8);
479}
480
481// Verify that we can change a timer's parameters during execution.
482TEST_P(AbstractEventLoopTest, TimerChangeParameters) {
Austin Schuh44019f92019-05-19 19:58:27 -0700483 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800484 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
485
486 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
487 iteration_list.push_back(loop->monotonic_now());
488 });
489
490 auto modifier_timer = loop->AddTimer([&loop, &test_timer]() {
491 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(30));
492 });
493
Neil Balch229001a2018-01-07 18:22:52 -0800494 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
495 modifier_timer->Setup(loop->monotonic_now() +
496 ::std::chrono::milliseconds(45));
497 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700498 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800499
500 EXPECT_EQ(iteration_list.size(), 7);
501}
502
503// Verify that we can disable a timer during execution.
504TEST_P(AbstractEventLoopTest, TimerDisable) {
Austin Schuh44019f92019-05-19 19:58:27 -0700505 auto loop = MakePrimary();
Neil Balch229001a2018-01-07 18:22:52 -0800506 ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
507
508 auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
509 iteration_list.push_back(loop->monotonic_now());
510 });
511
512 auto ender_timer = loop->AddTimer([&test_timer]() {
513 test_timer->Disable();
514 });
515
516 test_timer->Setup(loop->monotonic_now(), ::std::chrono::milliseconds(20));
517 ender_timer->Setup(loop->monotonic_now() +
518 ::std::chrono::milliseconds(45));
519 EndEventLoop(loop.get(), ::std::chrono::milliseconds(150));
Austin Schuh44019f92019-05-19 19:58:27 -0700520 Run();
Neil Balch229001a2018-01-07 18:22:52 -0800521
522 EXPECT_EQ(iteration_list.size(), 3);
523}
Austin Schuh7267c532019-05-19 19:55:53 -0700524
525// Verify that the send time on a message is roughly right.
526TEST_P(AbstractEventLoopTest, MessageSendTime) {
Austin Schuh44019f92019-05-19 19:58:27 -0700527 auto loop1 = MakePrimary();
Austin Schuh7267c532019-05-19 19:55:53 -0700528 auto loop2 = Make();
529 auto sender = loop1->MakeSender<TestMessage>("/test");
530 auto fetcher = loop2->MakeFetcher<TestMessage>("/test");
531
532 auto test_timer = loop1->AddTimer([&sender]() {
533 auto msg = sender.MakeMessage();
534 msg->msg_value = 200;
535 msg.Send();
536 });
537
538 test_timer->Setup(loop1->monotonic_now() + ::std::chrono::seconds(1));
539
540 EndEventLoop(loop1.get(), ::std::chrono::seconds(2));
Austin Schuh44019f92019-05-19 19:58:27 -0700541 Run();
Austin Schuh7267c532019-05-19 19:55:53 -0700542
543 EXPECT_TRUE(fetcher.Fetch());
544
545 monotonic_clock::duration time_offset =
546 fetcher->sent_time - (loop1->monotonic_now() - ::std::chrono::seconds(1));
547
548 EXPECT_TRUE(time_offset > ::std::chrono::milliseconds(-500))
Austin Schuh52d325c2019-06-23 18:59:06 -0700549 << ": Got " << fetcher->sent_time.time_since_epoch().count()
550 << " expected " << loop1->monotonic_now().time_since_epoch().count();
Austin Schuh7267c532019-05-19 19:55:53 -0700551 EXPECT_TRUE(time_offset < ::std::chrono::milliseconds(500))
552 << ": Got " << fetcher->sent_time.time_since_epoch().count()
553 << " expected " << loop1->monotonic_now().time_since_epoch().count();
554}
555
Austin Schuh52d325c2019-06-23 18:59:06 -0700556// Tests that a couple phased loops run in a row result in the correct offset
557// and period.
558TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
559 const chrono::milliseconds kOffset = chrono::milliseconds(400);
560 const int kCount = 5;
561
562 auto loop1 = MakePrimary();
563
564 // Collect up a couple of samples.
565 ::std::vector<::aos::monotonic_clock::time_point> times;
566
567 // Run kCount iterations.
568 loop1->AddPhasedLoop(
569 [&times, &loop1](int count) {
570 EXPECT_EQ(count, 1);
571 times.push_back(loop1->monotonic_now());
572 LOG(INFO, "%zu\n", times.size());
573 if (times.size() == kCount) {
574 loop1->Exit();
575 }
576 },
577 chrono::seconds(1), kOffset);
578
579 // Add a delay to make sure that delay during startup doesn't result in a
580 // "missed cycle".
581 SleepFor(chrono::seconds(2));
582
583 Run();
584
585 // Confirm that we got both the right number of samples, and it's odd.
586 EXPECT_EQ(times.size(), static_cast<size_t>(kCount));
587 EXPECT_EQ((times.size() % 2), 1);
588
589 // Grab the middle sample.
590 ::aos::monotonic_clock::time_point middle_time = times[times.size() / 2 + 1];
591
592 // Add up all the delays of all the times.
593 ::aos::monotonic_clock::duration sum = chrono::seconds(0);
594 for (const ::aos::monotonic_clock::time_point time : times) {
595 sum += time - middle_time;
596 }
597
598 // Average and add to the middle to find the average time.
599 sum /= times.size();
600 middle_time += sum;
601
602 // Compute the offset from the start of the second of the average time. This
603 // should be pretty close to the offset.
604 const ::aos::monotonic_clock::duration remainder =
605 middle_time.time_since_epoch() -
606 chrono::duration_cast<chrono::seconds>(middle_time.time_since_epoch());
607
608 const chrono::milliseconds kEpsilon(100);
609 EXPECT_LT(remainder, kOffset + kEpsilon);
610 EXPECT_GT(remainder, kOffset - kEpsilon);
611
612 // Make sure that the average duration is close to 1 second.
613 EXPECT_NEAR(chrono::duration_cast<chrono::duration<double>>(times.back() -
614 times.front())
615 .count() /
616 static_cast<double>(times.size() - 1),
617 1.0, 0.1);
618}
619
Parker Schuhe4a70d62017-12-27 20:10:20 -0800620} // namespace testing
621} // namespace aos