blob: 18e7cc9136dd324536ef6ca5c9899f0880c7283e [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"
Austin Schuh0de30f32020-12-06 12:44:28 -080013#include "aos/network/remote_message_generated.h"
Austin Schuh4c3b9702020-08-30 11:34:55 -070014#include "aos/network/timestamp_generated.h"
Neil Balchc8f41ed2018-01-20 22:06:53 -080015#include "gtest/gtest.h"
16
17namespace aos {
18namespace testing {
Brian Silverman28d14302020-09-18 15:26:17 -070019namespace {
20
21std::string ConfigPrefix() { return "aos/"; }
22
Austin Schuh0de30f32020-12-06 12:44:28 -080023using message_bridge::RemoteMessage;
Austin Schuh7267c532019-05-19 19:55:53 -070024namespace chrono = ::std::chrono;
25
Austin Schuh0de30f32020-12-06 12:44:28 -080026} // namespace
27
Neil Balchc8f41ed2018-01-20 22:06:53 -080028class SimulatedEventLoopTestFactory : public EventLoopTestFactory {
29 public:
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080030 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080031 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080032 return event_loop_factory_->MakeEventLoop(name, my_node());
Neil Balchc8f41ed2018-01-20 22:06:53 -080033 }
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080034 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080035 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080036 return event_loop_factory_->MakeEventLoop(name, my_node());
Austin Schuh44019f92019-05-19 19:58:27 -070037 }
38
Austin Schuh217a9782019-12-21 23:02:50 -080039 void Run() override { event_loop_factory_->Run(); }
40 void Exit() override { event_loop_factory_->Exit(); }
Austin Schuh44019f92019-05-19 19:58:27 -070041
Austin Schuh52d325c2019-06-23 18:59:06 -070042 // TODO(austin): Implement this. It's used currently for a phased loop test.
43 // I'm not sure how much that matters.
44 void SleepFor(::std::chrono::nanoseconds /*duration*/) override {}
45
Austin Schuh7d87b672019-12-01 20:23:49 -080046 void set_send_delay(std::chrono::nanoseconds send_delay) {
Austin Schuh217a9782019-12-21 23:02:50 -080047 MaybeMake();
48 event_loop_factory_->set_send_delay(send_delay);
Austin Schuh7d87b672019-12-01 20:23:49 -080049 }
50
Neil Balchc8f41ed2018-01-20 22:06:53 -080051 private:
Austin Schuh217a9782019-12-21 23:02:50 -080052 void MaybeMake() {
53 if (!event_loop_factory_) {
54 if (configuration()->has_nodes()) {
Austin Schuhac0771c2020-01-07 18:36:30 -080055 event_loop_factory_ =
56 std::make_unique<SimulatedEventLoopFactory>(configuration());
Austin Schuh217a9782019-12-21 23:02:50 -080057 } else {
58 event_loop_factory_ =
59 std::make_unique<SimulatedEventLoopFactory>(configuration());
60 }
61 }
62 }
63 std::unique_ptr<SimulatedEventLoopFactory> event_loop_factory_;
Neil Balchc8f41ed2018-01-20 22:06:53 -080064};
65
Brian Silverman77162972020-08-12 19:52:40 -070066INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCopyTest, AbstractEventLoopTest,
67 ::testing::Values(std::make_tuple(
68 []() {
69 return new SimulatedEventLoopTestFactory();
70 },
71 ReadMethod::COPY)));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070072
Brian Silverman77162972020-08-12 19:52:40 -070073INSTANTIATE_TEST_CASE_P(
74 SimulatedEventLoopCopyDeathTest, AbstractEventLoopDeathTest,
75 ::testing::Values(
76 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
77 ReadMethod::COPY)));
78
79INSTANTIATE_TEST_CASE_P(SimulatedEventLoopPinTest, AbstractEventLoopTest,
80 ::testing::Values(std::make_tuple(
81 []() {
82 return new SimulatedEventLoopTestFactory();
83 },
84 ReadMethod::PIN)));
85
86INSTANTIATE_TEST_CASE_P(
87 SimulatedEventLoopPinDeathTest, AbstractEventLoopDeathTest,
88 ::testing::Values(
89 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
90 ReadMethod::PIN)));
Neil Balchc8f41ed2018-01-20 22:06:53 -080091
92// Test that creating an event and running the scheduler runs the event.
93TEST(EventSchedulerTest, ScheduleEvent) {
94 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -080095 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -080096 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -080097 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -080098
Austin Schuh8bd96322020-02-13 21:18:22 -080099 scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuhac0771c2020-01-07 18:36:30 -0800100 [&counter]() { counter += 1; });
Austin Schuh8bd96322020-02-13 21:18:22 -0800101 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800102 EXPECT_EQ(counter, 1);
Ravago Jonescf453ab2020-05-06 21:14:53 -0700103 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(2),
104 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800105 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800106 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800107 EXPECT_EQ(counter, 1);
108}
109
110// Test that descheduling an already scheduled event doesn't run the event.
111TEST(EventSchedulerTest, DescheduleEvent) {
112 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -0800113 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -0800114 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -0800115 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -0800116
Austin Schuh8bd96322020-02-13 21:18:22 -0800117 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
118 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800119 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800120 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800121 EXPECT_EQ(counter, 0);
122}
Austin Schuh44019f92019-05-19 19:58:27 -0700123
Austin Schuh8fb315a2020-11-19 22:33:58 -0800124void SendTestMessage(aos::Sender<TestMessage> *sender, int value) {
125 aos::Sender<TestMessage>::Builder builder = sender->MakeBuilder();
126 TestMessage::Builder test_message_builder =
127 builder.MakeBuilder<TestMessage>();
128 test_message_builder.add_value(value);
129 builder.Send(test_message_builder.Finish());
130}
131
132// Test that sending a message after running gets properly notified.
133TEST(SimulatedEventLoopTest, SendAfterRunFor) {
134 SimulatedEventLoopTestFactory factory;
135
136 SimulatedEventLoopFactory simulated_event_loop_factory(
137 factory.configuration());
138
139 ::std::unique_ptr<EventLoop> ping_event_loop =
140 simulated_event_loop_factory.MakeEventLoop("ping");
141 aos::Sender<TestMessage> test_message_sender =
142 ping_event_loop->MakeSender<TestMessage>("/test");
143 SendTestMessage(&test_message_sender, 1);
144
145 std::unique_ptr<EventLoop> pong1_event_loop =
146 simulated_event_loop_factory.MakeEventLoop("pong");
147 MessageCounter<TestMessage> test_message_counter1(pong1_event_loop.get(),
148 "/test");
149
150 EXPECT_FALSE(ping_event_loop->is_running());
151
152 // Watchers start when you start running, so there should be nothing counted.
153 simulated_event_loop_factory.RunFor(chrono::seconds(1));
154 EXPECT_EQ(test_message_counter1.count(), 0u);
155
156 std::unique_ptr<EventLoop> pong2_event_loop =
157 simulated_event_loop_factory.MakeEventLoop("pong");
158 MessageCounter<TestMessage> test_message_counter2(pong2_event_loop.get(),
159 "/test");
160
161 // Pauses in the middle don't count though, so this should be counted.
162 // But, the fresh watcher shouldn't pick it up yet.
163 SendTestMessage(&test_message_sender, 2);
164
165 EXPECT_EQ(test_message_counter1.count(), 0u);
166 EXPECT_EQ(test_message_counter2.count(), 0u);
167 simulated_event_loop_factory.RunFor(chrono::seconds(1));
168
169 EXPECT_EQ(test_message_counter1.count(), 1u);
170 EXPECT_EQ(test_message_counter2.count(), 0u);
171}
172
173// Test that creating an event loop while running dies.
174TEST(SimulatedEventLoopDeathTest, MakeEventLoopWhileRunning) {
175 SimulatedEventLoopTestFactory factory;
176
177 SimulatedEventLoopFactory simulated_event_loop_factory(
178 factory.configuration());
179
180 ::std::unique_ptr<EventLoop> event_loop =
181 simulated_event_loop_factory.MakeEventLoop("ping");
182
183 auto timer = event_loop->AddTimer([&]() {
184 EXPECT_DEATH(
185 {
186 ::std::unique_ptr<EventLoop> event_loop2 =
187 simulated_event_loop_factory.MakeEventLoop("ping");
188 },
189 "event loop while running");
190 simulated_event_loop_factory.Exit();
191 });
192
193 event_loop->OnRun([&event_loop, &timer] {
194 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50));
195 });
196
197 simulated_event_loop_factory.Run();
198}
199
200// Test that creating a watcher after running dies.
201TEST(SimulatedEventLoopDeathTest, MakeWatcherAfterRunning) {
202 SimulatedEventLoopTestFactory factory;
203
204 SimulatedEventLoopFactory simulated_event_loop_factory(
205 factory.configuration());
206
207 ::std::unique_ptr<EventLoop> event_loop =
208 simulated_event_loop_factory.MakeEventLoop("ping");
209
210 simulated_event_loop_factory.RunFor(chrono::seconds(1));
211
212 EXPECT_DEATH(
213 { MessageCounter<TestMessage> counter(event_loop.get(), "/test"); },
214 "Can't add a watcher after running");
215
216 ::std::unique_ptr<EventLoop> event_loop2 =
217 simulated_event_loop_factory.MakeEventLoop("ping");
218
219 simulated_event_loop_factory.RunFor(chrono::seconds(1));
220
221 EXPECT_DEATH(
222 { MessageCounter<TestMessage> counter(event_loop2.get(), "/test"); },
223 "Can't add a watcher after running");
224}
225
Austin Schuh44019f92019-05-19 19:58:27 -0700226// Test that running for a time period with no handlers causes time to progress
227// correctly.
228TEST(SimulatedEventLoopTest, RunForNoHandlers) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800229 SimulatedEventLoopTestFactory factory;
230
231 SimulatedEventLoopFactory simulated_event_loop_factory(
232 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700233 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800234 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700235
236 simulated_event_loop_factory.RunFor(chrono::seconds(1));
237
238 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700239 event_loop->monotonic_now());
240}
241
242// Test that running for a time with a periodic handler causes time to end
243// correctly.
244TEST(SimulatedEventLoopTest, RunForTimerHandler) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800245 SimulatedEventLoopTestFactory factory;
246
247 SimulatedEventLoopFactory simulated_event_loop_factory(
248 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700249 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800250 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700251
252 int counter = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700253 auto timer = event_loop->AddTimer([&counter]() { ++counter; });
Austin Schuh44019f92019-05-19 19:58:27 -0700254 event_loop->OnRun([&event_loop, &timer] {
255 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50),
256 chrono::milliseconds(100));
257 });
258
259 simulated_event_loop_factory.RunFor(chrono::seconds(1));
260
261 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700262 event_loop->monotonic_now());
263 EXPECT_EQ(counter, 10);
264}
265
Austin Schuh7d87b672019-12-01 20:23:49 -0800266// Tests that watchers have latency in simulation.
267TEST(SimulatedEventLoopTest, WatcherTimingReport) {
268 SimulatedEventLoopTestFactory factory;
269 factory.set_send_delay(std::chrono::microseconds(50));
270
271 FLAGS_timing_report_ms = 1000;
272 auto loop1 = factory.MakePrimary("primary");
273 loop1->MakeWatcher("/test", [](const TestMessage &) {});
274
275 auto loop2 = factory.Make("sender_loop");
276
277 auto loop3 = factory.Make("report_fetcher");
278
279 Fetcher<timing::Report> report_fetcher =
280 loop3->MakeFetcher<timing::Report>("/aos");
281 EXPECT_FALSE(report_fetcher.Fetch());
282
283 auto sender = loop2->MakeSender<TestMessage>("/test");
284
285 // Send 10 messages in the middle of a timing report period so we get
286 // something interesting back.
287 auto test_timer = loop2->AddTimer([&sender]() {
288 for (int i = 0; i < 10; ++i) {
289 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
290 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
291 builder.add_value(200 + i);
292 ASSERT_TRUE(msg.Send(builder.Finish()));
293 }
294 });
295
296 // Quit after 1 timing report, mid way through the next cycle.
297 {
298 auto end_timer = loop1->AddTimer([&factory]() { factory.Exit(); });
299 end_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(2500));
300 end_timer->set_name("end");
301 }
302
303 loop1->OnRun([&test_timer, &loop1]() {
304 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
305 });
306
307 factory.Run();
308
309 // And, since we are here, check that the timing report makes sense.
310 // Start by looking for our event loop's timing.
311 FlatbufferDetachedBuffer<timing::Report> primary_report =
312 FlatbufferDetachedBuffer<timing::Report>::Empty();
313 while (report_fetcher.FetchNext()) {
314 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
315 if (report_fetcher->name()->string_view() == "primary") {
316 primary_report = CopyFlatBuffer(report_fetcher.get());
317 }
318 }
319
320 // Check the watcher report.
Ravago Jonescf453ab2020-05-06 21:14:53 -0700321 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh7d87b672019-12-01 20:23:49 -0800322
323 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
324
325 // Just the timing report timer.
326 ASSERT_NE(primary_report.message().timers(), nullptr);
327 EXPECT_EQ(primary_report.message().timers()->size(), 2);
328
329 // No phased loops
330 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
331
332 // And now confirm that the watcher received all 10 messages, and has latency.
333 ASSERT_NE(primary_report.message().watchers(), nullptr);
334 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
335 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
336 EXPECT_NEAR(
337 primary_report.message().watchers()->Get(0)->wakeup_latency()->average(),
338 0.00005, 1e-9);
339 EXPECT_NEAR(
340 primary_report.message().watchers()->Get(0)->wakeup_latency()->min(),
341 0.00005, 1e-9);
342 EXPECT_NEAR(
343 primary_report.message().watchers()->Get(0)->wakeup_latency()->max(),
344 0.00005, 1e-9);
345 EXPECT_EQ(primary_report.message()
346 .watchers()
347 ->Get(0)
348 ->wakeup_latency()
349 ->standard_deviation(),
350 0.0);
351
352 EXPECT_EQ(
353 primary_report.message().watchers()->Get(0)->handler_time()->average(),
354 0.0);
355 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->min(),
356 0.0);
357 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->max(),
358 0.0);
359 EXPECT_EQ(primary_report.message()
360 .watchers()
361 ->Get(0)
362 ->handler_time()
363 ->standard_deviation(),
364 0.0);
365}
366
Austin Schuh4c3b9702020-08-30 11:34:55 -0700367// Tests that ping and pong work when on 2 different nodes, and the message
368// gateway messages are sent out as expected.
Austin Schuh898f4972020-01-11 17:21:25 -0800369TEST(SimulatedEventLoopTest, MultinodePingPong) {
370 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700371 aos::configuration::ReadConfig(ConfigPrefix() +
372 "events/multinode_pingpong_config.json");
Austin Schuh898f4972020-01-11 17:21:25 -0800373 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
374 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700375 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh898f4972020-01-11 17:21:25 -0800376
377 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
378
379 std::unique_ptr<EventLoop> ping_event_loop =
380 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
381 Ping ping(ping_event_loop.get());
382
383 std::unique_ptr<EventLoop> pong_event_loop =
384 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
385 Pong pong(pong_event_loop.get());
386
387 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
388 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700389 MessageCounter<examples::Pong> pi2_pong_counter(
390 pi2_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700391 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi2_timestamp_fetcher =
392 pi2_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
393 "/pi1/aos");
394 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
395 pi2_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
Austin Schuh898f4972020-01-11 17:21:25 -0800396
Austin Schuh4c3b9702020-08-30 11:34:55 -0700397 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
398 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
Austin Schuh898f4972020-01-11 17:21:25 -0800399
400 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
401 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700402 MessageCounter<examples::Pong> pi1_pong_counter(
403 pi1_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700404 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
405 pi1_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
406 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi1_timestamp_fetcher =
407 pi1_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
408 "/aos");
409
Austin Schuh4c3b9702020-08-30 11:34:55 -0700410 // Count timestamps.
411 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
412 pi1_pong_counter_event_loop.get(), "/pi1/aos");
413 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
414 pi2_pong_counter_event_loop.get(), "/pi1/aos");
415 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
416 pi3_pong_counter_event_loop.get(), "/pi1/aos");
417 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
418 pi1_pong_counter_event_loop.get(), "/pi2/aos");
419 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
420 pi2_pong_counter_event_loop.get(), "/pi2/aos");
421 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
422 pi1_pong_counter_event_loop.get(), "/pi3/aos");
423 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
424 pi3_pong_counter_event_loop.get(), "/pi3/aos");
425
Austin Schuh2f8fd752020-09-01 22:38:28 -0700426 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800427 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700428 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800429 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700430 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
431
Austin Schuh4c3b9702020-08-30 11:34:55 -0700432 // Wait to let timestamp estimation start up before looking for the results.
433 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
434
Austin Schuh8fb315a2020-11-19 22:33:58 -0800435 std::unique_ptr<EventLoop> pi1_statistics_counter_event_loop =
436 simulated_event_loop_factory.MakeEventLoop("pi1_statistics_counter", pi1);
437 std::unique_ptr<EventLoop> pi2_statistics_counter_event_loop =
438 simulated_event_loop_factory.MakeEventLoop("pi2_statistics_counter", pi2);
439 std::unique_ptr<EventLoop> pi3_statistics_counter_event_loop =
440 simulated_event_loop_factory.MakeEventLoop("pi3_statistics_counter", pi3);
441
Austin Schuh4c3b9702020-08-30 11:34:55 -0700442 int pi1_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800443 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700444 "/pi1/aos", [&pi1_server_statistics_count](
445 const message_bridge::ServerStatistics &stats) {
446 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
447 EXPECT_EQ(stats.connections()->size(), 2u);
448 for (const message_bridge::ServerConnection *connection :
449 *stats.connections()) {
450 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800451 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700452 if (connection->node()->name()->string_view() == "pi2") {
453 EXPECT_GT(connection->sent_packets(), 50);
454 } else if (connection->node()->name()->string_view() == "pi3") {
455 EXPECT_GE(connection->sent_packets(), 5);
456 } else {
457 LOG(FATAL) << "Unknown connection";
458 }
459
460 EXPECT_TRUE(connection->has_monotonic_offset());
461 EXPECT_EQ(connection->monotonic_offset(), 0);
462 }
463 ++pi1_server_statistics_count;
464 });
465
466 int pi2_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800467 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700468 "/pi2/aos", [&pi2_server_statistics_count](
469 const message_bridge::ServerStatistics &stats) {
470 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
471 EXPECT_EQ(stats.connections()->size(), 1u);
472
473 const message_bridge::ServerConnection *connection =
474 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800475 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700476 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
477 EXPECT_GT(connection->sent_packets(), 50);
478 EXPECT_TRUE(connection->has_monotonic_offset());
479 EXPECT_EQ(connection->monotonic_offset(), 0);
480 ++pi2_server_statistics_count;
481 });
482
483 int pi3_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800484 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700485 "/pi3/aos", [&pi3_server_statistics_count](
486 const message_bridge::ServerStatistics &stats) {
487 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
488 EXPECT_EQ(stats.connections()->size(), 1u);
489
490 const message_bridge::ServerConnection *connection =
491 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800492 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700493 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
494 EXPECT_GE(connection->sent_packets(), 5);
495 EXPECT_TRUE(connection->has_monotonic_offset());
496 EXPECT_EQ(connection->monotonic_offset(), 0);
497 ++pi3_server_statistics_count;
498 });
499
500 int pi1_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800501 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700502 "/pi1/aos", [&pi1_client_statistics_count](
503 const message_bridge::ClientStatistics &stats) {
504 VLOG(1) << "pi1 ClientStatistics " << FlatbufferToJson(&stats);
505 EXPECT_EQ(stats.connections()->size(), 2u);
506
507 for (const message_bridge::ClientConnection *connection :
508 *stats.connections()) {
509 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
510 if (connection->node()->name()->string_view() == "pi2") {
511 EXPECT_GT(connection->received_packets(), 50);
512 } else if (connection->node()->name()->string_view() == "pi3") {
513 EXPECT_GE(connection->received_packets(), 5);
514 } else {
515 LOG(FATAL) << "Unknown connection";
516 }
517
518 EXPECT_TRUE(connection->has_monotonic_offset());
519 EXPECT_EQ(connection->monotonic_offset(), 150000);
520 }
521 ++pi1_client_statistics_count;
522 });
523
524 int pi2_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800525 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700526 "/pi2/aos", [&pi2_client_statistics_count](
527 const message_bridge::ClientStatistics &stats) {
528 VLOG(1) << "pi2 ClientStatistics " << FlatbufferToJson(&stats);
529 EXPECT_EQ(stats.connections()->size(), 1u);
530
531 const message_bridge::ClientConnection *connection =
532 stats.connections()->Get(0);
533 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
534 EXPECT_GT(connection->received_packets(), 50);
535 EXPECT_TRUE(connection->has_monotonic_offset());
536 EXPECT_EQ(connection->monotonic_offset(), 150000);
537 ++pi2_client_statistics_count;
538 });
539
540 int pi3_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800541 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700542 "/pi3/aos", [&pi3_client_statistics_count](
543 const message_bridge::ClientStatistics &stats) {
544 VLOG(1) << "pi3 ClientStatistics " << FlatbufferToJson(&stats);
545 EXPECT_EQ(stats.connections()->size(), 1u);
546
547 const message_bridge::ClientConnection *connection =
548 stats.connections()->Get(0);
549 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
550 EXPECT_GE(connection->received_packets(), 5);
551 EXPECT_TRUE(connection->has_monotonic_offset());
552 EXPECT_EQ(connection->monotonic_offset(), 150000);
553 ++pi3_client_statistics_count;
554 });
555
Austin Schuh2f8fd752020-09-01 22:38:28 -0700556 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
557 // channel.
558 const size_t pi1_timestamp_channel =
559 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
560 pi1_on_pi2_timestamp_fetcher.channel());
561 const size_t ping_timestamp_channel =
562 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
563 ping_on_pi2_fetcher.channel());
564
565 for (const Channel *channel :
566 *pi1_pong_counter_event_loop->configuration()->channels()) {
567 VLOG(1) << "Channel "
568 << configuration::ChannelIndex(
569 pi1_pong_counter_event_loop->configuration(), channel)
570 << " " << configuration::CleanedChannelToString(channel);
571 }
572
Austin Schuh8fb315a2020-11-19 22:33:58 -0800573 std::unique_ptr<EventLoop> pi1_remote_timestamp =
574 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
575
Austin Schuh2f8fd752020-09-01 22:38:28 -0700576 // For each remote timestamp we get back, confirm that it is either a ping
577 // message, or a timestamp we sent out. Also confirm that the timestamps are
578 // correct.
579 pi1_remote_timestamp->MakeWatcher(
580 "/pi1/aos/remote_timestamps/pi2",
581 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
582 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
Austin Schuh20ac95d2020-12-05 17:24:19 -0800583 &pi1_on_pi1_timestamp_fetcher, &simulated_event_loop_factory,
584 pi2](const RemoteMessage &header) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700585 VLOG(1) << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800586 EXPECT_TRUE(header.has_boot_uuid());
587 EXPECT_EQ(header.boot_uuid()->string_view(),
588 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
589 ->boot_uuid()
590 .string_view());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700591
592 const aos::monotonic_clock::time_point header_monotonic_sent_time(
593 chrono::nanoseconds(header.monotonic_sent_time()));
594 const aos::realtime_clock::time_point header_realtime_sent_time(
595 chrono::nanoseconds(header.realtime_sent_time()));
596 const aos::monotonic_clock::time_point header_monotonic_remote_time(
597 chrono::nanoseconds(header.monotonic_remote_time()));
598 const aos::realtime_clock::time_point header_realtime_remote_time(
599 chrono::nanoseconds(header.realtime_remote_time()));
600
601 const Context *pi1_context = nullptr;
602 const Context *pi2_context = nullptr;
603
604 if (header.channel_index() == pi1_timestamp_channel) {
605 // Find the forwarded message.
606 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
607 header_monotonic_sent_time) {
608 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
609 }
610
611 // And the source message.
612 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
613 header_monotonic_remote_time) {
614 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
615 }
616
617 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
618 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
619 } else if (header.channel_index() == ping_timestamp_channel) {
620 // Find the forwarded message.
621 while (ping_on_pi2_fetcher.context().monotonic_event_time <
622 header_monotonic_sent_time) {
623 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
624 }
625
626 // And the source message.
627 while (ping_on_pi1_fetcher.context().monotonic_event_time <
628 header_monotonic_remote_time) {
629 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
630 }
631
632 pi1_context = &ping_on_pi1_fetcher.context();
633 pi2_context = &ping_on_pi2_fetcher.context();
634 } else {
635 LOG(FATAL) << "Unknown channel";
636 }
637
638 // Confirm the forwarded message has matching timestamps to the
639 // timestamps we got back.
640 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700641 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700642 EXPECT_EQ(pi2_context->monotonic_event_time,
643 header_monotonic_sent_time);
644 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
645 EXPECT_EQ(pi2_context->realtime_remote_time,
646 header_realtime_remote_time);
647 EXPECT_EQ(pi2_context->monotonic_remote_time,
648 header_monotonic_remote_time);
649
650 // Confirm the forwarded message also matches the source message.
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700651 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700652 EXPECT_EQ(pi1_context->monotonic_event_time,
653 header_monotonic_remote_time);
654 EXPECT_EQ(pi1_context->realtime_event_time,
655 header_realtime_remote_time);
656 });
657
Austin Schuh4c3b9702020-08-30 11:34:55 -0700658 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
659 chrono::milliseconds(500) +
660 chrono::milliseconds(5));
661
662 EXPECT_EQ(pi1_pong_counter.count(), 1001);
663 EXPECT_EQ(pi2_pong_counter.count(), 1001);
664
665 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 100);
666 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 100);
667 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 100);
668 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 100);
669 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 100);
670 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 100);
671 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 100);
672
Austin Schuh20ac95d2020-12-05 17:24:19 -0800673 EXPECT_EQ(pi1_server_statistics_count, 10);
674 EXPECT_EQ(pi2_server_statistics_count, 10);
675 EXPECT_EQ(pi3_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700676
677 EXPECT_EQ(pi1_client_statistics_count, 95);
678 EXPECT_EQ(pi2_client_statistics_count, 95);
679 EXPECT_EQ(pi3_client_statistics_count, 95);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700680
681 // Also confirm that remote timestamps are being forwarded correctly.
682 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1101);
683 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1101);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700684}
685
686// Tests that an offset between nodes can be recovered and shows up in
687// ServerStatistics correctly.
688TEST(SimulatedEventLoopTest, MultinodePingPongWithOffset) {
689 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700690 aos::configuration::ReadConfig(ConfigPrefix() +
691 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700692 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
693 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
694 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
695
696 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
697 NodeEventLoopFactory *pi2_factory =
698 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
699
700 constexpr chrono::milliseconds kOffset{1501};
701 pi2_factory->SetDistributedOffset(kOffset, 1.0);
702
703 std::unique_ptr<EventLoop> ping_event_loop =
704 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
705 Ping ping(ping_event_loop.get());
706
707 std::unique_ptr<EventLoop> pong_event_loop =
708 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
709 Pong pong(pong_event_loop.get());
710
Austin Schuh8fb315a2020-11-19 22:33:58 -0800711 // Wait to let timestamp estimation start up before looking for the results.
712 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
713
Austin Schuh4c3b9702020-08-30 11:34:55 -0700714 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
715 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
716
717 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
718 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
719
720 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
721 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
722
Austin Schuh4c3b9702020-08-30 11:34:55 -0700723 // Confirm the offsets are being recovered correctly.
724 int pi1_server_statistics_count = 0;
725 pi1_pong_counter_event_loop->MakeWatcher(
726 "/pi1/aos", [&pi1_server_statistics_count,
727 kOffset](const message_bridge::ServerStatistics &stats) {
728 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
729 EXPECT_EQ(stats.connections()->size(), 2u);
730 for (const message_bridge::ServerConnection *connection :
731 *stats.connections()) {
732 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800733 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700734 if (connection->node()->name()->string_view() == "pi2") {
735 EXPECT_EQ(connection->monotonic_offset(),
736 chrono::nanoseconds(kOffset).count());
737 } else if (connection->node()->name()->string_view() == "pi3") {
738 EXPECT_EQ(connection->monotonic_offset(), 0);
739 } else {
740 LOG(FATAL) << "Unknown connection";
741 }
742
743 EXPECT_TRUE(connection->has_monotonic_offset());
744 }
745 ++pi1_server_statistics_count;
746 });
747
748 int pi2_server_statistics_count = 0;
749 pi2_pong_counter_event_loop->MakeWatcher(
750 "/pi2/aos", [&pi2_server_statistics_count,
751 kOffset](const message_bridge::ServerStatistics &stats) {
752 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
753 EXPECT_EQ(stats.connections()->size(), 1u);
754
755 const message_bridge::ServerConnection *connection =
756 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800757 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700758 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
759 EXPECT_TRUE(connection->has_monotonic_offset());
760 EXPECT_EQ(connection->monotonic_offset(),
761 -chrono::nanoseconds(kOffset).count());
762 ++pi2_server_statistics_count;
763 });
764
765 int pi3_server_statistics_count = 0;
766 pi3_pong_counter_event_loop->MakeWatcher(
767 "/pi3/aos", [&pi3_server_statistics_count](
768 const message_bridge::ServerStatistics &stats) {
769 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
770 EXPECT_EQ(stats.connections()->size(), 1u);
771
772 const message_bridge::ServerConnection *connection =
773 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800774 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700775 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
776 EXPECT_TRUE(connection->has_monotonic_offset());
777 EXPECT_EQ(connection->monotonic_offset(), 0);
778 ++pi3_server_statistics_count;
779 });
780
781 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
782 chrono::milliseconds(500) +
783 chrono::milliseconds(5));
784
Austin Schuh20ac95d2020-12-05 17:24:19 -0800785 EXPECT_EQ(pi1_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700786 EXPECT_EQ(pi2_server_statistics_count, 9);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800787 EXPECT_EQ(pi3_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700788}
789
790// Test that disabling statistics actually disables them.
791TEST(SimulatedEventLoopTest, MultinodeWithoutStatistics) {
792 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700793 aos::configuration::ReadConfig(ConfigPrefix() +
794 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700795 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
796 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
797 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
798
799 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
800 simulated_event_loop_factory.DisableStatistics();
801
802 std::unique_ptr<EventLoop> ping_event_loop =
803 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
804 Ping ping(ping_event_loop.get());
805
806 std::unique_ptr<EventLoop> pong_event_loop =
807 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
808 Pong pong(pong_event_loop.get());
809
810 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
811 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
812
813 MessageCounter<examples::Pong> pi2_pong_counter(
814 pi2_pong_counter_event_loop.get(), "/test");
815
816 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
817 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
818
819 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
820 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
821
822 MessageCounter<examples::Pong> pi1_pong_counter(
823 pi1_pong_counter_event_loop.get(), "/test");
824
825 // Count timestamps.
826 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
827 pi1_pong_counter_event_loop.get(), "/pi1/aos");
828 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
829 pi2_pong_counter_event_loop.get(), "/pi1/aos");
830 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
831 pi3_pong_counter_event_loop.get(), "/pi1/aos");
832 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
833 pi1_pong_counter_event_loop.get(), "/pi2/aos");
834 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
835 pi2_pong_counter_event_loop.get(), "/pi2/aos");
836 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
837 pi1_pong_counter_event_loop.get(), "/pi3/aos");
838 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
839 pi3_pong_counter_event_loop.get(), "/pi3/aos");
840
Austin Schuh2f8fd752020-09-01 22:38:28 -0700841 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800842 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700843 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800844 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700845 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
846
Austin Schuh4c3b9702020-08-30 11:34:55 -0700847 MessageCounter<message_bridge::ServerStatistics>
848 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
849 "/pi1/aos");
850 MessageCounter<message_bridge::ServerStatistics>
851 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
852 "/pi2/aos");
853 MessageCounter<message_bridge::ServerStatistics>
854 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
855 "/pi3/aos");
856
857 MessageCounter<message_bridge::ClientStatistics>
858 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
859 "/pi1/aos");
860 MessageCounter<message_bridge::ClientStatistics>
861 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
862 "/pi2/aos");
863 MessageCounter<message_bridge::ClientStatistics>
864 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
865 "/pi3/aos");
Austin Schuh898f4972020-01-11 17:21:25 -0800866
867 simulated_event_loop_factory.RunFor(chrono::seconds(10) +
868 chrono::milliseconds(5));
869
Austin Schuh4c3b9702020-08-30 11:34:55 -0700870 EXPECT_EQ(pi1_pong_counter.count(), 1001u);
871 EXPECT_EQ(pi2_pong_counter.count(), 1001u);
872
873 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 0u);
874 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 0u);
875 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 0u);
876 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 0u);
877 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 0u);
878 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 0u);
879 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 0u);
880
881 EXPECT_EQ(pi1_server_statistics_counter.count(), 0u);
882 EXPECT_EQ(pi2_server_statistics_counter.count(), 0u);
883 EXPECT_EQ(pi3_server_statistics_counter.count(), 0u);
884
885 EXPECT_EQ(pi1_client_statistics_counter.count(), 0u);
886 EXPECT_EQ(pi2_client_statistics_counter.count(), 0u);
887 EXPECT_EQ(pi3_client_statistics_counter.count(), 0u);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700888
889 // Also confirm that remote timestamps are being forwarded correctly.
890 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1001);
891 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1001);
Austin Schuh898f4972020-01-11 17:21:25 -0800892}
893
Austin Schuhc0b0f722020-12-12 18:36:06 -0800894bool AllConnected(const message_bridge::ServerStatistics *server_statistics) {
895 for (const message_bridge::ServerConnection *connection :
896 *server_statistics->connections()) {
897 if (connection->state() != message_bridge::State::CONNECTED) {
898 return false;
899 }
900 }
901 return true;
902}
903
904bool AllConnectedBut(const message_bridge::ServerStatistics *server_statistics,
905 std::string_view target) {
906 for (const message_bridge::ServerConnection *connection :
907 *server_statistics->connections()) {
908 if (connection->node()->name()->string_view() == target) {
909 if (connection->state() == message_bridge::State::CONNECTED) {
910 return false;
911 }
912 } else {
913 if (connection->state() != message_bridge::State::CONNECTED) {
914 return false;
915 }
916 }
917 }
918 return true;
919}
920
921bool AllConnected(const message_bridge::ClientStatistics *client_statistics) {
922 for (const message_bridge::ClientConnection *connection :
923 *client_statistics->connections()) {
924 if (connection->state() != message_bridge::State::CONNECTED) {
925 return false;
926 }
927 }
928 return true;
929}
930
931bool AllConnectedBut(const message_bridge::ClientStatistics *client_statistics,
932 std::string_view target) {
933 for (const message_bridge::ClientConnection *connection :
934 *client_statistics->connections()) {
935 if (connection->node()->name()->string_view() == target) {
936 if (connection->state() == message_bridge::State::CONNECTED) {
937 return false;
938 }
939 } else {
940 if (connection->state() != message_bridge::State::CONNECTED) {
941 return false;
942 }
943 }
944 }
945 return true;
946}
947
948// Test that disconnecting nodes actually disconnects them.
949TEST(SimulatedEventLoopTest, MultinodeDisconnect) {
950 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
951 aos::configuration::ReadConfig(ConfigPrefix() +
952 "events/multinode_pingpong_config.json");
953 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
954 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
955 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
956
957 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
958
959 std::unique_ptr<EventLoop> ping_event_loop =
960 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
961 Ping ping(ping_event_loop.get());
962
963 std::unique_ptr<EventLoop> pong_event_loop =
964 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
965 Pong pong(pong_event_loop.get());
966
967 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
968 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
969
970 MessageCounter<examples::Pong> pi2_pong_counter(
971 pi2_pong_counter_event_loop.get(), "/test");
972
973 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
974 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
975
976 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
977 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
978
979 MessageCounter<examples::Pong> pi1_pong_counter(
980 pi1_pong_counter_event_loop.get(), "/test");
981
982 // Count timestamps.
983 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
984 pi1_pong_counter_event_loop.get(), "/pi1/aos");
985 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
986 pi2_pong_counter_event_loop.get(), "/pi1/aos");
987 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
988 pi3_pong_counter_event_loop.get(), "/pi1/aos");
989 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
990 pi1_pong_counter_event_loop.get(), "/pi2/aos");
991 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
992 pi2_pong_counter_event_loop.get(), "/pi2/aos");
993 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
994 pi1_pong_counter_event_loop.get(), "/pi3/aos");
995 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
996 pi3_pong_counter_event_loop.get(), "/pi3/aos");
997
998 // Count remote timestamps
999 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
1000 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
1001 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
1002 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
1003
1004 MessageCounter<message_bridge::ServerStatistics>
1005 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
1006 "/pi1/aos");
1007 aos::Fetcher<message_bridge::ServerStatistics> pi1_server_statistics_fetcher =
1008 pi1_pong_counter_event_loop
1009 ->MakeFetcher<message_bridge::ServerStatistics>("/pi1/aos");
1010 aos::Fetcher<message_bridge::ClientStatistics> pi1_client_statistics_fetcher =
1011 pi1_pong_counter_event_loop
1012 ->MakeFetcher<message_bridge::ClientStatistics>("/pi1/aos");
1013
1014 MessageCounter<message_bridge::ServerStatistics>
1015 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
1016 "/pi2/aos");
1017 aos::Fetcher<message_bridge::ServerStatistics> pi2_server_statistics_fetcher =
1018 pi2_pong_counter_event_loop
1019 ->MakeFetcher<message_bridge::ServerStatistics>("/pi2/aos");
1020 aos::Fetcher<message_bridge::ClientStatistics> pi2_client_statistics_fetcher =
1021 pi2_pong_counter_event_loop
1022 ->MakeFetcher<message_bridge::ClientStatistics>("/pi2/aos");
1023
1024 MessageCounter<message_bridge::ServerStatistics>
1025 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
1026 "/pi3/aos");
1027 aos::Fetcher<message_bridge::ServerStatistics> pi3_server_statistics_fetcher =
1028 pi3_pong_counter_event_loop
1029 ->MakeFetcher<message_bridge::ServerStatistics>("/pi3/aos");
1030 aos::Fetcher<message_bridge::ClientStatistics> pi3_client_statistics_fetcher =
1031 pi3_pong_counter_event_loop
1032 ->MakeFetcher<message_bridge::ClientStatistics>("/pi3/aos");
1033
1034 MessageCounter<message_bridge::ClientStatistics>
1035 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
1036 "/pi1/aos");
1037 MessageCounter<message_bridge::ClientStatistics>
1038 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
1039 "/pi2/aos");
1040 MessageCounter<message_bridge::ClientStatistics>
1041 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
1042 "/pi3/aos");
1043
1044 simulated_event_loop_factory.RunFor(chrono::seconds(2) +
1045 chrono::milliseconds(5));
1046
1047 EXPECT_EQ(pi1_pong_counter.count(), 201u);
1048 EXPECT_EQ(pi2_pong_counter.count(), 201u);
1049
1050 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 20u);
1051 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 20u);
1052 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 20u);
1053 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 20u);
1054 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 20u);
1055 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 20u);
1056 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 20u);
1057
1058 EXPECT_EQ(pi1_server_statistics_counter.count(), 2u);
1059 EXPECT_EQ(pi2_server_statistics_counter.count(), 2u);
1060 EXPECT_EQ(pi3_server_statistics_counter.count(), 2u);
1061
1062 EXPECT_EQ(pi1_client_statistics_counter.count(), 20u);
1063 EXPECT_EQ(pi2_client_statistics_counter.count(), 20u);
1064 EXPECT_EQ(pi3_client_statistics_counter.count(), 20u);
1065
1066 // Also confirm that remote timestamps are being forwarded correctly.
1067 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 221);
1068 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 221);
1069
1070 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1071 EXPECT_TRUE(AllConnected(pi1_server_statistics_fetcher.get()))
1072 << " : " << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1073 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1074 EXPECT_TRUE(AllConnected(pi1_client_statistics_fetcher.get()))
1075 << " : " << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1076 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1077 EXPECT_TRUE(AllConnected(pi2_server_statistics_fetcher.get()))
1078 << " : " << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1079 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1080 EXPECT_TRUE(AllConnected(pi2_client_statistics_fetcher.get()))
1081 << " : " << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1082 EXPECT_TRUE(pi3_server_statistics_fetcher.Fetch());
1083 EXPECT_TRUE(AllConnected(pi3_server_statistics_fetcher.get()))
1084 << " : " << aos::FlatbufferToJson(pi3_server_statistics_fetcher.get());
1085 EXPECT_TRUE(pi3_client_statistics_fetcher.Fetch());
1086 EXPECT_TRUE(AllConnected(pi3_client_statistics_fetcher.get()))
1087 << " : " << aos::FlatbufferToJson(pi3_client_statistics_fetcher.get());
1088
1089 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)->Disconnect(pi3);
1090
1091 simulated_event_loop_factory.RunFor(chrono::seconds(2));
1092
1093 EXPECT_EQ(pi1_pong_counter.count(), 401u);
1094 EXPECT_EQ(pi2_pong_counter.count(), 401u);
1095
1096 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 40u);
1097 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 40u);
1098 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 20u);
1099 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 40u);
1100 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 40u);
1101 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 40u);
1102 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 40u);
1103
1104 EXPECT_EQ(pi1_server_statistics_counter.count(), 4u);
1105 EXPECT_EQ(pi2_server_statistics_counter.count(), 4u);
1106 EXPECT_EQ(pi3_server_statistics_counter.count(), 4u);
1107
1108 EXPECT_EQ(pi1_client_statistics_counter.count(), 40u);
1109 EXPECT_EQ(pi2_client_statistics_counter.count(), 40u);
1110 EXPECT_EQ(pi3_client_statistics_counter.count(), 40u);
1111
1112 // Also confirm that remote timestamps are being forwarded correctly.
1113 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 441);
1114 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 441);
1115
1116 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1117 EXPECT_TRUE(AllConnectedBut(pi1_server_statistics_fetcher.get(), "pi3"))
1118 << " : " << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1119 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1120 EXPECT_TRUE(AllConnected(pi1_client_statistics_fetcher.get()))
1121 << " : " << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1122 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1123 EXPECT_TRUE(AllConnected(pi2_server_statistics_fetcher.get()))
1124 << " : " << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1125 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1126 EXPECT_TRUE(AllConnected(pi2_client_statistics_fetcher.get()))
1127 << " : " << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1128 EXPECT_TRUE(pi3_server_statistics_fetcher.Fetch());
1129 EXPECT_TRUE(AllConnected(pi3_server_statistics_fetcher.get()))
1130 << " : " << aos::FlatbufferToJson(pi3_server_statistics_fetcher.get());
1131 EXPECT_TRUE(pi3_client_statistics_fetcher.Fetch());
1132 EXPECT_TRUE(AllConnectedBut(pi3_client_statistics_fetcher.get(), "pi1"))
1133 << " : " << aos::FlatbufferToJson(pi3_client_statistics_fetcher.get());
1134
1135 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)->Connect(pi3);
1136
1137 simulated_event_loop_factory.RunFor(chrono::seconds(2));
1138
1139 EXPECT_EQ(pi1_pong_counter.count(), 601u);
1140 EXPECT_EQ(pi2_pong_counter.count(), 601u);
1141
1142 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 60u);
1143 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 60u);
1144 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 40u);
1145 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 60u);
1146 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 60u);
1147 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 60u);
1148 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 60u);
1149
1150 EXPECT_EQ(pi1_server_statistics_counter.count(), 6u);
1151 EXPECT_EQ(pi2_server_statistics_counter.count(), 6u);
1152 EXPECT_EQ(pi3_server_statistics_counter.count(), 6u);
1153
1154 EXPECT_EQ(pi1_client_statistics_counter.count(), 60u);
1155 EXPECT_EQ(pi2_client_statistics_counter.count(), 60u);
1156 EXPECT_EQ(pi3_client_statistics_counter.count(), 60u);
1157
1158 // Also confirm that remote timestamps are being forwarded correctly.
1159 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 661);
1160 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 661);
1161
1162 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1163 EXPECT_TRUE(AllConnected(pi1_server_statistics_fetcher.get()))
1164 << " : " << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1165 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1166 EXPECT_TRUE(AllConnected(pi1_client_statistics_fetcher.get()))
1167 << " : " << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1168 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1169 EXPECT_TRUE(AllConnected(pi2_server_statistics_fetcher.get()))
1170 << " : " << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1171 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1172 EXPECT_TRUE(AllConnected(pi2_client_statistics_fetcher.get()))
1173 << " : " << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1174 EXPECT_TRUE(pi3_server_statistics_fetcher.Fetch());
1175 EXPECT_TRUE(AllConnected(pi3_server_statistics_fetcher.get()))
1176 << " : " << aos::FlatbufferToJson(pi3_server_statistics_fetcher.get());
1177 EXPECT_TRUE(pi3_client_statistics_fetcher.Fetch());
1178 EXPECT_TRUE(AllConnected(pi3_client_statistics_fetcher.get()))
1179 << " : " << aos::FlatbufferToJson(pi3_client_statistics_fetcher.get());
1180}
1181
Austin Schuh2febf0d2020-09-21 22:24:30 -07001182// Tests that the time offset having a slope doesn't break the world.
1183// SimulatedMessageBridge has enough self consistency CHECK statements to
1184// confirm, and we can can also check a message in each direction to make sure
1185// it gets delivered as expected.
1186TEST(SimulatedEventLoopTest, MultinodePingPongWithOffsetAndSlope) {
1187 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1188 aos::configuration::ReadConfig(ConfigPrefix() +
1189 "events/multinode_pingpong_config.json");
1190 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1191 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1192
1193 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1194 NodeEventLoopFactory *pi2_factory =
1195 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
1196
1197 // Move the pi far into the future so the slope is significant. And set it to
1198 // something reasonable.
1199 constexpr chrono::milliseconds kOffset{150100};
1200 pi2_factory->SetDistributedOffset(kOffset, 1.0001);
1201
1202 std::unique_ptr<EventLoop> ping_event_loop =
1203 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1204 Ping ping(ping_event_loop.get());
1205
1206 std::unique_ptr<EventLoop> pong_event_loop =
1207 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1208 Pong pong(pong_event_loop.get());
1209
1210 std::unique_ptr<EventLoop> pi1_counter_event_loop =
1211 simulated_event_loop_factory.MakeEventLoop("pi1_counter", pi1);
1212 std::unique_ptr<EventLoop> pi2_counter_event_loop =
1213 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi2);
1214
1215 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
1216 pi1_counter_event_loop->MakeFetcher<examples::Ping>("/test");
1217 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
1218 pi2_counter_event_loop->MakeFetcher<examples::Ping>("/test");
1219
1220 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
1221 pi2_counter_event_loop->MakeFetcher<examples::Pong>("/test");
1222 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
1223 pi1_counter_event_loop->MakeFetcher<examples::Pong>("/test");
1224
1225 // End after a pong message comes back. This will leave the latest messages
1226 // on all channels so we can look at timestamps easily and check they make
1227 // sense.
1228 std::unique_ptr<EventLoop> pi1_pong_ender =
1229 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi1);
1230 int count = 0;
1231 pi1_pong_ender->MakeWatcher(
1232 "/test", [&simulated_event_loop_factory, &count](const examples::Pong &) {
1233 if (++count == 100) {
1234 simulated_event_loop_factory.Exit();
1235 }
1236 });
1237
1238 // Run enough that messages should be delivered.
1239 simulated_event_loop_factory.Run();
1240
1241 // Grab the latest messages.
1242 EXPECT_TRUE(ping_on_pi1_fetcher.Fetch());
1243 EXPECT_TRUE(ping_on_pi2_fetcher.Fetch());
1244 EXPECT_TRUE(pong_on_pi1_fetcher.Fetch());
1245 EXPECT_TRUE(pong_on_pi2_fetcher.Fetch());
1246
1247 // Compute their time on the global distributed clock so we can compute
1248 // distance betwen them.
1249 const distributed_clock::time_point pi1_ping_time =
1250 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
1251 ->ToDistributedClock(
1252 ping_on_pi1_fetcher.context().monotonic_event_time);
1253 const distributed_clock::time_point pi2_ping_time =
1254 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1255 ->ToDistributedClock(
1256 ping_on_pi2_fetcher.context().monotonic_event_time);
1257 const distributed_clock::time_point pi1_pong_time =
1258 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
1259 ->ToDistributedClock(
1260 pong_on_pi1_fetcher.context().monotonic_event_time);
1261 const distributed_clock::time_point pi2_pong_time =
1262 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1263 ->ToDistributedClock(
1264 pong_on_pi2_fetcher.context().monotonic_event_time);
1265
1266 // And confirm the delivery delay is just about exactly 150 uS for both
1267 // directions like expected. There will be a couple ns of rounding errors in
1268 // the conversion functions that aren't worth accounting for right now. This
1269 // will either be really close, or really far.
1270 EXPECT_GE(pi2_ping_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
1271 pi1_ping_time);
1272 EXPECT_LE(pi2_ping_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
1273 pi1_ping_time);
1274
1275 EXPECT_GE(pi1_pong_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
1276 pi2_pong_time);
1277 EXPECT_LE(pi1_pong_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
1278 pi2_pong_time);
1279}
1280
Austin Schuh4c570ea2020-11-19 23:13:24 -08001281void SendPing(aos::Sender<examples::Ping> *sender, int value) {
1282 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
1283 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
1284 ping_builder.add_value(value);
1285 builder.Send(ping_builder.Finish());
1286}
1287
1288// Tests that reliable (and unreliable) ping messages get forwarded as expected.
1289TEST(SimulatedEventLoopTest, MultinodeStartupTesting) {
1290 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1291 aos::configuration::ReadConfig(ConfigPrefix() +
1292 "events/multinode_pingpong_config.json");
1293 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1294 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1295
1296 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1297
1298 std::unique_ptr<EventLoop> ping_event_loop =
1299 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1300 aos::Sender<examples::Ping> pi1_reliable_sender =
1301 ping_event_loop->MakeSender<examples::Ping>("/reliable");
1302 aos::Sender<examples::Ping> pi1_unreliable_sender =
1303 ping_event_loop->MakeSender<examples::Ping>("/unreliable");
1304 SendPing(&pi1_reliable_sender, 1);
1305 SendPing(&pi1_unreliable_sender, 1);
1306
1307 std::unique_ptr<EventLoop> pi2_pong_event_loop =
1308 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1309 MessageCounter<examples::Ping> pi2_reliable_counter(pi2_pong_event_loop.get(),
1310 "/reliable");
1311 MessageCounter<examples::Ping> pi2_unreliable_counter(
1312 pi2_pong_event_loop.get(), "/unreliable");
1313 aos::Fetcher<examples::Ping> reliable_on_pi2_fetcher =
1314 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/reliable");
1315 aos::Fetcher<examples::Ping> unreliable_on_pi2_fetcher =
1316 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/unreliable");
1317
1318 const size_t reliable_channel_index = configuration::ChannelIndex(
1319 pi2_pong_event_loop->configuration(), reliable_on_pi2_fetcher.channel());
1320
1321 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1322 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1323
Austin Schuheeaa2022021-01-02 21:52:03 -08001324 const chrono::nanoseconds network_delay =
1325 simulated_event_loop_factory.network_delay();
1326
Austin Schuh4c570ea2020-11-19 23:13:24 -08001327 int reliable_timestamp_count = 0;
1328 pi1_remote_timestamp->MakeWatcher(
1329 "/pi1/aos/remote_timestamps/pi2",
Austin Schuh20ac95d2020-12-05 17:24:19 -08001330 [reliable_channel_index, &reliable_timestamp_count,
Austin Schuheeaa2022021-01-02 21:52:03 -08001331 &simulated_event_loop_factory, pi2, network_delay, &pi2_pong_event_loop,
1332 &pi1_remote_timestamp](const RemoteMessage &header) {
Austin Schuh20ac95d2020-12-05 17:24:19 -08001333 EXPECT_TRUE(header.has_boot_uuid());
1334 EXPECT_EQ(header.boot_uuid()->string_view(),
1335 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1336 ->boot_uuid()
1337 .string_view());
Austin Schuh4c570ea2020-11-19 23:13:24 -08001338 VLOG(1) << aos::FlatbufferToJson(&header);
1339 if (header.channel_index() == reliable_channel_index) {
1340 ++reliable_timestamp_count;
1341 }
Austin Schuheeaa2022021-01-02 21:52:03 -08001342
1343 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1344 chrono::nanoseconds(header.monotonic_sent_time()));
1345
1346 EXPECT_EQ(pi1_remote_timestamp->context().monotonic_event_time,
1347 header_monotonic_sent_time + network_delay +
1348 (pi1_remote_timestamp->monotonic_now() -
1349 pi2_pong_event_loop->monotonic_now()));
Austin Schuh4c570ea2020-11-19 23:13:24 -08001350 });
1351
1352 // Wait to let timestamp estimation start up before looking for the results.
1353 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1354
1355 EXPECT_EQ(pi2_reliable_counter.count(), 1u);
1356 // This one isn't reliable, but was sent before the start. It should *not* be
1357 // delivered.
1358 EXPECT_EQ(pi2_unreliable_counter.count(), 0u);
1359 // Confirm we got a timestamp logged for the message that was forwarded.
1360 EXPECT_EQ(reliable_timestamp_count, 1u);
1361
1362 SendPing(&pi1_reliable_sender, 2);
1363 SendPing(&pi1_unreliable_sender, 2);
1364 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1365 EXPECT_EQ(pi2_reliable_counter.count(), 2u);
1366 EXPECT_EQ(pi2_unreliable_counter.count(), 1u);
1367
1368 EXPECT_EQ(reliable_timestamp_count, 2u);
1369}
1370
Austin Schuh20ac95d2020-12-05 17:24:19 -08001371// Tests that rebooting a node changes the ServerStatistics message and the
1372// RemoteTimestamp message.
1373TEST(SimulatedEventLoopTest, BootUUIDTest) {
1374 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1375 aos::configuration::ReadConfig(ConfigPrefix() +
1376 "events/multinode_pingpong_config.json");
1377 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1378 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1379
1380 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1381
1382 std::unique_ptr<EventLoop> ping_event_loop =
1383 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1384 Ping ping(ping_event_loop.get());
1385
1386 std::unique_ptr<EventLoop> pong_event_loop =
1387 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1388 Pong pong(pong_event_loop.get());
1389
1390 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1391 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1392 std::string expected_boot_uuid(
1393 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1394 ->boot_uuid()
1395 .string_view());
1396
1397 int timestamp_count = 0;
1398 pi1_remote_timestamp->MakeWatcher(
1399 "/pi1/aos/remote_timestamps/pi2",
1400 [&timestamp_count, &expected_boot_uuid](const RemoteMessage &header) {
1401 EXPECT_TRUE(header.has_boot_uuid());
1402 EXPECT_EQ(header.boot_uuid()->string_view(), expected_boot_uuid);
1403 VLOG(1) << aos::FlatbufferToJson(&header);
1404 ++timestamp_count;
1405 });
1406
1407 int pi1_server_statistics_count = 0;
1408 pi1_remote_timestamp->MakeWatcher(
1409 "/pi1/aos", [&pi1_server_statistics_count, &expected_boot_uuid](
1410 const message_bridge::ServerStatistics &stats) {
1411 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
1412 for (const message_bridge::ServerConnection *connection :
1413 *stats.connections()) {
1414 EXPECT_TRUE(connection->has_boot_uuid());
1415 if (connection->node()->name()->string_view() == "pi2") {
1416 EXPECT_EQ(expected_boot_uuid,
1417 connection->boot_uuid()->string_view())
1418 << " : Got " << aos::FlatbufferToJson(&stats);
1419 ++pi1_server_statistics_count;
1420 }
1421 }
1422 });
1423
1424 // Let a couple of ServerStatistics messages show up before rebooting.
1425 simulated_event_loop_factory.RunFor(chrono::milliseconds(2001));
1426
1427 EXPECT_GT(timestamp_count, 100);
1428 EXPECT_GE(pi1_server_statistics_count, 1u);
1429
1430 // Confirm that reboot changes the UUID.
1431 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)->Reboot();
1432
1433 EXPECT_NE(expected_boot_uuid,
1434 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1435 ->boot_uuid()
1436 .string_view());
1437
1438 expected_boot_uuid =
1439 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1440 ->boot_uuid()
1441 .string_view();
1442 timestamp_count = 0;
1443 pi1_server_statistics_count = 0;
1444
1445 simulated_event_loop_factory.RunFor(chrono::milliseconds(2000));
1446 EXPECT_GT(timestamp_count, 100);
1447 EXPECT_GE(pi1_server_statistics_count, 1u);
1448}
1449
Neil Balchc8f41ed2018-01-20 22:06:53 -08001450} // namespace testing
1451} // namespace aos