blob: d7b3c3de935b8146262a5c6a9007c52cdf613ea4 [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 Schuh2f8fd752020-09-01 22:38:28 -07006#include "aos/events/logging/logger_generated.h"
Austin Schuh01b4c352020-09-21 23:09:39 -07007#include "aos/events/message_counter.h"
Austin Schuh898f4972020-01-11 17:21:25 -08008#include "aos/events/ping_lib.h"
9#include "aos/events/pong_lib.h"
Austin Schuh7d87b672019-12-01 20:23:49 -080010#include "aos/events/test_message_generated.h"
Austin Schuh4c3b9702020-08-30 11:34:55 -070011#include "aos/network/message_bridge_client_generated.h"
12#include "aos/network/message_bridge_server_generated.h"
13#include "aos/network/timestamp_generated.h"
Neil Balchc8f41ed2018-01-20 22:06:53 -080014#include "gtest/gtest.h"
15
16namespace aos {
17namespace testing {
Brian Silverman28d14302020-09-18 15:26:17 -070018namespace {
19
20std::string ConfigPrefix() { return "aos/"; }
21
22} // namespace
Neil Balchc8f41ed2018-01-20 22:06:53 -080023
Austin Schuh7267c532019-05-19 19:55:53 -070024namespace chrono = ::std::chrono;
25
Neil Balchc8f41ed2018-01-20 22:06:53 -080026class SimulatedEventLoopTestFactory : public EventLoopTestFactory {
27 public:
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080028 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080029 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080030 return event_loop_factory_->MakeEventLoop(name, my_node());
Neil Balchc8f41ed2018-01-20 22:06:53 -080031 }
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080032 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080033 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080034 return event_loop_factory_->MakeEventLoop(name, my_node());
Austin Schuh44019f92019-05-19 19:58:27 -070035 }
36
Austin Schuh217a9782019-12-21 23:02:50 -080037 void Run() override { event_loop_factory_->Run(); }
38 void Exit() override { event_loop_factory_->Exit(); }
Austin Schuh44019f92019-05-19 19:58:27 -070039
Austin Schuh52d325c2019-06-23 18:59:06 -070040 // TODO(austin): Implement this. It's used currently for a phased loop test.
41 // I'm not sure how much that matters.
42 void SleepFor(::std::chrono::nanoseconds /*duration*/) override {}
43
Austin Schuh7d87b672019-12-01 20:23:49 -080044 void set_send_delay(std::chrono::nanoseconds send_delay) {
Austin Schuh217a9782019-12-21 23:02:50 -080045 MaybeMake();
46 event_loop_factory_->set_send_delay(send_delay);
Austin Schuh7d87b672019-12-01 20:23:49 -080047 }
48
Neil Balchc8f41ed2018-01-20 22:06:53 -080049 private:
Austin Schuh217a9782019-12-21 23:02:50 -080050 void MaybeMake() {
51 if (!event_loop_factory_) {
52 if (configuration()->has_nodes()) {
Austin Schuhac0771c2020-01-07 18:36:30 -080053 event_loop_factory_ =
54 std::make_unique<SimulatedEventLoopFactory>(configuration());
Austin Schuh217a9782019-12-21 23:02:50 -080055 } else {
56 event_loop_factory_ =
57 std::make_unique<SimulatedEventLoopFactory>(configuration());
58 }
59 }
60 }
61 std::unique_ptr<SimulatedEventLoopFactory> event_loop_factory_;
Neil Balchc8f41ed2018-01-20 22:06:53 -080062};
63
Brian Silverman77162972020-08-12 19:52:40 -070064INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCopyTest, AbstractEventLoopTest,
65 ::testing::Values(std::make_tuple(
66 []() {
67 return new SimulatedEventLoopTestFactory();
68 },
69 ReadMethod::COPY)));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070070
Brian Silverman77162972020-08-12 19:52:40 -070071INSTANTIATE_TEST_CASE_P(
72 SimulatedEventLoopCopyDeathTest, AbstractEventLoopDeathTest,
73 ::testing::Values(
74 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
75 ReadMethod::COPY)));
76
77INSTANTIATE_TEST_CASE_P(SimulatedEventLoopPinTest, AbstractEventLoopTest,
78 ::testing::Values(std::make_tuple(
79 []() {
80 return new SimulatedEventLoopTestFactory();
81 },
82 ReadMethod::PIN)));
83
84INSTANTIATE_TEST_CASE_P(
85 SimulatedEventLoopPinDeathTest, AbstractEventLoopDeathTest,
86 ::testing::Values(
87 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
88 ReadMethod::PIN)));
Neil Balchc8f41ed2018-01-20 22:06:53 -080089
90// Test that creating an event and running the scheduler runs the event.
91TEST(EventSchedulerTest, ScheduleEvent) {
92 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -080093 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -080094 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -080095 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -080096
Austin Schuh8bd96322020-02-13 21:18:22 -080097 scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuhac0771c2020-01-07 18:36:30 -080098 [&counter]() { counter += 1; });
Austin Schuh8bd96322020-02-13 21:18:22 -080099 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800100 EXPECT_EQ(counter, 1);
Ravago Jonescf453ab2020-05-06 21:14:53 -0700101 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(2),
102 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800103 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800104 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800105 EXPECT_EQ(counter, 1);
106}
107
108// Test that descheduling an already scheduled event doesn't run the event.
109TEST(EventSchedulerTest, DescheduleEvent) {
110 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -0800111 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -0800112 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -0800113 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -0800114
Austin Schuh8bd96322020-02-13 21:18:22 -0800115 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
116 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800117 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800118 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800119 EXPECT_EQ(counter, 0);
120}
Austin Schuh44019f92019-05-19 19:58:27 -0700121
Austin Schuh8fb315a2020-11-19 22:33:58 -0800122void SendTestMessage(aos::Sender<TestMessage> *sender, int value) {
123 aos::Sender<TestMessage>::Builder builder = sender->MakeBuilder();
124 TestMessage::Builder test_message_builder =
125 builder.MakeBuilder<TestMessage>();
126 test_message_builder.add_value(value);
127 builder.Send(test_message_builder.Finish());
128}
129
130// Test that sending a message after running gets properly notified.
131TEST(SimulatedEventLoopTest, SendAfterRunFor) {
132 SimulatedEventLoopTestFactory factory;
133
134 SimulatedEventLoopFactory simulated_event_loop_factory(
135 factory.configuration());
136
137 ::std::unique_ptr<EventLoop> ping_event_loop =
138 simulated_event_loop_factory.MakeEventLoop("ping");
139 aos::Sender<TestMessage> test_message_sender =
140 ping_event_loop->MakeSender<TestMessage>("/test");
141 SendTestMessage(&test_message_sender, 1);
142
143 std::unique_ptr<EventLoop> pong1_event_loop =
144 simulated_event_loop_factory.MakeEventLoop("pong");
145 MessageCounter<TestMessage> test_message_counter1(pong1_event_loop.get(),
146 "/test");
147
148 EXPECT_FALSE(ping_event_loop->is_running());
149
150 // Watchers start when you start running, so there should be nothing counted.
151 simulated_event_loop_factory.RunFor(chrono::seconds(1));
152 EXPECT_EQ(test_message_counter1.count(), 0u);
153
154 std::unique_ptr<EventLoop> pong2_event_loop =
155 simulated_event_loop_factory.MakeEventLoop("pong");
156 MessageCounter<TestMessage> test_message_counter2(pong2_event_loop.get(),
157 "/test");
158
159 // Pauses in the middle don't count though, so this should be counted.
160 // But, the fresh watcher shouldn't pick it up yet.
161 SendTestMessage(&test_message_sender, 2);
162
163 EXPECT_EQ(test_message_counter1.count(), 0u);
164 EXPECT_EQ(test_message_counter2.count(), 0u);
165 simulated_event_loop_factory.RunFor(chrono::seconds(1));
166
167 EXPECT_EQ(test_message_counter1.count(), 1u);
168 EXPECT_EQ(test_message_counter2.count(), 0u);
169}
170
171// Test that creating an event loop while running dies.
172TEST(SimulatedEventLoopDeathTest, MakeEventLoopWhileRunning) {
173 SimulatedEventLoopTestFactory factory;
174
175 SimulatedEventLoopFactory simulated_event_loop_factory(
176 factory.configuration());
177
178 ::std::unique_ptr<EventLoop> event_loop =
179 simulated_event_loop_factory.MakeEventLoop("ping");
180
181 auto timer = event_loop->AddTimer([&]() {
182 EXPECT_DEATH(
183 {
184 ::std::unique_ptr<EventLoop> event_loop2 =
185 simulated_event_loop_factory.MakeEventLoop("ping");
186 },
187 "event loop while running");
188 simulated_event_loop_factory.Exit();
189 });
190
191 event_loop->OnRun([&event_loop, &timer] {
192 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50));
193 });
194
195 simulated_event_loop_factory.Run();
196}
197
198// Test that creating a watcher after running dies.
199TEST(SimulatedEventLoopDeathTest, MakeWatcherAfterRunning) {
200 SimulatedEventLoopTestFactory factory;
201
202 SimulatedEventLoopFactory simulated_event_loop_factory(
203 factory.configuration());
204
205 ::std::unique_ptr<EventLoop> event_loop =
206 simulated_event_loop_factory.MakeEventLoop("ping");
207
208 simulated_event_loop_factory.RunFor(chrono::seconds(1));
209
210 EXPECT_DEATH(
211 { MessageCounter<TestMessage> counter(event_loop.get(), "/test"); },
212 "Can't add a watcher after running");
213
214 ::std::unique_ptr<EventLoop> event_loop2 =
215 simulated_event_loop_factory.MakeEventLoop("ping");
216
217 simulated_event_loop_factory.RunFor(chrono::seconds(1));
218
219 EXPECT_DEATH(
220 { MessageCounter<TestMessage> counter(event_loop2.get(), "/test"); },
221 "Can't add a watcher after running");
222}
223
Austin Schuh44019f92019-05-19 19:58:27 -0700224// Test that running for a time period with no handlers causes time to progress
225// correctly.
226TEST(SimulatedEventLoopTest, RunForNoHandlers) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800227 SimulatedEventLoopTestFactory factory;
228
229 SimulatedEventLoopFactory simulated_event_loop_factory(
230 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700231 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800232 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700233
234 simulated_event_loop_factory.RunFor(chrono::seconds(1));
235
236 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700237 event_loop->monotonic_now());
238}
239
240// Test that running for a time with a periodic handler causes time to end
241// correctly.
242TEST(SimulatedEventLoopTest, RunForTimerHandler) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800243 SimulatedEventLoopTestFactory factory;
244
245 SimulatedEventLoopFactory simulated_event_loop_factory(
246 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700247 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800248 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700249
250 int counter = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700251 auto timer = event_loop->AddTimer([&counter]() { ++counter; });
Austin Schuh44019f92019-05-19 19:58:27 -0700252 event_loop->OnRun([&event_loop, &timer] {
253 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50),
254 chrono::milliseconds(100));
255 });
256
257 simulated_event_loop_factory.RunFor(chrono::seconds(1));
258
259 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700260 event_loop->monotonic_now());
261 EXPECT_EQ(counter, 10);
262}
263
Austin Schuh7d87b672019-12-01 20:23:49 -0800264// Tests that watchers have latency in simulation.
265TEST(SimulatedEventLoopTest, WatcherTimingReport) {
266 SimulatedEventLoopTestFactory factory;
267 factory.set_send_delay(std::chrono::microseconds(50));
268
269 FLAGS_timing_report_ms = 1000;
270 auto loop1 = factory.MakePrimary("primary");
271 loop1->MakeWatcher("/test", [](const TestMessage &) {});
272
273 auto loop2 = factory.Make("sender_loop");
274
275 auto loop3 = factory.Make("report_fetcher");
276
277 Fetcher<timing::Report> report_fetcher =
278 loop3->MakeFetcher<timing::Report>("/aos");
279 EXPECT_FALSE(report_fetcher.Fetch());
280
281 auto sender = loop2->MakeSender<TestMessage>("/test");
282
283 // Send 10 messages in the middle of a timing report period so we get
284 // something interesting back.
285 auto test_timer = loop2->AddTimer([&sender]() {
286 for (int i = 0; i < 10; ++i) {
287 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
288 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
289 builder.add_value(200 + i);
290 ASSERT_TRUE(msg.Send(builder.Finish()));
291 }
292 });
293
294 // Quit after 1 timing report, mid way through the next cycle.
295 {
296 auto end_timer = loop1->AddTimer([&factory]() { factory.Exit(); });
297 end_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(2500));
298 end_timer->set_name("end");
299 }
300
301 loop1->OnRun([&test_timer, &loop1]() {
302 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
303 });
304
305 factory.Run();
306
307 // And, since we are here, check that the timing report makes sense.
308 // Start by looking for our event loop's timing.
309 FlatbufferDetachedBuffer<timing::Report> primary_report =
310 FlatbufferDetachedBuffer<timing::Report>::Empty();
311 while (report_fetcher.FetchNext()) {
312 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
313 if (report_fetcher->name()->string_view() == "primary") {
314 primary_report = CopyFlatBuffer(report_fetcher.get());
315 }
316 }
317
318 // Check the watcher report.
Ravago Jonescf453ab2020-05-06 21:14:53 -0700319 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh7d87b672019-12-01 20:23:49 -0800320
321 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
322
323 // Just the timing report timer.
324 ASSERT_NE(primary_report.message().timers(), nullptr);
325 EXPECT_EQ(primary_report.message().timers()->size(), 2);
326
327 // No phased loops
328 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
329
330 // And now confirm that the watcher received all 10 messages, and has latency.
331 ASSERT_NE(primary_report.message().watchers(), nullptr);
332 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
333 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
334 EXPECT_NEAR(
335 primary_report.message().watchers()->Get(0)->wakeup_latency()->average(),
336 0.00005, 1e-9);
337 EXPECT_NEAR(
338 primary_report.message().watchers()->Get(0)->wakeup_latency()->min(),
339 0.00005, 1e-9);
340 EXPECT_NEAR(
341 primary_report.message().watchers()->Get(0)->wakeup_latency()->max(),
342 0.00005, 1e-9);
343 EXPECT_EQ(primary_report.message()
344 .watchers()
345 ->Get(0)
346 ->wakeup_latency()
347 ->standard_deviation(),
348 0.0);
349
350 EXPECT_EQ(
351 primary_report.message().watchers()->Get(0)->handler_time()->average(),
352 0.0);
353 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->min(),
354 0.0);
355 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->max(),
356 0.0);
357 EXPECT_EQ(primary_report.message()
358 .watchers()
359 ->Get(0)
360 ->handler_time()
361 ->standard_deviation(),
362 0.0);
363}
364
Austin Schuh4c3b9702020-08-30 11:34:55 -0700365// Tests that ping and pong work when on 2 different nodes, and the message
366// gateway messages are sent out as expected.
Austin Schuh898f4972020-01-11 17:21:25 -0800367TEST(SimulatedEventLoopTest, MultinodePingPong) {
368 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700369 aos::configuration::ReadConfig(ConfigPrefix() +
370 "events/multinode_pingpong_config.json");
Austin Schuh898f4972020-01-11 17:21:25 -0800371 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
372 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700373 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh898f4972020-01-11 17:21:25 -0800374
375 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
376
377 std::unique_ptr<EventLoop> ping_event_loop =
378 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
379 Ping ping(ping_event_loop.get());
380
381 std::unique_ptr<EventLoop> pong_event_loop =
382 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
383 Pong pong(pong_event_loop.get());
384
385 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
386 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700387 MessageCounter<examples::Pong> pi2_pong_counter(
388 pi2_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700389 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi2_timestamp_fetcher =
390 pi2_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
391 "/pi1/aos");
392 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
393 pi2_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
Austin Schuh898f4972020-01-11 17:21:25 -0800394
Austin Schuh4c3b9702020-08-30 11:34:55 -0700395 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
396 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
Austin Schuh898f4972020-01-11 17:21:25 -0800397
398 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
399 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700400 MessageCounter<examples::Pong> pi1_pong_counter(
401 pi1_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700402 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
403 pi1_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
404 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi1_timestamp_fetcher =
405 pi1_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
406 "/aos");
407
Austin Schuh4c3b9702020-08-30 11:34:55 -0700408 // Count timestamps.
409 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
410 pi1_pong_counter_event_loop.get(), "/pi1/aos");
411 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
412 pi2_pong_counter_event_loop.get(), "/pi1/aos");
413 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
414 pi3_pong_counter_event_loop.get(), "/pi1/aos");
415 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
416 pi1_pong_counter_event_loop.get(), "/pi2/aos");
417 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
418 pi2_pong_counter_event_loop.get(), "/pi2/aos");
419 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
420 pi1_pong_counter_event_loop.get(), "/pi3/aos");
421 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
422 pi3_pong_counter_event_loop.get(), "/pi3/aos");
423
Austin Schuh2f8fd752020-09-01 22:38:28 -0700424 // Count remote timestamps
425 MessageCounter<logger::MessageHeader> remote_timestamps_pi2_on_pi1(
426 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
427 MessageCounter<logger::MessageHeader> remote_timestamps_pi1_on_pi2(
428 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
429
Austin Schuh4c3b9702020-08-30 11:34:55 -0700430 // Wait to let timestamp estimation start up before looking for the results.
431 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
432
Austin Schuh8fb315a2020-11-19 22:33:58 -0800433 std::unique_ptr<EventLoop> pi1_statistics_counter_event_loop =
434 simulated_event_loop_factory.MakeEventLoop("pi1_statistics_counter", pi1);
435 std::unique_ptr<EventLoop> pi2_statistics_counter_event_loop =
436 simulated_event_loop_factory.MakeEventLoop("pi2_statistics_counter", pi2);
437 std::unique_ptr<EventLoop> pi3_statistics_counter_event_loop =
438 simulated_event_loop_factory.MakeEventLoop("pi3_statistics_counter", pi3);
439
Austin Schuh4c3b9702020-08-30 11:34:55 -0700440 int pi1_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800441 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700442 "/pi1/aos", [&pi1_server_statistics_count](
443 const message_bridge::ServerStatistics &stats) {
444 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
445 EXPECT_EQ(stats.connections()->size(), 2u);
446 for (const message_bridge::ServerConnection *connection :
447 *stats.connections()) {
448 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
449 if (connection->node()->name()->string_view() == "pi2") {
450 EXPECT_GT(connection->sent_packets(), 50);
451 } else if (connection->node()->name()->string_view() == "pi3") {
452 EXPECT_GE(connection->sent_packets(), 5);
453 } else {
454 LOG(FATAL) << "Unknown connection";
455 }
456
457 EXPECT_TRUE(connection->has_monotonic_offset());
458 EXPECT_EQ(connection->monotonic_offset(), 0);
459 }
460 ++pi1_server_statistics_count;
461 });
462
463 int pi2_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800464 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700465 "/pi2/aos", [&pi2_server_statistics_count](
466 const message_bridge::ServerStatistics &stats) {
467 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
468 EXPECT_EQ(stats.connections()->size(), 1u);
469
470 const message_bridge::ServerConnection *connection =
471 stats.connections()->Get(0);
472 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
473 EXPECT_GT(connection->sent_packets(), 50);
474 EXPECT_TRUE(connection->has_monotonic_offset());
475 EXPECT_EQ(connection->monotonic_offset(), 0);
476 ++pi2_server_statistics_count;
477 });
478
479 int pi3_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800480 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700481 "/pi3/aos", [&pi3_server_statistics_count](
482 const message_bridge::ServerStatistics &stats) {
483 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
484 EXPECT_EQ(stats.connections()->size(), 1u);
485
486 const message_bridge::ServerConnection *connection =
487 stats.connections()->Get(0);
488 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
489 EXPECT_GE(connection->sent_packets(), 5);
490 EXPECT_TRUE(connection->has_monotonic_offset());
491 EXPECT_EQ(connection->monotonic_offset(), 0);
492 ++pi3_server_statistics_count;
493 });
494
495 int pi1_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800496 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700497 "/pi1/aos", [&pi1_client_statistics_count](
498 const message_bridge::ClientStatistics &stats) {
499 VLOG(1) << "pi1 ClientStatistics " << FlatbufferToJson(&stats);
500 EXPECT_EQ(stats.connections()->size(), 2u);
501
502 for (const message_bridge::ClientConnection *connection :
503 *stats.connections()) {
504 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
505 if (connection->node()->name()->string_view() == "pi2") {
506 EXPECT_GT(connection->received_packets(), 50);
507 } else if (connection->node()->name()->string_view() == "pi3") {
508 EXPECT_GE(connection->received_packets(), 5);
509 } else {
510 LOG(FATAL) << "Unknown connection";
511 }
512
513 EXPECT_TRUE(connection->has_monotonic_offset());
514 EXPECT_EQ(connection->monotonic_offset(), 150000);
515 }
516 ++pi1_client_statistics_count;
517 });
518
519 int pi2_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800520 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700521 "/pi2/aos", [&pi2_client_statistics_count](
522 const message_bridge::ClientStatistics &stats) {
523 VLOG(1) << "pi2 ClientStatistics " << FlatbufferToJson(&stats);
524 EXPECT_EQ(stats.connections()->size(), 1u);
525
526 const message_bridge::ClientConnection *connection =
527 stats.connections()->Get(0);
528 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
529 EXPECT_GT(connection->received_packets(), 50);
530 EXPECT_TRUE(connection->has_monotonic_offset());
531 EXPECT_EQ(connection->monotonic_offset(), 150000);
532 ++pi2_client_statistics_count;
533 });
534
535 int pi3_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800536 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700537 "/pi3/aos", [&pi3_client_statistics_count](
538 const message_bridge::ClientStatistics &stats) {
539 VLOG(1) << "pi3 ClientStatistics " << FlatbufferToJson(&stats);
540 EXPECT_EQ(stats.connections()->size(), 1u);
541
542 const message_bridge::ClientConnection *connection =
543 stats.connections()->Get(0);
544 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
545 EXPECT_GE(connection->received_packets(), 5);
546 EXPECT_TRUE(connection->has_monotonic_offset());
547 EXPECT_EQ(connection->monotonic_offset(), 150000);
548 ++pi3_client_statistics_count;
549 });
550
Austin Schuh2f8fd752020-09-01 22:38:28 -0700551 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
552 // channel.
553 const size_t pi1_timestamp_channel =
554 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
555 pi1_on_pi2_timestamp_fetcher.channel());
556 const size_t ping_timestamp_channel =
557 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
558 ping_on_pi2_fetcher.channel());
559
560 for (const Channel *channel :
561 *pi1_pong_counter_event_loop->configuration()->channels()) {
562 VLOG(1) << "Channel "
563 << configuration::ChannelIndex(
564 pi1_pong_counter_event_loop->configuration(), channel)
565 << " " << configuration::CleanedChannelToString(channel);
566 }
567
Austin Schuh8fb315a2020-11-19 22:33:58 -0800568 std::unique_ptr<EventLoop> pi1_remote_timestamp =
569 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
570
Austin Schuh2f8fd752020-09-01 22:38:28 -0700571 // For each remote timestamp we get back, confirm that it is either a ping
572 // message, or a timestamp we sent out. Also confirm that the timestamps are
573 // correct.
574 pi1_remote_timestamp->MakeWatcher(
575 "/pi1/aos/remote_timestamps/pi2",
576 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
577 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
578 &pi1_on_pi1_timestamp_fetcher](const logger::MessageHeader &header) {
579 VLOG(1) << aos::FlatbufferToJson(&header);
580
581 const aos::monotonic_clock::time_point header_monotonic_sent_time(
582 chrono::nanoseconds(header.monotonic_sent_time()));
583 const aos::realtime_clock::time_point header_realtime_sent_time(
584 chrono::nanoseconds(header.realtime_sent_time()));
585 const aos::monotonic_clock::time_point header_monotonic_remote_time(
586 chrono::nanoseconds(header.monotonic_remote_time()));
587 const aos::realtime_clock::time_point header_realtime_remote_time(
588 chrono::nanoseconds(header.realtime_remote_time()));
589
590 const Context *pi1_context = nullptr;
591 const Context *pi2_context = nullptr;
592
593 if (header.channel_index() == pi1_timestamp_channel) {
594 // Find the forwarded message.
595 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
596 header_monotonic_sent_time) {
597 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
598 }
599
600 // And the source message.
601 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
602 header_monotonic_remote_time) {
603 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
604 }
605
606 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
607 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
608 } else if (header.channel_index() == ping_timestamp_channel) {
609 // Find the forwarded message.
610 while (ping_on_pi2_fetcher.context().monotonic_event_time <
611 header_monotonic_sent_time) {
612 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
613 }
614
615 // And the source message.
616 while (ping_on_pi1_fetcher.context().monotonic_event_time <
617 header_monotonic_remote_time) {
618 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
619 }
620
621 pi1_context = &ping_on_pi1_fetcher.context();
622 pi2_context = &ping_on_pi2_fetcher.context();
623 } else {
624 LOG(FATAL) << "Unknown channel";
625 }
626
627 // Confirm the forwarded message has matching timestamps to the
628 // timestamps we got back.
629 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700630 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700631 EXPECT_EQ(pi2_context->monotonic_event_time,
632 header_monotonic_sent_time);
633 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
634 EXPECT_EQ(pi2_context->realtime_remote_time,
635 header_realtime_remote_time);
636 EXPECT_EQ(pi2_context->monotonic_remote_time,
637 header_monotonic_remote_time);
638
639 // Confirm the forwarded message also matches the source message.
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700640 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700641 EXPECT_EQ(pi1_context->monotonic_event_time,
642 header_monotonic_remote_time);
643 EXPECT_EQ(pi1_context->realtime_event_time,
644 header_realtime_remote_time);
645 });
646
Austin Schuh4c3b9702020-08-30 11:34:55 -0700647 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
648 chrono::milliseconds(500) +
649 chrono::milliseconds(5));
650
651 EXPECT_EQ(pi1_pong_counter.count(), 1001);
652 EXPECT_EQ(pi2_pong_counter.count(), 1001);
653
654 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 100);
655 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 100);
656 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 100);
657 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 100);
658 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 100);
659 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 100);
660 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 100);
661
662 EXPECT_EQ(pi1_server_statistics_count, 9);
663 EXPECT_EQ(pi2_server_statistics_count, 9);
664 EXPECT_EQ(pi3_server_statistics_count, 9);
665
666 EXPECT_EQ(pi1_client_statistics_count, 95);
667 EXPECT_EQ(pi2_client_statistics_count, 95);
668 EXPECT_EQ(pi3_client_statistics_count, 95);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700669
670 // Also confirm that remote timestamps are being forwarded correctly.
671 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1101);
672 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1101);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700673}
674
675// Tests that an offset between nodes can be recovered and shows up in
676// ServerStatistics correctly.
677TEST(SimulatedEventLoopTest, MultinodePingPongWithOffset) {
678 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700679 aos::configuration::ReadConfig(ConfigPrefix() +
680 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700681 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
682 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
683 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
684
685 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
686 NodeEventLoopFactory *pi2_factory =
687 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
688
689 constexpr chrono::milliseconds kOffset{1501};
690 pi2_factory->SetDistributedOffset(kOffset, 1.0);
691
692 std::unique_ptr<EventLoop> ping_event_loop =
693 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
694 Ping ping(ping_event_loop.get());
695
696 std::unique_ptr<EventLoop> pong_event_loop =
697 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
698 Pong pong(pong_event_loop.get());
699
Austin Schuh8fb315a2020-11-19 22:33:58 -0800700 // Wait to let timestamp estimation start up before looking for the results.
701 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
702
Austin Schuh4c3b9702020-08-30 11:34:55 -0700703 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
704 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
705
706 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
707 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
708
709 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
710 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
711
Austin Schuh4c3b9702020-08-30 11:34:55 -0700712
713 // Confirm the offsets are being recovered correctly.
714 int pi1_server_statistics_count = 0;
715 pi1_pong_counter_event_loop->MakeWatcher(
716 "/pi1/aos", [&pi1_server_statistics_count,
717 kOffset](const message_bridge::ServerStatistics &stats) {
718 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
719 EXPECT_EQ(stats.connections()->size(), 2u);
720 for (const message_bridge::ServerConnection *connection :
721 *stats.connections()) {
722 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
723 if (connection->node()->name()->string_view() == "pi2") {
724 EXPECT_EQ(connection->monotonic_offset(),
725 chrono::nanoseconds(kOffset).count());
726 } else if (connection->node()->name()->string_view() == "pi3") {
727 EXPECT_EQ(connection->monotonic_offset(), 0);
728 } else {
729 LOG(FATAL) << "Unknown connection";
730 }
731
732 EXPECT_TRUE(connection->has_monotonic_offset());
733 }
734 ++pi1_server_statistics_count;
735 });
736
737 int pi2_server_statistics_count = 0;
738 pi2_pong_counter_event_loop->MakeWatcher(
739 "/pi2/aos", [&pi2_server_statistics_count,
740 kOffset](const message_bridge::ServerStatistics &stats) {
741 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
742 EXPECT_EQ(stats.connections()->size(), 1u);
743
744 const message_bridge::ServerConnection *connection =
745 stats.connections()->Get(0);
746 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
747 EXPECT_TRUE(connection->has_monotonic_offset());
748 EXPECT_EQ(connection->monotonic_offset(),
749 -chrono::nanoseconds(kOffset).count());
750 ++pi2_server_statistics_count;
751 });
752
753 int pi3_server_statistics_count = 0;
754 pi3_pong_counter_event_loop->MakeWatcher(
755 "/pi3/aos", [&pi3_server_statistics_count](
756 const message_bridge::ServerStatistics &stats) {
757 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
758 EXPECT_EQ(stats.connections()->size(), 1u);
759
760 const message_bridge::ServerConnection *connection =
761 stats.connections()->Get(0);
762 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
763 EXPECT_TRUE(connection->has_monotonic_offset());
764 EXPECT_EQ(connection->monotonic_offset(), 0);
765 ++pi3_server_statistics_count;
766 });
767
768 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
769 chrono::milliseconds(500) +
770 chrono::milliseconds(5));
771
772 EXPECT_EQ(pi1_server_statistics_count, 9);
773 EXPECT_EQ(pi2_server_statistics_count, 9);
774 EXPECT_EQ(pi3_server_statistics_count, 9);
775}
776
777// Test that disabling statistics actually disables them.
778TEST(SimulatedEventLoopTest, MultinodeWithoutStatistics) {
779 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700780 aos::configuration::ReadConfig(ConfigPrefix() +
781 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700782 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
783 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
784 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
785
786 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
787 simulated_event_loop_factory.DisableStatistics();
788
789 std::unique_ptr<EventLoop> ping_event_loop =
790 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
791 Ping ping(ping_event_loop.get());
792
793 std::unique_ptr<EventLoop> pong_event_loop =
794 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
795 Pong pong(pong_event_loop.get());
796
797 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
798 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
799
800 MessageCounter<examples::Pong> pi2_pong_counter(
801 pi2_pong_counter_event_loop.get(), "/test");
802
803 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
804 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
805
806 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
807 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
808
809 MessageCounter<examples::Pong> pi1_pong_counter(
810 pi1_pong_counter_event_loop.get(), "/test");
811
812 // Count timestamps.
813 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
814 pi1_pong_counter_event_loop.get(), "/pi1/aos");
815 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
816 pi2_pong_counter_event_loop.get(), "/pi1/aos");
817 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
818 pi3_pong_counter_event_loop.get(), "/pi1/aos");
819 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
820 pi1_pong_counter_event_loop.get(), "/pi2/aos");
821 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
822 pi2_pong_counter_event_loop.get(), "/pi2/aos");
823 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
824 pi1_pong_counter_event_loop.get(), "/pi3/aos");
825 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
826 pi3_pong_counter_event_loop.get(), "/pi3/aos");
827
Austin Schuh2f8fd752020-09-01 22:38:28 -0700828 // Count remote timestamps
829 MessageCounter<logger::MessageHeader> remote_timestamps_pi2_on_pi1(
830 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
831 MessageCounter<logger::MessageHeader> remote_timestamps_pi1_on_pi2(
832 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
833
Austin Schuh4c3b9702020-08-30 11:34:55 -0700834 MessageCounter<message_bridge::ServerStatistics>
835 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
836 "/pi1/aos");
837 MessageCounter<message_bridge::ServerStatistics>
838 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
839 "/pi2/aos");
840 MessageCounter<message_bridge::ServerStatistics>
841 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
842 "/pi3/aos");
843
844 MessageCounter<message_bridge::ClientStatistics>
845 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
846 "/pi1/aos");
847 MessageCounter<message_bridge::ClientStatistics>
848 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
849 "/pi2/aos");
850 MessageCounter<message_bridge::ClientStatistics>
851 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
852 "/pi3/aos");
Austin Schuh898f4972020-01-11 17:21:25 -0800853
854 simulated_event_loop_factory.RunFor(chrono::seconds(10) +
855 chrono::milliseconds(5));
856
Austin Schuh4c3b9702020-08-30 11:34:55 -0700857 EXPECT_EQ(pi1_pong_counter.count(), 1001u);
858 EXPECT_EQ(pi2_pong_counter.count(), 1001u);
859
860 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 0u);
861 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 0u);
862 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 0u);
863 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 0u);
864 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 0u);
865 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 0u);
866 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 0u);
867
868 EXPECT_EQ(pi1_server_statistics_counter.count(), 0u);
869 EXPECT_EQ(pi2_server_statistics_counter.count(), 0u);
870 EXPECT_EQ(pi3_server_statistics_counter.count(), 0u);
871
872 EXPECT_EQ(pi1_client_statistics_counter.count(), 0u);
873 EXPECT_EQ(pi2_client_statistics_counter.count(), 0u);
874 EXPECT_EQ(pi3_client_statistics_counter.count(), 0u);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700875
876 // Also confirm that remote timestamps are being forwarded correctly.
877 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1001);
878 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1001);
Austin Schuh898f4972020-01-11 17:21:25 -0800879}
880
Austin Schuh2febf0d2020-09-21 22:24:30 -0700881// Tests that the time offset having a slope doesn't break the world.
882// SimulatedMessageBridge has enough self consistency CHECK statements to
883// confirm, and we can can also check a message in each direction to make sure
884// it gets delivered as expected.
885TEST(SimulatedEventLoopTest, MultinodePingPongWithOffsetAndSlope) {
886 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
887 aos::configuration::ReadConfig(ConfigPrefix() +
888 "events/multinode_pingpong_config.json");
889 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
890 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
891
892 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
893 NodeEventLoopFactory *pi2_factory =
894 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
895
896 // Move the pi far into the future so the slope is significant. And set it to
897 // something reasonable.
898 constexpr chrono::milliseconds kOffset{150100};
899 pi2_factory->SetDistributedOffset(kOffset, 1.0001);
900
901 std::unique_ptr<EventLoop> ping_event_loop =
902 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
903 Ping ping(ping_event_loop.get());
904
905 std::unique_ptr<EventLoop> pong_event_loop =
906 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
907 Pong pong(pong_event_loop.get());
908
909 std::unique_ptr<EventLoop> pi1_counter_event_loop =
910 simulated_event_loop_factory.MakeEventLoop("pi1_counter", pi1);
911 std::unique_ptr<EventLoop> pi2_counter_event_loop =
912 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi2);
913
914 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
915 pi1_counter_event_loop->MakeFetcher<examples::Ping>("/test");
916 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
917 pi2_counter_event_loop->MakeFetcher<examples::Ping>("/test");
918
919 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
920 pi2_counter_event_loop->MakeFetcher<examples::Pong>("/test");
921 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
922 pi1_counter_event_loop->MakeFetcher<examples::Pong>("/test");
923
924 // End after a pong message comes back. This will leave the latest messages
925 // on all channels so we can look at timestamps easily and check they make
926 // sense.
927 std::unique_ptr<EventLoop> pi1_pong_ender =
928 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi1);
929 int count = 0;
930 pi1_pong_ender->MakeWatcher(
931 "/test", [&simulated_event_loop_factory, &count](const examples::Pong &) {
932 if (++count == 100) {
933 simulated_event_loop_factory.Exit();
934 }
935 });
936
937 // Run enough that messages should be delivered.
938 simulated_event_loop_factory.Run();
939
940 // Grab the latest messages.
941 EXPECT_TRUE(ping_on_pi1_fetcher.Fetch());
942 EXPECT_TRUE(ping_on_pi2_fetcher.Fetch());
943 EXPECT_TRUE(pong_on_pi1_fetcher.Fetch());
944 EXPECT_TRUE(pong_on_pi2_fetcher.Fetch());
945
946 // Compute their time on the global distributed clock so we can compute
947 // distance betwen them.
948 const distributed_clock::time_point pi1_ping_time =
949 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
950 ->ToDistributedClock(
951 ping_on_pi1_fetcher.context().monotonic_event_time);
952 const distributed_clock::time_point pi2_ping_time =
953 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
954 ->ToDistributedClock(
955 ping_on_pi2_fetcher.context().monotonic_event_time);
956 const distributed_clock::time_point pi1_pong_time =
957 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
958 ->ToDistributedClock(
959 pong_on_pi1_fetcher.context().monotonic_event_time);
960 const distributed_clock::time_point pi2_pong_time =
961 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
962 ->ToDistributedClock(
963 pong_on_pi2_fetcher.context().monotonic_event_time);
964
965 // And confirm the delivery delay is just about exactly 150 uS for both
966 // directions like expected. There will be a couple ns of rounding errors in
967 // the conversion functions that aren't worth accounting for right now. This
968 // will either be really close, or really far.
969 EXPECT_GE(pi2_ping_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
970 pi1_ping_time);
971 EXPECT_LE(pi2_ping_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
972 pi1_ping_time);
973
974 EXPECT_GE(pi1_pong_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
975 pi2_pong_time);
976 EXPECT_LE(pi1_pong_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
977 pi2_pong_time);
978}
979
Neil Balchc8f41ed2018-01-20 22:06:53 -0800980} // namespace testing
981} // namespace aos