blob: 37989438571e46b4c0faedb56bdaa5f9dadee4e1 [file] [log] [blame]
Austin Schuhe84c3ed2019-12-14 15:29:48 -08001#include <chrono>
2#include <thread>
3
Austin Schuh2f8fd752020-09-01 22:38:28 -07004#include "absl/strings/str_cat.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -08005#include "aos/events/ping_generated.h"
6#include "aos/events/pong_generated.h"
Brian Silverman7b266d92021-02-17 21:24:02 -08007#include "aos/ipc_lib/event.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -08008#include "aos/network/message_bridge_client_lib.h"
9#include "aos/network/message_bridge_server_lib.h"
Jim Ostrowski2192ddb2020-06-24 19:07:31 -070010#include "aos/network/team_number.h"
Austin Schuhe991fe22020-11-18 16:53:39 -080011#include "aos/util/file.h"
Brian Silverman7b266d92021-02-17 21:24:02 -080012#include "gtest/gtest.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -080013
Austin Schuh8902fa52021-03-14 22:39:24 -070014DECLARE_string(boot_uuid);
15
Austin Schuhe84c3ed2019-12-14 15:29:48 -080016namespace aos {
Austin Schuh2f8fd752020-09-01 22:38:28 -070017void SetShmBase(const std::string_view base);
18
Austin Schuhe84c3ed2019-12-14 15:29:48 -080019namespace message_bridge {
20namespace testing {
21
22namespace chrono = std::chrono;
23
Austin Schuhe991fe22020-11-18 16:53:39 -080024std::string ShmBase(const std::string_view node) {
Austin Schuh2f8fd752020-09-01 22:38:28 -070025 const char *tmpdir_c_str = getenv("TEST_TMPDIR");
26 if (tmpdir_c_str != nullptr) {
Austin Schuhe991fe22020-11-18 16:53:39 -080027 return absl::StrCat(tmpdir_c_str, "/", node);
Austin Schuh2f8fd752020-09-01 22:38:28 -070028 } else {
Austin Schuhe991fe22020-11-18 16:53:39 -080029 return absl::StrCat("/dev/shm/", node);
Austin Schuh2f8fd752020-09-01 22:38:28 -070030 }
31}
32
Austin Schuhe991fe22020-11-18 16:53:39 -080033void DoSetShmBase(const std::string_view node) {
34 aos::SetShmBase(ShmBase(node));
35}
36
Austin Schuh36a2c3e2021-02-18 22:28:38 -080037// Parameters to run all the tests with.
38struct Param {
39 // The config file to use.
40 std::string config;
41 // If true, the RemoteMessage channel should be shared between all the remote
42 // channels. If false, there will be 1 RemoteMessage channel per remote
43 // channel.
44 bool shared;
45};
46
47class MessageBridgeParameterizedTest
48 : public ::testing::TestWithParam<struct Param> {
Austin Schuh0de30f32020-12-06 12:44:28 -080049 public:
Austin Schuh36a2c3e2021-02-18 22:28:38 -080050 MessageBridgeParameterizedTest()
51 : config(aos::configuration::ReadConfig(
Austin Schuh8902fa52021-03-14 22:39:24 -070052 absl::StrCat("aos/network/", GetParam().config))),
53 pi1_boot_uuid_(UUID::Random()),
54 pi2_boot_uuid_(UUID::Random()) {
Austin Schuh0de30f32020-12-06 12:44:28 -080055 util::UnlinkRecursive(ShmBase("pi1"));
56 util::UnlinkRecursive(ShmBase("pi2"));
57 }
Austin Schuhe991fe22020-11-18 16:53:39 -080058
Austin Schuh36a2c3e2021-02-18 22:28:38 -080059 bool shared() const { return GetParam().shared; }
60
Austin Schuh0a2f12f2021-01-08 22:48:29 -080061 void OnPi1() {
62 DoSetShmBase("pi1");
63 FLAGS_override_hostname = "raspberrypi";
Austin Schuh8902fa52021-03-14 22:39:24 -070064 FLAGS_boot_uuid = pi1_boot_uuid_.ToString();
Austin Schuh0a2f12f2021-01-08 22:48:29 -080065 }
66
67 void OnPi2() {
68 DoSetShmBase("pi2");
69 FLAGS_override_hostname = "raspberrypi2";
Austin Schuh8902fa52021-03-14 22:39:24 -070070 FLAGS_boot_uuid = pi2_boot_uuid_.ToString();
Austin Schuh0a2f12f2021-01-08 22:48:29 -080071 }
72
73 void MakePi1Server() {
74 OnPi1();
75 FLAGS_application_name = "pi1_message_bridge_server";
76 pi1_server_event_loop =
Austin Schuhf466ab52021-02-16 22:00:38 -080077 std::make_unique<aos::ShmEventLoop>(&config.message());
Austin Schuh0a2f12f2021-01-08 22:48:29 -080078 pi1_server_event_loop->SetRuntimeRealtimePriority(1);
79 pi1_message_bridge_server =
80 std::make_unique<MessageBridgeServer>(pi1_server_event_loop.get());
81 }
82
83 void RunPi1Server(chrono::nanoseconds duration) {
84 // Setup a shutdown callback.
85 aos::TimerHandler *const quit = pi1_server_event_loop->AddTimer(
86 [this]() { pi1_server_event_loop->Exit(); });
87 pi1_server_event_loop->OnRun([this, quit, duration]() {
88 // Stop between timestamps, not exactly on them.
89 quit->Setup(pi1_server_event_loop->monotonic_now() + duration);
90 });
91
92 pi1_server_event_loop->Run();
93 }
94
95 void StartPi1Server() {
96 pi1_server_thread = std::thread([this]() {
97 LOG(INFO) << "Started pi1_message_bridge_server";
98 pi1_server_event_loop->Run();
99 });
100 }
101
102 void StopPi1Server() {
103 if (pi1_server_thread.joinable()) {
104 pi1_server_event_loop->Exit();
105 pi1_server_thread.join();
106 pi1_server_thread = std::thread();
107 }
108 pi1_message_bridge_server.reset();
109 pi1_server_event_loop.reset();
110 }
111
112 void MakePi1Client() {
113 OnPi1();
114 FLAGS_application_name = "pi1_message_bridge_client";
115 pi1_client_event_loop =
Austin Schuhf466ab52021-02-16 22:00:38 -0800116 std::make_unique<aos::ShmEventLoop>(&config.message());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800117 pi1_client_event_loop->SetRuntimeRealtimePriority(1);
118 pi1_message_bridge_client =
119 std::make_unique<MessageBridgeClient>(pi1_client_event_loop.get());
120 }
121
122 void StartPi1Client() {
123 pi1_client_thread = std::thread([this]() {
124 LOG(INFO) << "Started pi1_message_bridge_client";
125 pi1_client_event_loop->Run();
126 });
127 }
128
129 void StopPi1Client() {
130 pi1_client_event_loop->Exit();
131 pi1_client_thread.join();
132 pi1_client_thread = std::thread();
133 pi1_message_bridge_client.reset();
134 pi1_client_event_loop.reset();
135 }
136
137 void MakePi1Test() {
138 OnPi1();
139 FLAGS_application_name = "test1";
140 pi1_test_event_loop =
Austin Schuhf466ab52021-02-16 22:00:38 -0800141 std::make_unique<aos::ShmEventLoop>(&config.message());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800142
143 pi1_test_event_loop->MakeWatcher(
144 "/pi1/aos", [](const ServerStatistics &stats) {
145 VLOG(1) << "/pi1/aos ServerStatistics " << FlatbufferToJson(&stats);
146 });
147
148 pi1_test_event_loop->MakeWatcher(
149 "/pi1/aos", [](const ClientStatistics &stats) {
150 VLOG(1) << "/pi1/aos ClientStatistics " << FlatbufferToJson(&stats);
151 });
152
153 pi1_test_event_loop->MakeWatcher(
154 "/pi1/aos", [](const Timestamp &timestamp) {
155 VLOG(1) << "/pi1/aos Timestamp " << FlatbufferToJson(&timestamp);
156 });
Austin Schuh8902fa52021-03-14 22:39:24 -0700157 pi1_test_event_loop->MakeWatcher(
158 "/pi2/aos", [this](const Timestamp &timestamp) {
159 VLOG(1) << "/pi2/aos Timestamp " << FlatbufferToJson(&timestamp);
160 EXPECT_EQ(pi1_test_event_loop->context().remote_boot_uuid,
161 pi2_boot_uuid_);
162 });
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800163 }
164
165 void StartPi1Test() {
166 pi1_test_thread = std::thread([this]() {
167 LOG(INFO) << "Started pi1_test";
168 pi1_test_event_loop->Run();
169 });
170 }
171
172 void StopPi1Test() {
173 pi1_test_event_loop->Exit();
174 pi1_test_thread.join();
175 }
176
177 void MakePi2Server() {
178 OnPi2();
179 FLAGS_application_name = "pi2_message_bridge_server";
180 pi2_server_event_loop =
Austin Schuhf466ab52021-02-16 22:00:38 -0800181 std::make_unique<aos::ShmEventLoop>(&config.message());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800182 pi2_server_event_loop->SetRuntimeRealtimePriority(1);
183 pi2_message_bridge_server =
184 std::make_unique<MessageBridgeServer>(pi2_server_event_loop.get());
185 }
186
187 void RunPi2Server(chrono::nanoseconds duration) {
188 // Setup a shutdown callback.
189 aos::TimerHandler *const quit = pi2_server_event_loop->AddTimer(
190 [this]() { pi2_server_event_loop->Exit(); });
191 pi2_server_event_loop->OnRun([this, quit, duration]() {
192 // Stop between timestamps, not exactly on them.
193 quit->Setup(pi2_server_event_loop->monotonic_now() + duration);
194 });
195
196 pi2_server_event_loop->Run();
197 }
198
199 void StartPi2Server() {
200 pi2_server_thread = std::thread([this]() {
201 LOG(INFO) << "Started pi2_message_bridge_server";
202 pi2_server_event_loop->Run();
203 });
204 }
205
206 void StopPi2Server() {
207 if (pi2_server_thread.joinable()) {
208 pi2_server_event_loop->Exit();
209 pi2_server_thread.join();
210 pi2_server_thread = std::thread();
211 }
212 pi2_message_bridge_server.reset();
213 pi2_server_event_loop.reset();
214 }
215
216 void MakePi2Client() {
217 OnPi2();
218 FLAGS_application_name = "pi2_message_bridge_client";
219 pi2_client_event_loop =
Austin Schuhf466ab52021-02-16 22:00:38 -0800220 std::make_unique<aos::ShmEventLoop>(&config.message());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800221 pi2_client_event_loop->SetRuntimeRealtimePriority(1);
222 pi2_message_bridge_client =
223 std::make_unique<MessageBridgeClient>(pi2_client_event_loop.get());
224 }
225
226 void RunPi2Client(chrono::nanoseconds duration) {
227 // Run for 5 seconds to make sure we have time to estimate the offset.
228 aos::TimerHandler *const quit = pi2_client_event_loop->AddTimer(
229 [this]() { pi2_client_event_loop->Exit(); });
230 pi2_client_event_loop->OnRun([this, quit, duration]() {
231 // Stop between timestamps, not exactly on them.
232 quit->Setup(pi2_client_event_loop->monotonic_now() + duration);
233 });
234
235 // And go!
236 pi2_client_event_loop->Run();
237 }
238
239 void StartPi2Client() {
240 pi2_client_thread = std::thread([this]() {
241 LOG(INFO) << "Started pi2_message_bridge_client";
242 pi2_client_event_loop->Run();
243 });
244 }
245
246 void StopPi2Client() {
247 if (pi2_client_thread.joinable()) {
248 pi2_client_event_loop->Exit();
249 pi2_client_thread.join();
250 pi2_client_thread = std::thread();
251 }
252 pi2_message_bridge_client.reset();
253 pi2_client_event_loop.reset();
254 }
255
256 void MakePi2Test() {
257 OnPi2();
258 FLAGS_application_name = "test2";
259 pi2_test_event_loop =
Austin Schuhf466ab52021-02-16 22:00:38 -0800260 std::make_unique<aos::ShmEventLoop>(&config.message());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800261
262 pi2_test_event_loop->MakeWatcher(
263 "/pi2/aos", [](const ServerStatistics &stats) {
264 VLOG(1) << "/pi2/aos ServerStatistics " << FlatbufferToJson(&stats);
265 });
266
267 pi2_test_event_loop->MakeWatcher(
268 "/pi2/aos", [](const ClientStatistics &stats) {
269 VLOG(1) << "/pi2/aos ClientStatistics " << FlatbufferToJson(&stats);
270 });
271
272 pi2_test_event_loop->MakeWatcher(
Austin Schuh8902fa52021-03-14 22:39:24 -0700273 "/pi1/aos", [this](const Timestamp &timestamp) {
274 VLOG(1) << "/pi1/aos Timestamp " << FlatbufferToJson(&timestamp);
275 EXPECT_EQ(pi2_test_event_loop->context().remote_boot_uuid,
276 pi1_boot_uuid_);
277 });
278 pi2_test_event_loop->MakeWatcher(
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800279 "/pi2/aos", [](const Timestamp &timestamp) {
280 VLOG(1) << "/pi2/aos Timestamp " << FlatbufferToJson(&timestamp);
281 });
282 }
283
284 void StartPi2Test() {
285 pi2_test_thread = std::thread([this]() {
286 LOG(INFO) << "Started pi2_message_bridge_test";
287 pi2_test_event_loop->Run();
288 });
289 }
290
291 void StopPi2Test() {
292 pi2_test_event_loop->Exit();
293 pi2_test_thread.join();
294 }
295
Austin Schuhf466ab52021-02-16 22:00:38 -0800296 aos::FlatbufferDetachedBuffer<aos::Configuration> config;
Austin Schuh8902fa52021-03-14 22:39:24 -0700297 const UUID pi1_boot_uuid_;
298 const UUID pi2_boot_uuid_;
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800299
300 std::unique_ptr<aos::ShmEventLoop> pi1_server_event_loop;
301 std::unique_ptr<MessageBridgeServer> pi1_message_bridge_server;
302 std::thread pi1_server_thread;
303
304 std::unique_ptr<aos::ShmEventLoop> pi1_client_event_loop;
305 std::unique_ptr<MessageBridgeClient> pi1_message_bridge_client;
306 std::thread pi1_client_thread;
307
308 std::unique_ptr<aos::ShmEventLoop> pi1_test_event_loop;
309 std::thread pi1_test_thread;
310
311 std::unique_ptr<aos::ShmEventLoop> pi2_server_event_loop;
312 std::unique_ptr<MessageBridgeServer> pi2_message_bridge_server;
313 std::thread pi2_server_thread;
314
315 std::unique_ptr<aos::ShmEventLoop> pi2_client_event_loop;
316 std::unique_ptr<MessageBridgeClient> pi2_message_bridge_client;
317 std::thread pi2_client_thread;
318
319 std::unique_ptr<aos::ShmEventLoop> pi2_test_event_loop;
320 std::thread pi2_test_thread;
Austin Schuhe991fe22020-11-18 16:53:39 -0800321};
322
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800323// Test that we can send a ping message over sctp and receive it.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800324TEST_P(MessageBridgeParameterizedTest, PingPong) {
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800325 // This is rather annoying to set up. We need to start up a client and
326 // server, on the same node, but get them to think that they are on different
327 // nodes.
328 //
329 // We then get to wait until they are connected.
330 //
331 // After they are connected, we send a Ping message.
332 //
333 // On the other end, we receive a Pong message.
334 //
335 // But, we need the client to not post directly to "/test" like it would in a
336 // real system, otherwise we will re-send the ping message... So, use an
337 // application specific map to have the client post somewhere else.
338 //
339 // To top this all off, each of these needs to be done with a ShmEventLoop,
340 // which needs to run in a separate thread... And it is really hard to get
341 // everything started up reliably. So just be super generous on timeouts and
342 // hope for the best. We can be more generous in the future if we need to.
343 //
344 // We are faking the application names by passing in --application_name=foo
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800345 OnPi1();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800346 // Force ourselves to be "raspberrypi" and allocate everything.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700347
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800348 MakePi1Server();
349 MakePi1Client();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800350
351 // And build the app which sends the pings.
352 FLAGS_application_name = "ping";
Austin Schuhf466ab52021-02-16 22:00:38 -0800353 aos::ShmEventLoop ping_event_loop(&config.message());
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800354 aos::Sender<examples::Ping> ping_sender =
355 ping_event_loop.MakeSender<examples::Ping>("/test");
356
Austin Schuhf466ab52021-02-16 22:00:38 -0800357 aos::ShmEventLoop pi1_test_event_loop(&config.message());
Austin Schuh0de30f32020-12-06 12:44:28 -0800358 aos::Fetcher<RemoteMessage> message_header_fetcher1 =
359 pi1_test_event_loop.MakeFetcher<RemoteMessage>(
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800360 shared() ? "/pi1/aos/remote_timestamps/pi2"
361 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700362
363 // Fetchers for confirming the remote timestamps made it.
364 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
365 ping_event_loop.MakeFetcher<examples::Ping>("/test");
366 aos::Fetcher<Timestamp> pi1_on_pi1_timestamp_fetcher =
367 ping_event_loop.MakeFetcher<Timestamp>("/aos");
368
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800369 // Now do it for "raspberrypi2", the client.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800370 OnPi2();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700371
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800372 MakePi2Client();
373 MakePi2Server();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800374
375 // And build the app which sends the pongs.
376 FLAGS_application_name = "pong";
Austin Schuhf466ab52021-02-16 22:00:38 -0800377 aos::ShmEventLoop pong_event_loop(&config.message());
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800378
Austin Schuh7bc59052020-02-16 23:48:33 -0800379 // And build the app for testing.
380 FLAGS_application_name = "test";
Austin Schuhf466ab52021-02-16 22:00:38 -0800381 aos::ShmEventLoop test_event_loop(&config.message());
Austin Schuh7bc59052020-02-16 23:48:33 -0800382
383 aos::Fetcher<ClientStatistics> client_statistics_fetcher =
384 test_event_loop.MakeFetcher<ClientStatistics>("/aos");
Austin Schuh0de30f32020-12-06 12:44:28 -0800385 aos::Fetcher<RemoteMessage> message_header_fetcher2 =
386 test_event_loop.MakeFetcher<RemoteMessage>(
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800387 shared() ? "/pi2/aos/remote_timestamps/pi1"
388 : "/pi2/aos/remote_timestamps/pi1/pi2/aos/"
389 "aos-message_bridge-Timestamp");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700390
391 // Event loop for fetching data delivered to pi2 from pi1 to match up
392 // messages.
Austin Schuhf466ab52021-02-16 22:00:38 -0800393 aos::ShmEventLoop delivered_messages_event_loop(&config.message());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700394 aos::Fetcher<Timestamp> pi1_on_pi2_timestamp_fetcher =
395 delivered_messages_event_loop.MakeFetcher<Timestamp>("/pi1/aos");
396 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
397 delivered_messages_event_loop.MakeFetcher<examples::Ping>("/test");
398 EXPECT_FALSE(ping_on_pi2_fetcher.Fetch());
399 EXPECT_FALSE(pi1_on_pi2_timestamp_fetcher.Fetch());
Austin Schuh7bc59052020-02-16 23:48:33 -0800400
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800401 // Count the pongs.
402 int pong_count = 0;
Austin Schuh8902fa52021-03-14 22:39:24 -0700403 pong_event_loop.MakeWatcher("/test", [&pong_count, &pong_event_loop,
404 this](const examples::Ping &ping) {
405 EXPECT_EQ(pong_event_loop.context().remote_boot_uuid, pi1_boot_uuid_);
406 ++pong_count;
407 VLOG(1) << "Got ping back " << FlatbufferToJson(&ping);
408 });
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800409
410 FLAGS_override_hostname = "";
411
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800412 // Wait until we are connected, then send.
413 int ping_count = 0;
Austin Schuh7bc59052020-02-16 23:48:33 -0800414 int pi1_server_statistics_count = 0;
Austin Schuh61e973f2021-02-21 21:43:56 -0800415 ping_event_loop.MakeWatcher("/pi1/aos", [this, &ping_count, &ping_sender,
416 &pi1_server_statistics_count](
417 const ServerStatistics &stats) {
418 VLOG(1) << "/pi1/aos ServerStatistics " << FlatbufferToJson(&stats);
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800419
Austin Schuh61e973f2021-02-21 21:43:56 -0800420 ASSERT_TRUE(stats.has_connections());
421 EXPECT_EQ(stats.connections()->size(), 1);
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800422
Austin Schuh61e973f2021-02-21 21:43:56 -0800423 bool connected = false;
424 for (const ServerConnection *connection : *stats.connections()) {
425 // Confirm that we are estimating the server time offset correctly. It
426 // should be about 0 since we are on the same machine here.
427 if (connection->has_monotonic_offset()) {
428 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
429 chrono::milliseconds(1));
430 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
431 chrono::milliseconds(-1));
432 ++pi1_server_statistics_count;
433 }
Austin Schuh7bc59052020-02-16 23:48:33 -0800434
Austin Schuh61e973f2021-02-21 21:43:56 -0800435 if (connection->node()->name()->string_view() ==
436 pi2_client_event_loop->node()->name()->string_view()) {
437 if (connection->state() == State::CONNECTED) {
438 EXPECT_TRUE(connection->has_boot_uuid());
439 connected = true;
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800440 }
Austin Schuh61e973f2021-02-21 21:43:56 -0800441 }
442 }
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800443
Austin Schuh61e973f2021-02-21 21:43:56 -0800444 if (connected) {
445 VLOG(1) << "Connected! Sent ping.";
446 auto builder = ping_sender.MakeBuilder();
447 examples::Ping::Builder ping_builder =
448 builder.MakeBuilder<examples::Ping>();
449 ping_builder.add_value(ping_count + 971);
450 builder.Send(ping_builder.Finish());
451 ++ping_count;
452 }
453 });
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800454
Austin Schuh7bc59052020-02-16 23:48:33 -0800455 // Confirm both client and server statistics messages have decent offsets in
456 // them.
457 int pi2_server_statistics_count = 0;
Austin Schuh196a4452020-03-15 23:12:03 -0700458 pong_event_loop.MakeWatcher("/pi2/aos", [&pi2_server_statistics_count](
Austin Schuh7bc59052020-02-16 23:48:33 -0800459 const ServerStatistics &stats) {
Austin Schuh1ca49e92020-12-11 00:01:27 -0800460 VLOG(1) << "/pi2/aos ServerStatistics " << FlatbufferToJson(&stats);
Austin Schuh7bc59052020-02-16 23:48:33 -0800461 for (const ServerConnection *connection : *stats.connections()) {
462 if (connection->has_monotonic_offset()) {
463 ++pi2_server_statistics_count;
464 // Confirm that we are estimating the server time offset correctly. It
465 // should be about 0 since we are on the same machine here.
466 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
467 chrono::milliseconds(1));
468 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
469 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800470 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh7bc59052020-02-16 23:48:33 -0800471 }
472 }
473 });
474
475 int pi1_client_statistics_count = 0;
Austin Schuh5344c352020-04-12 17:04:26 -0700476 ping_event_loop.MakeWatcher("/pi1/aos", [&pi1_client_statistics_count](
477 const ClientStatistics &stats) {
Austin Schuh1ca49e92020-12-11 00:01:27 -0800478 VLOG(1) << "/pi1/aos ClientStatistics " << FlatbufferToJson(&stats);
Austin Schuh7bc59052020-02-16 23:48:33 -0800479
Austin Schuh5344c352020-04-12 17:04:26 -0700480 for (const ClientConnection *connection : *stats.connections()) {
481 if (connection->has_monotonic_offset()) {
482 ++pi1_client_statistics_count;
483 // It takes at least 10 microseconds to send a message between the
484 // client and server. The min (filtered) time shouldn't be over 10
485 // milliseconds on localhost. This might have to bump up if this is
486 // proving flaky.
487 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
Austin Schuh3edddcc2020-12-29 13:32:02 -0800488 chrono::milliseconds(10))
489 << " " << connection->monotonic_offset()
490 << "ns vs 10000ns on iteration " << pi1_client_statistics_count;
Austin Schuh5344c352020-04-12 17:04:26 -0700491 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
Austin Schuh3edddcc2020-12-29 13:32:02 -0800492 chrono::microseconds(10))
493 << " " << connection->monotonic_offset()
494 << "ns vs 10000ns on iteration " << pi1_client_statistics_count;
Austin Schuh5344c352020-04-12 17:04:26 -0700495 }
496 }
497 });
Austin Schuh7bc59052020-02-16 23:48:33 -0800498
499 int pi2_client_statistics_count = 0;
Austin Schuh196a4452020-03-15 23:12:03 -0700500 pong_event_loop.MakeWatcher("/pi2/aos", [&pi2_client_statistics_count](
Austin Schuh7bc59052020-02-16 23:48:33 -0800501 const ClientStatistics &stats) {
Austin Schuh1ca49e92020-12-11 00:01:27 -0800502 VLOG(1) << "/pi2/aos ClientStatistics " << FlatbufferToJson(&stats);
Austin Schuh7bc59052020-02-16 23:48:33 -0800503
504 for (const ClientConnection *connection : *stats.connections()) {
505 if (connection->has_monotonic_offset()) {
506 ++pi2_client_statistics_count;
507 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
508 chrono::milliseconds(10));
509 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
510 chrono::microseconds(10));
511 }
512 }
513 });
514
Austin Schuh196a4452020-03-15 23:12:03 -0700515 ping_event_loop.MakeWatcher("/pi1/aos", [](const Timestamp &timestamp) {
Austin Schuh7bc59052020-02-16 23:48:33 -0800516 EXPECT_TRUE(timestamp.has_offsets());
Austin Schuh1ca49e92020-12-11 00:01:27 -0800517 VLOG(1) << "/pi1/aos Timestamp " << FlatbufferToJson(&timestamp);
Austin Schuh7bc59052020-02-16 23:48:33 -0800518 });
Austin Schuh196a4452020-03-15 23:12:03 -0700519 pong_event_loop.MakeWatcher("/pi2/aos", [](const Timestamp &timestamp) {
Austin Schuh7bc59052020-02-16 23:48:33 -0800520 EXPECT_TRUE(timestamp.has_offsets());
Austin Schuh1ca49e92020-12-11 00:01:27 -0800521 VLOG(1) << "/pi2/aos Timestamp " << FlatbufferToJson(&timestamp);
Austin Schuh7bc59052020-02-16 23:48:33 -0800522 });
523
524 // Run for 5 seconds to make sure we have time to estimate the offset.
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800525 aos::TimerHandler *quit = ping_event_loop.AddTimer(
526 [&ping_event_loop]() { ping_event_loop.Exit(); });
527 ping_event_loop.OnRun([quit, &ping_event_loop]() {
Austin Schuh7bc59052020-02-16 23:48:33 -0800528 // Stop between timestamps, not exactly on them.
529 quit->Setup(ping_event_loop.monotonic_now() + chrono::milliseconds(5050));
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800530 });
531
Austin Schuh2f8fd752020-09-01 22:38:28 -0700532 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
533 // channel.
534 const size_t pi1_timestamp_channel = configuration::ChannelIndex(
535 pong_event_loop.configuration(), pi1_on_pi2_timestamp_fetcher.channel());
536 const size_t ping_timestamp_channel =
537 configuration::ChannelIndex(delivered_messages_event_loop.configuration(),
538 ping_on_pi2_fetcher.channel());
539
540 for (const Channel *channel : *ping_event_loop.configuration()->channels()) {
541 VLOG(1) << "Channel "
542 << configuration::ChannelIndex(ping_event_loop.configuration(),
543 channel)
544 << " " << configuration::CleanedChannelToString(channel);
545 }
546
547 // For each remote timestamp we get back, confirm that it is either a ping
548 // message, or a timestamp we sent out. Also confirm that the timestamps are
549 // correct.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800550 for (std::pair<int, std::string> channel :
551 shared()
552 ? std::vector<std::pair<
553 int, std::string>>{{-1, "/pi1/aos/remote_timestamps/pi2"}}
554 : std::vector<std::pair<int, std::string>>{
555 {pi1_timestamp_channel,
556 "/pi1/aos/remote_timestamps/pi2/pi1/aos/"
557 "aos-message_bridge-Timestamp"},
558 {ping_timestamp_channel,
559 "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping"}}) {
560 ping_event_loop.MakeWatcher(
561 channel.second,
562 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
563 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
564 &pi1_on_pi1_timestamp_fetcher,
565 channel_index = channel.first](const RemoteMessage &header) {
566 VLOG(1) << "/pi1/aos/remote_timestamps/pi2 RemoteMessage "
567 << aos::FlatbufferToJson(&header);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700568
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800569 EXPECT_TRUE(header.has_boot_uuid());
570 if (channel_index != -1) {
571 ASSERT_EQ(channel_index, header.channel_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700572 }
573
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800574 const aos::monotonic_clock::time_point header_monotonic_sent_time(
575 chrono::nanoseconds(header.monotonic_sent_time()));
576 const aos::realtime_clock::time_point header_realtime_sent_time(
577 chrono::nanoseconds(header.realtime_sent_time()));
578 const aos::monotonic_clock::time_point header_monotonic_remote_time(
579 chrono::nanoseconds(header.monotonic_remote_time()));
580 const aos::realtime_clock::time_point header_realtime_remote_time(
581 chrono::nanoseconds(header.realtime_remote_time()));
582
583 const Context *pi1_context = nullptr;
584 const Context *pi2_context = nullptr;
585
586 if (header.channel_index() == pi1_timestamp_channel) {
587 // Find the forwarded message.
588 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
589 header_monotonic_sent_time) {
590 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
591 }
592
593 // And the source message.
594 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
595 header_monotonic_remote_time) {
596 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
597 }
598
599 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
600 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
601 } else if (header.channel_index() == ping_timestamp_channel) {
602 // Find the forwarded message.
603 while (ping_on_pi2_fetcher.context().monotonic_event_time <
604 header_monotonic_sent_time) {
605 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
606 }
607
608 // And the source message.
609 while (ping_on_pi1_fetcher.context().monotonic_event_time <
610 header_monotonic_remote_time) {
611 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
612 }
613
614 pi1_context = &ping_on_pi1_fetcher.context();
615 pi2_context = &ping_on_pi2_fetcher.context();
616 } else {
617 LOG(FATAL) << "Unknown channel";
Austin Schuh2f8fd752020-09-01 22:38:28 -0700618 }
619
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800620 // Confirm the forwarded message has matching timestamps to the
621 // timestamps we got back.
622 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
623 EXPECT_EQ(pi2_context->monotonic_event_time,
624 header_monotonic_sent_time);
625 EXPECT_EQ(pi2_context->realtime_event_time,
626 header_realtime_sent_time);
627 EXPECT_EQ(pi2_context->realtime_remote_time,
628 header_realtime_remote_time);
629 EXPECT_EQ(pi2_context->monotonic_remote_time,
630 header_monotonic_remote_time);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700631
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800632 // Confirm the forwarded message also matches the source message.
633 EXPECT_EQ(pi1_context->queue_index, header.queue_index());
634 EXPECT_EQ(pi1_context->monotonic_event_time,
635 header_monotonic_remote_time);
636 EXPECT_EQ(pi1_context->realtime_event_time,
637 header_realtime_remote_time);
638 });
639 }
Austin Schuh2f8fd752020-09-01 22:38:28 -0700640
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800641 // Start everything up. Pong is the only thing we don't know how to wait
642 // on, so start it first.
Austin Schuh7bc59052020-02-16 23:48:33 -0800643 std::thread pong_thread([&pong_event_loop]() { pong_event_loop.Run(); });
644
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800645 StartPi1Server();
646 StartPi1Client();
647 StartPi2Client();
648 StartPi2Server();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800649
650 // And go!
651 ping_event_loop.Run();
652
653 // Shut everyone else down
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800654 StopPi1Server();
655 StopPi1Client();
656 StopPi2Client();
657 StopPi2Server();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800658 pong_event_loop.Exit();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800659 pong_thread.join();
660
661 // Make sure we sent something.
662 EXPECT_GE(ping_count, 1);
663 // And got something back.
664 EXPECT_GE(pong_count, 1);
Austin Schuh7bc59052020-02-16 23:48:33 -0800665
666 // Confirm that we are estimating a monotonic offset on the client.
667 ASSERT_TRUE(client_statistics_fetcher.Fetch());
668
669 EXPECT_EQ(client_statistics_fetcher->connections()->size(), 1u);
670 EXPECT_EQ(client_statistics_fetcher->connections()
671 ->Get(0)
672 ->node()
673 ->name()
674 ->string_view(),
675 "pi1");
676
677 // Make sure the offset in one direction is less than a second.
678 EXPECT_GT(
679 client_statistics_fetcher->connections()->Get(0)->monotonic_offset(), 0);
680 EXPECT_LT(
681 client_statistics_fetcher->connections()->Get(0)->monotonic_offset(),
682 1000000000);
683
684 EXPECT_GE(pi1_server_statistics_count, 2);
685 EXPECT_GE(pi2_server_statistics_count, 2);
686 EXPECT_GE(pi1_client_statistics_count, 2);
687 EXPECT_GE(pi2_client_statistics_count, 2);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700688
689 // Confirm we got timestamps back!
690 EXPECT_TRUE(message_header_fetcher1.Fetch());
691 EXPECT_TRUE(message_header_fetcher2.Fetch());
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800692}
693
Austin Schuh5344c352020-04-12 17:04:26 -0700694// Test that the client disconnecting triggers the server offsets on both sides
695// to clear.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800696TEST_P(MessageBridgeParameterizedTest, ClientRestart) {
Austin Schuh5344c352020-04-12 17:04:26 -0700697 // This is rather annoying to set up. We need to start up a client and
698 // server, on the same node, but get them to think that they are on different
699 // nodes.
700 //
701 // We need the client to not post directly to "/test" like it would in a
702 // real system, otherwise we will re-send the ping message... So, use an
703 // application specific map to have the client post somewhere else.
704 //
705 // To top this all off, each of these needs to be done with a ShmEventLoop,
706 // which needs to run in a separate thread... And it is really hard to get
707 // everything started up reliably. So just be super generous on timeouts and
708 // hope for the best. We can be more generous in the future if we need to.
709 //
710 // We are faking the application names by passing in --application_name=foo
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800711 OnPi1();
Austin Schuh5344c352020-04-12 17:04:26 -0700712
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800713 MakePi1Server();
714 MakePi1Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700715
716 // And build the app for testing.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800717 MakePi1Test();
Austin Schuh5344c352020-04-12 17:04:26 -0700718 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800719 pi1_test_event_loop->MakeFetcher<ServerStatistics>("/pi1/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700720
721 // Now do it for "raspberrypi2", the client.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800722 OnPi2();
723 MakePi2Server();
Austin Schuh5344c352020-04-12 17:04:26 -0700724
725 // And build the app for testing.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800726 MakePi2Test();
Austin Schuh5344c352020-04-12 17:04:26 -0700727 aos::Fetcher<ServerStatistics> pi2_server_statistics_fetcher =
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800728 pi2_test_event_loop->MakeFetcher<ServerStatistics>("/pi2/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700729
730 // Wait until we are connected, then send.
Austin Schuh5344c352020-04-12 17:04:26 -0700731
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800732 StartPi1Test();
733 StartPi2Test();
734 StartPi1Server();
735 StartPi1Client();
736 StartPi2Server();
Austin Schuh5344c352020-04-12 17:04:26 -0700737
738 {
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800739 MakePi2Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700740
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800741 RunPi2Client(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700742
743 // Now confirm we are synchronized.
744 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
745 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
746
747 const ServerConnection *const pi1_connection =
748 pi1_server_statistics_fetcher->connections()->Get(0);
749 const ServerConnection *const pi2_connection =
750 pi2_server_statistics_fetcher->connections()->Get(0);
751
752 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
753 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
754 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
755 chrono::milliseconds(1));
756 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
757 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800758 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700759
760 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
761 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
762 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
763 chrono::milliseconds(1));
764 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
765 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800766 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800767
768 StopPi2Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700769 }
770
771 std::this_thread::sleep_for(std::chrono::seconds(2));
772
773 {
774 // Now confirm we are un-synchronized.
775 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
776 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
777 const ServerConnection *const pi1_connection =
778 pi1_server_statistics_fetcher->connections()->Get(0);
779 const ServerConnection *const pi2_connection =
780 pi2_server_statistics_fetcher->connections()->Get(0);
781
782 EXPECT_EQ(pi1_connection->state(), State::DISCONNECTED);
783 EXPECT_FALSE(pi1_connection->has_monotonic_offset());
Austin Schuh20ac95d2020-12-05 17:24:19 -0800784 EXPECT_FALSE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700785 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
786 EXPECT_FALSE(pi2_connection->has_monotonic_offset());
Austin Schuh20ac95d2020-12-05 17:24:19 -0800787 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700788 }
789
790 {
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800791 MakePi2Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700792 // And go!
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800793 RunPi2Client(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700794
795 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
796 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
797
798 // Now confirm we are synchronized again.
799 const ServerConnection *const pi1_connection =
800 pi1_server_statistics_fetcher->connections()->Get(0);
801 const ServerConnection *const pi2_connection =
802 pi2_server_statistics_fetcher->connections()->Get(0);
803
804 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
805 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
806 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
807 chrono::milliseconds(1));
808 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
809 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800810 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700811
812 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
813 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
814 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
815 chrono::milliseconds(1));
816 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
817 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800818 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800819
820 StopPi2Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700821 }
822
823 // Shut everyone else down
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800824 StopPi1Server();
825 StopPi1Client();
826 StopPi2Server();
827 StopPi1Test();
828 StopPi2Test();
Austin Schuh5344c352020-04-12 17:04:26 -0700829}
830
831// Test that the server disconnecting triggers the server offsets on the other
832// side to clear, along with the other client.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800833TEST_P(MessageBridgeParameterizedTest, ServerRestart) {
Austin Schuh5344c352020-04-12 17:04:26 -0700834 // This is rather annoying to set up. We need to start up a client and
835 // server, on the same node, but get them to think that they are on different
836 // nodes.
837 //
838 // We need the client to not post directly to "/test" like it would in a
839 // real system, otherwise we will re-send the ping message... So, use an
840 // application specific map to have the client post somewhere else.
841 //
842 // To top this all off, each of these needs to be done with a ShmEventLoop,
843 // which needs to run in a separate thread... And it is really hard to get
844 // everything started up reliably. So just be super generous on timeouts and
845 // hope for the best. We can be more generous in the future if we need to.
846 //
847 // We are faking the application names by passing in --application_name=foo
Austin Schuh5344c352020-04-12 17:04:26 -0700848 // Force ourselves to be "raspberrypi" and allocate everything.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800849 OnPi1();
850 MakePi1Server();
851 MakePi1Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700852
853 // And build the app for testing.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800854 MakePi1Test();
Austin Schuh5344c352020-04-12 17:04:26 -0700855 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800856 pi1_test_event_loop->MakeFetcher<ServerStatistics>("/pi1/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700857 aos::Fetcher<ClientStatistics> pi1_client_statistics_fetcher =
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800858 pi1_test_event_loop->MakeFetcher<ClientStatistics>("/pi1/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700859
860 // Now do it for "raspberrypi2", the client.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800861 OnPi2();
862 MakePi2Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700863
864 // And build the app for testing.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800865 MakePi2Test();
Austin Schuh5344c352020-04-12 17:04:26 -0700866 aos::Fetcher<ServerStatistics> pi2_server_statistics_fetcher =
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800867 pi2_test_event_loop->MakeFetcher<ServerStatistics>("/pi2/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700868
869 // Start everything up. Pong is the only thing we don't know how to wait on,
870 // so start it first.
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800871 StartPi1Test();
872 StartPi2Test();
873 StartPi1Server();
874 StartPi1Client();
875 StartPi2Client();
Austin Schuh5344c352020-04-12 17:04:26 -0700876
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800877 // Confirm both client and server statistics messages have decent offsets in
878 // them.
Austin Schuh5344c352020-04-12 17:04:26 -0700879
880 {
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800881 MakePi2Server();
Austin Schuh5344c352020-04-12 17:04:26 -0700882
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800883 RunPi2Server(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700884
885 // Now confirm we are synchronized.
886 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
887 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
888
889 const ServerConnection *const pi1_connection =
890 pi1_server_statistics_fetcher->connections()->Get(0);
891 const ServerConnection *const pi2_connection =
892 pi2_server_statistics_fetcher->connections()->Get(0);
893
894 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
895 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
896 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
897 chrono::milliseconds(1));
898 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
899 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800900 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700901
902 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
903 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
904 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
905 chrono::milliseconds(1));
906 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
907 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800908 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800909
910 StopPi2Server();
Austin Schuh5344c352020-04-12 17:04:26 -0700911 }
912
913 std::this_thread::sleep_for(std::chrono::seconds(2));
914
915 {
916 // And confirm we are unsynchronized.
917 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
918 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
919
920 const ServerConnection *const pi1_server_connection =
921 pi1_server_statistics_fetcher->connections()->Get(0);
922 const ClientConnection *const pi1_client_connection =
923 pi1_client_statistics_fetcher->connections()->Get(0);
924
925 EXPECT_EQ(pi1_server_connection->state(), State::CONNECTED);
926 EXPECT_FALSE(pi1_server_connection->has_monotonic_offset());
Austin Schuh20ac95d2020-12-05 17:24:19 -0800927 EXPECT_TRUE(pi1_server_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700928 EXPECT_EQ(pi1_client_connection->state(), State::DISCONNECTED);
929 EXPECT_FALSE(pi1_client_connection->has_monotonic_offset());
930 }
931
932 {
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800933 MakePi2Server();
Austin Schuh5344c352020-04-12 17:04:26 -0700934
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800935 RunPi2Server(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700936
937 // And confirm we are synchronized again.
938 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
939 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
940
941 const ServerConnection *const pi1_connection =
942 pi1_server_statistics_fetcher->connections()->Get(0);
943 const ServerConnection *const pi2_connection =
944 pi2_server_statistics_fetcher->connections()->Get(0);
945
946 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
947 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
948 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
949 chrono::milliseconds(1));
950 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
951 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800952 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700953
954 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
955 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
956 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
957 chrono::milliseconds(1));
958 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
959 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800960 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800961
962 StopPi2Server();
Austin Schuh5344c352020-04-12 17:04:26 -0700963 }
964
965 // Shut everyone else down
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800966 StopPi1Server();
967 StopPi1Client();
968 StopPi2Client();
969 StopPi1Test();
970 StopPi2Test();
Austin Schuh5344c352020-04-12 17:04:26 -0700971}
972
Austin Schuh4889b182020-11-18 19:11:56 -0800973// TODO(austin): The above test confirms that the external state does the right
Austin Schuh5344c352020-04-12 17:04:26 -0700974// thing, but doesn't confirm that the internal state does. We either need to
975// expose a way to check the state in a thread-safe way, or need a way to jump
976// time for one node to do that.
977
Austin Schuh4889b182020-11-18 19:11:56 -0800978void SendPing(aos::Sender<examples::Ping> *sender, int value) {
979 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
980 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
981 ping_builder.add_value(value);
982 builder.Send(ping_builder.Finish());
983}
984
985// Tests that when a message is sent before the bridge starts up, but is
986// configured as reliable, we forward it. Confirm this survives a client reset.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800987TEST_P(MessageBridgeParameterizedTest, ReliableSentBeforeClientStartup) {
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800988 OnPi1();
Austin Schuh4889b182020-11-18 19:11:56 -0800989
990 FLAGS_application_name = "sender";
Austin Schuhf466ab52021-02-16 22:00:38 -0800991 aos::ShmEventLoop send_event_loop(&config.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800992 aos::Sender<examples::Ping> ping_sender =
993 send_event_loop.MakeSender<examples::Ping>("/test");
994 SendPing(&ping_sender, 1);
995 aos::Sender<examples::Ping> unreliable_ping_sender =
996 send_event_loop.MakeSender<examples::Ping>("/unreliable");
997 SendPing(&unreliable_ping_sender, 1);
998
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800999 MakePi1Server();
1000 MakePi1Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001001
1002 FLAGS_application_name = "pi1_timestamp";
Austin Schuhf466ab52021-02-16 22:00:38 -08001003 aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config.message());
Austin Schuh4889b182020-11-18 19:11:56 -08001004
1005 // Now do it for "raspberrypi2", the client.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001006 OnPi2();
Austin Schuh4889b182020-11-18 19:11:56 -08001007
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001008 MakePi2Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001009
Austin Schuhf466ab52021-02-16 22:00:38 -08001010 aos::ShmEventLoop receive_event_loop(&config.message());
Austin Schuh4889b182020-11-18 19:11:56 -08001011 aos::Fetcher<examples::Ping> ping_fetcher =
1012 receive_event_loop.MakeFetcher<examples::Ping>("/test");
1013 aos::Fetcher<examples::Ping> unreliable_ping_fetcher =
1014 receive_event_loop.MakeFetcher<examples::Ping>("/unreliable");
1015 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
1016 receive_event_loop.MakeFetcher<ClientStatistics>("/pi2/aos");
1017
1018 const size_t ping_channel_index = configuration::ChannelIndex(
1019 receive_event_loop.configuration(), ping_fetcher.channel());
1020
1021 std::atomic<int> ping_timestamp_count{0};
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001022 const std::string channel_name =
1023 shared() ? "/pi1/aos/remote_timestamps/pi2"
1024 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping";
Austin Schuh4889b182020-11-18 19:11:56 -08001025 pi1_remote_timestamp_event_loop.MakeWatcher(
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001026 channel_name, [this, channel_name, ping_channel_index,
1027 &ping_timestamp_count](const RemoteMessage &header) {
Austin Schuh61e973f2021-02-21 21:43:56 -08001028 VLOG(1) << channel_name << " RemoteMessage "
Austin Schuh0de30f32020-12-06 12:44:28 -08001029 << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -08001030 EXPECT_TRUE(header.has_boot_uuid());
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001031 if (shared() && header.channel_index() != ping_channel_index) {
1032 return;
Austin Schuh4889b182020-11-18 19:11:56 -08001033 }
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001034 CHECK_EQ(header.channel_index(), ping_channel_index);
1035 ++ping_timestamp_count;
Austin Schuh4889b182020-11-18 19:11:56 -08001036 });
1037
1038 // Before everything starts up, confirm there is no message.
1039 EXPECT_FALSE(ping_fetcher.Fetch());
1040 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
1041
1042 // Spin up the persistant pieces.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001043 StartPi1Server();
1044 StartPi1Client();
1045 StartPi2Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001046
1047 // Event used to wait for the timestamp counting thread to start.
1048 aos::Event event;
1049 std::thread pi1_remote_timestamp_thread(
1050 [&pi1_remote_timestamp_event_loop, &event]() {
1051 pi1_remote_timestamp_event_loop.OnRun([&event]() { event.Set(); });
1052 pi1_remote_timestamp_event_loop.Run();
1053 });
1054
1055 event.Wait();
1056
1057 {
1058 // Now, spin up a client for 2 seconds.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001059 MakePi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001060
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001061 RunPi2Client(chrono::milliseconds(2050));
Austin Schuh4889b182020-11-18 19:11:56 -08001062
1063 // Confirm there is no detected duplicate packet.
1064 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1065 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1066 ->Get(0)
1067 ->duplicate_packets(),
1068 0u);
1069
Austin Schuhe61d4382021-03-31 21:33:02 -07001070 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1071 ->Get(0)
1072 ->partial_deliveries(),
1073 0u);
1074
Austin Schuh4889b182020-11-18 19:11:56 -08001075 EXPECT_TRUE(ping_fetcher.Fetch());
1076 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
1077 EXPECT_EQ(ping_timestamp_count, 1);
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001078
1079 StopPi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001080 }
1081
1082 {
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001083 // Now, spin up a client for 2 seconds.
1084 MakePi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001085
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001086 RunPi2Client(chrono::milliseconds(5050));
Austin Schuh4889b182020-11-18 19:11:56 -08001087
1088 // Confirm we detect the duplicate packet correctly.
1089 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1090 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1091 ->Get(0)
1092 ->duplicate_packets(),
1093 1u);
1094
Austin Schuhe61d4382021-03-31 21:33:02 -07001095 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1096 ->Get(0)
1097 ->partial_deliveries(),
1098 0u);
1099
Austin Schuh4889b182020-11-18 19:11:56 -08001100 EXPECT_EQ(ping_timestamp_count, 1);
1101 EXPECT_FALSE(ping_fetcher.Fetch());
1102 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001103
1104 StopPi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001105 }
1106
1107 // Shut everyone else down
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001108 StopPi1Client();
1109 StopPi2Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001110 pi1_remote_timestamp_event_loop.Exit();
1111 pi1_remote_timestamp_thread.join();
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001112 StopPi1Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001113}
1114
1115// Tests that when a message is sent before the bridge starts up, but is
1116// configured as reliable, we forward it. Confirm this works across server
1117// resets.
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001118TEST_P(MessageBridgeParameterizedTest, ReliableSentBeforeServerStartup) {
Austin Schuh4889b182020-11-18 19:11:56 -08001119 // Now do it for "raspberrypi2", the client.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001120 OnPi2();
Austin Schuh4889b182020-11-18 19:11:56 -08001121
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001122 MakePi2Server();
1123 MakePi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001124
Austin Schuhf466ab52021-02-16 22:00:38 -08001125 aos::ShmEventLoop receive_event_loop(&config.message());
Austin Schuh4889b182020-11-18 19:11:56 -08001126 aos::Fetcher<examples::Ping> ping_fetcher =
1127 receive_event_loop.MakeFetcher<examples::Ping>("/test");
1128 aos::Fetcher<examples::Ping> unreliable_ping_fetcher =
1129 receive_event_loop.MakeFetcher<examples::Ping>("/unreliable");
1130 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
1131 receive_event_loop.MakeFetcher<ClientStatistics>("/pi2/aos");
1132
Austin Schuh4889b182020-11-18 19:11:56 -08001133 // Force ourselves to be "raspberrypi" and allocate everything.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001134 OnPi1();
Austin Schuh4889b182020-11-18 19:11:56 -08001135
1136 FLAGS_application_name = "sender";
Austin Schuhf466ab52021-02-16 22:00:38 -08001137 aos::ShmEventLoop send_event_loop(&config.message());
Austin Schuh4889b182020-11-18 19:11:56 -08001138 aos::Sender<examples::Ping> ping_sender =
1139 send_event_loop.MakeSender<examples::Ping>("/test");
1140 {
1141 aos::Sender<examples::Ping>::Builder builder = ping_sender.MakeBuilder();
1142 examples::Ping::Builder ping_builder =
1143 builder.MakeBuilder<examples::Ping>();
1144 ping_builder.add_value(1);
1145 builder.Send(ping_builder.Finish());
1146 }
1147
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001148 MakePi1Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001149
1150 FLAGS_application_name = "pi1_timestamp";
Austin Schuhf466ab52021-02-16 22:00:38 -08001151 aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config.message());
Austin Schuh4889b182020-11-18 19:11:56 -08001152
1153 const size_t ping_channel_index = configuration::ChannelIndex(
1154 receive_event_loop.configuration(), ping_fetcher.channel());
1155
1156 std::atomic<int> ping_timestamp_count{0};
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001157 const std::string channel_name =
1158 shared() ? "/pi1/aos/remote_timestamps/pi2"
1159 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping";
Austin Schuh4889b182020-11-18 19:11:56 -08001160 pi1_remote_timestamp_event_loop.MakeWatcher(
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001161 channel_name, [this, channel_name, ping_channel_index,
1162 &ping_timestamp_count](const RemoteMessage &header) {
1163 VLOG(1) << channel_name << " RemoteMessage "
Austin Schuh0de30f32020-12-06 12:44:28 -08001164 << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -08001165 EXPECT_TRUE(header.has_boot_uuid());
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001166 if (shared() && header.channel_index() != ping_channel_index) {
1167 return;
Austin Schuh4889b182020-11-18 19:11:56 -08001168 }
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001169 CHECK_EQ(header.channel_index(), ping_channel_index);
1170 ++ping_timestamp_count;
Austin Schuh4889b182020-11-18 19:11:56 -08001171 });
1172
1173 // Before everything starts up, confirm there is no message.
1174 EXPECT_FALSE(ping_fetcher.Fetch());
1175 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
1176
1177 // Spin up the persistant pieces.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001178 StartPi1Client();
1179 StartPi2Server();
1180 StartPi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001181
1182 // Event used to wait for the timestamp counting thread to start.
1183 aos::Event event;
1184 std::thread pi1_remote_timestamp_thread(
1185 [&pi1_remote_timestamp_event_loop, &event]() {
1186 pi1_remote_timestamp_event_loop.OnRun([&event]() { event.Set(); });
1187 pi1_remote_timestamp_event_loop.Run();
1188 });
1189
1190 event.Wait();
1191
1192 {
1193 // Now, spin up a server for 2 seconds.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001194 MakePi1Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001195
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001196 RunPi1Server(chrono::milliseconds(2050));
Austin Schuh4889b182020-11-18 19:11:56 -08001197
1198 // Confirm there is no detected duplicate packet.
1199 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1200 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1201 ->Get(0)
1202 ->duplicate_packets(),
1203 0u);
1204
Austin Schuhe61d4382021-03-31 21:33:02 -07001205 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1206 ->Get(0)
1207 ->partial_deliveries(),
1208 0u);
1209
Austin Schuh4889b182020-11-18 19:11:56 -08001210 EXPECT_TRUE(ping_fetcher.Fetch());
1211 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
1212 EXPECT_EQ(ping_timestamp_count, 1);
1213 LOG(INFO) << "Shutting down first pi1 MessageBridgeServer";
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001214
1215 StopPi1Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001216 }
1217
1218 {
1219 // Now, spin up a second server for 2 seconds.
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001220 MakePi1Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001221
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001222 RunPi1Server(chrono::milliseconds(2050));
Austin Schuh4889b182020-11-18 19:11:56 -08001223
1224 // Confirm we detect the duplicate packet correctly.
1225 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1226 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1227 ->Get(0)
1228 ->duplicate_packets(),
1229 1u);
1230
Austin Schuhe61d4382021-03-31 21:33:02 -07001231
1232 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1233 ->Get(0)
1234 ->partial_deliveries(),
1235 0u);
1236
Austin Schuh4889b182020-11-18 19:11:56 -08001237 EXPECT_EQ(ping_timestamp_count, 1);
1238 EXPECT_FALSE(ping_fetcher.Fetch());
1239 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001240
1241 StopPi1Server();
Austin Schuh4889b182020-11-18 19:11:56 -08001242 }
1243
1244 // Shut everyone else down
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001245 StopPi1Client();
1246 StopPi2Server();
1247 StopPi2Client();
Austin Schuh4889b182020-11-18 19:11:56 -08001248 pi1_remote_timestamp_event_loop.Exit();
1249 pi1_remote_timestamp_thread.join();
Austin Schuh4889b182020-11-18 19:11:56 -08001250}
1251
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -07001252INSTANTIATE_TEST_SUITE_P(
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001253 MessageBridgeTests, MessageBridgeParameterizedTest,
1254 ::testing::Values(
1255 Param{"message_bridge_test_combined_timestamps_common_config.json",
1256 true},
1257 Param{"message_bridge_test_common_config.json", false}));
1258
Austin Schuhe84c3ed2019-12-14 15:29:48 -08001259} // namespace testing
1260} // namespace message_bridge
1261} // namespace aos