blob: 7b7c861600dc4816c4c279084c5e52132c983bc0 [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
Austin Schuh6bae8252021-02-07 22:01:49 -080067auto CommonParameters() {
68 return ::testing::Combine(
69 ::testing::Values([]() { return new SimulatedEventLoopTestFactory(); }),
70 ::testing::Values(ReadMethod::COPY, ReadMethod::PIN),
71 ::testing::Values(DoTimingReports::kYes, DoTimingReports::kNo));
72}
Austin Schuh6b6dfa52019-06-12 20:16:20 -070073
Austin Schuh6bae8252021-02-07 22:01:49 -080074INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCommonTest, AbstractEventLoopTest,
75 CommonParameters());
Brian Silverman77162972020-08-12 19:52:40 -070076
Austin Schuh6bae8252021-02-07 22:01:49 -080077INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCommonDeathTest,
78 AbstractEventLoopDeathTest, CommonParameters());
Neil Balchc8f41ed2018-01-20 22:06:53 -080079
80// Test that creating an event and running the scheduler runs the event.
81TEST(EventSchedulerTest, ScheduleEvent) {
82 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -080083 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -080084 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -080085 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -080086
Austin Schuh8bd96322020-02-13 21:18:22 -080087 scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuhac0771c2020-01-07 18:36:30 -080088 [&counter]() { counter += 1; });
Austin Schuh8bd96322020-02-13 21:18:22 -080089 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -080090 EXPECT_EQ(counter, 1);
Ravago Jonescf453ab2020-05-06 21:14:53 -070091 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(2),
92 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -080093 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -080094 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -080095 EXPECT_EQ(counter, 1);
96}
97
98// Test that descheduling an already scheduled event doesn't run the event.
99TEST(EventSchedulerTest, DescheduleEvent) {
100 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -0800101 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -0800102 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -0800103 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -0800104
Austin Schuh8bd96322020-02-13 21:18:22 -0800105 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
106 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800107 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800108 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800109 EXPECT_EQ(counter, 0);
110}
Austin Schuh44019f92019-05-19 19:58:27 -0700111
Austin Schuh8fb315a2020-11-19 22:33:58 -0800112void SendTestMessage(aos::Sender<TestMessage> *sender, int value) {
113 aos::Sender<TestMessage>::Builder builder = sender->MakeBuilder();
114 TestMessage::Builder test_message_builder =
115 builder.MakeBuilder<TestMessage>();
116 test_message_builder.add_value(value);
117 builder.Send(test_message_builder.Finish());
118}
119
120// Test that sending a message after running gets properly notified.
121TEST(SimulatedEventLoopTest, SendAfterRunFor) {
122 SimulatedEventLoopTestFactory factory;
123
124 SimulatedEventLoopFactory simulated_event_loop_factory(
125 factory.configuration());
126
127 ::std::unique_ptr<EventLoop> ping_event_loop =
128 simulated_event_loop_factory.MakeEventLoop("ping");
129 aos::Sender<TestMessage> test_message_sender =
130 ping_event_loop->MakeSender<TestMessage>("/test");
131 SendTestMessage(&test_message_sender, 1);
132
133 std::unique_ptr<EventLoop> pong1_event_loop =
134 simulated_event_loop_factory.MakeEventLoop("pong");
135 MessageCounter<TestMessage> test_message_counter1(pong1_event_loop.get(),
136 "/test");
137
138 EXPECT_FALSE(ping_event_loop->is_running());
139
140 // Watchers start when you start running, so there should be nothing counted.
141 simulated_event_loop_factory.RunFor(chrono::seconds(1));
142 EXPECT_EQ(test_message_counter1.count(), 0u);
143
144 std::unique_ptr<EventLoop> pong2_event_loop =
145 simulated_event_loop_factory.MakeEventLoop("pong");
146 MessageCounter<TestMessage> test_message_counter2(pong2_event_loop.get(),
147 "/test");
148
149 // Pauses in the middle don't count though, so this should be counted.
150 // But, the fresh watcher shouldn't pick it up yet.
151 SendTestMessage(&test_message_sender, 2);
152
153 EXPECT_EQ(test_message_counter1.count(), 0u);
154 EXPECT_EQ(test_message_counter2.count(), 0u);
155 simulated_event_loop_factory.RunFor(chrono::seconds(1));
156
157 EXPECT_EQ(test_message_counter1.count(), 1u);
158 EXPECT_EQ(test_message_counter2.count(), 0u);
159}
160
161// Test that creating an event loop while running dies.
162TEST(SimulatedEventLoopDeathTest, MakeEventLoopWhileRunning) {
163 SimulatedEventLoopTestFactory factory;
164
165 SimulatedEventLoopFactory simulated_event_loop_factory(
166 factory.configuration());
167
168 ::std::unique_ptr<EventLoop> event_loop =
169 simulated_event_loop_factory.MakeEventLoop("ping");
170
171 auto timer = event_loop->AddTimer([&]() {
172 EXPECT_DEATH(
173 {
174 ::std::unique_ptr<EventLoop> event_loop2 =
175 simulated_event_loop_factory.MakeEventLoop("ping");
176 },
177 "event loop while running");
178 simulated_event_loop_factory.Exit();
179 });
180
181 event_loop->OnRun([&event_loop, &timer] {
182 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50));
183 });
184
185 simulated_event_loop_factory.Run();
186}
187
188// Test that creating a watcher after running dies.
189TEST(SimulatedEventLoopDeathTest, MakeWatcherAfterRunning) {
190 SimulatedEventLoopTestFactory factory;
191
192 SimulatedEventLoopFactory simulated_event_loop_factory(
193 factory.configuration());
194
195 ::std::unique_ptr<EventLoop> event_loop =
196 simulated_event_loop_factory.MakeEventLoop("ping");
197
198 simulated_event_loop_factory.RunFor(chrono::seconds(1));
199
200 EXPECT_DEATH(
201 { MessageCounter<TestMessage> counter(event_loop.get(), "/test"); },
202 "Can't add a watcher after running");
203
204 ::std::unique_ptr<EventLoop> event_loop2 =
205 simulated_event_loop_factory.MakeEventLoop("ping");
206
207 simulated_event_loop_factory.RunFor(chrono::seconds(1));
208
209 EXPECT_DEATH(
210 { MessageCounter<TestMessage> counter(event_loop2.get(), "/test"); },
211 "Can't add a watcher after running");
212}
213
Austin Schuh44019f92019-05-19 19:58:27 -0700214// Test that running for a time period with no handlers causes time to progress
215// correctly.
216TEST(SimulatedEventLoopTest, RunForNoHandlers) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800217 SimulatedEventLoopTestFactory factory;
218
219 SimulatedEventLoopFactory simulated_event_loop_factory(
220 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700221 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800222 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700223
224 simulated_event_loop_factory.RunFor(chrono::seconds(1));
225
226 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700227 event_loop->monotonic_now());
228}
229
230// Test that running for a time with a periodic handler causes time to end
231// correctly.
232TEST(SimulatedEventLoopTest, RunForTimerHandler) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800233 SimulatedEventLoopTestFactory factory;
234
235 SimulatedEventLoopFactory simulated_event_loop_factory(
236 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700237 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800238 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700239
240 int counter = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700241 auto timer = event_loop->AddTimer([&counter]() { ++counter; });
Austin Schuh44019f92019-05-19 19:58:27 -0700242 event_loop->OnRun([&event_loop, &timer] {
243 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50),
244 chrono::milliseconds(100));
245 });
246
247 simulated_event_loop_factory.RunFor(chrono::seconds(1));
248
249 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700250 event_loop->monotonic_now());
251 EXPECT_EQ(counter, 10);
252}
253
Austin Schuh7d87b672019-12-01 20:23:49 -0800254// Tests that watchers have latency in simulation.
255TEST(SimulatedEventLoopTest, WatcherTimingReport) {
256 SimulatedEventLoopTestFactory factory;
257 factory.set_send_delay(std::chrono::microseconds(50));
258
259 FLAGS_timing_report_ms = 1000;
260 auto loop1 = factory.MakePrimary("primary");
261 loop1->MakeWatcher("/test", [](const TestMessage &) {});
262
263 auto loop2 = factory.Make("sender_loop");
264
265 auto loop3 = factory.Make("report_fetcher");
266
267 Fetcher<timing::Report> report_fetcher =
268 loop3->MakeFetcher<timing::Report>("/aos");
269 EXPECT_FALSE(report_fetcher.Fetch());
270
271 auto sender = loop2->MakeSender<TestMessage>("/test");
272
273 // Send 10 messages in the middle of a timing report period so we get
274 // something interesting back.
275 auto test_timer = loop2->AddTimer([&sender]() {
276 for (int i = 0; i < 10; ++i) {
277 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
278 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
279 builder.add_value(200 + i);
280 ASSERT_TRUE(msg.Send(builder.Finish()));
281 }
282 });
283
284 // Quit after 1 timing report, mid way through the next cycle.
285 {
286 auto end_timer = loop1->AddTimer([&factory]() { factory.Exit(); });
287 end_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(2500));
288 end_timer->set_name("end");
289 }
290
291 loop1->OnRun([&test_timer, &loop1]() {
292 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
293 });
294
295 factory.Run();
296
297 // And, since we are here, check that the timing report makes sense.
298 // Start by looking for our event loop's timing.
299 FlatbufferDetachedBuffer<timing::Report> primary_report =
300 FlatbufferDetachedBuffer<timing::Report>::Empty();
301 while (report_fetcher.FetchNext()) {
302 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
303 if (report_fetcher->name()->string_view() == "primary") {
304 primary_report = CopyFlatBuffer(report_fetcher.get());
305 }
306 }
307
308 // Check the watcher report.
Ravago Jonescf453ab2020-05-06 21:14:53 -0700309 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh7d87b672019-12-01 20:23:49 -0800310
311 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
312
313 // Just the timing report timer.
314 ASSERT_NE(primary_report.message().timers(), nullptr);
315 EXPECT_EQ(primary_report.message().timers()->size(), 2);
316
317 // No phased loops
318 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
319
320 // And now confirm that the watcher received all 10 messages, and has latency.
321 ASSERT_NE(primary_report.message().watchers(), nullptr);
322 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
323 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
324 EXPECT_NEAR(
325 primary_report.message().watchers()->Get(0)->wakeup_latency()->average(),
326 0.00005, 1e-9);
327 EXPECT_NEAR(
328 primary_report.message().watchers()->Get(0)->wakeup_latency()->min(),
329 0.00005, 1e-9);
330 EXPECT_NEAR(
331 primary_report.message().watchers()->Get(0)->wakeup_latency()->max(),
332 0.00005, 1e-9);
333 EXPECT_EQ(primary_report.message()
334 .watchers()
335 ->Get(0)
336 ->wakeup_latency()
337 ->standard_deviation(),
338 0.0);
339
340 EXPECT_EQ(
341 primary_report.message().watchers()->Get(0)->handler_time()->average(),
342 0.0);
343 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->min(),
344 0.0);
345 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->max(),
346 0.0);
347 EXPECT_EQ(primary_report.message()
348 .watchers()
349 ->Get(0)
350 ->handler_time()
351 ->standard_deviation(),
352 0.0);
353}
354
Austin Schuh4c3b9702020-08-30 11:34:55 -0700355// Tests that ping and pong work when on 2 different nodes, and the message
356// gateway messages are sent out as expected.
Austin Schuh898f4972020-01-11 17:21:25 -0800357TEST(SimulatedEventLoopTest, MultinodePingPong) {
358 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700359 aos::configuration::ReadConfig(ConfigPrefix() +
360 "events/multinode_pingpong_config.json");
Austin Schuh898f4972020-01-11 17:21:25 -0800361 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
362 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700363 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh898f4972020-01-11 17:21:25 -0800364
365 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
366
367 std::unique_ptr<EventLoop> ping_event_loop =
368 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
369 Ping ping(ping_event_loop.get());
370
371 std::unique_ptr<EventLoop> pong_event_loop =
372 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
373 Pong pong(pong_event_loop.get());
374
375 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
376 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700377 MessageCounter<examples::Pong> pi2_pong_counter(
378 pi2_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700379 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi2_timestamp_fetcher =
380 pi2_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
381 "/pi1/aos");
382 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
383 pi2_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
Austin Schuh898f4972020-01-11 17:21:25 -0800384
Austin Schuh4c3b9702020-08-30 11:34:55 -0700385 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
386 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
Austin Schuh898f4972020-01-11 17:21:25 -0800387
388 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
389 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700390 MessageCounter<examples::Pong> pi1_pong_counter(
391 pi1_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700392 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
393 pi1_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
394 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi1_timestamp_fetcher =
395 pi1_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
396 "/aos");
397
Austin Schuh4c3b9702020-08-30 11:34:55 -0700398 // Count timestamps.
399 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
400 pi1_pong_counter_event_loop.get(), "/pi1/aos");
401 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
402 pi2_pong_counter_event_loop.get(), "/pi1/aos");
403 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
404 pi3_pong_counter_event_loop.get(), "/pi1/aos");
405 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
406 pi1_pong_counter_event_loop.get(), "/pi2/aos");
407 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
408 pi2_pong_counter_event_loop.get(), "/pi2/aos");
409 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
410 pi1_pong_counter_event_loop.get(), "/pi3/aos");
411 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
412 pi3_pong_counter_event_loop.get(), "/pi3/aos");
413
Austin Schuh2f8fd752020-09-01 22:38:28 -0700414 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800415 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700416 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800417 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700418 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
419
Austin Schuh4c3b9702020-08-30 11:34:55 -0700420 // Wait to let timestamp estimation start up before looking for the results.
421 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
422
Austin Schuh8fb315a2020-11-19 22:33:58 -0800423 std::unique_ptr<EventLoop> pi1_statistics_counter_event_loop =
424 simulated_event_loop_factory.MakeEventLoop("pi1_statistics_counter", pi1);
425 std::unique_ptr<EventLoop> pi2_statistics_counter_event_loop =
426 simulated_event_loop_factory.MakeEventLoop("pi2_statistics_counter", pi2);
427 std::unique_ptr<EventLoop> pi3_statistics_counter_event_loop =
428 simulated_event_loop_factory.MakeEventLoop("pi3_statistics_counter", pi3);
429
Austin Schuh4c3b9702020-08-30 11:34:55 -0700430 int pi1_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800431 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700432 "/pi1/aos", [&pi1_server_statistics_count](
433 const message_bridge::ServerStatistics &stats) {
434 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
435 EXPECT_EQ(stats.connections()->size(), 2u);
436 for (const message_bridge::ServerConnection *connection :
437 *stats.connections()) {
438 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800439 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700440 if (connection->node()->name()->string_view() == "pi2") {
441 EXPECT_GT(connection->sent_packets(), 50);
442 } else if (connection->node()->name()->string_view() == "pi3") {
443 EXPECT_GE(connection->sent_packets(), 5);
444 } else {
445 LOG(FATAL) << "Unknown connection";
446 }
447
448 EXPECT_TRUE(connection->has_monotonic_offset());
449 EXPECT_EQ(connection->monotonic_offset(), 0);
450 }
451 ++pi1_server_statistics_count;
452 });
453
454 int pi2_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800455 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700456 "/pi2/aos", [&pi2_server_statistics_count](
457 const message_bridge::ServerStatistics &stats) {
458 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
459 EXPECT_EQ(stats.connections()->size(), 1u);
460
461 const message_bridge::ServerConnection *connection =
462 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800463 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700464 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
465 EXPECT_GT(connection->sent_packets(), 50);
466 EXPECT_TRUE(connection->has_monotonic_offset());
467 EXPECT_EQ(connection->monotonic_offset(), 0);
468 ++pi2_server_statistics_count;
469 });
470
471 int pi3_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800472 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700473 "/pi3/aos", [&pi3_server_statistics_count](
474 const message_bridge::ServerStatistics &stats) {
475 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
476 EXPECT_EQ(stats.connections()->size(), 1u);
477
478 const message_bridge::ServerConnection *connection =
479 stats.connections()->Get(0);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800480 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh4c3b9702020-08-30 11:34:55 -0700481 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
482 EXPECT_GE(connection->sent_packets(), 5);
483 EXPECT_TRUE(connection->has_monotonic_offset());
484 EXPECT_EQ(connection->monotonic_offset(), 0);
485 ++pi3_server_statistics_count;
486 });
487
488 int pi1_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800489 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700490 "/pi1/aos", [&pi1_client_statistics_count](
491 const message_bridge::ClientStatistics &stats) {
492 VLOG(1) << "pi1 ClientStatistics " << FlatbufferToJson(&stats);
493 EXPECT_EQ(stats.connections()->size(), 2u);
494
495 for (const message_bridge::ClientConnection *connection :
496 *stats.connections()) {
497 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
498 if (connection->node()->name()->string_view() == "pi2") {
499 EXPECT_GT(connection->received_packets(), 50);
500 } else if (connection->node()->name()->string_view() == "pi3") {
501 EXPECT_GE(connection->received_packets(), 5);
502 } else {
503 LOG(FATAL) << "Unknown connection";
504 }
505
506 EXPECT_TRUE(connection->has_monotonic_offset());
507 EXPECT_EQ(connection->monotonic_offset(), 150000);
508 }
509 ++pi1_client_statistics_count;
510 });
511
512 int pi2_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800513 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700514 "/pi2/aos", [&pi2_client_statistics_count](
515 const message_bridge::ClientStatistics &stats) {
516 VLOG(1) << "pi2 ClientStatistics " << FlatbufferToJson(&stats);
517 EXPECT_EQ(stats.connections()->size(), 1u);
518
519 const message_bridge::ClientConnection *connection =
520 stats.connections()->Get(0);
521 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
522 EXPECT_GT(connection->received_packets(), 50);
523 EXPECT_TRUE(connection->has_monotonic_offset());
524 EXPECT_EQ(connection->monotonic_offset(), 150000);
525 ++pi2_client_statistics_count;
526 });
527
528 int pi3_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800529 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700530 "/pi3/aos", [&pi3_client_statistics_count](
531 const message_bridge::ClientStatistics &stats) {
532 VLOG(1) << "pi3 ClientStatistics " << FlatbufferToJson(&stats);
533 EXPECT_EQ(stats.connections()->size(), 1u);
534
535 const message_bridge::ClientConnection *connection =
536 stats.connections()->Get(0);
537 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
538 EXPECT_GE(connection->received_packets(), 5);
539 EXPECT_TRUE(connection->has_monotonic_offset());
540 EXPECT_EQ(connection->monotonic_offset(), 150000);
541 ++pi3_client_statistics_count;
542 });
543
Austin Schuh2f8fd752020-09-01 22:38:28 -0700544 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
545 // channel.
546 const size_t pi1_timestamp_channel =
547 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
548 pi1_on_pi2_timestamp_fetcher.channel());
549 const size_t ping_timestamp_channel =
550 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
551 ping_on_pi2_fetcher.channel());
552
553 for (const Channel *channel :
554 *pi1_pong_counter_event_loop->configuration()->channels()) {
555 VLOG(1) << "Channel "
556 << configuration::ChannelIndex(
557 pi1_pong_counter_event_loop->configuration(), channel)
558 << " " << configuration::CleanedChannelToString(channel);
559 }
560
Austin Schuh8fb315a2020-11-19 22:33:58 -0800561 std::unique_ptr<EventLoop> pi1_remote_timestamp =
562 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
563
Austin Schuh2f8fd752020-09-01 22:38:28 -0700564 // For each remote timestamp we get back, confirm that it is either a ping
565 // message, or a timestamp we sent out. Also confirm that the timestamps are
566 // correct.
567 pi1_remote_timestamp->MakeWatcher(
568 "/pi1/aos/remote_timestamps/pi2",
569 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
570 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
Austin Schuh20ac95d2020-12-05 17:24:19 -0800571 &pi1_on_pi1_timestamp_fetcher, &simulated_event_loop_factory,
572 pi2](const RemoteMessage &header) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700573 VLOG(1) << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800574 EXPECT_TRUE(header.has_boot_uuid());
575 EXPECT_EQ(header.boot_uuid()->string_view(),
576 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
577 ->boot_uuid()
578 .string_view());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700579
580 const aos::monotonic_clock::time_point header_monotonic_sent_time(
581 chrono::nanoseconds(header.monotonic_sent_time()));
582 const aos::realtime_clock::time_point header_realtime_sent_time(
583 chrono::nanoseconds(header.realtime_sent_time()));
584 const aos::monotonic_clock::time_point header_monotonic_remote_time(
585 chrono::nanoseconds(header.monotonic_remote_time()));
586 const aos::realtime_clock::time_point header_realtime_remote_time(
587 chrono::nanoseconds(header.realtime_remote_time()));
588
589 const Context *pi1_context = nullptr;
590 const Context *pi2_context = nullptr;
591
592 if (header.channel_index() == pi1_timestamp_channel) {
593 // Find the forwarded message.
594 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
595 header_monotonic_sent_time) {
596 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
597 }
598
599 // And the source message.
600 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
601 header_monotonic_remote_time) {
602 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
603 }
604
605 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
606 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
607 } else if (header.channel_index() == ping_timestamp_channel) {
608 // Find the forwarded message.
609 while (ping_on_pi2_fetcher.context().monotonic_event_time <
610 header_monotonic_sent_time) {
611 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
612 }
613
614 // And the source message.
615 while (ping_on_pi1_fetcher.context().monotonic_event_time <
616 header_monotonic_remote_time) {
617 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
618 }
619
620 pi1_context = &ping_on_pi1_fetcher.context();
621 pi2_context = &ping_on_pi2_fetcher.context();
622 } else {
623 LOG(FATAL) << "Unknown channel";
624 }
625
626 // Confirm the forwarded message has matching timestamps to the
627 // timestamps we got back.
628 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700629 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700630 EXPECT_EQ(pi2_context->monotonic_event_time,
631 header_monotonic_sent_time);
632 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
633 EXPECT_EQ(pi2_context->realtime_remote_time,
634 header_realtime_remote_time);
635 EXPECT_EQ(pi2_context->monotonic_remote_time,
636 header_monotonic_remote_time);
637
638 // Confirm the forwarded message also matches the source message.
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700639 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700640 EXPECT_EQ(pi1_context->monotonic_event_time,
641 header_monotonic_remote_time);
642 EXPECT_EQ(pi1_context->realtime_event_time,
643 header_realtime_remote_time);
644 });
645
Austin Schuh4c3b9702020-08-30 11:34:55 -0700646 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
647 chrono::milliseconds(500) +
648 chrono::milliseconds(5));
649
650 EXPECT_EQ(pi1_pong_counter.count(), 1001);
651 EXPECT_EQ(pi2_pong_counter.count(), 1001);
652
653 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 100);
654 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 100);
655 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 100);
656 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 100);
657 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 100);
658 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 100);
659 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 100);
660
Austin Schuh20ac95d2020-12-05 17:24:19 -0800661 EXPECT_EQ(pi1_server_statistics_count, 10);
662 EXPECT_EQ(pi2_server_statistics_count, 10);
663 EXPECT_EQ(pi3_server_statistics_count, 10);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700664
665 EXPECT_EQ(pi1_client_statistics_count, 95);
666 EXPECT_EQ(pi2_client_statistics_count, 95);
667 EXPECT_EQ(pi3_client_statistics_count, 95);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700668
669 // Also confirm that remote timestamps are being forwarded correctly.
670 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1101);
671 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1101);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700672}
673
674// Tests that an offset between nodes can be recovered and shows up in
675// ServerStatistics correctly.
676TEST(SimulatedEventLoopTest, MultinodePingPongWithOffset) {
677 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700678 aos::configuration::ReadConfig(ConfigPrefix() +
679 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700680 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
Austin Schuh87dd3832021-01-01 23:07:31 -0800681 const size_t pi1_index = configuration::GetNodeIndex(&config.message(), pi1);
682 ASSERT_EQ(pi1_index, 0u);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700683 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh87dd3832021-01-01 23:07:31 -0800684 const size_t pi2_index = configuration::GetNodeIndex(&config.message(), pi2);
685 ASSERT_EQ(pi2_index, 1u);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700686 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh87dd3832021-01-01 23:07:31 -0800687 const size_t pi3_index = configuration::GetNodeIndex(&config.message(), pi3);
688 ASSERT_EQ(pi3_index, 2u);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700689
Austin Schuh87dd3832021-01-01 23:07:31 -0800690 message_bridge::TestingTimeConverter time(
691 configuration::NodesCount(&config.message()));
Austin Schuh4c3b9702020-08-30 11:34:55 -0700692 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
693 NodeEventLoopFactory *pi2_factory =
694 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
Austin Schuh87dd3832021-01-01 23:07:31 -0800695 pi2_factory->SetTimeConverter(&time);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700696
697 constexpr chrono::milliseconds kOffset{1501};
Austin Schuh87dd3832021-01-01 23:07:31 -0800698 time.AddNextTimestamp(
699 distributed_clock::epoch(),
700 {monotonic_clock::epoch(), monotonic_clock::epoch() + kOffset,
701 monotonic_clock::epoch()});
Austin Schuh4c3b9702020-08-30 11:34:55 -0700702
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 Schuh87dd3832021-01-01 23:07:31 -0800714 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
715 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
716
Austin Schuh4c3b9702020-08-30 11:34:55 -0700717 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
718 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
719
720 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
721 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
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");
Austin Schuh87dd3832021-01-01 23:07:31 -08001191 const size_t pi1_index = configuration::GetNodeIndex(&config.message(), pi1);
1192 ASSERT_EQ(pi1_index, 0u);
Austin Schuh2febf0d2020-09-21 22:24:30 -07001193 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh87dd3832021-01-01 23:07:31 -08001194 const size_t pi2_index = configuration::GetNodeIndex(&config.message(), pi2);
1195 ASSERT_EQ(pi2_index, 1u);
1196 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
1197 const size_t pi3_index = configuration::GetNodeIndex(&config.message(), pi3);
1198 ASSERT_EQ(pi3_index, 2u);
Austin Schuh2febf0d2020-09-21 22:24:30 -07001199
Austin Schuh87dd3832021-01-01 23:07:31 -08001200 message_bridge::TestingTimeConverter time(
1201 configuration::NodesCount(&config.message()));
Austin Schuh2febf0d2020-09-21 22:24:30 -07001202 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1203 NodeEventLoopFactory *pi2_factory =
1204 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
Austin Schuh87dd3832021-01-01 23:07:31 -08001205 pi2_factory->SetTimeConverter(&time);
Austin Schuh2febf0d2020-09-21 22:24:30 -07001206
Austin Schuh2febf0d2020-09-21 22:24:30 -07001207 constexpr chrono::milliseconds kOffset{150100};
Austin Schuh87dd3832021-01-01 23:07:31 -08001208 time.AddNextTimestamp(
1209 distributed_clock::epoch(),
1210 {monotonic_clock::epoch(), monotonic_clock::epoch() + kOffset,
1211 monotonic_clock::epoch()});
1212 time.AddNextTimestamp(
1213 distributed_clock::epoch() + chrono::seconds(10),
1214 {monotonic_clock::epoch() + chrono::milliseconds(9999),
1215 monotonic_clock::epoch() + kOffset + chrono::seconds(10),
1216 monotonic_clock::epoch() + chrono::milliseconds(9999)});
Austin Schuh2febf0d2020-09-21 22:24:30 -07001217
1218 std::unique_ptr<EventLoop> ping_event_loop =
1219 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1220 Ping ping(ping_event_loop.get());
1221
1222 std::unique_ptr<EventLoop> pong_event_loop =
1223 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1224 Pong pong(pong_event_loop.get());
1225
1226 std::unique_ptr<EventLoop> pi1_counter_event_loop =
1227 simulated_event_loop_factory.MakeEventLoop("pi1_counter", pi1);
1228 std::unique_ptr<EventLoop> pi2_counter_event_loop =
1229 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi2);
1230
1231 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
1232 pi1_counter_event_loop->MakeFetcher<examples::Ping>("/test");
1233 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
1234 pi2_counter_event_loop->MakeFetcher<examples::Ping>("/test");
1235
1236 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
1237 pi2_counter_event_loop->MakeFetcher<examples::Pong>("/test");
1238 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
1239 pi1_counter_event_loop->MakeFetcher<examples::Pong>("/test");
1240
1241 // End after a pong message comes back. This will leave the latest messages
1242 // on all channels so we can look at timestamps easily and check they make
1243 // sense.
1244 std::unique_ptr<EventLoop> pi1_pong_ender =
1245 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi1);
1246 int count = 0;
1247 pi1_pong_ender->MakeWatcher(
1248 "/test", [&simulated_event_loop_factory, &count](const examples::Pong &) {
1249 if (++count == 100) {
1250 simulated_event_loop_factory.Exit();
1251 }
1252 });
1253
1254 // Run enough that messages should be delivered.
1255 simulated_event_loop_factory.Run();
1256
1257 // Grab the latest messages.
1258 EXPECT_TRUE(ping_on_pi1_fetcher.Fetch());
1259 EXPECT_TRUE(ping_on_pi2_fetcher.Fetch());
1260 EXPECT_TRUE(pong_on_pi1_fetcher.Fetch());
1261 EXPECT_TRUE(pong_on_pi2_fetcher.Fetch());
1262
1263 // Compute their time on the global distributed clock so we can compute
1264 // distance betwen them.
1265 const distributed_clock::time_point pi1_ping_time =
1266 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
1267 ->ToDistributedClock(
1268 ping_on_pi1_fetcher.context().monotonic_event_time);
1269 const distributed_clock::time_point pi2_ping_time =
1270 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1271 ->ToDistributedClock(
1272 ping_on_pi2_fetcher.context().monotonic_event_time);
1273 const distributed_clock::time_point pi1_pong_time =
1274 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
1275 ->ToDistributedClock(
1276 pong_on_pi1_fetcher.context().monotonic_event_time);
1277 const distributed_clock::time_point pi2_pong_time =
1278 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1279 ->ToDistributedClock(
1280 pong_on_pi2_fetcher.context().monotonic_event_time);
1281
1282 // And confirm the delivery delay is just about exactly 150 uS for both
1283 // directions like expected. There will be a couple ns of rounding errors in
1284 // the conversion functions that aren't worth accounting for right now. This
1285 // will either be really close, or really far.
1286 EXPECT_GE(pi2_ping_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
1287 pi1_ping_time);
1288 EXPECT_LE(pi2_ping_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
1289 pi1_ping_time);
1290
1291 EXPECT_GE(pi1_pong_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
1292 pi2_pong_time);
1293 EXPECT_LE(pi1_pong_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
1294 pi2_pong_time);
1295}
1296
Austin Schuh4c570ea2020-11-19 23:13:24 -08001297void SendPing(aos::Sender<examples::Ping> *sender, int value) {
1298 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
1299 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
1300 ping_builder.add_value(value);
1301 builder.Send(ping_builder.Finish());
1302}
1303
1304// Tests that reliable (and unreliable) ping messages get forwarded as expected.
1305TEST(SimulatedEventLoopTest, MultinodeStartupTesting) {
1306 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1307 aos::configuration::ReadConfig(ConfigPrefix() +
1308 "events/multinode_pingpong_config.json");
1309 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1310 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1311
1312 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1313
1314 std::unique_ptr<EventLoop> ping_event_loop =
1315 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1316 aos::Sender<examples::Ping> pi1_reliable_sender =
1317 ping_event_loop->MakeSender<examples::Ping>("/reliable");
1318 aos::Sender<examples::Ping> pi1_unreliable_sender =
1319 ping_event_loop->MakeSender<examples::Ping>("/unreliable");
1320 SendPing(&pi1_reliable_sender, 1);
1321 SendPing(&pi1_unreliable_sender, 1);
1322
1323 std::unique_ptr<EventLoop> pi2_pong_event_loop =
1324 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1325 MessageCounter<examples::Ping> pi2_reliable_counter(pi2_pong_event_loop.get(),
1326 "/reliable");
1327 MessageCounter<examples::Ping> pi2_unreliable_counter(
1328 pi2_pong_event_loop.get(), "/unreliable");
1329 aos::Fetcher<examples::Ping> reliable_on_pi2_fetcher =
1330 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/reliable");
1331 aos::Fetcher<examples::Ping> unreliable_on_pi2_fetcher =
1332 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/unreliable");
1333
1334 const size_t reliable_channel_index = configuration::ChannelIndex(
1335 pi2_pong_event_loop->configuration(), reliable_on_pi2_fetcher.channel());
1336
1337 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1338 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1339
Austin Schuheeaa2022021-01-02 21:52:03 -08001340 const chrono::nanoseconds network_delay =
1341 simulated_event_loop_factory.network_delay();
1342
Austin Schuh4c570ea2020-11-19 23:13:24 -08001343 int reliable_timestamp_count = 0;
1344 pi1_remote_timestamp->MakeWatcher(
1345 "/pi1/aos/remote_timestamps/pi2",
Austin Schuh20ac95d2020-12-05 17:24:19 -08001346 [reliable_channel_index, &reliable_timestamp_count,
Austin Schuheeaa2022021-01-02 21:52:03 -08001347 &simulated_event_loop_factory, pi2, network_delay, &pi2_pong_event_loop,
1348 &pi1_remote_timestamp](const RemoteMessage &header) {
Austin Schuh20ac95d2020-12-05 17:24:19 -08001349 EXPECT_TRUE(header.has_boot_uuid());
1350 EXPECT_EQ(header.boot_uuid()->string_view(),
1351 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1352 ->boot_uuid()
1353 .string_view());
Austin Schuh4c570ea2020-11-19 23:13:24 -08001354 VLOG(1) << aos::FlatbufferToJson(&header);
1355 if (header.channel_index() == reliable_channel_index) {
1356 ++reliable_timestamp_count;
1357 }
Austin Schuheeaa2022021-01-02 21:52:03 -08001358
1359 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1360 chrono::nanoseconds(header.monotonic_sent_time()));
1361
1362 EXPECT_EQ(pi1_remote_timestamp->context().monotonic_event_time,
1363 header_monotonic_sent_time + network_delay +
1364 (pi1_remote_timestamp->monotonic_now() -
1365 pi2_pong_event_loop->monotonic_now()));
Austin Schuh4c570ea2020-11-19 23:13:24 -08001366 });
1367
1368 // Wait to let timestamp estimation start up before looking for the results.
1369 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1370
1371 EXPECT_EQ(pi2_reliable_counter.count(), 1u);
1372 // This one isn't reliable, but was sent before the start. It should *not* be
1373 // delivered.
1374 EXPECT_EQ(pi2_unreliable_counter.count(), 0u);
1375 // Confirm we got a timestamp logged for the message that was forwarded.
1376 EXPECT_EQ(reliable_timestamp_count, 1u);
1377
1378 SendPing(&pi1_reliable_sender, 2);
1379 SendPing(&pi1_unreliable_sender, 2);
1380 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1381 EXPECT_EQ(pi2_reliable_counter.count(), 2u);
1382 EXPECT_EQ(pi2_unreliable_counter.count(), 1u);
1383
1384 EXPECT_EQ(reliable_timestamp_count, 2u);
1385}
1386
Austin Schuh20ac95d2020-12-05 17:24:19 -08001387// Tests that rebooting a node changes the ServerStatistics message and the
1388// RemoteTimestamp message.
1389TEST(SimulatedEventLoopTest, BootUUIDTest) {
1390 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
1391 aos::configuration::ReadConfig(ConfigPrefix() +
1392 "events/multinode_pingpong_config.json");
1393 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
1394 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
1395
1396 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
1397
1398 std::unique_ptr<EventLoop> ping_event_loop =
1399 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1400 Ping ping(ping_event_loop.get());
1401
1402 std::unique_ptr<EventLoop> pong_event_loop =
1403 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1404 Pong pong(pong_event_loop.get());
1405
1406 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1407 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1408 std::string expected_boot_uuid(
1409 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1410 ->boot_uuid()
1411 .string_view());
1412
1413 int timestamp_count = 0;
1414 pi1_remote_timestamp->MakeWatcher(
1415 "/pi1/aos/remote_timestamps/pi2",
1416 [&timestamp_count, &expected_boot_uuid](const RemoteMessage &header) {
1417 EXPECT_TRUE(header.has_boot_uuid());
1418 EXPECT_EQ(header.boot_uuid()->string_view(), expected_boot_uuid);
1419 VLOG(1) << aos::FlatbufferToJson(&header);
1420 ++timestamp_count;
1421 });
1422
1423 int pi1_server_statistics_count = 0;
1424 pi1_remote_timestamp->MakeWatcher(
1425 "/pi1/aos", [&pi1_server_statistics_count, &expected_boot_uuid](
1426 const message_bridge::ServerStatistics &stats) {
1427 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
1428 for (const message_bridge::ServerConnection *connection :
1429 *stats.connections()) {
1430 EXPECT_TRUE(connection->has_boot_uuid());
1431 if (connection->node()->name()->string_view() == "pi2") {
1432 EXPECT_EQ(expected_boot_uuid,
1433 connection->boot_uuid()->string_view())
1434 << " : Got " << aos::FlatbufferToJson(&stats);
1435 ++pi1_server_statistics_count;
1436 }
1437 }
1438 });
1439
1440 // Let a couple of ServerStatistics messages show up before rebooting.
1441 simulated_event_loop_factory.RunFor(chrono::milliseconds(2001));
1442
1443 EXPECT_GT(timestamp_count, 100);
1444 EXPECT_GE(pi1_server_statistics_count, 1u);
1445
1446 // Confirm that reboot changes the UUID.
1447 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)->Reboot();
1448
1449 EXPECT_NE(expected_boot_uuid,
1450 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1451 ->boot_uuid()
1452 .string_view());
1453
1454 expected_boot_uuid =
1455 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
1456 ->boot_uuid()
1457 .string_view();
1458 timestamp_count = 0;
1459 pi1_server_statistics_count = 0;
1460
1461 simulated_event_loop_factory.RunFor(chrono::milliseconds(2000));
1462 EXPECT_GT(timestamp_count, 100);
1463 EXPECT_GE(pi1_server_statistics_count, 1u);
1464}
1465
Neil Balchc8f41ed2018-01-20 22:06:53 -08001466} // namespace testing
1467} // namespace aos