blob: 44ba3e5ee158bb4cc6aa3bf8e7226b1be57c983b [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/simulated_event_loop.h"
2
Austin Schuh5f1cc5c2019-12-01 18:01:11 -08003#include <string_view>
4
Alex Perrycb7da4b2019-08-28 19:35:56 -07005#include "aos/events/event_loop_param_test.h"
Austin Schuh898f4972020-01-11 17:21:25 -08006#include "aos/events/ping_lib.h"
7#include "aos/events/pong_lib.h"
Austin Schuh7d87b672019-12-01 20:23:49 -08008#include "aos/events/test_message_generated.h"
Austin Schuh4c3b9702020-08-30 11:34:55 -07009#include "aos/network/message_bridge_client_generated.h"
10#include "aos/network/message_bridge_server_generated.h"
11#include "aos/network/timestamp_generated.h"
Neil Balchc8f41ed2018-01-20 22:06:53 -080012#include "gtest/gtest.h"
13
14namespace aos {
15namespace testing {
16
Austin Schuh7267c532019-05-19 19:55:53 -070017namespace chrono = ::std::chrono;
18
Neil Balchc8f41ed2018-01-20 22:06:53 -080019class SimulatedEventLoopTestFactory : public EventLoopTestFactory {
20 public:
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080021 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080022 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080023 return event_loop_factory_->MakeEventLoop(name, my_node());
Neil Balchc8f41ed2018-01-20 22:06:53 -080024 }
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080025 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080026 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080027 return event_loop_factory_->MakeEventLoop(name, my_node());
Austin Schuh44019f92019-05-19 19:58:27 -070028 }
29
Austin Schuh217a9782019-12-21 23:02:50 -080030 void Run() override { event_loop_factory_->Run(); }
31 void Exit() override { event_loop_factory_->Exit(); }
Austin Schuh44019f92019-05-19 19:58:27 -070032
Austin Schuh52d325c2019-06-23 18:59:06 -070033 // TODO(austin): Implement this. It's used currently for a phased loop test.
34 // I'm not sure how much that matters.
35 void SleepFor(::std::chrono::nanoseconds /*duration*/) override {}
36
Austin Schuh7d87b672019-12-01 20:23:49 -080037 void set_send_delay(std::chrono::nanoseconds send_delay) {
Austin Schuh217a9782019-12-21 23:02:50 -080038 MaybeMake();
39 event_loop_factory_->set_send_delay(send_delay);
Austin Schuh7d87b672019-12-01 20:23:49 -080040 }
41
Neil Balchc8f41ed2018-01-20 22:06:53 -080042 private:
Austin Schuh217a9782019-12-21 23:02:50 -080043 void MaybeMake() {
44 if (!event_loop_factory_) {
45 if (configuration()->has_nodes()) {
Austin Schuhac0771c2020-01-07 18:36:30 -080046 event_loop_factory_ =
47 std::make_unique<SimulatedEventLoopFactory>(configuration());
Austin Schuh217a9782019-12-21 23:02:50 -080048 } else {
49 event_loop_factory_ =
50 std::make_unique<SimulatedEventLoopFactory>(configuration());
51 }
52 }
53 }
54 std::unique_ptr<SimulatedEventLoopFactory> event_loop_factory_;
Neil Balchc8f41ed2018-01-20 22:06:53 -080055};
56
Brian Silverman77162972020-08-12 19:52:40 -070057INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCopyTest, AbstractEventLoopTest,
58 ::testing::Values(std::make_tuple(
59 []() {
60 return new SimulatedEventLoopTestFactory();
61 },
62 ReadMethod::COPY)));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070063
Brian Silverman77162972020-08-12 19:52:40 -070064INSTANTIATE_TEST_CASE_P(
65 SimulatedEventLoopCopyDeathTest, AbstractEventLoopDeathTest,
66 ::testing::Values(
67 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
68 ReadMethod::COPY)));
69
70INSTANTIATE_TEST_CASE_P(SimulatedEventLoopPinTest, AbstractEventLoopTest,
71 ::testing::Values(std::make_tuple(
72 []() {
73 return new SimulatedEventLoopTestFactory();
74 },
75 ReadMethod::PIN)));
76
77INSTANTIATE_TEST_CASE_P(
78 SimulatedEventLoopPinDeathTest, AbstractEventLoopDeathTest,
79 ::testing::Values(
80 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
81 ReadMethod::PIN)));
Neil Balchc8f41ed2018-01-20 22:06:53 -080082
83// Test that creating an event and running the scheduler runs the event.
84TEST(EventSchedulerTest, ScheduleEvent) {
85 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -080086 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -080087 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -080088 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -080089
Austin Schuh8bd96322020-02-13 21:18:22 -080090 scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuhac0771c2020-01-07 18:36:30 -080091 [&counter]() { counter += 1; });
Austin Schuh8bd96322020-02-13 21:18:22 -080092 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -080093 EXPECT_EQ(counter, 1);
Ravago Jonescf453ab2020-05-06 21:14:53 -070094 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(2),
95 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -080096 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -080097 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -080098 EXPECT_EQ(counter, 1);
99}
100
101// Test that descheduling an already scheduled event doesn't run the event.
102TEST(EventSchedulerTest, DescheduleEvent) {
103 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -0800104 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -0800105 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -0800106 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -0800107
Austin Schuh8bd96322020-02-13 21:18:22 -0800108 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
109 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800110 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800111 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800112 EXPECT_EQ(counter, 0);
113}
Austin Schuh44019f92019-05-19 19:58:27 -0700114
115// Test that running for a time period with no handlers causes time to progress
116// correctly.
117TEST(SimulatedEventLoopTest, RunForNoHandlers) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800118 SimulatedEventLoopTestFactory factory;
119
120 SimulatedEventLoopFactory simulated_event_loop_factory(
121 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700122 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800123 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700124
125 simulated_event_loop_factory.RunFor(chrono::seconds(1));
126
127 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700128 event_loop->monotonic_now());
129}
130
131// Test that running for a time with a periodic handler causes time to end
132// correctly.
133TEST(SimulatedEventLoopTest, RunForTimerHandler) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800134 SimulatedEventLoopTestFactory factory;
135
136 SimulatedEventLoopFactory simulated_event_loop_factory(
137 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700138 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800139 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700140
141 int counter = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700142 auto timer = event_loop->AddTimer([&counter]() { ++counter; });
Austin Schuh44019f92019-05-19 19:58:27 -0700143 event_loop->OnRun([&event_loop, &timer] {
144 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50),
145 chrono::milliseconds(100));
146 });
147
148 simulated_event_loop_factory.RunFor(chrono::seconds(1));
149
150 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700151 event_loop->monotonic_now());
152 EXPECT_EQ(counter, 10);
153}
154
Austin Schuh7d87b672019-12-01 20:23:49 -0800155// Tests that watchers have latency in simulation.
156TEST(SimulatedEventLoopTest, WatcherTimingReport) {
157 SimulatedEventLoopTestFactory factory;
158 factory.set_send_delay(std::chrono::microseconds(50));
159
160 FLAGS_timing_report_ms = 1000;
161 auto loop1 = factory.MakePrimary("primary");
162 loop1->MakeWatcher("/test", [](const TestMessage &) {});
163
164 auto loop2 = factory.Make("sender_loop");
165
166 auto loop3 = factory.Make("report_fetcher");
167
168 Fetcher<timing::Report> report_fetcher =
169 loop3->MakeFetcher<timing::Report>("/aos");
170 EXPECT_FALSE(report_fetcher.Fetch());
171
172 auto sender = loop2->MakeSender<TestMessage>("/test");
173
174 // Send 10 messages in the middle of a timing report period so we get
175 // something interesting back.
176 auto test_timer = loop2->AddTimer([&sender]() {
177 for (int i = 0; i < 10; ++i) {
178 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
179 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
180 builder.add_value(200 + i);
181 ASSERT_TRUE(msg.Send(builder.Finish()));
182 }
183 });
184
185 // Quit after 1 timing report, mid way through the next cycle.
186 {
187 auto end_timer = loop1->AddTimer([&factory]() { factory.Exit(); });
188 end_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(2500));
189 end_timer->set_name("end");
190 }
191
192 loop1->OnRun([&test_timer, &loop1]() {
193 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
194 });
195
196 factory.Run();
197
198 // And, since we are here, check that the timing report makes sense.
199 // Start by looking for our event loop's timing.
200 FlatbufferDetachedBuffer<timing::Report> primary_report =
201 FlatbufferDetachedBuffer<timing::Report>::Empty();
202 while (report_fetcher.FetchNext()) {
203 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
204 if (report_fetcher->name()->string_view() == "primary") {
205 primary_report = CopyFlatBuffer(report_fetcher.get());
206 }
207 }
208
209 // Check the watcher report.
Ravago Jonescf453ab2020-05-06 21:14:53 -0700210 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh7d87b672019-12-01 20:23:49 -0800211
212 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
213
214 // Just the timing report timer.
215 ASSERT_NE(primary_report.message().timers(), nullptr);
216 EXPECT_EQ(primary_report.message().timers()->size(), 2);
217
218 // No phased loops
219 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
220
221 // And now confirm that the watcher received all 10 messages, and has latency.
222 ASSERT_NE(primary_report.message().watchers(), nullptr);
223 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
224 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
225 EXPECT_NEAR(
226 primary_report.message().watchers()->Get(0)->wakeup_latency()->average(),
227 0.00005, 1e-9);
228 EXPECT_NEAR(
229 primary_report.message().watchers()->Get(0)->wakeup_latency()->min(),
230 0.00005, 1e-9);
231 EXPECT_NEAR(
232 primary_report.message().watchers()->Get(0)->wakeup_latency()->max(),
233 0.00005, 1e-9);
234 EXPECT_EQ(primary_report.message()
235 .watchers()
236 ->Get(0)
237 ->wakeup_latency()
238 ->standard_deviation(),
239 0.0);
240
241 EXPECT_EQ(
242 primary_report.message().watchers()->Get(0)->handler_time()->average(),
243 0.0);
244 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->min(),
245 0.0);
246 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->max(),
247 0.0);
248 EXPECT_EQ(primary_report.message()
249 .watchers()
250 ->Get(0)
251 ->handler_time()
252 ->standard_deviation(),
253 0.0);
254}
255
Austin Schuh4c3b9702020-08-30 11:34:55 -0700256template <typename T>
257class MessageCounter {
258 public:
259 MessageCounter(aos::EventLoop *event_loop, std::string_view name) {
260 event_loop->MakeNoArgWatcher<T>(name, [this]() { ++count_; });
261 }
262
263 size_t count() const { return count_; }
264
265 private:
266 size_t count_ = 0;
267};
268
269// Tests that ping and pong work when on 2 different nodes, and the message
270// gateway messages are sent out as expected.
Austin Schuh898f4972020-01-11 17:21:25 -0800271TEST(SimulatedEventLoopTest, MultinodePingPong) {
272 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
273 aos::configuration::ReadConfig(
274 "aos/events/multinode_pingpong_config.json");
275 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
276 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700277 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh898f4972020-01-11 17:21:25 -0800278
279 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
280
281 std::unique_ptr<EventLoop> ping_event_loop =
282 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
283 Ping ping(ping_event_loop.get());
284
285 std::unique_ptr<EventLoop> pong_event_loop =
286 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
287 Pong pong(pong_event_loop.get());
288
289 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
290 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700291 MessageCounter<examples::Pong> pi2_pong_counter(
292 pi2_pong_counter_event_loop.get(), "/test");
Austin Schuh898f4972020-01-11 17:21:25 -0800293
Austin Schuh4c3b9702020-08-30 11:34:55 -0700294 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
295 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
Austin Schuh898f4972020-01-11 17:21:25 -0800296
297 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
298 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700299 MessageCounter<examples::Pong> pi1_pong_counter(
300 pi1_pong_counter_event_loop.get(), "/test");
301
302 // Count timestamps.
303 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
304 pi1_pong_counter_event_loop.get(), "/pi1/aos");
305 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
306 pi2_pong_counter_event_loop.get(), "/pi1/aos");
307 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
308 pi3_pong_counter_event_loop.get(), "/pi1/aos");
309 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
310 pi1_pong_counter_event_loop.get(), "/pi2/aos");
311 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
312 pi2_pong_counter_event_loop.get(), "/pi2/aos");
313 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
314 pi1_pong_counter_event_loop.get(), "/pi3/aos");
315 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
316 pi3_pong_counter_event_loop.get(), "/pi3/aos");
317
318 // Wait to let timestamp estimation start up before looking for the results.
319 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
320
321 int pi1_server_statistics_count = 0;
Austin Schuh898f4972020-01-11 17:21:25 -0800322 pi1_pong_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700323 "/pi1/aos", [&pi1_server_statistics_count](
324 const message_bridge::ServerStatistics &stats) {
325 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
326 EXPECT_EQ(stats.connections()->size(), 2u);
327 for (const message_bridge::ServerConnection *connection :
328 *stats.connections()) {
329 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
330 if (connection->node()->name()->string_view() == "pi2") {
331 EXPECT_GT(connection->sent_packets(), 50);
332 } else if (connection->node()->name()->string_view() == "pi3") {
333 EXPECT_GE(connection->sent_packets(), 5);
334 } else {
335 LOG(FATAL) << "Unknown connection";
336 }
337
338 EXPECT_TRUE(connection->has_monotonic_offset());
339 EXPECT_EQ(connection->monotonic_offset(), 0);
340 }
341 ++pi1_server_statistics_count;
342 });
343
344 int pi2_server_statistics_count = 0;
345 pi2_pong_counter_event_loop->MakeWatcher(
346 "/pi2/aos", [&pi2_server_statistics_count](
347 const message_bridge::ServerStatistics &stats) {
348 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
349 EXPECT_EQ(stats.connections()->size(), 1u);
350
351 const message_bridge::ServerConnection *connection =
352 stats.connections()->Get(0);
353 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
354 EXPECT_GT(connection->sent_packets(), 50);
355 EXPECT_TRUE(connection->has_monotonic_offset());
356 EXPECT_EQ(connection->monotonic_offset(), 0);
357 ++pi2_server_statistics_count;
358 });
359
360 int pi3_server_statistics_count = 0;
361 pi3_pong_counter_event_loop->MakeWatcher(
362 "/pi3/aos", [&pi3_server_statistics_count](
363 const message_bridge::ServerStatistics &stats) {
364 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
365 EXPECT_EQ(stats.connections()->size(), 1u);
366
367 const message_bridge::ServerConnection *connection =
368 stats.connections()->Get(0);
369 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
370 EXPECT_GE(connection->sent_packets(), 5);
371 EXPECT_TRUE(connection->has_monotonic_offset());
372 EXPECT_EQ(connection->monotonic_offset(), 0);
373 ++pi3_server_statistics_count;
374 });
375
376 int pi1_client_statistics_count = 0;
377 pi1_pong_counter_event_loop->MakeWatcher(
378 "/pi1/aos", [&pi1_client_statistics_count](
379 const message_bridge::ClientStatistics &stats) {
380 VLOG(1) << "pi1 ClientStatistics " << FlatbufferToJson(&stats);
381 EXPECT_EQ(stats.connections()->size(), 2u);
382
383 for (const message_bridge::ClientConnection *connection :
384 *stats.connections()) {
385 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
386 if (connection->node()->name()->string_view() == "pi2") {
387 EXPECT_GT(connection->received_packets(), 50);
388 } else if (connection->node()->name()->string_view() == "pi3") {
389 EXPECT_GE(connection->received_packets(), 5);
390 } else {
391 LOG(FATAL) << "Unknown connection";
392 }
393
394 EXPECT_TRUE(connection->has_monotonic_offset());
395 EXPECT_EQ(connection->monotonic_offset(), 150000);
396 }
397 ++pi1_client_statistics_count;
398 });
399
400 int pi2_client_statistics_count = 0;
401 pi2_pong_counter_event_loop->MakeWatcher(
402 "/pi2/aos", [&pi2_client_statistics_count](
403 const message_bridge::ClientStatistics &stats) {
404 VLOG(1) << "pi2 ClientStatistics " << FlatbufferToJson(&stats);
405 EXPECT_EQ(stats.connections()->size(), 1u);
406
407 const message_bridge::ClientConnection *connection =
408 stats.connections()->Get(0);
409 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
410 EXPECT_GT(connection->received_packets(), 50);
411 EXPECT_TRUE(connection->has_monotonic_offset());
412 EXPECT_EQ(connection->monotonic_offset(), 150000);
413 ++pi2_client_statistics_count;
414 });
415
416 int pi3_client_statistics_count = 0;
417 pi3_pong_counter_event_loop->MakeWatcher(
418 "/pi3/aos", [&pi3_client_statistics_count](
419 const message_bridge::ClientStatistics &stats) {
420 VLOG(1) << "pi3 ClientStatistics " << FlatbufferToJson(&stats);
421 EXPECT_EQ(stats.connections()->size(), 1u);
422
423 const message_bridge::ClientConnection *connection =
424 stats.connections()->Get(0);
425 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
426 EXPECT_GE(connection->received_packets(), 5);
427 EXPECT_TRUE(connection->has_monotonic_offset());
428 EXPECT_EQ(connection->monotonic_offset(), 150000);
429 ++pi3_client_statistics_count;
430 });
431
432 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
433 chrono::milliseconds(500) +
434 chrono::milliseconds(5));
435
436 EXPECT_EQ(pi1_pong_counter.count(), 1001);
437 EXPECT_EQ(pi2_pong_counter.count(), 1001);
438
439 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 100);
440 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 100);
441 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 100);
442 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 100);
443 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 100);
444 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 100);
445 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 100);
446
447 EXPECT_EQ(pi1_server_statistics_count, 9);
448 EXPECT_EQ(pi2_server_statistics_count, 9);
449 EXPECT_EQ(pi3_server_statistics_count, 9);
450
451 EXPECT_EQ(pi1_client_statistics_count, 95);
452 EXPECT_EQ(pi2_client_statistics_count, 95);
453 EXPECT_EQ(pi3_client_statistics_count, 95);
454}
455
456// Tests that an offset between nodes can be recovered and shows up in
457// ServerStatistics correctly.
458TEST(SimulatedEventLoopTest, MultinodePingPongWithOffset) {
459 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
460 aos::configuration::ReadConfig(
461 "aos/events/multinode_pingpong_config.json");
462 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
463 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
464 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
465
466 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
467 NodeEventLoopFactory *pi2_factory =
468 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
469
470 constexpr chrono::milliseconds kOffset{1501};
471 pi2_factory->SetDistributedOffset(kOffset, 1.0);
472
473 std::unique_ptr<EventLoop> ping_event_loop =
474 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
475 Ping ping(ping_event_loop.get());
476
477 std::unique_ptr<EventLoop> pong_event_loop =
478 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
479 Pong pong(pong_event_loop.get());
480
481 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
482 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
483
484 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
485 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
486
487 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
488 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
489
490 // Wait to let timestamp estimation start up before looking for the results.
491 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
492
493 // Confirm the offsets are being recovered correctly.
494 int pi1_server_statistics_count = 0;
495 pi1_pong_counter_event_loop->MakeWatcher(
496 "/pi1/aos", [&pi1_server_statistics_count,
497 kOffset](const message_bridge::ServerStatistics &stats) {
498 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
499 EXPECT_EQ(stats.connections()->size(), 2u);
500 for (const message_bridge::ServerConnection *connection :
501 *stats.connections()) {
502 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
503 if (connection->node()->name()->string_view() == "pi2") {
504 EXPECT_EQ(connection->monotonic_offset(),
505 chrono::nanoseconds(kOffset).count());
506 } else if (connection->node()->name()->string_view() == "pi3") {
507 EXPECT_EQ(connection->monotonic_offset(), 0);
508 } else {
509 LOG(FATAL) << "Unknown connection";
510 }
511
512 EXPECT_TRUE(connection->has_monotonic_offset());
513 }
514 ++pi1_server_statistics_count;
515 });
516
517 int pi2_server_statistics_count = 0;
518 pi2_pong_counter_event_loop->MakeWatcher(
519 "/pi2/aos", [&pi2_server_statistics_count,
520 kOffset](const message_bridge::ServerStatistics &stats) {
521 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
522 EXPECT_EQ(stats.connections()->size(), 1u);
523
524 const message_bridge::ServerConnection *connection =
525 stats.connections()->Get(0);
526 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
527 EXPECT_TRUE(connection->has_monotonic_offset());
528 EXPECT_EQ(connection->monotonic_offset(),
529 -chrono::nanoseconds(kOffset).count());
530 ++pi2_server_statistics_count;
531 });
532
533 int pi3_server_statistics_count = 0;
534 pi3_pong_counter_event_loop->MakeWatcher(
535 "/pi3/aos", [&pi3_server_statistics_count](
536 const message_bridge::ServerStatistics &stats) {
537 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
538 EXPECT_EQ(stats.connections()->size(), 1u);
539
540 const message_bridge::ServerConnection *connection =
541 stats.connections()->Get(0);
542 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
543 EXPECT_TRUE(connection->has_monotonic_offset());
544 EXPECT_EQ(connection->monotonic_offset(), 0);
545 ++pi3_server_statistics_count;
546 });
547
548 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
549 chrono::milliseconds(500) +
550 chrono::milliseconds(5));
551
552 EXPECT_EQ(pi1_server_statistics_count, 9);
553 EXPECT_EQ(pi2_server_statistics_count, 9);
554 EXPECT_EQ(pi3_server_statistics_count, 9);
555}
556
557// Test that disabling statistics actually disables them.
558TEST(SimulatedEventLoopTest, MultinodeWithoutStatistics) {
559 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
560 aos::configuration::ReadConfig(
561 "aos/events/multinode_pingpong_config.json");
562 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
563 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
564 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
565
566 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
567 simulated_event_loop_factory.DisableStatistics();
568
569 std::unique_ptr<EventLoop> ping_event_loop =
570 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
571 Ping ping(ping_event_loop.get());
572
573 std::unique_ptr<EventLoop> pong_event_loop =
574 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
575 Pong pong(pong_event_loop.get());
576
577 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
578 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
579
580 MessageCounter<examples::Pong> pi2_pong_counter(
581 pi2_pong_counter_event_loop.get(), "/test");
582
583 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
584 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
585
586 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
587 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
588
589 MessageCounter<examples::Pong> pi1_pong_counter(
590 pi1_pong_counter_event_loop.get(), "/test");
591
592 // Count timestamps.
593 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
594 pi1_pong_counter_event_loop.get(), "/pi1/aos");
595 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
596 pi2_pong_counter_event_loop.get(), "/pi1/aos");
597 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
598 pi3_pong_counter_event_loop.get(), "/pi1/aos");
599 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
600 pi1_pong_counter_event_loop.get(), "/pi2/aos");
601 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
602 pi2_pong_counter_event_loop.get(), "/pi2/aos");
603 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
604 pi1_pong_counter_event_loop.get(), "/pi3/aos");
605 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
606 pi3_pong_counter_event_loop.get(), "/pi3/aos");
607
608 MessageCounter<message_bridge::ServerStatistics>
609 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
610 "/pi1/aos");
611 MessageCounter<message_bridge::ServerStatistics>
612 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
613 "/pi2/aos");
614 MessageCounter<message_bridge::ServerStatistics>
615 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
616 "/pi3/aos");
617
618 MessageCounter<message_bridge::ClientStatistics>
619 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
620 "/pi1/aos");
621 MessageCounter<message_bridge::ClientStatistics>
622 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
623 "/pi2/aos");
624 MessageCounter<message_bridge::ClientStatistics>
625 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
626 "/pi3/aos");
Austin Schuh898f4972020-01-11 17:21:25 -0800627
628 simulated_event_loop_factory.RunFor(chrono::seconds(10) +
629 chrono::milliseconds(5));
630
Austin Schuh4c3b9702020-08-30 11:34:55 -0700631 EXPECT_EQ(pi1_pong_counter.count(), 1001u);
632 EXPECT_EQ(pi2_pong_counter.count(), 1001u);
633
634 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 0u);
635 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 0u);
636 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 0u);
637 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 0u);
638 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 0u);
639 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 0u);
640 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 0u);
641
642 EXPECT_EQ(pi1_server_statistics_counter.count(), 0u);
643 EXPECT_EQ(pi2_server_statistics_counter.count(), 0u);
644 EXPECT_EQ(pi3_server_statistics_counter.count(), 0u);
645
646 EXPECT_EQ(pi1_client_statistics_counter.count(), 0u);
647 EXPECT_EQ(pi2_client_statistics_counter.count(), 0u);
648 EXPECT_EQ(pi3_client_statistics_counter.count(), 0u);
Austin Schuh898f4972020-01-11 17:21:25 -0800649}
650
Neil Balchc8f41ed2018-01-20 22:06:53 -0800651} // namespace testing
652} // namespace aos