blob: fb144c3ea2c84cf57b58fada6a85d7af703f2cbd [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/events/simulated_event_loop.h"
2
Austin Schuh5f1cc5c2019-12-01 18:01:11 -08003#include <string_view>
4
Alex Perrycb7da4b2019-08-28 19:35:56 -07005#include "aos/events/event_loop_param_test.h"
Austin Schuh2f8fd752020-09-01 22:38:28 -07006#include "aos/events/logging/logger_generated.h"
Austin Schuh01b4c352020-09-21 23:09:39 -07007#include "aos/events/message_counter.h"
Austin Schuh898f4972020-01-11 17:21:25 -08008#include "aos/events/ping_lib.h"
9#include "aos/events/pong_lib.h"
Austin Schuh7d87b672019-12-01 20:23:49 -080010#include "aos/events/test_message_generated.h"
Austin Schuh4c3b9702020-08-30 11:34:55 -070011#include "aos/network/message_bridge_client_generated.h"
12#include "aos/network/message_bridge_server_generated.h"
Austin Schuh0de30f32020-12-06 12:44:28 -080013#include "aos/network/remote_message_generated.h"
Austin Schuh4c3b9702020-08-30 11:34:55 -070014#include "aos/network/timestamp_generated.h"
Neil Balchc8f41ed2018-01-20 22:06:53 -080015#include "gtest/gtest.h"
16
17namespace aos {
18namespace testing {
Brian Silverman28d14302020-09-18 15:26:17 -070019namespace {
20
21std::string ConfigPrefix() { return "aos/"; }
22
Austin Schuh0de30f32020-12-06 12:44:28 -080023using message_bridge::RemoteMessage;
Austin Schuh7267c532019-05-19 19:55:53 -070024namespace chrono = ::std::chrono;
25
Austin Schuh0de30f32020-12-06 12:44:28 -080026} // namespace
27
Neil Balchc8f41ed2018-01-20 22:06:53 -080028class SimulatedEventLoopTestFactory : public EventLoopTestFactory {
29 public:
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080030 ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080031 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080032 return event_loop_factory_->MakeEventLoop(name, my_node());
Neil Balchc8f41ed2018-01-20 22:06:53 -080033 }
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080034 ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
Austin Schuh217a9782019-12-21 23:02:50 -080035 MaybeMake();
Austin Schuhac0771c2020-01-07 18:36:30 -080036 return event_loop_factory_->MakeEventLoop(name, my_node());
Austin Schuh44019f92019-05-19 19:58:27 -070037 }
38
Austin Schuh217a9782019-12-21 23:02:50 -080039 void Run() override { event_loop_factory_->Run(); }
40 void Exit() override { event_loop_factory_->Exit(); }
Austin Schuh44019f92019-05-19 19:58:27 -070041
Austin Schuh52d325c2019-06-23 18:59:06 -070042 // TODO(austin): Implement this. It's used currently for a phased loop test.
43 // I'm not sure how much that matters.
44 void SleepFor(::std::chrono::nanoseconds /*duration*/) override {}
45
Austin Schuh7d87b672019-12-01 20:23:49 -080046 void set_send_delay(std::chrono::nanoseconds send_delay) {
Austin Schuh217a9782019-12-21 23:02:50 -080047 MaybeMake();
48 event_loop_factory_->set_send_delay(send_delay);
Austin Schuh7d87b672019-12-01 20:23:49 -080049 }
50
Neil Balchc8f41ed2018-01-20 22:06:53 -080051 private:
Austin Schuh217a9782019-12-21 23:02:50 -080052 void MaybeMake() {
53 if (!event_loop_factory_) {
54 if (configuration()->has_nodes()) {
Austin Schuhac0771c2020-01-07 18:36:30 -080055 event_loop_factory_ =
56 std::make_unique<SimulatedEventLoopFactory>(configuration());
Austin Schuh217a9782019-12-21 23:02:50 -080057 } else {
58 event_loop_factory_ =
59 std::make_unique<SimulatedEventLoopFactory>(configuration());
60 }
61 }
62 }
63 std::unique_ptr<SimulatedEventLoopFactory> event_loop_factory_;
Neil Balchc8f41ed2018-01-20 22:06:53 -080064};
65
Brian Silverman77162972020-08-12 19:52:40 -070066INSTANTIATE_TEST_CASE_P(SimulatedEventLoopCopyTest, AbstractEventLoopTest,
67 ::testing::Values(std::make_tuple(
68 []() {
69 return new SimulatedEventLoopTestFactory();
70 },
71 ReadMethod::COPY)));
Austin Schuh6b6dfa52019-06-12 20:16:20 -070072
Brian Silverman77162972020-08-12 19:52:40 -070073INSTANTIATE_TEST_CASE_P(
74 SimulatedEventLoopCopyDeathTest, AbstractEventLoopDeathTest,
75 ::testing::Values(
76 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
77 ReadMethod::COPY)));
78
79INSTANTIATE_TEST_CASE_P(SimulatedEventLoopPinTest, AbstractEventLoopTest,
80 ::testing::Values(std::make_tuple(
81 []() {
82 return new SimulatedEventLoopTestFactory();
83 },
84 ReadMethod::PIN)));
85
86INSTANTIATE_TEST_CASE_P(
87 SimulatedEventLoopPinDeathTest, AbstractEventLoopDeathTest,
88 ::testing::Values(
89 std::make_tuple([]() { return new SimulatedEventLoopTestFactory(); },
90 ReadMethod::PIN)));
Neil Balchc8f41ed2018-01-20 22:06:53 -080091
92// Test that creating an event and running the scheduler runs the event.
93TEST(EventSchedulerTest, ScheduleEvent) {
94 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -080095 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -080096 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -080097 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -080098
Austin Schuh8bd96322020-02-13 21:18:22 -080099 scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuhac0771c2020-01-07 18:36:30 -0800100 [&counter]() { counter += 1; });
Austin Schuh8bd96322020-02-13 21:18:22 -0800101 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800102 EXPECT_EQ(counter, 1);
Ravago Jonescf453ab2020-05-06 21:14:53 -0700103 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(2),
104 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800105 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800106 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800107 EXPECT_EQ(counter, 1);
108}
109
110// Test that descheduling an already scheduled event doesn't run the event.
111TEST(EventSchedulerTest, DescheduleEvent) {
112 int counter = 0;
Austin Schuh8bd96322020-02-13 21:18:22 -0800113 EventSchedulerScheduler scheduler_scheduler;
Neil Balchc8f41ed2018-01-20 22:06:53 -0800114 EventScheduler scheduler;
Austin Schuh8bd96322020-02-13 21:18:22 -0800115 scheduler_scheduler.AddEventScheduler(&scheduler);
Neil Balchc8f41ed2018-01-20 22:06:53 -0800116
Austin Schuh8bd96322020-02-13 21:18:22 -0800117 auto token = scheduler.Schedule(monotonic_clock::epoch() + chrono::seconds(1),
118 [&counter]() { counter += 1; });
Neil Balchc8f41ed2018-01-20 22:06:53 -0800119 scheduler.Deschedule(token);
Austin Schuh8bd96322020-02-13 21:18:22 -0800120 scheduler_scheduler.Run();
Neil Balchc8f41ed2018-01-20 22:06:53 -0800121 EXPECT_EQ(counter, 0);
122}
Austin Schuh44019f92019-05-19 19:58:27 -0700123
Austin Schuh8fb315a2020-11-19 22:33:58 -0800124void SendTestMessage(aos::Sender<TestMessage> *sender, int value) {
125 aos::Sender<TestMessage>::Builder builder = sender->MakeBuilder();
126 TestMessage::Builder test_message_builder =
127 builder.MakeBuilder<TestMessage>();
128 test_message_builder.add_value(value);
129 builder.Send(test_message_builder.Finish());
130}
131
132// Test that sending a message after running gets properly notified.
133TEST(SimulatedEventLoopTest, SendAfterRunFor) {
134 SimulatedEventLoopTestFactory factory;
135
136 SimulatedEventLoopFactory simulated_event_loop_factory(
137 factory.configuration());
138
139 ::std::unique_ptr<EventLoop> ping_event_loop =
140 simulated_event_loop_factory.MakeEventLoop("ping");
141 aos::Sender<TestMessage> test_message_sender =
142 ping_event_loop->MakeSender<TestMessage>("/test");
143 SendTestMessage(&test_message_sender, 1);
144
145 std::unique_ptr<EventLoop> pong1_event_loop =
146 simulated_event_loop_factory.MakeEventLoop("pong");
147 MessageCounter<TestMessage> test_message_counter1(pong1_event_loop.get(),
148 "/test");
149
150 EXPECT_FALSE(ping_event_loop->is_running());
151
152 // Watchers start when you start running, so there should be nothing counted.
153 simulated_event_loop_factory.RunFor(chrono::seconds(1));
154 EXPECT_EQ(test_message_counter1.count(), 0u);
155
156 std::unique_ptr<EventLoop> pong2_event_loop =
157 simulated_event_loop_factory.MakeEventLoop("pong");
158 MessageCounter<TestMessage> test_message_counter2(pong2_event_loop.get(),
159 "/test");
160
161 // Pauses in the middle don't count though, so this should be counted.
162 // But, the fresh watcher shouldn't pick it up yet.
163 SendTestMessage(&test_message_sender, 2);
164
165 EXPECT_EQ(test_message_counter1.count(), 0u);
166 EXPECT_EQ(test_message_counter2.count(), 0u);
167 simulated_event_loop_factory.RunFor(chrono::seconds(1));
168
169 EXPECT_EQ(test_message_counter1.count(), 1u);
170 EXPECT_EQ(test_message_counter2.count(), 0u);
171}
172
173// Test that creating an event loop while running dies.
174TEST(SimulatedEventLoopDeathTest, MakeEventLoopWhileRunning) {
175 SimulatedEventLoopTestFactory factory;
176
177 SimulatedEventLoopFactory simulated_event_loop_factory(
178 factory.configuration());
179
180 ::std::unique_ptr<EventLoop> event_loop =
181 simulated_event_loop_factory.MakeEventLoop("ping");
182
183 auto timer = event_loop->AddTimer([&]() {
184 EXPECT_DEATH(
185 {
186 ::std::unique_ptr<EventLoop> event_loop2 =
187 simulated_event_loop_factory.MakeEventLoop("ping");
188 },
189 "event loop while running");
190 simulated_event_loop_factory.Exit();
191 });
192
193 event_loop->OnRun([&event_loop, &timer] {
194 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50));
195 });
196
197 simulated_event_loop_factory.Run();
198}
199
200// Test that creating a watcher after running dies.
201TEST(SimulatedEventLoopDeathTest, MakeWatcherAfterRunning) {
202 SimulatedEventLoopTestFactory factory;
203
204 SimulatedEventLoopFactory simulated_event_loop_factory(
205 factory.configuration());
206
207 ::std::unique_ptr<EventLoop> event_loop =
208 simulated_event_loop_factory.MakeEventLoop("ping");
209
210 simulated_event_loop_factory.RunFor(chrono::seconds(1));
211
212 EXPECT_DEATH(
213 { MessageCounter<TestMessage> counter(event_loop.get(), "/test"); },
214 "Can't add a watcher after running");
215
216 ::std::unique_ptr<EventLoop> event_loop2 =
217 simulated_event_loop_factory.MakeEventLoop("ping");
218
219 simulated_event_loop_factory.RunFor(chrono::seconds(1));
220
221 EXPECT_DEATH(
222 { MessageCounter<TestMessage> counter(event_loop2.get(), "/test"); },
223 "Can't add a watcher after running");
224}
225
Austin Schuh44019f92019-05-19 19:58:27 -0700226// Test that running for a time period with no handlers causes time to progress
227// correctly.
228TEST(SimulatedEventLoopTest, RunForNoHandlers) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800229 SimulatedEventLoopTestFactory factory;
230
231 SimulatedEventLoopFactory simulated_event_loop_factory(
232 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700233 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800234 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700235
236 simulated_event_loop_factory.RunFor(chrono::seconds(1));
237
238 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700239 event_loop->monotonic_now());
240}
241
242// Test that running for a time with a periodic handler causes time to end
243// correctly.
244TEST(SimulatedEventLoopTest, RunForTimerHandler) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800245 SimulatedEventLoopTestFactory factory;
246
247 SimulatedEventLoopFactory simulated_event_loop_factory(
248 factory.configuration());
Austin Schuh44019f92019-05-19 19:58:27 -0700249 ::std::unique_ptr<EventLoop> event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800250 simulated_event_loop_factory.MakeEventLoop("loop");
Austin Schuh44019f92019-05-19 19:58:27 -0700251
252 int counter = 0;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700253 auto timer = event_loop->AddTimer([&counter]() { ++counter; });
Austin Schuh44019f92019-05-19 19:58:27 -0700254 event_loop->OnRun([&event_loop, &timer] {
255 timer->Setup(event_loop->monotonic_now() + chrono::milliseconds(50),
256 chrono::milliseconds(100));
257 });
258
259 simulated_event_loop_factory.RunFor(chrono::seconds(1));
260
261 EXPECT_EQ(::aos::monotonic_clock::epoch() + chrono::seconds(1),
Austin Schuh44019f92019-05-19 19:58:27 -0700262 event_loop->monotonic_now());
263 EXPECT_EQ(counter, 10);
264}
265
Austin Schuh7d87b672019-12-01 20:23:49 -0800266// Tests that watchers have latency in simulation.
267TEST(SimulatedEventLoopTest, WatcherTimingReport) {
268 SimulatedEventLoopTestFactory factory;
269 factory.set_send_delay(std::chrono::microseconds(50));
270
271 FLAGS_timing_report_ms = 1000;
272 auto loop1 = factory.MakePrimary("primary");
273 loop1->MakeWatcher("/test", [](const TestMessage &) {});
274
275 auto loop2 = factory.Make("sender_loop");
276
277 auto loop3 = factory.Make("report_fetcher");
278
279 Fetcher<timing::Report> report_fetcher =
280 loop3->MakeFetcher<timing::Report>("/aos");
281 EXPECT_FALSE(report_fetcher.Fetch());
282
283 auto sender = loop2->MakeSender<TestMessage>("/test");
284
285 // Send 10 messages in the middle of a timing report period so we get
286 // something interesting back.
287 auto test_timer = loop2->AddTimer([&sender]() {
288 for (int i = 0; i < 10; ++i) {
289 aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
290 TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
291 builder.add_value(200 + i);
292 ASSERT_TRUE(msg.Send(builder.Finish()));
293 }
294 });
295
296 // Quit after 1 timing report, mid way through the next cycle.
297 {
298 auto end_timer = loop1->AddTimer([&factory]() { factory.Exit(); });
299 end_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(2500));
300 end_timer->set_name("end");
301 }
302
303 loop1->OnRun([&test_timer, &loop1]() {
304 test_timer->Setup(loop1->monotonic_now() + chrono::milliseconds(1500));
305 });
306
307 factory.Run();
308
309 // And, since we are here, check that the timing report makes sense.
310 // Start by looking for our event loop's timing.
311 FlatbufferDetachedBuffer<timing::Report> primary_report =
312 FlatbufferDetachedBuffer<timing::Report>::Empty();
313 while (report_fetcher.FetchNext()) {
314 LOG(INFO) << "Report " << FlatbufferToJson(report_fetcher.get());
315 if (report_fetcher->name()->string_view() == "primary") {
316 primary_report = CopyFlatBuffer(report_fetcher.get());
317 }
318 }
319
320 // Check the watcher report.
Ravago Jonescf453ab2020-05-06 21:14:53 -0700321 VLOG(1) << FlatbufferToJson(primary_report, {.multi_line = true});
Austin Schuh7d87b672019-12-01 20:23:49 -0800322
323 EXPECT_EQ(primary_report.message().name()->string_view(), "primary");
324
325 // Just the timing report timer.
326 ASSERT_NE(primary_report.message().timers(), nullptr);
327 EXPECT_EQ(primary_report.message().timers()->size(), 2);
328
329 // No phased loops
330 ASSERT_EQ(primary_report.message().phased_loops(), nullptr);
331
332 // And now confirm that the watcher received all 10 messages, and has latency.
333 ASSERT_NE(primary_report.message().watchers(), nullptr);
334 ASSERT_EQ(primary_report.message().watchers()->size(), 1);
335 EXPECT_EQ(primary_report.message().watchers()->Get(0)->count(), 10);
336 EXPECT_NEAR(
337 primary_report.message().watchers()->Get(0)->wakeup_latency()->average(),
338 0.00005, 1e-9);
339 EXPECT_NEAR(
340 primary_report.message().watchers()->Get(0)->wakeup_latency()->min(),
341 0.00005, 1e-9);
342 EXPECT_NEAR(
343 primary_report.message().watchers()->Get(0)->wakeup_latency()->max(),
344 0.00005, 1e-9);
345 EXPECT_EQ(primary_report.message()
346 .watchers()
347 ->Get(0)
348 ->wakeup_latency()
349 ->standard_deviation(),
350 0.0);
351
352 EXPECT_EQ(
353 primary_report.message().watchers()->Get(0)->handler_time()->average(),
354 0.0);
355 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->min(),
356 0.0);
357 EXPECT_EQ(primary_report.message().watchers()->Get(0)->handler_time()->max(),
358 0.0);
359 EXPECT_EQ(primary_report.message()
360 .watchers()
361 ->Get(0)
362 ->handler_time()
363 ->standard_deviation(),
364 0.0);
365}
366
Austin Schuh4c3b9702020-08-30 11:34:55 -0700367// Tests that ping and pong work when on 2 different nodes, and the message
368// gateway messages are sent out as expected.
Austin Schuh898f4972020-01-11 17:21:25 -0800369TEST(SimulatedEventLoopTest, MultinodePingPong) {
370 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700371 aos::configuration::ReadConfig(ConfigPrefix() +
372 "events/multinode_pingpong_config.json");
Austin Schuh898f4972020-01-11 17:21:25 -0800373 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
374 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700375 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
Austin Schuh898f4972020-01-11 17:21:25 -0800376
377 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
378
379 std::unique_ptr<EventLoop> ping_event_loop =
380 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
381 Ping ping(ping_event_loop.get());
382
383 std::unique_ptr<EventLoop> pong_event_loop =
384 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
385 Pong pong(pong_event_loop.get());
386
387 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
388 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700389 MessageCounter<examples::Pong> pi2_pong_counter(
390 pi2_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700391 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi2_timestamp_fetcher =
392 pi2_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
393 "/pi1/aos");
394 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
395 pi2_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
Austin Schuh898f4972020-01-11 17:21:25 -0800396
Austin Schuh4c3b9702020-08-30 11:34:55 -0700397 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
398 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
Austin Schuh898f4972020-01-11 17:21:25 -0800399
400 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
401 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700402 MessageCounter<examples::Pong> pi1_pong_counter(
403 pi1_pong_counter_event_loop.get(), "/test");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700404 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
405 pi1_pong_counter_event_loop->MakeFetcher<examples::Ping>("/test");
406 aos::Fetcher<message_bridge::Timestamp> pi1_on_pi1_timestamp_fetcher =
407 pi1_pong_counter_event_loop->MakeFetcher<message_bridge::Timestamp>(
408 "/aos");
409
Austin Schuh4c3b9702020-08-30 11:34:55 -0700410 // Count timestamps.
411 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
412 pi1_pong_counter_event_loop.get(), "/pi1/aos");
413 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
414 pi2_pong_counter_event_loop.get(), "/pi1/aos");
415 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
416 pi3_pong_counter_event_loop.get(), "/pi1/aos");
417 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
418 pi1_pong_counter_event_loop.get(), "/pi2/aos");
419 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
420 pi2_pong_counter_event_loop.get(), "/pi2/aos");
421 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
422 pi1_pong_counter_event_loop.get(), "/pi3/aos");
423 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
424 pi3_pong_counter_event_loop.get(), "/pi3/aos");
425
Austin Schuh2f8fd752020-09-01 22:38:28 -0700426 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800427 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700428 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800429 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700430 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
431
Austin Schuh4c3b9702020-08-30 11:34:55 -0700432 // Wait to let timestamp estimation start up before looking for the results.
433 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
434
Austin Schuh8fb315a2020-11-19 22:33:58 -0800435 std::unique_ptr<EventLoop> pi1_statistics_counter_event_loop =
436 simulated_event_loop_factory.MakeEventLoop("pi1_statistics_counter", pi1);
437 std::unique_ptr<EventLoop> pi2_statistics_counter_event_loop =
438 simulated_event_loop_factory.MakeEventLoop("pi2_statistics_counter", pi2);
439 std::unique_ptr<EventLoop> pi3_statistics_counter_event_loop =
440 simulated_event_loop_factory.MakeEventLoop("pi3_statistics_counter", pi3);
441
Austin Schuh4c3b9702020-08-30 11:34:55 -0700442 int pi1_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800443 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700444 "/pi1/aos", [&pi1_server_statistics_count](
445 const message_bridge::ServerStatistics &stats) {
446 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
447 EXPECT_EQ(stats.connections()->size(), 2u);
448 for (const message_bridge::ServerConnection *connection :
449 *stats.connections()) {
450 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
451 if (connection->node()->name()->string_view() == "pi2") {
452 EXPECT_GT(connection->sent_packets(), 50);
453 } else if (connection->node()->name()->string_view() == "pi3") {
454 EXPECT_GE(connection->sent_packets(), 5);
455 } else {
456 LOG(FATAL) << "Unknown connection";
457 }
458
459 EXPECT_TRUE(connection->has_monotonic_offset());
460 EXPECT_EQ(connection->monotonic_offset(), 0);
461 }
462 ++pi1_server_statistics_count;
463 });
464
465 int pi2_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800466 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700467 "/pi2/aos", [&pi2_server_statistics_count](
468 const message_bridge::ServerStatistics &stats) {
469 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
470 EXPECT_EQ(stats.connections()->size(), 1u);
471
472 const message_bridge::ServerConnection *connection =
473 stats.connections()->Get(0);
474 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
475 EXPECT_GT(connection->sent_packets(), 50);
476 EXPECT_TRUE(connection->has_monotonic_offset());
477 EXPECT_EQ(connection->monotonic_offset(), 0);
478 ++pi2_server_statistics_count;
479 });
480
481 int pi3_server_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800482 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700483 "/pi3/aos", [&pi3_server_statistics_count](
484 const message_bridge::ServerStatistics &stats) {
485 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
486 EXPECT_EQ(stats.connections()->size(), 1u);
487
488 const message_bridge::ServerConnection *connection =
489 stats.connections()->Get(0);
490 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
491 EXPECT_GE(connection->sent_packets(), 5);
492 EXPECT_TRUE(connection->has_monotonic_offset());
493 EXPECT_EQ(connection->monotonic_offset(), 0);
494 ++pi3_server_statistics_count;
495 });
496
497 int pi1_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800498 pi1_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700499 "/pi1/aos", [&pi1_client_statistics_count](
500 const message_bridge::ClientStatistics &stats) {
501 VLOG(1) << "pi1 ClientStatistics " << FlatbufferToJson(&stats);
502 EXPECT_EQ(stats.connections()->size(), 2u);
503
504 for (const message_bridge::ClientConnection *connection :
505 *stats.connections()) {
506 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
507 if (connection->node()->name()->string_view() == "pi2") {
508 EXPECT_GT(connection->received_packets(), 50);
509 } else if (connection->node()->name()->string_view() == "pi3") {
510 EXPECT_GE(connection->received_packets(), 5);
511 } else {
512 LOG(FATAL) << "Unknown connection";
513 }
514
515 EXPECT_TRUE(connection->has_monotonic_offset());
516 EXPECT_EQ(connection->monotonic_offset(), 150000);
517 }
518 ++pi1_client_statistics_count;
519 });
520
521 int pi2_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800522 pi2_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700523 "/pi2/aos", [&pi2_client_statistics_count](
524 const message_bridge::ClientStatistics &stats) {
525 VLOG(1) << "pi2 ClientStatistics " << FlatbufferToJson(&stats);
526 EXPECT_EQ(stats.connections()->size(), 1u);
527
528 const message_bridge::ClientConnection *connection =
529 stats.connections()->Get(0);
530 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
531 EXPECT_GT(connection->received_packets(), 50);
532 EXPECT_TRUE(connection->has_monotonic_offset());
533 EXPECT_EQ(connection->monotonic_offset(), 150000);
534 ++pi2_client_statistics_count;
535 });
536
537 int pi3_client_statistics_count = 0;
Austin Schuh8fb315a2020-11-19 22:33:58 -0800538 pi3_statistics_counter_event_loop->MakeWatcher(
Austin Schuh4c3b9702020-08-30 11:34:55 -0700539 "/pi3/aos", [&pi3_client_statistics_count](
540 const message_bridge::ClientStatistics &stats) {
541 VLOG(1) << "pi3 ClientStatistics " << FlatbufferToJson(&stats);
542 EXPECT_EQ(stats.connections()->size(), 1u);
543
544 const message_bridge::ClientConnection *connection =
545 stats.connections()->Get(0);
546 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
547 EXPECT_GE(connection->received_packets(), 5);
548 EXPECT_TRUE(connection->has_monotonic_offset());
549 EXPECT_EQ(connection->monotonic_offset(), 150000);
550 ++pi3_client_statistics_count;
551 });
552
Austin Schuh2f8fd752020-09-01 22:38:28 -0700553 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
554 // channel.
555 const size_t pi1_timestamp_channel =
556 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
557 pi1_on_pi2_timestamp_fetcher.channel());
558 const size_t ping_timestamp_channel =
559 configuration::ChannelIndex(pi1_pong_counter_event_loop->configuration(),
560 ping_on_pi2_fetcher.channel());
561
562 for (const Channel *channel :
563 *pi1_pong_counter_event_loop->configuration()->channels()) {
564 VLOG(1) << "Channel "
565 << configuration::ChannelIndex(
566 pi1_pong_counter_event_loop->configuration(), channel)
567 << " " << configuration::CleanedChannelToString(channel);
568 }
569
Austin Schuh8fb315a2020-11-19 22:33:58 -0800570 std::unique_ptr<EventLoop> pi1_remote_timestamp =
571 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
572
Austin Schuh2f8fd752020-09-01 22:38:28 -0700573 // For each remote timestamp we get back, confirm that it is either a ping
574 // message, or a timestamp we sent out. Also confirm that the timestamps are
575 // correct.
576 pi1_remote_timestamp->MakeWatcher(
577 "/pi1/aos/remote_timestamps/pi2",
578 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
579 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
Austin Schuh0de30f32020-12-06 12:44:28 -0800580 &pi1_on_pi1_timestamp_fetcher](const RemoteMessage &header) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700581 VLOG(1) << aos::FlatbufferToJson(&header);
582
583 const aos::monotonic_clock::time_point header_monotonic_sent_time(
584 chrono::nanoseconds(header.monotonic_sent_time()));
585 const aos::realtime_clock::time_point header_realtime_sent_time(
586 chrono::nanoseconds(header.realtime_sent_time()));
587 const aos::monotonic_clock::time_point header_monotonic_remote_time(
588 chrono::nanoseconds(header.monotonic_remote_time()));
589 const aos::realtime_clock::time_point header_realtime_remote_time(
590 chrono::nanoseconds(header.realtime_remote_time()));
591
592 const Context *pi1_context = nullptr;
593 const Context *pi2_context = nullptr;
594
595 if (header.channel_index() == pi1_timestamp_channel) {
596 // Find the forwarded message.
597 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
598 header_monotonic_sent_time) {
599 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
600 }
601
602 // And the source message.
603 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
604 header_monotonic_remote_time) {
605 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
606 }
607
608 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
609 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
610 } else if (header.channel_index() == ping_timestamp_channel) {
611 // Find the forwarded message.
612 while (ping_on_pi2_fetcher.context().monotonic_event_time <
613 header_monotonic_sent_time) {
614 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
615 }
616
617 // And the source message.
618 while (ping_on_pi1_fetcher.context().monotonic_event_time <
619 header_monotonic_remote_time) {
620 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
621 }
622
623 pi1_context = &ping_on_pi1_fetcher.context();
624 pi2_context = &ping_on_pi2_fetcher.context();
625 } else {
626 LOG(FATAL) << "Unknown channel";
627 }
628
629 // Confirm the forwarded message has matching timestamps to the
630 // timestamps we got back.
631 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700632 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700633 EXPECT_EQ(pi2_context->monotonic_event_time,
634 header_monotonic_sent_time);
635 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
636 EXPECT_EQ(pi2_context->realtime_remote_time,
637 header_realtime_remote_time);
638 EXPECT_EQ(pi2_context->monotonic_remote_time,
639 header_monotonic_remote_time);
640
641 // Confirm the forwarded message also matches the source message.
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700642 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700643 EXPECT_EQ(pi1_context->monotonic_event_time,
644 header_monotonic_remote_time);
645 EXPECT_EQ(pi1_context->realtime_event_time,
646 header_realtime_remote_time);
647 });
648
Austin Schuh4c3b9702020-08-30 11:34:55 -0700649 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
650 chrono::milliseconds(500) +
651 chrono::milliseconds(5));
652
653 EXPECT_EQ(pi1_pong_counter.count(), 1001);
654 EXPECT_EQ(pi2_pong_counter.count(), 1001);
655
656 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 100);
657 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 100);
658 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 100);
659 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 100);
660 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 100);
661 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 100);
662 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 100);
663
664 EXPECT_EQ(pi1_server_statistics_count, 9);
665 EXPECT_EQ(pi2_server_statistics_count, 9);
666 EXPECT_EQ(pi3_server_statistics_count, 9);
667
668 EXPECT_EQ(pi1_client_statistics_count, 95);
669 EXPECT_EQ(pi2_client_statistics_count, 95);
670 EXPECT_EQ(pi3_client_statistics_count, 95);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700671
672 // Also confirm that remote timestamps are being forwarded correctly.
673 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1101);
674 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1101);
Austin Schuh4c3b9702020-08-30 11:34:55 -0700675}
676
677// Tests that an offset between nodes can be recovered and shows up in
678// ServerStatistics correctly.
679TEST(SimulatedEventLoopTest, MultinodePingPongWithOffset) {
680 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700681 aos::configuration::ReadConfig(ConfigPrefix() +
682 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700683 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
684 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
685 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
686
687 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
688 NodeEventLoopFactory *pi2_factory =
689 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
690
691 constexpr chrono::milliseconds kOffset{1501};
692 pi2_factory->SetDistributedOffset(kOffset, 1.0);
693
694 std::unique_ptr<EventLoop> ping_event_loop =
695 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
696 Ping ping(ping_event_loop.get());
697
698 std::unique_ptr<EventLoop> pong_event_loop =
699 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
700 Pong pong(pong_event_loop.get());
701
Austin Schuh8fb315a2020-11-19 22:33:58 -0800702 // Wait to let timestamp estimation start up before looking for the results.
703 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
704
Austin Schuh4c3b9702020-08-30 11:34:55 -0700705 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
706 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
707
708 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
709 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
710
711 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
712 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
713
Austin Schuh4c3b9702020-08-30 11:34:55 -0700714 // Confirm the offsets are being recovered correctly.
715 int pi1_server_statistics_count = 0;
716 pi1_pong_counter_event_loop->MakeWatcher(
717 "/pi1/aos", [&pi1_server_statistics_count,
718 kOffset](const message_bridge::ServerStatistics &stats) {
719 VLOG(1) << "pi1 ServerStatistics " << FlatbufferToJson(&stats);
720 EXPECT_EQ(stats.connections()->size(), 2u);
721 for (const message_bridge::ServerConnection *connection :
722 *stats.connections()) {
723 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
724 if (connection->node()->name()->string_view() == "pi2") {
725 EXPECT_EQ(connection->monotonic_offset(),
726 chrono::nanoseconds(kOffset).count());
727 } else if (connection->node()->name()->string_view() == "pi3") {
728 EXPECT_EQ(connection->monotonic_offset(), 0);
729 } else {
730 LOG(FATAL) << "Unknown connection";
731 }
732
733 EXPECT_TRUE(connection->has_monotonic_offset());
734 }
735 ++pi1_server_statistics_count;
736 });
737
738 int pi2_server_statistics_count = 0;
739 pi2_pong_counter_event_loop->MakeWatcher(
740 "/pi2/aos", [&pi2_server_statistics_count,
741 kOffset](const message_bridge::ServerStatistics &stats) {
742 VLOG(1) << "pi2 ServerStatistics " << FlatbufferToJson(&stats);
743 EXPECT_EQ(stats.connections()->size(), 1u);
744
745 const message_bridge::ServerConnection *connection =
746 stats.connections()->Get(0);
747 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
748 EXPECT_TRUE(connection->has_monotonic_offset());
749 EXPECT_EQ(connection->monotonic_offset(),
750 -chrono::nanoseconds(kOffset).count());
751 ++pi2_server_statistics_count;
752 });
753
754 int pi3_server_statistics_count = 0;
755 pi3_pong_counter_event_loop->MakeWatcher(
756 "/pi3/aos", [&pi3_server_statistics_count](
757 const message_bridge::ServerStatistics &stats) {
758 VLOG(1) << "pi3 ServerStatistics " << FlatbufferToJson(&stats);
759 EXPECT_EQ(stats.connections()->size(), 1u);
760
761 const message_bridge::ServerConnection *connection =
762 stats.connections()->Get(0);
763 EXPECT_EQ(connection->state(), message_bridge::State::CONNECTED);
764 EXPECT_TRUE(connection->has_monotonic_offset());
765 EXPECT_EQ(connection->monotonic_offset(), 0);
766 ++pi3_server_statistics_count;
767 });
768
769 simulated_event_loop_factory.RunFor(chrono::seconds(10) -
770 chrono::milliseconds(500) +
771 chrono::milliseconds(5));
772
773 EXPECT_EQ(pi1_server_statistics_count, 9);
774 EXPECT_EQ(pi2_server_statistics_count, 9);
775 EXPECT_EQ(pi3_server_statistics_count, 9);
776}
777
778// Test that disabling statistics actually disables them.
779TEST(SimulatedEventLoopTest, MultinodeWithoutStatistics) {
780 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Brian Silverman28d14302020-09-18 15:26:17 -0700781 aos::configuration::ReadConfig(ConfigPrefix() +
782 "events/multinode_pingpong_config.json");
Austin Schuh4c3b9702020-08-30 11:34:55 -0700783 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
784 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
785 const Node *pi3 = configuration::GetNode(&config.message(), "pi3");
786
787 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
788 simulated_event_loop_factory.DisableStatistics();
789
790 std::unique_ptr<EventLoop> ping_event_loop =
791 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
792 Ping ping(ping_event_loop.get());
793
794 std::unique_ptr<EventLoop> pong_event_loop =
795 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
796 Pong pong(pong_event_loop.get());
797
798 std::unique_ptr<EventLoop> pi2_pong_counter_event_loop =
799 simulated_event_loop_factory.MakeEventLoop("pi2_pong_counter", pi2);
800
801 MessageCounter<examples::Pong> pi2_pong_counter(
802 pi2_pong_counter_event_loop.get(), "/test");
803
804 std::unique_ptr<EventLoop> pi3_pong_counter_event_loop =
805 simulated_event_loop_factory.MakeEventLoop("pi3_pong_counter", pi3);
806
807 std::unique_ptr<EventLoop> pi1_pong_counter_event_loop =
808 simulated_event_loop_factory.MakeEventLoop("pi1_pong_counter", pi1);
809
810 MessageCounter<examples::Pong> pi1_pong_counter(
811 pi1_pong_counter_event_loop.get(), "/test");
812
813 // Count timestamps.
814 MessageCounter<message_bridge::Timestamp> pi1_on_pi1_timestamp_counter(
815 pi1_pong_counter_event_loop.get(), "/pi1/aos");
816 MessageCounter<message_bridge::Timestamp> pi1_on_pi2_timestamp_counter(
817 pi2_pong_counter_event_loop.get(), "/pi1/aos");
818 MessageCounter<message_bridge::Timestamp> pi1_on_pi3_timestamp_counter(
819 pi3_pong_counter_event_loop.get(), "/pi1/aos");
820 MessageCounter<message_bridge::Timestamp> pi2_on_pi1_timestamp_counter(
821 pi1_pong_counter_event_loop.get(), "/pi2/aos");
822 MessageCounter<message_bridge::Timestamp> pi2_on_pi2_timestamp_counter(
823 pi2_pong_counter_event_loop.get(), "/pi2/aos");
824 MessageCounter<message_bridge::Timestamp> pi3_on_pi1_timestamp_counter(
825 pi1_pong_counter_event_loop.get(), "/pi3/aos");
826 MessageCounter<message_bridge::Timestamp> pi3_on_pi3_timestamp_counter(
827 pi3_pong_counter_event_loop.get(), "/pi3/aos");
828
Austin Schuh2f8fd752020-09-01 22:38:28 -0700829 // Count remote timestamps
Austin Schuh0de30f32020-12-06 12:44:28 -0800830 MessageCounter<RemoteMessage> remote_timestamps_pi2_on_pi1(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700831 pi1_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi2");
Austin Schuh0de30f32020-12-06 12:44:28 -0800832 MessageCounter<RemoteMessage> remote_timestamps_pi1_on_pi2(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700833 pi2_pong_counter_event_loop.get(), "/aos/remote_timestamps/pi1");
834
Austin Schuh4c3b9702020-08-30 11:34:55 -0700835 MessageCounter<message_bridge::ServerStatistics>
836 pi1_server_statistics_counter(pi1_pong_counter_event_loop.get(),
837 "/pi1/aos");
838 MessageCounter<message_bridge::ServerStatistics>
839 pi2_server_statistics_counter(pi2_pong_counter_event_loop.get(),
840 "/pi2/aos");
841 MessageCounter<message_bridge::ServerStatistics>
842 pi3_server_statistics_counter(pi3_pong_counter_event_loop.get(),
843 "/pi3/aos");
844
845 MessageCounter<message_bridge::ClientStatistics>
846 pi1_client_statistics_counter(pi1_pong_counter_event_loop.get(),
847 "/pi1/aos");
848 MessageCounter<message_bridge::ClientStatistics>
849 pi2_client_statistics_counter(pi2_pong_counter_event_loop.get(),
850 "/pi2/aos");
851 MessageCounter<message_bridge::ClientStatistics>
852 pi3_client_statistics_counter(pi3_pong_counter_event_loop.get(),
853 "/pi3/aos");
Austin Schuh898f4972020-01-11 17:21:25 -0800854
855 simulated_event_loop_factory.RunFor(chrono::seconds(10) +
856 chrono::milliseconds(5));
857
Austin Schuh4c3b9702020-08-30 11:34:55 -0700858 EXPECT_EQ(pi1_pong_counter.count(), 1001u);
859 EXPECT_EQ(pi2_pong_counter.count(), 1001u);
860
861 EXPECT_EQ(pi1_on_pi1_timestamp_counter.count(), 0u);
862 EXPECT_EQ(pi1_on_pi2_timestamp_counter.count(), 0u);
863 EXPECT_EQ(pi1_on_pi3_timestamp_counter.count(), 0u);
864 EXPECT_EQ(pi2_on_pi1_timestamp_counter.count(), 0u);
865 EXPECT_EQ(pi2_on_pi2_timestamp_counter.count(), 0u);
866 EXPECT_EQ(pi3_on_pi1_timestamp_counter.count(), 0u);
867 EXPECT_EQ(pi3_on_pi3_timestamp_counter.count(), 0u);
868
869 EXPECT_EQ(pi1_server_statistics_counter.count(), 0u);
870 EXPECT_EQ(pi2_server_statistics_counter.count(), 0u);
871 EXPECT_EQ(pi3_server_statistics_counter.count(), 0u);
872
873 EXPECT_EQ(pi1_client_statistics_counter.count(), 0u);
874 EXPECT_EQ(pi2_client_statistics_counter.count(), 0u);
875 EXPECT_EQ(pi3_client_statistics_counter.count(), 0u);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700876
877 // Also confirm that remote timestamps are being forwarded correctly.
878 EXPECT_EQ(remote_timestamps_pi2_on_pi1.count(), 1001);
879 EXPECT_EQ(remote_timestamps_pi1_on_pi2.count(), 1001);
Austin Schuh898f4972020-01-11 17:21:25 -0800880}
881
Austin Schuh2febf0d2020-09-21 22:24:30 -0700882// Tests that the time offset having a slope doesn't break the world.
883// SimulatedMessageBridge has enough self consistency CHECK statements to
884// confirm, and we can can also check a message in each direction to make sure
885// it gets delivered as expected.
886TEST(SimulatedEventLoopTest, MultinodePingPongWithOffsetAndSlope) {
887 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
888 aos::configuration::ReadConfig(ConfigPrefix() +
889 "events/multinode_pingpong_config.json");
890 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
891 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
892
893 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
894 NodeEventLoopFactory *pi2_factory =
895 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2);
896
897 // Move the pi far into the future so the slope is significant. And set it to
898 // something reasonable.
899 constexpr chrono::milliseconds kOffset{150100};
900 pi2_factory->SetDistributedOffset(kOffset, 1.0001);
901
902 std::unique_ptr<EventLoop> ping_event_loop =
903 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
904 Ping ping(ping_event_loop.get());
905
906 std::unique_ptr<EventLoop> pong_event_loop =
907 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
908 Pong pong(pong_event_loop.get());
909
910 std::unique_ptr<EventLoop> pi1_counter_event_loop =
911 simulated_event_loop_factory.MakeEventLoop("pi1_counter", pi1);
912 std::unique_ptr<EventLoop> pi2_counter_event_loop =
913 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi2);
914
915 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
916 pi1_counter_event_loop->MakeFetcher<examples::Ping>("/test");
917 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
918 pi2_counter_event_loop->MakeFetcher<examples::Ping>("/test");
919
920 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
921 pi2_counter_event_loop->MakeFetcher<examples::Pong>("/test");
922 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
923 pi1_counter_event_loop->MakeFetcher<examples::Pong>("/test");
924
925 // End after a pong message comes back. This will leave the latest messages
926 // on all channels so we can look at timestamps easily and check they make
927 // sense.
928 std::unique_ptr<EventLoop> pi1_pong_ender =
929 simulated_event_loop_factory.MakeEventLoop("pi2_counter", pi1);
930 int count = 0;
931 pi1_pong_ender->MakeWatcher(
932 "/test", [&simulated_event_loop_factory, &count](const examples::Pong &) {
933 if (++count == 100) {
934 simulated_event_loop_factory.Exit();
935 }
936 });
937
938 // Run enough that messages should be delivered.
939 simulated_event_loop_factory.Run();
940
941 // Grab the latest messages.
942 EXPECT_TRUE(ping_on_pi1_fetcher.Fetch());
943 EXPECT_TRUE(ping_on_pi2_fetcher.Fetch());
944 EXPECT_TRUE(pong_on_pi1_fetcher.Fetch());
945 EXPECT_TRUE(pong_on_pi2_fetcher.Fetch());
946
947 // Compute their time on the global distributed clock so we can compute
948 // distance betwen them.
949 const distributed_clock::time_point pi1_ping_time =
950 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
951 ->ToDistributedClock(
952 ping_on_pi1_fetcher.context().monotonic_event_time);
953 const distributed_clock::time_point pi2_ping_time =
954 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
955 ->ToDistributedClock(
956 ping_on_pi2_fetcher.context().monotonic_event_time);
957 const distributed_clock::time_point pi1_pong_time =
958 simulated_event_loop_factory.GetNodeEventLoopFactory(pi1)
959 ->ToDistributedClock(
960 pong_on_pi1_fetcher.context().monotonic_event_time);
961 const distributed_clock::time_point pi2_pong_time =
962 simulated_event_loop_factory.GetNodeEventLoopFactory(pi2)
963 ->ToDistributedClock(
964 pong_on_pi2_fetcher.context().monotonic_event_time);
965
966 // And confirm the delivery delay is just about exactly 150 uS for both
967 // directions like expected. There will be a couple ns of rounding errors in
968 // the conversion functions that aren't worth accounting for right now. This
969 // will either be really close, or really far.
970 EXPECT_GE(pi2_ping_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
971 pi1_ping_time);
972 EXPECT_LE(pi2_ping_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
973 pi1_ping_time);
974
975 EXPECT_GE(pi1_pong_time, chrono::microseconds(150) - chrono::nanoseconds(10) +
976 pi2_pong_time);
977 EXPECT_LE(pi1_pong_time, chrono::microseconds(150) + chrono::nanoseconds(10) +
978 pi2_pong_time);
979}
980
Austin Schuh4c570ea2020-11-19 23:13:24 -0800981void SendPing(aos::Sender<examples::Ping> *sender, int value) {
982 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
983 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
984 ping_builder.add_value(value);
985 builder.Send(ping_builder.Finish());
986}
987
988// Tests that reliable (and unreliable) ping messages get forwarded as expected.
989TEST(SimulatedEventLoopTest, MultinodeStartupTesting) {
990 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
991 aos::configuration::ReadConfig(ConfigPrefix() +
992 "events/multinode_pingpong_config.json");
993 const Node *pi1 = configuration::GetNode(&config.message(), "pi1");
994 const Node *pi2 = configuration::GetNode(&config.message(), "pi2");
995
996 SimulatedEventLoopFactory simulated_event_loop_factory(&config.message());
997
998 std::unique_ptr<EventLoop> ping_event_loop =
999 simulated_event_loop_factory.MakeEventLoop("ping", pi1);
1000 aos::Sender<examples::Ping> pi1_reliable_sender =
1001 ping_event_loop->MakeSender<examples::Ping>("/reliable");
1002 aos::Sender<examples::Ping> pi1_unreliable_sender =
1003 ping_event_loop->MakeSender<examples::Ping>("/unreliable");
1004 SendPing(&pi1_reliable_sender, 1);
1005 SendPing(&pi1_unreliable_sender, 1);
1006
1007 std::unique_ptr<EventLoop> pi2_pong_event_loop =
1008 simulated_event_loop_factory.MakeEventLoop("pong", pi2);
1009 MessageCounter<examples::Ping> pi2_reliable_counter(pi2_pong_event_loop.get(),
1010 "/reliable");
1011 MessageCounter<examples::Ping> pi2_unreliable_counter(
1012 pi2_pong_event_loop.get(), "/unreliable");
1013 aos::Fetcher<examples::Ping> reliable_on_pi2_fetcher =
1014 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/reliable");
1015 aos::Fetcher<examples::Ping> unreliable_on_pi2_fetcher =
1016 pi2_pong_event_loop->MakeFetcher<examples::Ping>("/unreliable");
1017
1018 const size_t reliable_channel_index = configuration::ChannelIndex(
1019 pi2_pong_event_loop->configuration(), reliable_on_pi2_fetcher.channel());
1020
1021 std::unique_ptr<EventLoop> pi1_remote_timestamp =
1022 simulated_event_loop_factory.MakeEventLoop("pi1_remote_timestamp", pi1);
1023
1024 int reliable_timestamp_count = 0;
1025 pi1_remote_timestamp->MakeWatcher(
1026 "/pi1/aos/remote_timestamps/pi2",
1027 [reliable_channel_index,
Austin Schuh0de30f32020-12-06 12:44:28 -08001028 &reliable_timestamp_count](const RemoteMessage &header) {
Austin Schuh4c570ea2020-11-19 23:13:24 -08001029 VLOG(1) << aos::FlatbufferToJson(&header);
1030 if (header.channel_index() == reliable_channel_index) {
1031 ++reliable_timestamp_count;
1032 }
1033 });
1034
1035 // Wait to let timestamp estimation start up before looking for the results.
1036 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1037
1038 EXPECT_EQ(pi2_reliable_counter.count(), 1u);
1039 // This one isn't reliable, but was sent before the start. It should *not* be
1040 // delivered.
1041 EXPECT_EQ(pi2_unreliable_counter.count(), 0u);
1042 // Confirm we got a timestamp logged for the message that was forwarded.
1043 EXPECT_EQ(reliable_timestamp_count, 1u);
1044
1045 SendPing(&pi1_reliable_sender, 2);
1046 SendPing(&pi1_unreliable_sender, 2);
1047 simulated_event_loop_factory.RunFor(chrono::milliseconds(500));
1048 EXPECT_EQ(pi2_reliable_counter.count(), 2u);
1049 EXPECT_EQ(pi2_unreliable_counter.count(), 1u);
1050
1051 EXPECT_EQ(reliable_timestamp_count, 2u);
1052}
1053
Neil Balchc8f41ed2018-01-20 22:06:53 -08001054} // namespace testing
1055} // namespace aos