blob: bdf52c117eac34c4ead385cf2e7d0469a9e44268 [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 // Confirm the offsets are being recovered correctly.
713 int pi1_server_statistics_count = 0;
714 pi1_pong_counter_event_loop->MakeWatcher(
715 "/pi1/aos", [&pi1_server_statistics_count,
716 kOffset](const message_bridge::ServerStatistics &stats) {
717 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
718 EXPECT_EQ(stats.connections()->size(), 2u);
719 for (const message_bridge::ServerConnection *connection :
720 *stats.connections()) {
721 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
722 if (connection->node()->name()->string_view() == "pi2") {
723 EXPECT_EQ(connection->monotonic_offset(),
724 chrono::nanoseconds(kOffset).count());
725 } else if (connection->node()->name()->string_view() == "pi3") {
726 EXPECT_EQ(connection->monotonic_offset(), 0);
727 } else {
728 LOG(FATAL) << "Unknown connection";
729 }
730
731 EXPECT_TRUE(connection->has_monotonic_offset());
732 }
733 ++pi1_server_statistics_count;
734 });
735
736 int pi2_server_statistics_count = 0;
737 pi2_pong_counter_event_loop->MakeWatcher(
738 "/pi2/aos", [&pi2_server_statistics_count,
739 kOffset](const message_bridge::ServerStatistics &stats) {
740 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
741 EXPECT_EQ(stats.connections()->size(), 1u);
742
743 const message_bridge::ServerConnection *connection =
744 stats.connections()->Get(0);
745 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
746 EXPECT_TRUE(connection->has_monotonic_offset());
747 EXPECT_EQ(connection->monotonic_offset(),
748 -chrono::nanoseconds(kOffset).count());
749 ++pi2_server_statistics_count;
750 });
751
752 int pi3_server_statistics_count = 0;
753 pi3_pong_counter_event_loop->MakeWatcher(
754 "/pi3/aos", [&pi3_server_statistics_count](
755 const message_bridge::ServerStatistics &stats) {
756 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
757 EXPECT_EQ(stats.connections()->size(), 1u);
758
759 const message_bridge::ServerConnection *connection =
760 stats.connections()->Get(0);
761 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
762 EXPECT_TRUE(connection->has_monotonic_offset());
763 EXPECT_EQ(connection->monotonic_offset(), 0);
764 ++pi3_server_statistics_count;
765 });
766
767 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
768 chrono::milliseconds(500) +
769 chrono::milliseconds(5));
770
771 EXPECT_EQ(pi1_server_statistics_count, 9);
772 EXPECT_EQ(pi2_server_statistics_count, 9);
773 EXPECT_EQ(pi3_server_statistics_count, 9);
774}
775
776// Test that disabling statistics actually disables them.
777TEST(SimulatedEventLoopTest, MultinodeWithoutStatistics) {
778 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700779 aos::configuration::ReadConfig(ConfigPrefix() +
780 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700781 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
782 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
783 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
784
785 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
786 simulated_event_loop_factory.DisableStatistics();
787
788 std::unique_ptr<EventLoop> ping_event_loop =
789 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
790 Ping ping(ping_event_loop.get());
791
792 std::unique_ptr<EventLoop> pong_event_loop =
793 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
794 Pong pong(pong_event_loop.get());
795
796 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
797 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
798
799 MessageCounter<examples::Pong> pi2_pong_counter(
800 pi2_pong_counter_event_loop.get(), "/test");
801
802 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
803 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
804
805 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
806 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
807
808 MessageCounter<examples::Pong> pi1_pong_counter(
809 pi1_pong_counter_event_loop.get(), "/test");
810
811 // Count timestamps.
812 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
813 pi1_pong_counter_event_loop.get(), "/pi1/aos");
814 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
815 pi2_pong_counter_event_loop.get(), "/pi1/aos");
816 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
817 pi3_pong_counter_event_loop.get(), "/pi1/aos");
818 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
819 pi1_pong_counter_event_loop.get(), "/pi2/aos");
820 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
821 pi2_pong_counter_event_loop.get(), "/pi2/aos");
822 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
823 pi1_pong_counter_event_loop.get(), "/pi3/aos");
824 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
825 pi3_pong_counter_event_loop.get(), "/pi3/aos");
826
Austin Schuh2f8fd752020-09-01 22:38:28 -0700827 // Count remote timestamps
828 MessageCounter<logger::MessageHeader> remote_timestamps_pi2_on_pi1(
829 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
830 MessageCounter<logger::MessageHeader> remote_timestamps_pi1_on_pi2(
831 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
832
Austin Schuh4c3b9702020-08-30 11:34:55 -0700833 MessageCounter<message_bridge::ServerStatistics>
834 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
835 "/pi1/aos");
836 MessageCounter<message_bridge::ServerStatistics>
837 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
838 "/pi2/aos");
839 MessageCounter<message_bridge::ServerStatistics>
840 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
841 "/pi3/aos");
842
843 MessageCounter<message_bridge::ClientStatistics>
844 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
845 "/pi1/aos");
846 MessageCounter<message_bridge::ClientStatistics>
847 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
848 "/pi2/aos");
849 MessageCounter<message_bridge::ClientStatistics>
850 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
851 "/pi3/aos");
Austin Schuh898f4972020-01-11 17:21:25 -0800852
853 simulated_event_loop_factory.RunFor(chrono::seconds(10) +
854 chrono::milliseconds(5));
855
Austin Schuh4c3b9702020-08-30 11:34:55 -0700856 EXPECT_EQ(pi1_pong_counter.count(), 1001u);
857 EXPECT_EQ(pi2_pong_counter.count(), 1001u);
858
859 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 0u);
860 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 0u);
861 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 0u);
862 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 0u);
863 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 0u);
864 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 0u);
865 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 0u);
866
867 EXPECT_EQ(pi1_server_statistics_counter.count(), 0u);
868 EXPECT_EQ(pi2_server_statistics_counter.count(), 0u);
869 EXPECT_EQ(pi3_server_statistics_counter.count(), 0u);
870
871 EXPECT_EQ(pi1_client_statistics_counter.count(), 0u);
872 EXPECT_EQ(pi2_client_statistics_counter.count(), 0u);
873 EXPECT_EQ(pi3_client_statistics_counter.count(), 0u);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700874
875 // Also confirm that remote timestamps are being forwarded correctly.
876 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1001);
877 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1001);
Austin Schuh898f4972020-01-11 17:21:25 -0800878}
879
Austin Schuh2febf0d2020-09-21 22:24:30 -0700880// Tests that the time offset having a slope doesn't break the world.
881// SimulatedMessageBridge has enough self consistency CHECK statements to
882// confirm, and we can can also check a message in each direction to make sure
883// it gets delivered as expected.
884TEST(SimulatedEventLoopTest, MultinodePingPongWithOffsetAndSlope) {
885 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
886 aos::configuration::ReadConfig(ConfigPrefix() +
887 "events/multinode_pingpong_config.json");
888 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
889 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
890
891 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
892 NodeEventLoopFactory *pi2_factory =
893 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
894
895 // Move the pi far into the future so the slope is significant. And set it to
896 // something reasonable.
897 constexpr chrono::milliseconds kOffset{150100};
898 pi2_factory->SetDistributedOffset(kOffset, 1.0001);
899
900 std::unique_ptr<EventLoop> ping_event_loop =
901 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
902 Ping ping(ping_event_loop.get());
903
904 std::unique_ptr<EventLoop> pong_event_loop =
905 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
906 Pong pong(pong_event_loop.get());
907
908 std::unique_ptr<EventLoop> pi1_counter_event_loop =
909 simulated_event_loop_factory.MakeEventLoop("pi1_counter", pi1);
910 std::unique_ptr<EventLoop> pi2_counter_event_loop =
911 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi2);
912
913 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
914 pi1_counter_event_loop->MakeFetcher<examples::Ping>("/test");
915 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
916 pi2_counter_event_loop->MakeFetcher<examples::Ping>("/test");
917
918 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
919 pi2_counter_event_loop->MakeFetcher<examples::Pong>("/test");
920 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
921 pi1_counter_event_loop->MakeFetcher<examples::Pong>("/test");
922
923 // End after a pong message comes back. This will leave the latest messages
924 // on all channels so we can look at timestamps easily and check they make
925 // sense.
926 std::unique_ptr<EventLoop> pi1_pong_ender =
927 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi1);
928 int count = 0;
929 pi1_pong_ender->MakeWatcher(
930 "/test", [&simulated_event_loop_factory, &count](const examples::Pong &) {
931 if (++count == 100) {
932 simulated_event_loop_factory.Exit();
933 }
934 });
935
936 // Run enough that messages should be delivered.
937 simulated_event_loop_factory.Run();
938
939 // Grab the latest messages.
940 EXPECT_TRUE(ping_on_pi1_fetcher.Fetch());
941 EXPECT_TRUE(ping_on_pi2_fetcher.Fetch());
942 EXPECT_TRUE(pong_on_pi1_fetcher.Fetch());
943 EXPECT_TRUE(pong_on_pi2_fetcher.Fetch());
944
945 // Compute their time on the global distributed clock so we can compute
946 // distance betwen them.
947 const distributed_clock::time_point pi1_ping_time =
948 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
949 ->ToDistributedClock(
950 ping_on_pi1_fetcher.context().monotonic_event_time);
951 const distributed_clock::time_point pi2_ping_time =
952 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
953 ->ToDistributedClock(
954 ping_on_pi2_fetcher.context().monotonic_event_time);
955 const distributed_clock::time_point pi1_pong_time =
956 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
957 ->ToDistributedClock(
958 pong_on_pi1_fetcher.context().monotonic_event_time);
959 const distributed_clock::time_point pi2_pong_time =
960 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
961 ->ToDistributedClock(
962 pong_on_pi2_fetcher.context().monotonic_event_time);
963
964 // And confirm the delivery delay is just about exactly 150 uS for both
965 // directions like expected. There will be a couple ns of rounding errors in
966 // the conversion functions that aren't worth accounting for right now. This
967 // will either be really close, or really far.
968 EXPECT_GE(pi2_ping_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
969 pi1_ping_time);
970 EXPECT_LE(pi2_ping_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
971 pi1_ping_time);
972
973 EXPECT_GE(pi1_pong_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
974 pi2_pong_time);
975 EXPECT_LE(pi1_pong_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
976 pi2_pong_time);
977}
978
Austin Schuh4c570ea2020-11-19 23:13:24 -0800979void SendPing(aos::Sender<examples::Ping> *sender, int value) {
980 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
981 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
982 ping_builder.add_value(value);
983 builder.Send(ping_builder.Finish());
984}
985
986// Tests that reliable (and unreliable) ping messages get forwarded as expected.
987TEST(SimulatedEventLoopTest, MultinodeStartupTesting) {
988 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
989 aos::configuration::ReadConfig(ConfigPrefix() +
990 "events/multinode_pingpong_config.json");
991 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
992 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
993
994 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
995
996 std::unique_ptr<EventLoop> ping_event_loop =
997 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
998 aos::Sender<examples::Ping> pi1_reliable_sender =
999 ping_event_loop->MakeSender<examples::Ping>("/reliable");
1000 aos::Sender<examples::Ping> pi1_unreliable_sender =
1001 ping_event_loop->MakeSender<examples::Ping>("/unreliable");
1002 SendPing(&pi1_reliable_sender, 1);
1003 SendPing(&pi1_unreliable_sender, 1);
1004
1005 std::unique_ptr<EventLoop> pi2_pong_event_loop =
1006 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1007 MessageCounter<examples::Ping> pi2_reliable_counter(pi2_pong_event_loop.get(),
1008 "/reliable");
1009 MessageCounter<examples::Ping> pi2_unreliable_counter(
1010 pi2_pong_event_loop.get(), "/unreliable");
1011 aos::Fetcher<examples::Ping> reliable_on_pi2_fetcher =
1012 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/reliable");
1013 aos::Fetcher<examples::Ping> unreliable_on_pi2_fetcher =
1014 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/unreliable");
1015
1016 const size_t reliable_channel_index = configuration::ChannelIndex(
1017 pi2_pong_event_loop->configuration(), reliable_on_pi2_fetcher.channel());
1018
1019 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1020 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1021
1022 int reliable_timestamp_count = 0;
1023 pi1_remote_timestamp->MakeWatcher(
1024 "/pi1/aos/remote_timestamps/pi2",
1025 [reliable_channel_index,
1026 &reliable_timestamp_count](const logger::MessageHeader &header) {
1027 VLOG(1) << aos::FlatbufferToJson(&header);
1028 if (header.channel_index() == reliable_channel_index) {
1029 ++reliable_timestamp_count;
1030 }
1031 });
1032
1033 // Wait to let timestamp estimation start up before looking for the results.
1034 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1035
1036 EXPECT_EQ(pi2_reliable_counter.count(), 1u);
1037 // This one isn't reliable, but was sent before the start. It should *not* be
1038 // delivered.
1039 EXPECT_EQ(pi2_unreliable_counter.count(), 0u);
1040 // Confirm we got a timestamp logged for the message that was forwarded.
1041 EXPECT_EQ(reliable_timestamp_count, 1u);
1042
1043 SendPing(&pi1_reliable_sender, 2);
1044 SendPing(&pi1_unreliable_sender, 2);
1045 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1046 EXPECT_EQ(pi2_reliable_counter.count(), 2u);
1047 EXPECT_EQ(pi2_unreliable_counter.count(), 1u);
1048
1049 EXPECT_EQ(reliable_timestamp_count, 2u);
1050}
1051
Neil Balchc8f41ed2018-01-20 22:06:53 -08001052} // namespace testing
1053} // namespace aos