blob: 0fb757bc65351043939351ce3dbc62df565847c0 [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 Schuh87dd3832021-01-01 23:07:31 -080014#include "aos/network/testing_time_converter.h"
Austin Schuh4c3b9702020-08-30 11:34:55 -070015#include "aos/network/timestamp_generated.h"
Neil Balchc8f41ed2018-01-20 22:06:53 -080016#include "gtest/gtest.h"
17
18namespace aos {
19namespace testing {
Brian Silverman28d14302020-09-18 15:26:17 -070020namespace {
21
22std::string ConfigPrefix() { return "aos/"; }
23
Austin Schuh0de30f32020-12-06 12:44:28 -080024using message_bridge::RemoteMessage;
Austin Schuh7267c532019-05-19 19:55:53 -070025namespace chrono = ::std::chrono;
26
Austin Schuh0de30f32020-12-06 12:44:28 -080027} // namespace
28
Neil Balchc8f41ed2018-01-20 22:06:53 -080029class SimulatedEventLoopTestFactory : public EventLoopTestFactory {
30 public:
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080031 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080032 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080033 return event_loop_factory_->MakeEventLoop(name, my_node());
Neil Balchc8f41ed2018-01-20 22:06:53 -080034 }
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080035 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080036 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080037 return event_loop_factory_->MakeEventLoop(name, my_node());
Austin Schuh44019f92019-05-19 19:58:27 -070038 }
39
Austin Schuh217a9782019-12-21 23:02:50 -080040 void Run() override { event_loop_factory_->Run(); }
41 void Exit() override { event_loop_factory_->Exit(); }
Austin Schuh44019f92019-05-19 19:58:27 -070042
Austin Schuh52d325c2019-06-23 18:59:06 -070043 // TODO(austin): Implement this. It's used currently for a phased loop test.
44 // I'm not sure how much that matters.
45 void SleepFor(::std::chrono::nanoseconds /*duration*/) override {}
46
Austin Schuh7d87b672019-12-01 20:23:49 -080047 void set_send_delay(std::chrono::nanoseconds send_delay) {
Austin Schuh217a9782019-12-21 23:02:50 -080048 MaybeMake();
49 event_loop_factory_->set_send_delay(send_delay);
Austin Schuh7d87b672019-12-01 20:23:49 -080050 }
51
Neil Balchc8f41ed2018-01-20 22:06:53 -080052 private:
Austin Schuh217a9782019-12-21 23:02:50 -080053 void MaybeMake() {
54 if (!event_loop_factory_) {
55 if (configuration()->has_nodes()) {
Austin Schuhac0771c2020-01-07 18:36:30 -080056 event_loop_factory_ =
57 std::make_unique<SimulatedEventLoopFactory>(configuration());
Austin Schuh217a9782019-12-21 23:02:50 -080058 } else {
59 event_loop_factory_ =
60 std::make_unique<SimulatedEventLoopFactory>(configuration());
61 }
62 }
63 }
64 std::unique_ptr<SimulatedEventLoopFactory> event_loop_factory_;
Neil Balchc8f41ed2018-01-20 22:06:53 -080065};
66
Brian Silverman77162972020-08-12 19:52:40 -070067INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCopyTest, AbstractEventLoopTest,
68 ::testing::Values(std::make_tuple(
69 []() {
70 return new SimulatedEventLoopTestFactory();
71 },
72 ReadMethod::COPY)));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070073
Brian Silverman77162972020-08-12 19:52:40 -070074INSTANTIATE_TEST_CASE_P(
75 SimulatedEventLoopCopyDeathTest, AbstractEventLoopDeathTest,
76 ::testing::Values(
77 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
78 ReadMethod::COPY)));
79
80INSTANTIATE_TEST_CASE_P(SimulatedEventLoopPinTest, AbstractEventLoopTest,
81 ::testing::Values(std::make_tuple(
82 []() {
83 return new SimulatedEventLoopTestFactory();
84 },
85 ReadMethod::PIN)));
86
87INSTANTIATE_TEST_CASE_P(
88 SimulatedEventLoopPinDeathTest, AbstractEventLoopDeathTest,
89 ::testing::Values(
90 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
91 ReadMethod::PIN)));
Neil Balchc8f41ed2018-01-20 22:06:53 -080092
93// Test that creating an event and running the scheduler runs the event.
94TEST(EventSchedulerTest, ScheduleEvent) {
95 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -080096 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -080097 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -080098 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -080099
Austin Schuh8bd96322020-02-13 21:18:22 -0800100 scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuhac0771c2020-01-07 18:36:30 -0800101 [&counter]() { counter += 1; });
Austin Schuh8bd96322020-02-13 21:18:22 -0800102 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800103 EXPECT_EQ(counter, 1);
Ravago Jonescf453ab2020-05-06 21:14:53 -0700104 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(2),
105 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800106 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800107 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800108 EXPECT_EQ(counter, 1);
109}
110
111// Test that descheduling an already scheduled event doesn't run the event.
112TEST(EventSchedulerTest, DescheduleEvent) {
113 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -0800114 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -0800115 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -0800116 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -0800117
Austin Schuh8bd96322020-02-13 21:18:22 -0800118 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
119 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800120 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800121 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800122 EXPECT_EQ(counter, 0);
123}
Austin Schuh44019f92019-05-19 19:58:27 -0700124
Austin Schuh8fb315a2020-11-19 22:33:58 -0800125void SendTestMessage(aos::Sender<TestMessage> *sender, int value) {
126 aos::Sender<TestMessage>::Builder builder = sender->MakeBuilder();
127 TestMessage::Builder test_message_builder =
128 builder.MakeBuilder<TestMessage>();
129 test_message_builder.add_value(value);
130 builder.Send(test_message_builder.Finish());
131}
132
133// Test that sending a message after running gets properly notified.
134TEST(SimulatedEventLoopTest, SendAfterRunFor) {
135 SimulatedEventLoopTestFactory factory;
136
137 SimulatedEventLoopFactory simulated_event_loop_factory(
138 factory.configuration());
139
140 ::std::unique_ptr<EventLoop> ping_event_loop =
141 simulated_event_loop_factory.MakeEventLoop("ping");
142 aos::Sender<TestMessage> test_message_sender =
143 ping_event_loop->MakeSender<TestMessage>("/test");
144 SendTestMessage(&test_message_sender, 1);
145
146 std::unique_ptr<EventLoop> pong1_event_loop =
147 simulated_event_loop_factory.MakeEventLoop("pong");
148 MessageCounter<TestMessage> test_message_counter1(pong1_event_loop.get(),
149 "/test");
150
151 EXPECT_FALSE(ping_event_loop->is_running());
152
153 // Watchers start when you start running, so there should be nothing counted.
154 simulated_event_loop_factory.RunFor(chrono::seconds(1));
155 EXPECT_EQ(test_message_counter1.count(), 0u);
156
157 std::unique_ptr<EventLoop> pong2_event_loop =
158 simulated_event_loop_factory.MakeEventLoop("pong");
159 MessageCounter<TestMessage> test_message_counter2(pong2_event_loop.get(),
160 "/test");
161
162 // Pauses in the middle don't count though, so this should be counted.
163 // But, the fresh watcher shouldn't pick it up yet.
164 SendTestMessage(&test_message_sender, 2);
165
166 EXPECT_EQ(test_message_counter1.count(), 0u);
167 EXPECT_EQ(test_message_counter2.count(), 0u);
168 simulated_event_loop_factory.RunFor(chrono::seconds(1));
169
170 EXPECT_EQ(test_message_counter1.count(), 1u);
171 EXPECT_EQ(test_message_counter2.count(), 0u);
172}
173
174// Test that creating an event loop while running dies.
175TEST(SimulatedEventLoopDeathTest, MakeEventLoopWhileRunning) {
176 SimulatedEventLoopTestFactory factory;
177
178 SimulatedEventLoopFactory simulated_event_loop_factory(
179 factory.configuration());
180
181 ::std::unique_ptr<EventLoop> event_loop =
182 simulated_event_loop_factory.MakeEventLoop("ping");
183
184 auto timer = event_loop->AddTimer([&]() {
185 EXPECT_DEATH(
186 {
187 ::std::unique_ptr<EventLoop> event_loop2 =
188 simulated_event_loop_factory.MakeEventLoop("ping");
189 },
190 "event loop while running");
191 simulated_event_loop_factory.Exit();
192 });
193
194 event_loop->OnRun([&event_loop, &timer] {
195 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50));
196 });
197
198 simulated_event_loop_factory.Run();
199}
200
201// Test that creating a watcher after running dies.
202TEST(SimulatedEventLoopDeathTest, MakeWatcherAfterRunning) {
203 SimulatedEventLoopTestFactory factory;
204
205 SimulatedEventLoopFactory simulated_event_loop_factory(
206 factory.configuration());
207
208 ::std::unique_ptr<EventLoop> event_loop =
209 simulated_event_loop_factory.MakeEventLoop("ping");
210
211 simulated_event_loop_factory.RunFor(chrono::seconds(1));
212
213 EXPECT_DEATH(
214 { MessageCounter<TestMessage> counter(event_loop.get(), "/test"); },
215 "Can't add a watcher after running");
216
217 ::std::unique_ptr<EventLoop> event_loop2 =
218 simulated_event_loop_factory.MakeEventLoop("ping");
219
220 simulated_event_loop_factory.RunFor(chrono::seconds(1));
221
222 EXPECT_DEATH(
223 { MessageCounter<TestMessage> counter(event_loop2.get(), "/test"); },
224 "Can't add a watcher after running");
225}
226
Austin Schuh44019f92019-05-19 19:58:27 -0700227// Test that running for a time period with no handlers causes time to progress
228// correctly.
229TEST(SimulatedEventLoopTest, RunForNoHandlers) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800230 SimulatedEventLoopTestFactory factory;
231
232 SimulatedEventLoopFactory simulated_event_loop_factory(
233 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700234 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800235 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700236
237 simulated_event_loop_factory.RunFor(chrono::seconds(1));
238
239 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700240 event_loop->monotonic_now());
241}
242
243// Test that running for a time with a periodic handler causes time to end
244// correctly.
245TEST(SimulatedEventLoopTest, RunForTimerHandler) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800246 SimulatedEventLoopTestFactory factory;
247
248 SimulatedEventLoopFactory simulated_event_loop_factory(
249 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700250 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800251 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700252
253 int counter = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700254 auto timer = event_loop->AddTimer([&counter]() { ++counter; });
Austin Schuh44019f92019-05-19 19:58:27 -0700255 event_loop->OnRun([&event_loop, &timer] {
256 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50),
257 chrono::milliseconds(100));
258 });
259
260 simulated_event_loop_factory.RunFor(chrono::seconds(1));
261
262 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700263 event_loop->monotonic_now());
264 EXPECT_EQ(counter, 10);
265}
266
Austin Schuh7d87b672019-12-01 20:23:49 -0800267// Tests that watchers have latency in simulation.
268TEST(SimulatedEventLoopTest, WatcherTimingReport) {
269 SimulatedEventLoopTestFactory factory;
270 factory.set_send_delay(std::chrono::microseconds(50));
271
272 FLAGS_timing_report_ms = 1000;
273 auto loop1 = factory.MakePrimary("primary");
274 loop1->MakeWatcher("/test", [](const TestMessage &) {});
275
276 auto loop2 = factory.Make("sender_loop");
277
278 auto loop3 = factory.Make("report_fetcher");
279
280 Fetcher<timing::Report> report_fetcher =
281 loop3->MakeFetcher<timing::Report>("/aos");
282 EXPECT_FALSE(report_fetcher.Fetch());
283
284 auto sender = loop2->MakeSender<TestMessage>("/test");
285
286 // Send 10 messages in the middle of a timing report period so we get
287 // something interesting back.
288 auto test_timer = loop2->AddTimer([&sender]() {
289 for (int i = 0; i < 10; ++i) {
290 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
291 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
292 builder.add_value(200 + i);
293 ASSERT_TRUE(msg.Send(builder.Finish()));
294 }
295 });
296
297 // Quit after 1 timing report, mid way through the next cycle.
298 {
299 auto end_timer = loop1->AddTimer([&factory]() { factory.Exit(); });
300 end_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(2500));
301 end_timer->set_name("end");
302 }
303
304 loop1->OnRun([&test_timer, &loop1]() {
305 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
306 });
307
308 factory.Run();
309
310 // And, since we are here, check that the timing report makes sense.
311 // Start by looking for our event loop's timing.
312 FlatbufferDetachedBuffer<timing::Report> primary_report =
313 FlatbufferDetachedBuffer<timing::Report>::Empty();
314 while (report_fetcher.FetchNext()) {
315 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
316 if (report_fetcher->name()->string_view() == "primary") {
317 primary_report = CopyFlatBuffer(report_fetcher.get());
318 }
319 }
320
321 // Check the watcher report.
Ravago Jonescf453ab2020-05-06 21:14:53 -0700322 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh7d87b672019-12-01 20:23:49 -0800323
324 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
325
326 // Just the timing report timer.
327 ASSERT_NE(primary_report.message().timers(), nullptr);
328 EXPECT_EQ(primary_report.message().timers()->size(), 2);
329
330 // No phased loops
331 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
332
333 // And now confirm that the watcher received all 10 messages, and has latency.
334 ASSERT_NE(primary_report.message().watchers(), nullptr);
335 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
336 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
337 EXPECT_NEAR(
338 primary_report.message().watchers()->Get(0)->wakeup_latency()->average(),
339 0.00005, 1e-9);
340 EXPECT_NEAR(
341 primary_report.message().watchers()->Get(0)->wakeup_latency()->min(),
342 0.00005, 1e-9);
343 EXPECT_NEAR(
344 primary_report.message().watchers()->Get(0)->wakeup_latency()->max(),
345 0.00005, 1e-9);
346 EXPECT_EQ(primary_report.message()
347 .watchers()
348 ->Get(0)
349 ->wakeup_latency()
350 ->standard_deviation(),
351 0.0);
352
353 EXPECT_EQ(
354 primary_report.message().watchers()->Get(0)->handler_time()->average(),
355 0.0);
356 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->min(),
357 0.0);
358 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->max(),
359 0.0);
360 EXPECT_EQ(primary_report.message()
361 .watchers()
362 ->Get(0)
363 ->handler_time()
364 ->standard_deviation(),
365 0.0);
366}
367
Austin Schuh4c3b9702020-08-30 11:34:55 -0700368// Tests that ping and pong work when on 2 different nodes, and the message
369// gateway messages are sent out as expected.
Austin Schuh898f4972020-01-11 17:21:25 -0800370TEST(SimulatedEventLoopTest, MultinodePingPong) {
371 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700372 aos::configuration::ReadConfig(ConfigPrefix() +
373 "events/multinode_pingpong_config.json");
Austin Schuh898f4972020-01-11 17:21:25 -0800374 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
375 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700376 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh898f4972020-01-11 17:21:25 -0800377
378 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
379
380 std::unique_ptr<EventLoop> ping_event_loop =
381 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
382 Ping ping(ping_event_loop.get());
383
384 std::unique_ptr<EventLoop> pong_event_loop =
385 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
386 Pong pong(pong_event_loop.get());
387
388 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
389 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700390 MessageCounter<examples::Pong> pi2_pong_counter(
391 pi2_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700392 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi2_timestamp_fetcher =
393 pi2_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
394 "/pi1/aos");
395 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
396 pi2_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
Austin Schuh898f4972020-01-11 17:21:25 -0800397
Austin Schuh4c3b9702020-08-30 11:34:55 -0700398 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
399 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
Austin Schuh898f4972020-01-11 17:21:25 -0800400
401 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
402 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700403 MessageCounter<examples::Pong> pi1_pong_counter(
404 pi1_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700405 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
406 pi1_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
407 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi1_timestamp_fetcher =
408 pi1_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
409 "/aos");
410
Austin Schuh4c3b9702020-08-30 11:34:55 -0700411 // Count timestamps.
412 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
413 pi1_pong_counter_event_loop.get(), "/pi1/aos");
414 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
415 pi2_pong_counter_event_loop.get(), "/pi1/aos");
416 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
417 pi3_pong_counter_event_loop.get(), "/pi1/aos");
418 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
419 pi1_pong_counter_event_loop.get(), "/pi2/aos");
420 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
421 pi2_pong_counter_event_loop.get(), "/pi2/aos");
422 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
423 pi1_pong_counter_event_loop.get(), "/pi3/aos");
424 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
425 pi3_pong_counter_event_loop.get(), "/pi3/aos");
426
Austin Schuh2f8fd752020-09-01 22:38:28 -0700427 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800428 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700429 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800430 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700431 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
432
Austin Schuh4c3b9702020-08-30 11:34:55 -0700433 // Wait to let timestamp estimation start up before looking for the results.
434 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
435
Austin Schuh8fb315a2020-11-19 22:33:58 -0800436 std::unique_ptr<EventLoop> pi1_statistics_counter_event_loop =
437 simulated_event_loop_factory.MakeEventLoop("pi1_statistics_counter", pi1);
438 std::unique_ptr<EventLoop> pi2_statistics_counter_event_loop =
439 simulated_event_loop_factory.MakeEventLoop("pi2_statistics_counter", pi2);
440 std::unique_ptr<EventLoop> pi3_statistics_counter_event_loop =
441 simulated_event_loop_factory.MakeEventLoop("pi3_statistics_counter", pi3);
442
Austin Schuh4c3b9702020-08-30 11:34:55 -0700443 int pi1_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800444 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700445 "/pi1/aos", [&pi1_server_statistics_count](
446 const message_bridge::ServerStatistics &stats) {
447 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
448 EXPECT_EQ(stats.connections()->size(), 2u);
449 for (const message_bridge::ServerConnection *connection :
450 *stats.connections()) {
451 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800452 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700453 if (connection->node()->name()->string_view() == "pi2") {
454 EXPECT_GT(connection->sent_packets(), 50);
455 } else if (connection->node()->name()->string_view() == "pi3") {
456 EXPECT_GE(connection->sent_packets(), 5);
457 } else {
458 LOG(FATAL) << "Unknown connection";
459 }
460
461 EXPECT_TRUE(connection->has_monotonic_offset());
462 EXPECT_EQ(connection->monotonic_offset(), 0);
463 }
464 ++pi1_server_statistics_count;
465 });
466
467 int pi2_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800468 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700469 "/pi2/aos", [&pi2_server_statistics_count](
470 const message_bridge::ServerStatistics &stats) {
471 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
472 EXPECT_EQ(stats.connections()->size(), 1u);
473
474 const message_bridge::ServerConnection *connection =
475 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800476 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700477 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
478 EXPECT_GT(connection->sent_packets(), 50);
479 EXPECT_TRUE(connection->has_monotonic_offset());
480 EXPECT_EQ(connection->monotonic_offset(), 0);
481 ++pi2_server_statistics_count;
482 });
483
484 int pi3_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800485 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700486 "/pi3/aos", [&pi3_server_statistics_count](
487 const message_bridge::ServerStatistics &stats) {
488 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
489 EXPECT_EQ(stats.connections()->size(), 1u);
490
491 const message_bridge::ServerConnection *connection =
492 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800493 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700494 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
495 EXPECT_GE(connection->sent_packets(), 5);
496 EXPECT_TRUE(connection->has_monotonic_offset());
497 EXPECT_EQ(connection->monotonic_offset(), 0);
498 ++pi3_server_statistics_count;
499 });
500
501 int pi1_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800502 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700503 "/pi1/aos", [&pi1_client_statistics_count](
504 const message_bridge::ClientStatistics &stats) {
505 VLOG(1) << "pi1 ClientStatistics " << FlatbufferToJson(&stats);
506 EXPECT_EQ(stats.connections()->size(), 2u);
507
508 for (const message_bridge::ClientConnection *connection :
509 *stats.connections()) {
510 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
511 if (connection->node()->name()->string_view() == "pi2") {
512 EXPECT_GT(connection->received_packets(), 50);
513 } else if (connection->node()->name()->string_view() == "pi3") {
514 EXPECT_GE(connection->received_packets(), 5);
515 } else {
516 LOG(FATAL) << "Unknown connection";
517 }
518
519 EXPECT_TRUE(connection->has_monotonic_offset());
520 EXPECT_EQ(connection->monotonic_offset(), 150000);
521 }
522 ++pi1_client_statistics_count;
523 });
524
525 int pi2_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800526 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700527 "/pi2/aos", [&pi2_client_statistics_count](
528 const message_bridge::ClientStatistics &stats) {
529 VLOG(1) << "pi2 ClientStatistics " << FlatbufferToJson(&stats);
530 EXPECT_EQ(stats.connections()->size(), 1u);
531
532 const message_bridge::ClientConnection *connection =
533 stats.connections()->Get(0);
534 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
535 EXPECT_GT(connection->received_packets(), 50);
536 EXPECT_TRUE(connection->has_monotonic_offset());
537 EXPECT_EQ(connection->monotonic_offset(), 150000);
538 ++pi2_client_statistics_count;
539 });
540
541 int pi3_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800542 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700543 "/pi3/aos", [&pi3_client_statistics_count](
544 const message_bridge::ClientStatistics &stats) {
545 VLOG(1) << "pi3 ClientStatistics " << FlatbufferToJson(&stats);
546 EXPECT_EQ(stats.connections()->size(), 1u);
547
548 const message_bridge::ClientConnection *connection =
549 stats.connections()->Get(0);
550 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
551 EXPECT_GE(connection->received_packets(), 5);
552 EXPECT_TRUE(connection->has_monotonic_offset());
553 EXPECT_EQ(connection->monotonic_offset(), 150000);
554 ++pi3_client_statistics_count;
555 });
556
Austin Schuh2f8fd752020-09-01 22:38:28 -0700557 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
558 // channel.
559 const size_t pi1_timestamp_channel =
560 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
561 pi1_on_pi2_timestamp_fetcher.channel());
562 const size_t ping_timestamp_channel =
563 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
564 ping_on_pi2_fetcher.channel());
565
566 for (const Channel *channel :
567 *pi1_pong_counter_event_loop->configuration()->channels()) {
568 VLOG(1) << "Channel "
569 << configuration::ChannelIndex(
570 pi1_pong_counter_event_loop->configuration(), channel)
571 << " " << configuration::CleanedChannelToString(channel);
572 }
573
Austin Schuh8fb315a2020-11-19 22:33:58 -0800574 std::unique_ptr<EventLoop> pi1_remote_timestamp =
575 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
576
Austin Schuh2f8fd752020-09-01 22:38:28 -0700577 // For each remote timestamp we get back, confirm that it is either a ping
578 // message, or a timestamp we sent out. Also confirm that the timestamps are
579 // correct.
580 pi1_remote_timestamp->MakeWatcher(
581 "/pi1/aos/remote_timestamps/pi2",
582 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
583 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
Austin Schuh20ac95d2020-12-05 17:24:19 -0800584 &pi1_on_pi1_timestamp_fetcher, &simulated_event_loop_factory,
585 pi2](const RemoteMessage &header) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700586 VLOG(1) << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800587 EXPECT_TRUE(header.has_boot_uuid());
588 EXPECT_EQ(header.boot_uuid()->string_view(),
589 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
590 ->boot_uuid()
591 .string_view());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700592
593 const aos::monotonic_clock::time_point header_monotonic_sent_time(
594 chrono::nanoseconds(header.monotonic_sent_time()));
595 const aos::realtime_clock::time_point header_realtime_sent_time(
596 chrono::nanoseconds(header.realtime_sent_time()));
597 const aos::monotonic_clock::time_point header_monotonic_remote_time(
598 chrono::nanoseconds(header.monotonic_remote_time()));
599 const aos::realtime_clock::time_point header_realtime_remote_time(
600 chrono::nanoseconds(header.realtime_remote_time()));
601
602 const Context *pi1_context = nullptr;
603 const Context *pi2_context = nullptr;
604
605 if (header.channel_index() == pi1_timestamp_channel) {
606 // Find the forwarded message.
607 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
608 header_monotonic_sent_time) {
609 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
610 }
611
612 // And the source message.
613 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
614 header_monotonic_remote_time) {
615 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
616 }
617
618 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
619 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
620 } else if (header.channel_index() == ping_timestamp_channel) {
621 // Find the forwarded message.
622 while (ping_on_pi2_fetcher.context().monotonic_event_time <
623 header_monotonic_sent_time) {
624 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
625 }
626
627 // And the source message.
628 while (ping_on_pi1_fetcher.context().monotonic_event_time <
629 header_monotonic_remote_time) {
630 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
631 }
632
633 pi1_context = &ping_on_pi1_fetcher.context();
634 pi2_context = &ping_on_pi2_fetcher.context();
635 } else {
636 LOG(FATAL) << "Unknown channel";
637 }
638
639 // Confirm the forwarded message has matching timestamps to the
640 // timestamps we got back.
641 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700642 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700643 EXPECT_EQ(pi2_context->monotonic_event_time,
644 header_monotonic_sent_time);
645 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
646 EXPECT_EQ(pi2_context->realtime_remote_time,
647 header_realtime_remote_time);
648 EXPECT_EQ(pi2_context->monotonic_remote_time,
649 header_monotonic_remote_time);
650
651 // Confirm the forwarded message also matches the source message.
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700652 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700653 EXPECT_EQ(pi1_context->monotonic_event_time,
654 header_monotonic_remote_time);
655 EXPECT_EQ(pi1_context->realtime_event_time,
656 header_realtime_remote_time);
657 });
658
Austin Schuh4c3b9702020-08-30 11:34:55 -0700659 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
660 chrono::milliseconds(500) +
661 chrono::milliseconds(5));
662
663 EXPECT_EQ(pi1_pong_counter.count(), 1001);
664 EXPECT_EQ(pi2_pong_counter.count(), 1001);
665
666 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 100);
667 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 100);
668 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 100);
669 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 100);
670 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 100);
671 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 100);
672 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 100);
673
Austin Schuh20ac95d2020-12-05 17:24:19 -0800674 EXPECT_EQ(pi1_server_statistics_count, 10);
675 EXPECT_EQ(pi2_server_statistics_count, 10);
676 EXPECT_EQ(pi3_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700677
678 EXPECT_EQ(pi1_client_statistics_count, 95);
679 EXPECT_EQ(pi2_client_statistics_count, 95);
680 EXPECT_EQ(pi3_client_statistics_count, 95);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700681
682 // Also confirm that remote timestamps are being forwarded correctly.
683 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1101);
684 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1101);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700685}
686
687// Tests that an offset between nodes can be recovered and shows up in
688// ServerStatistics correctly.
689TEST(SimulatedEventLoopTest, MultinodePingPongWithOffset) {
690 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700691 aos::configuration::ReadConfig(ConfigPrefix() +
692 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700693 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
Austin Schuh87dd3832021-01-01 23:07:31 -0800694 const size_t pi1_index = configuration::GetNodeIndex(&config.message(), pi1);
695 ASSERT_EQ(pi1_index, 0u);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700696 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh87dd3832021-01-01 23:07:31 -0800697 const size_t pi2_index = configuration::GetNodeIndex(&config.message(), pi2);
698 ASSERT_EQ(pi2_index, 1u);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700699 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh87dd3832021-01-01 23:07:31 -0800700 const size_t pi3_index = configuration::GetNodeIndex(&config.message(), pi3);
701 ASSERT_EQ(pi3_index, 2u);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700702
Austin Schuh87dd3832021-01-01 23:07:31 -0800703 message_bridge::TestingTimeConverter time(
704 configuration::NodesCount(&config.message()));
Austin Schuh4c3b9702020-08-30 11:34:55 -0700705 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
706 NodeEventLoopFactory *pi2_factory =
707 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
Austin Schuh87dd3832021-01-01 23:07:31 -0800708 pi2_factory->SetTimeConverter(&time);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700709
710 constexpr chrono::milliseconds kOffset{1501};
Austin Schuh87dd3832021-01-01 23:07:31 -0800711 time.AddNextTimestamp(
712 distributed_clock::epoch(),
713 {monotonic_clock::epoch(), monotonic_clock::epoch() + kOffset,
714 monotonic_clock::epoch()});
Austin Schuh4c3b9702020-08-30 11:34:55 -0700715
716 std::unique_ptr<EventLoop> ping_event_loop =
717 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
718 Ping ping(ping_event_loop.get());
719
720 std::unique_ptr<EventLoop> pong_event_loop =
721 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
722 Pong pong(pong_event_loop.get());
723
Austin Schuh8fb315a2020-11-19 22:33:58 -0800724 // Wait to let timestamp estimation start up before looking for the results.
725 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
726
Austin Schuh87dd3832021-01-01 23:07:31 -0800727 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
728 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
729
Austin Schuh4c3b9702020-08-30 11:34:55 -0700730 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
731 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
732
733 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
734 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
735
Austin Schuh4c3b9702020-08-30 11:34:55 -0700736 // Confirm the offsets are being recovered correctly.
737 int pi1_server_statistics_count = 0;
738 pi1_pong_counter_event_loop->MakeWatcher(
739 "/pi1/aos", [&pi1_server_statistics_count,
740 kOffset](const message_bridge::ServerStatistics &stats) {
741 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
742 EXPECT_EQ(stats.connections()->size(), 2u);
743 for (const message_bridge::ServerConnection *connection :
744 *stats.connections()) {
745 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800746 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700747 if (connection->node()->name()->string_view() == "pi2") {
748 EXPECT_EQ(connection->monotonic_offset(),
749 chrono::nanoseconds(kOffset).count());
750 } else if (connection->node()->name()->string_view() == "pi3") {
751 EXPECT_EQ(connection->monotonic_offset(), 0);
752 } else {
753 LOG(FATAL) << "Unknown connection";
754 }
755
756 EXPECT_TRUE(connection->has_monotonic_offset());
757 }
758 ++pi1_server_statistics_count;
759 });
760
761 int pi2_server_statistics_count = 0;
762 pi2_pong_counter_event_loop->MakeWatcher(
763 "/pi2/aos", [&pi2_server_statistics_count,
764 kOffset](const message_bridge::ServerStatistics &stats) {
765 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
766 EXPECT_EQ(stats.connections()->size(), 1u);
767
768 const message_bridge::ServerConnection *connection =
769 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800770 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700771 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
772 EXPECT_TRUE(connection->has_monotonic_offset());
773 EXPECT_EQ(connection->monotonic_offset(),
774 -chrono::nanoseconds(kOffset).count());
775 ++pi2_server_statistics_count;
776 });
777
778 int pi3_server_statistics_count = 0;
779 pi3_pong_counter_event_loop->MakeWatcher(
780 "/pi3/aos", [&pi3_server_statistics_count](
781 const message_bridge::ServerStatistics &stats) {
782 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
783 EXPECT_EQ(stats.connections()->size(), 1u);
784
785 const message_bridge::ServerConnection *connection =
786 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800787 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700788 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
789 EXPECT_TRUE(connection->has_monotonic_offset());
790 EXPECT_EQ(connection->monotonic_offset(), 0);
791 ++pi3_server_statistics_count;
792 });
793
794 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
795 chrono::milliseconds(500) +
796 chrono::milliseconds(5));
797
Austin Schuh20ac95d2020-12-05 17:24:19 -0800798 EXPECT_EQ(pi1_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700799 EXPECT_EQ(pi2_server_statistics_count, 9);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800800 EXPECT_EQ(pi3_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700801}
802
803// Test that disabling statistics actually disables them.
804TEST(SimulatedEventLoopTest, MultinodeWithoutStatistics) {
805 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700806 aos::configuration::ReadConfig(ConfigPrefix() +
807 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700808 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
809 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
810 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
811
812 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
813 simulated_event_loop_factory.DisableStatistics();
814
815 std::unique_ptr<EventLoop> ping_event_loop =
816 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
817 Ping ping(ping_event_loop.get());
818
819 std::unique_ptr<EventLoop> pong_event_loop =
820 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
821 Pong pong(pong_event_loop.get());
822
823 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
824 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
825
826 MessageCounter<examples::Pong> pi2_pong_counter(
827 pi2_pong_counter_event_loop.get(), "/test");
828
829 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
830 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
831
832 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
833 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
834
835 MessageCounter<examples::Pong> pi1_pong_counter(
836 pi1_pong_counter_event_loop.get(), "/test");
837
838 // Count timestamps.
839 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
840 pi1_pong_counter_event_loop.get(), "/pi1/aos");
841 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
842 pi2_pong_counter_event_loop.get(), "/pi1/aos");
843 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
844 pi3_pong_counter_event_loop.get(), "/pi1/aos");
845 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
846 pi1_pong_counter_event_loop.get(), "/pi2/aos");
847 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
848 pi2_pong_counter_event_loop.get(), "/pi2/aos");
849 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
850 pi1_pong_counter_event_loop.get(), "/pi3/aos");
851 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
852 pi3_pong_counter_event_loop.get(), "/pi3/aos");
853
Austin Schuh2f8fd752020-09-01 22:38:28 -0700854 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800855 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700856 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800857 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700858 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
859
Austin Schuh4c3b9702020-08-30 11:34:55 -0700860 MessageCounter<message_bridge::ServerStatistics>
861 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
862 "/pi1/aos");
863 MessageCounter<message_bridge::ServerStatistics>
864 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
865 "/pi2/aos");
866 MessageCounter<message_bridge::ServerStatistics>
867 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
868 "/pi3/aos");
869
870 MessageCounter<message_bridge::ClientStatistics>
871 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
872 "/pi1/aos");
873 MessageCounter<message_bridge::ClientStatistics>
874 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
875 "/pi2/aos");
876 MessageCounter<message_bridge::ClientStatistics>
877 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
878 "/pi3/aos");
Austin Schuh898f4972020-01-11 17:21:25 -0800879
880 simulated_event_loop_factory.RunFor(chrono::seconds(10) +
881 chrono::milliseconds(5));
882
Austin Schuh4c3b9702020-08-30 11:34:55 -0700883 EXPECT_EQ(pi1_pong_counter.count(), 1001u);
884 EXPECT_EQ(pi2_pong_counter.count(), 1001u);
885
886 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 0u);
887 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 0u);
888 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 0u);
889 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 0u);
890 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 0u);
891 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 0u);
892 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 0u);
893
894 EXPECT_EQ(pi1_server_statistics_counter.count(), 0u);
895 EXPECT_EQ(pi2_server_statistics_counter.count(), 0u);
896 EXPECT_EQ(pi3_server_statistics_counter.count(), 0u);
897
898 EXPECT_EQ(pi1_client_statistics_counter.count(), 0u);
899 EXPECT_EQ(pi2_client_statistics_counter.count(), 0u);
900 EXPECT_EQ(pi3_client_statistics_counter.count(), 0u);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700901
902 // Also confirm that remote timestamps are being forwarded correctly.
903 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1001);
904 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1001);
Austin Schuh898f4972020-01-11 17:21:25 -0800905}
906
Austin Schuhc0b0f722020-12-12 18:36:06 -0800907bool AllConnected(const message_bridge::ServerStatistics *server_statistics) {
908 for (const message_bridge::ServerConnection *connection :
909 *server_statistics->connections()) {
910 if (connection->state() != message_bridge::State::CONNECTED) {
911 return false;
912 }
913 }
914 return true;
915}
916
917bool AllConnectedBut(const message_bridge::ServerStatistics *server_statistics,
918 std::string_view target) {
919 for (const message_bridge::ServerConnection *connection :
920 *server_statistics->connections()) {
921 if (connection->node()->name()->string_view() == target) {
922 if (connection->state() == message_bridge::State::CONNECTED) {
923 return false;
924 }
925 } else {
926 if (connection->state() != message_bridge::State::CONNECTED) {
927 return false;
928 }
929 }
930 }
931 return true;
932}
933
934bool AllConnected(const message_bridge::ClientStatistics *client_statistics) {
935 for (const message_bridge::ClientConnection *connection :
936 *client_statistics->connections()) {
937 if (connection->state() != message_bridge::State::CONNECTED) {
938 return false;
939 }
940 }
941 return true;
942}
943
944bool AllConnectedBut(const message_bridge::ClientStatistics *client_statistics,
945 std::string_view target) {
946 for (const message_bridge::ClientConnection *connection :
947 *client_statistics->connections()) {
948 if (connection->node()->name()->string_view() == target) {
949 if (connection->state() == message_bridge::State::CONNECTED) {
950 return false;
951 }
952 } else {
953 if (connection->state() != message_bridge::State::CONNECTED) {
954 return false;
955 }
956 }
957 }
958 return true;
959}
960
961// Test that disconnecting nodes actually disconnects them.
962TEST(SimulatedEventLoopTest, MultinodeDisconnect) {
963 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
964 aos::configuration::ReadConfig(ConfigPrefix() +
965 "events/multinode_pingpong_config.json");
966 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
967 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
968 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
969
970 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
971
972 std::unique_ptr<EventLoop> ping_event_loop =
973 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
974 Ping ping(ping_event_loop.get());
975
976 std::unique_ptr<EventLoop> pong_event_loop =
977 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
978 Pong pong(pong_event_loop.get());
979
980 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
981 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
982
983 MessageCounter<examples::Pong> pi2_pong_counter(
984 pi2_pong_counter_event_loop.get(), "/test");
985
986 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
987 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
988
989 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
990 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
991
992 MessageCounter<examples::Pong> pi1_pong_counter(
993 pi1_pong_counter_event_loop.get(), "/test");
994
995 // Count timestamps.
996 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
997 pi1_pong_counter_event_loop.get(), "/pi1/aos");
998 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
999 pi2_pong_counter_event_loop.get(), "/pi1/aos");
1000 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
1001 pi3_pong_counter_event_loop.get(), "/pi1/aos");
1002 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
1003 pi1_pong_counter_event_loop.get(), "/pi2/aos");
1004 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
1005 pi2_pong_counter_event_loop.get(), "/pi2/aos");
1006 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
1007 pi1_pong_counter_event_loop.get(), "/pi3/aos");
1008 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
1009 pi3_pong_counter_event_loop.get(), "/pi3/aos");
1010
1011 // Count remote timestamps
1012 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
1013 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
1014 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
1015 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
1016
1017 MessageCounter<message_bridge::ServerStatistics>
1018 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
1019 "/pi1/aos");
1020 aos::Fetcher<message_bridge::ServerStatistics> pi1_server_statistics_fetcher =
1021 pi1_pong_counter_event_loop
1022 ->MakeFetcher<message_bridge::ServerStatistics>("/pi1/aos");
1023 aos::Fetcher<message_bridge::ClientStatistics> pi1_client_statistics_fetcher =
1024 pi1_pong_counter_event_loop
1025 ->MakeFetcher<message_bridge::ClientStatistics>("/pi1/aos");
1026
1027 MessageCounter<message_bridge::ServerStatistics>
1028 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
1029 "/pi2/aos");
1030 aos::Fetcher<message_bridge::ServerStatistics> pi2_server_statistics_fetcher =
1031 pi2_pong_counter_event_loop
1032 ->MakeFetcher<message_bridge::ServerStatistics>("/pi2/aos");
1033 aos::Fetcher<message_bridge::ClientStatistics> pi2_client_statistics_fetcher =
1034 pi2_pong_counter_event_loop
1035 ->MakeFetcher<message_bridge::ClientStatistics>("/pi2/aos");
1036
1037 MessageCounter<message_bridge::ServerStatistics>
1038 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
1039 "/pi3/aos");
1040 aos::Fetcher<message_bridge::ServerStatistics> pi3_server_statistics_fetcher =
1041 pi3_pong_counter_event_loop
1042 ->MakeFetcher<message_bridge::ServerStatistics>("/pi3/aos");
1043 aos::Fetcher<message_bridge::ClientStatistics> pi3_client_statistics_fetcher =
1044 pi3_pong_counter_event_loop
1045 ->MakeFetcher<message_bridge::ClientStatistics>("/pi3/aos");
1046
1047 MessageCounter<message_bridge::ClientStatistics>
1048 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
1049 "/pi1/aos");
1050 MessageCounter<message_bridge::ClientStatistics>
1051 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
1052 "/pi2/aos");
1053 MessageCounter<message_bridge::ClientStatistics>
1054 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
1055 "/pi3/aos");
1056
1057 simulated_event_loop_factory.RunFor(chrono::seconds(2) +
1058 chrono::milliseconds(5));
1059
1060 EXPECT_EQ(pi1_pong_counter.count(), 201u);
1061 EXPECT_EQ(pi2_pong_counter.count(), 201u);
1062
1063 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 20u);
1064 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 20u);
1065 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 20u);
1066 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 20u);
1067 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 20u);
1068 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 20u);
1069 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 20u);
1070
1071 EXPECT_EQ(pi1_server_statistics_counter.count(), 2u);
1072 EXPECT_EQ(pi2_server_statistics_counter.count(), 2u);
1073 EXPECT_EQ(pi3_server_statistics_counter.count(), 2u);
1074
1075 EXPECT_EQ(pi1_client_statistics_counter.count(), 20u);
1076 EXPECT_EQ(pi2_client_statistics_counter.count(), 20u);
1077 EXPECT_EQ(pi3_client_statistics_counter.count(), 20u);
1078
1079 // Also confirm that remote timestamps are being forwarded correctly.
1080 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 221);
1081 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 221);
1082
1083 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1084 EXPECT_TRUE(AllConnected(pi1_server_statistics_fetcher.get()))
1085 << " : " << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1086 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1087 EXPECT_TRUE(AllConnected(pi1_client_statistics_fetcher.get()))
1088 << " : " << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1089 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1090 EXPECT_TRUE(AllConnected(pi2_server_statistics_fetcher.get()))
1091 << " : " << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1092 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1093 EXPECT_TRUE(AllConnected(pi2_client_statistics_fetcher.get()))
1094 << " : " << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1095 EXPECT_TRUE(pi3_server_statistics_fetcher.Fetch());
1096 EXPECT_TRUE(AllConnected(pi3_server_statistics_fetcher.get()))
1097 << " : " << aos::FlatbufferToJson(pi3_server_statistics_fetcher.get());
1098 EXPECT_TRUE(pi3_client_statistics_fetcher.Fetch());
1099 EXPECT_TRUE(AllConnected(pi3_client_statistics_fetcher.get()))
1100 << " : " << aos::FlatbufferToJson(pi3_client_statistics_fetcher.get());
1101
1102 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)->Disconnect(pi3);
1103
1104 simulated_event_loop_factory.RunFor(chrono::seconds(2));
1105
1106 EXPECT_EQ(pi1_pong_counter.count(), 401u);
1107 EXPECT_EQ(pi2_pong_counter.count(), 401u);
1108
1109 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 40u);
1110 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 40u);
1111 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 20u);
1112 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 40u);
1113 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 40u);
1114 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 40u);
1115 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 40u);
1116
1117 EXPECT_EQ(pi1_server_statistics_counter.count(), 4u);
1118 EXPECT_EQ(pi2_server_statistics_counter.count(), 4u);
1119 EXPECT_EQ(pi3_server_statistics_counter.count(), 4u);
1120
1121 EXPECT_EQ(pi1_client_statistics_counter.count(), 40u);
1122 EXPECT_EQ(pi2_client_statistics_counter.count(), 40u);
1123 EXPECT_EQ(pi3_client_statistics_counter.count(), 40u);
1124
1125 // Also confirm that remote timestamps are being forwarded correctly.
1126 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 441);
1127 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 441);
1128
1129 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1130 EXPECT_TRUE(AllConnectedBut(pi1_server_statistics_fetcher.get(), "pi3"))
1131 << " : " << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1132 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1133 EXPECT_TRUE(AllConnected(pi1_client_statistics_fetcher.get()))
1134 << " : " << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1135 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1136 EXPECT_TRUE(AllConnected(pi2_server_statistics_fetcher.get()))
1137 << " : " << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1138 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1139 EXPECT_TRUE(AllConnected(pi2_client_statistics_fetcher.get()))
1140 << " : " << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1141 EXPECT_TRUE(pi3_server_statistics_fetcher.Fetch());
1142 EXPECT_TRUE(AllConnected(pi3_server_statistics_fetcher.get()))
1143 << " : " << aos::FlatbufferToJson(pi3_server_statistics_fetcher.get());
1144 EXPECT_TRUE(pi3_client_statistics_fetcher.Fetch());
1145 EXPECT_TRUE(AllConnectedBut(pi3_client_statistics_fetcher.get(), "pi1"))
1146 << " : " << aos::FlatbufferToJson(pi3_client_statistics_fetcher.get());
1147
1148 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)->Connect(pi3);
1149
1150 simulated_event_loop_factory.RunFor(chrono::seconds(2));
1151
1152 EXPECT_EQ(pi1_pong_counter.count(), 601u);
1153 EXPECT_EQ(pi2_pong_counter.count(), 601u);
1154
1155 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 60u);
1156 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 60u);
1157 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 40u);
1158 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 60u);
1159 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 60u);
1160 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 60u);
1161 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 60u);
1162
1163 EXPECT_EQ(pi1_server_statistics_counter.count(), 6u);
1164 EXPECT_EQ(pi2_server_statistics_counter.count(), 6u);
1165 EXPECT_EQ(pi3_server_statistics_counter.count(), 6u);
1166
1167 EXPECT_EQ(pi1_client_statistics_counter.count(), 60u);
1168 EXPECT_EQ(pi2_client_statistics_counter.count(), 60u);
1169 EXPECT_EQ(pi3_client_statistics_counter.count(), 60u);
1170
1171 // Also confirm that remote timestamps are being forwarded correctly.
1172 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 661);
1173 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 661);
1174
1175 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1176 EXPECT_TRUE(AllConnected(pi1_server_statistics_fetcher.get()))
1177 << " : " << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1178 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1179 EXPECT_TRUE(AllConnected(pi1_client_statistics_fetcher.get()))
1180 << " : " << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1181 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1182 EXPECT_TRUE(AllConnected(pi2_server_statistics_fetcher.get()))
1183 << " : " << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1184 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1185 EXPECT_TRUE(AllConnected(pi2_client_statistics_fetcher.get()))
1186 << " : " << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1187 EXPECT_TRUE(pi3_server_statistics_fetcher.Fetch());
1188 EXPECT_TRUE(AllConnected(pi3_server_statistics_fetcher.get()))
1189 << " : " << aos::FlatbufferToJson(pi3_server_statistics_fetcher.get());
1190 EXPECT_TRUE(pi3_client_statistics_fetcher.Fetch());
1191 EXPECT_TRUE(AllConnected(pi3_client_statistics_fetcher.get()))
1192 << " : " << aos::FlatbufferToJson(pi3_client_statistics_fetcher.get());
1193}
1194
Austin Schuh2febf0d2020-09-21 22:24:30 -07001195// Tests that the time offset having a slope doesn't break the world.
1196// SimulatedMessageBridge has enough self consistency CHECK statements to
1197// confirm, and we can can also check a message in each direction to make sure
1198// it gets delivered as expected.
1199TEST(SimulatedEventLoopTest, MultinodePingPongWithOffsetAndSlope) {
1200 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1201 aos::configuration::ReadConfig(ConfigPrefix() +
1202 "events/multinode_pingpong_config.json");
1203 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
Austin Schuh87dd3832021-01-01 23:07:31 -08001204 const size_t pi1_index = configuration::GetNodeIndex(&config.message(), pi1);
1205 ASSERT_EQ(pi1_index, 0u);
Austin Schuh2febf0d2020-09-21 22:24:30 -07001206 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh87dd3832021-01-01 23:07:31 -08001207 const size_t pi2_index = configuration::GetNodeIndex(&config.message(), pi2);
1208 ASSERT_EQ(pi2_index, 1u);
1209 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
1210 const size_t pi3_index = configuration::GetNodeIndex(&config.message(), pi3);
1211 ASSERT_EQ(pi3_index, 2u);
Austin Schuh2febf0d2020-09-21 22:24:30 -07001212
Austin Schuh87dd3832021-01-01 23:07:31 -08001213 message_bridge::TestingTimeConverter time(
1214 configuration::NodesCount(&config.message()));
Austin Schuh2febf0d2020-09-21 22:24:30 -07001215 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1216 NodeEventLoopFactory *pi2_factory =
1217 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
Austin Schuh87dd3832021-01-01 23:07:31 -08001218 pi2_factory->SetTimeConverter(&time);
Austin Schuh2febf0d2020-09-21 22:24:30 -07001219
Austin Schuh2febf0d2020-09-21 22:24:30 -07001220 constexpr chrono::milliseconds kOffset{150100};
Austin Schuh87dd3832021-01-01 23:07:31 -08001221 time.AddNextTimestamp(
1222 distributed_clock::epoch(),
1223 {monotonic_clock::epoch(), monotonic_clock::epoch() + kOffset,
1224 monotonic_clock::epoch()});
1225 time.AddNextTimestamp(
1226 distributed_clock::epoch() + chrono::seconds(10),
1227 {monotonic_clock::epoch() + chrono::milliseconds(9999),
1228 monotonic_clock::epoch() + kOffset + chrono::seconds(10),
1229 monotonic_clock::epoch() + chrono::milliseconds(9999)});
Austin Schuh2febf0d2020-09-21 22:24:30 -07001230
1231 std::unique_ptr<EventLoop> ping_event_loop =
1232 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1233 Ping ping(ping_event_loop.get());
1234
1235 std::unique_ptr<EventLoop> pong_event_loop =
1236 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1237 Pong pong(pong_event_loop.get());
1238
1239 std::unique_ptr<EventLoop> pi1_counter_event_loop =
1240 simulated_event_loop_factory.MakeEventLoop("pi1_counter", pi1);
1241 std::unique_ptr<EventLoop> pi2_counter_event_loop =
1242 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi2);
1243
1244 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
1245 pi1_counter_event_loop->MakeFetcher<examples::Ping>("/test");
1246 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
1247 pi2_counter_event_loop->MakeFetcher<examples::Ping>("/test");
1248
1249 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
1250 pi2_counter_event_loop->MakeFetcher<examples::Pong>("/test");
1251 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
1252 pi1_counter_event_loop->MakeFetcher<examples::Pong>("/test");
1253
1254 // End after a pong message comes back. This will leave the latest messages
1255 // on all channels so we can look at timestamps easily and check they make
1256 // sense.
1257 std::unique_ptr<EventLoop> pi1_pong_ender =
1258 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi1);
1259 int count = 0;
1260 pi1_pong_ender->MakeWatcher(
1261 "/test", [&simulated_event_loop_factory, &count](const examples::Pong &) {
1262 if (++count == 100) {
1263 simulated_event_loop_factory.Exit();
1264 }
1265 });
1266
1267 // Run enough that messages should be delivered.
1268 simulated_event_loop_factory.Run();
1269
1270 // Grab the latest messages.
1271 EXPECT_TRUE(ping_on_pi1_fetcher.Fetch());
1272 EXPECT_TRUE(ping_on_pi2_fetcher.Fetch());
1273 EXPECT_TRUE(pong_on_pi1_fetcher.Fetch());
1274 EXPECT_TRUE(pong_on_pi2_fetcher.Fetch());
1275
1276 // Compute their time on the global distributed clock so we can compute
1277 // distance betwen them.
1278 const distributed_clock::time_point pi1_ping_time =
1279 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
1280 ->ToDistributedClock(
1281 ping_on_pi1_fetcher.context().monotonic_event_time);
1282 const distributed_clock::time_point pi2_ping_time =
1283 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1284 ->ToDistributedClock(
1285 ping_on_pi2_fetcher.context().monotonic_event_time);
1286 const distributed_clock::time_point pi1_pong_time =
1287 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
1288 ->ToDistributedClock(
1289 pong_on_pi1_fetcher.context().monotonic_event_time);
1290 const distributed_clock::time_point pi2_pong_time =
1291 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1292 ->ToDistributedClock(
1293 pong_on_pi2_fetcher.context().monotonic_event_time);
1294
1295 // And confirm the delivery delay is just about exactly 150 uS for both
1296 // directions like expected. There will be a couple ns of rounding errors in
1297 // the conversion functions that aren't worth accounting for right now. This
1298 // will either be really close, or really far.
1299 EXPECT_GE(pi2_ping_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
1300 pi1_ping_time);
1301 EXPECT_LE(pi2_ping_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
1302 pi1_ping_time);
1303
1304 EXPECT_GE(pi1_pong_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
1305 pi2_pong_time);
1306 EXPECT_LE(pi1_pong_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
1307 pi2_pong_time);
1308}
1309
Austin Schuh4c570ea2020-11-19 23:13:24 -08001310void SendPing(aos::Sender<examples::Ping> *sender, int value) {
1311 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
1312 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
1313 ping_builder.add_value(value);
1314 builder.Send(ping_builder.Finish());
1315}
1316
1317// Tests that reliable (and unreliable) ping messages get forwarded as expected.
1318TEST(SimulatedEventLoopTest, MultinodeStartupTesting) {
1319 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1320 aos::configuration::ReadConfig(ConfigPrefix() +
1321 "events/multinode_pingpong_config.json");
1322 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1323 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1324
1325 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1326
1327 std::unique_ptr<EventLoop> ping_event_loop =
1328 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1329 aos::Sender<examples::Ping> pi1_reliable_sender =
1330 ping_event_loop->MakeSender<examples::Ping>("/reliable");
1331 aos::Sender<examples::Ping> pi1_unreliable_sender =
1332 ping_event_loop->MakeSender<examples::Ping>("/unreliable");
1333 SendPing(&pi1_reliable_sender, 1);
1334 SendPing(&pi1_unreliable_sender, 1);
1335
1336 std::unique_ptr<EventLoop> pi2_pong_event_loop =
1337 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1338 MessageCounter<examples::Ping> pi2_reliable_counter(pi2_pong_event_loop.get(),
1339 "/reliable");
1340 MessageCounter<examples::Ping> pi2_unreliable_counter(
1341 pi2_pong_event_loop.get(), "/unreliable");
1342 aos::Fetcher<examples::Ping> reliable_on_pi2_fetcher =
1343 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/reliable");
1344 aos::Fetcher<examples::Ping> unreliable_on_pi2_fetcher =
1345 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/unreliable");
1346
1347 const size_t reliable_channel_index = configuration::ChannelIndex(
1348 pi2_pong_event_loop->configuration(), reliable_on_pi2_fetcher.channel());
1349
1350 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1351 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1352
Austin Schuheeaa2022021-01-02 21:52:03 -08001353 const chrono::nanoseconds network_delay =
1354 simulated_event_loop_factory.network_delay();
1355
Austin Schuh4c570ea2020-11-19 23:13:24 -08001356 int reliable_timestamp_count = 0;
1357 pi1_remote_timestamp->MakeWatcher(
1358 "/pi1/aos/remote_timestamps/pi2",
Austin Schuh20ac95d2020-12-05 17:24:19 -08001359 [reliable_channel_index, &reliable_timestamp_count,
Austin Schuheeaa2022021-01-02 21:52:03 -08001360 &simulated_event_loop_factory, pi2, network_delay, &pi2_pong_event_loop,
1361 &pi1_remote_timestamp](const RemoteMessage &header) {
Austin Schuh20ac95d2020-12-05 17:24:19 -08001362 EXPECT_TRUE(header.has_boot_uuid());
1363 EXPECT_EQ(header.boot_uuid()->string_view(),
1364 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1365 ->boot_uuid()
1366 .string_view());
Austin Schuh4c570ea2020-11-19 23:13:24 -08001367 VLOG(1) << aos::FlatbufferToJson(&header);
1368 if (header.channel_index() == reliable_channel_index) {
1369 ++reliable_timestamp_count;
1370 }
Austin Schuheeaa2022021-01-02 21:52:03 -08001371
1372 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1373 chrono::nanoseconds(header.monotonic_sent_time()));
1374
1375 EXPECT_EQ(pi1_remote_timestamp->context().monotonic_event_time,
1376 header_monotonic_sent_time + network_delay +
1377 (pi1_remote_timestamp->monotonic_now() -
1378 pi2_pong_event_loop->monotonic_now()));
Austin Schuh4c570ea2020-11-19 23:13:24 -08001379 });
1380
1381 // Wait to let timestamp estimation start up before looking for the results.
1382 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1383
1384 EXPECT_EQ(pi2_reliable_counter.count(), 1u);
1385 // This one isn't reliable, but was sent before the start. It should *not* be
1386 // delivered.
1387 EXPECT_EQ(pi2_unreliable_counter.count(), 0u);
1388 // Confirm we got a timestamp logged for the message that was forwarded.
1389 EXPECT_EQ(reliable_timestamp_count, 1u);
1390
1391 SendPing(&pi1_reliable_sender, 2);
1392 SendPing(&pi1_unreliable_sender, 2);
1393 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1394 EXPECT_EQ(pi2_reliable_counter.count(), 2u);
1395 EXPECT_EQ(pi2_unreliable_counter.count(), 1u);
1396
1397 EXPECT_EQ(reliable_timestamp_count, 2u);
1398}
1399
Austin Schuh20ac95d2020-12-05 17:24:19 -08001400// Tests that rebooting a node changes the ServerStatistics message and the
1401// RemoteTimestamp message.
1402TEST(SimulatedEventLoopTest, BootUUIDTest) {
1403 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1404 aos::configuration::ReadConfig(ConfigPrefix() +
1405 "events/multinode_pingpong_config.json");
1406 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1407 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1408
1409 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1410
1411 std::unique_ptr<EventLoop> ping_event_loop =
1412 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1413 Ping ping(ping_event_loop.get());
1414
1415 std::unique_ptr<EventLoop> pong_event_loop =
1416 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1417 Pong pong(pong_event_loop.get());
1418
1419 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1420 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1421 std::string expected_boot_uuid(
1422 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1423 ->boot_uuid()
1424 .string_view());
1425
1426 int timestamp_count = 0;
1427 pi1_remote_timestamp->MakeWatcher(
1428 "/pi1/aos/remote_timestamps/pi2",
1429 [&timestamp_count, &expected_boot_uuid](const RemoteMessage &header) {
1430 EXPECT_TRUE(header.has_boot_uuid());
1431 EXPECT_EQ(header.boot_uuid()->string_view(), expected_boot_uuid);
1432 VLOG(1) << aos::FlatbufferToJson(&header);
1433 ++timestamp_count;
1434 });
1435
1436 int pi1_server_statistics_count = 0;
1437 pi1_remote_timestamp->MakeWatcher(
1438 "/pi1/aos", [&pi1_server_statistics_count, &expected_boot_uuid](
1439 const message_bridge::ServerStatistics &stats) {
1440 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
1441 for (const message_bridge::ServerConnection *connection :
1442 *stats.connections()) {
1443 EXPECT_TRUE(connection->has_boot_uuid());
1444 if (connection->node()->name()->string_view() == "pi2") {
1445 EXPECT_EQ(expected_boot_uuid,
1446 connection->boot_uuid()->string_view())
1447 << " : Got " << aos::FlatbufferToJson(&stats);
1448 ++pi1_server_statistics_count;
1449 }
1450 }
1451 });
1452
1453 // Let a couple of ServerStatistics messages show up before rebooting.
1454 simulated_event_loop_factory.RunFor(chrono::milliseconds(2001));
1455
1456 EXPECT_GT(timestamp_count, 100);
1457 EXPECT_GE(pi1_server_statistics_count, 1u);
1458
1459 // Confirm that reboot changes the UUID.
1460 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)->Reboot();
1461
1462 EXPECT_NE(expected_boot_uuid,
1463 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1464 ->boot_uuid()
1465 .string_view());
1466
1467 expected_boot_uuid =
1468 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1469 ->boot_uuid()
1470 .string_view();
1471 timestamp_count = 0;
1472 pi1_server_statistics_count = 0;
1473
1474 simulated_event_loop_factory.RunFor(chrono::milliseconds(2000));
1475 EXPECT_GT(timestamp_count, 100);
1476 EXPECT_GE(pi1_server_statistics_count, 1u);
1477}
1478
Neil Balchc8f41ed2018-01-20 22:06:53 -08001479} // namespace testing
1480} // namespace aos