blob: 350cf267ba6d80aaf49b3c87da26565baf7e1a0a [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"
Philipp Schrader790cb542023-07-05 21:06:52 -07005#include "gtest/gtest.h"
6
Austin Schuhe84c3ed2019-12-14 15:29:48 -08007#include "aos/events/ping_generated.h"
8#include "aos/events/pong_generated.h"
Brian Silverman7b266d92021-02-17 21:24:02 -08009#include "aos/ipc_lib/event.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -080010#include "aos/network/message_bridge_client_lib.h"
Austin Schuh89f23e32023-05-15 17:06:43 -070011#include "aos/network/message_bridge_protocol.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -080012#include "aos/network/message_bridge_server_lib.h"
James Kuszmaul79b2f032023-06-02 21:02:27 -070013#include "aos/network/message_bridge_test_lib.h"
Jim Ostrowski2192ddb2020-06-24 19:07:31 -070014#include "aos/network/team_number.h"
Austin Schuhb0e439d2023-05-15 10:55:40 -070015#include "aos/sha256.h"
Austin Schuh373f1762021-06-02 21:07:09 -070016#include "aos/testing/path.h"
Austin Schuhe991fe22020-11-18 16:53:39 -080017#include "aos/util/file.h"
Austin Schuhe84c3ed2019-12-14 15:29:48 -080018
Stephan Pleinesf63bde82024-01-13 15:59:33 -080019namespace aos::message_bridge::testing {
Austin Schuhe84c3ed2019-12-14 15:29:48 -080020
James Kuszmaul79b2f032023-06-02 21:02:27 -070021// Note: All of these tests spin up ShmEventLoop's in separate threads to allow
22// us to run the "real" message bridge. This requires extra threading and timing
23// coordination to make happen, which is the reason for some of the extra
24// complexity in these tests.
Austin Schuhe991fe22020-11-18 16:53:39 -080025
Austin Schuhe84c3ed2019-12-14 15:29:48 -080026// Test that we can send a ping message over sctp and receive it.
Austin Schuh36a2c3e2021-02-18 22:28:38 -080027TEST_P(MessageBridgeParameterizedTest, PingPong) {
Austin Schuhe84c3ed2019-12-14 15:29:48 -080028 // This is rather annoying to set up. We need to start up a client and
29 // server, on the same node, but get them to think that they are on different
30 // nodes.
31 //
32 // We then get to wait until they are connected.
33 //
34 // After they are connected, we send a Ping message.
35 //
36 // On the other end, we receive a Pong message.
37 //
38 // But, we need the client to not post directly to "/test" like it would in a
39 // real system, otherwise we will re-send the ping message... So, use an
40 // application specific map to have the client post somewhere else.
41 //
42 // To top this all off, each of these needs to be done with a ShmEventLoop,
43 // which needs to run in a separate thread... And it is really hard to get
44 // everything started up reliably. So just be super generous on timeouts and
45 // hope for the best. We can be more generous in the future if we need to.
46 //
47 // We are faking the application names by passing in --application_name=foo
Kiran Mohan38648482024-03-15 15:56:14 -070048 pi1_.OnPi();
Austin Schuhe84c3ed2019-12-14 15:29:48 -080049 // Force ourselves to be "raspberrypi" and allocate everything.
Austin Schuh2f8fd752020-09-01 22:38:28 -070050
Kiran Mohan38648482024-03-15 15:56:14 -070051 pi1_.MakeServer();
52 pi1_.MakeClient();
Austin Schuhe84c3ed2019-12-14 15:29:48 -080053
Austin Schuh89e1e9c2023-05-15 14:38:44 -070054 const std::string long_data = std::string(10000, 'a');
55
Austin Schuhe84c3ed2019-12-14 15:29:48 -080056 // And build the app which sends the pings.
57 FLAGS_application_name = "ping";
Kiran Mohan38648482024-03-15 15:56:14 -070058 aos::ShmEventLoop ping_event_loop(&config_.message());
Austin Schuhe84c3ed2019-12-14 15:29:48 -080059 aos::Sender<examples::Ping> ping_sender =
60 ping_event_loop.MakeSender<examples::Ping>("/test");
61
Kiran Mohan38648482024-03-15 15:56:14 -070062 aos::ShmEventLoop pi1_test_event_loop_(&pi1_.config_.message());
Austin Schuh0de30f32020-12-06 12:44:28 -080063 aos::Fetcher<RemoteMessage> message_header_fetcher1 =
Kiran Mohan38648482024-03-15 15:56:14 -070064 pi1_test_event_loop_.MakeFetcher<RemoteMessage>(
Austin Schuh36a2c3e2021-02-18 22:28:38 -080065 shared() ? "/pi1/aos/remote_timestamps/pi2"
66 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping");
Austin Schuh2f8fd752020-09-01 22:38:28 -070067
68 // Fetchers for confirming the remote timestamps made it.
69 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
70 ping_event_loop.MakeFetcher<examples::Ping>("/test");
71 aos::Fetcher<Timestamp> pi1_on_pi1_timestamp_fetcher =
72 ping_event_loop.MakeFetcher<Timestamp>("/aos");
73
Austin Schuhe84c3ed2019-12-14 15:29:48 -080074 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -070075 pi2_.OnPi();
Austin Schuh2f8fd752020-09-01 22:38:28 -070076
Kiran Mohan38648482024-03-15 15:56:14 -070077 pi2_.MakeClient();
78 pi2_.MakeServer();
Austin Schuhe84c3ed2019-12-14 15:29:48 -080079
80 // And build the app which sends the pongs.
81 FLAGS_application_name = "pong";
Kiran Mohan38648482024-03-15 15:56:14 -070082 aos::ShmEventLoop pong_event_loop(&config_.message());
Austin Schuhe84c3ed2019-12-14 15:29:48 -080083
Austin Schuh7bc59052020-02-16 23:48:33 -080084 // And build the app for testing.
85 FLAGS_application_name = "test";
Kiran Mohan38648482024-03-15 15:56:14 -070086 aos::ShmEventLoop test_event_loop(&config_.message());
Austin Schuh7bc59052020-02-16 23:48:33 -080087
88 aos::Fetcher<ClientStatistics> client_statistics_fetcher =
89 test_event_loop.MakeFetcher<ClientStatistics>("/aos");
Austin Schuh0de30f32020-12-06 12:44:28 -080090 aos::Fetcher<RemoteMessage> message_header_fetcher2 =
91 test_event_loop.MakeFetcher<RemoteMessage>(
Austin Schuh36a2c3e2021-02-18 22:28:38 -080092 shared() ? "/pi2/aos/remote_timestamps/pi1"
93 : "/pi2/aos/remote_timestamps/pi1/pi2/aos/"
94 "aos-message_bridge-Timestamp");
Austin Schuh2f8fd752020-09-01 22:38:28 -070095
96 // Event loop for fetching data delivered to pi2 from pi1 to match up
97 // messages.
Kiran Mohan38648482024-03-15 15:56:14 -070098 aos::ShmEventLoop delivered_messages_event_loop(&config_.message());
Austin Schuh2f8fd752020-09-01 22:38:28 -070099 aos::Fetcher<Timestamp> pi1_on_pi2_timestamp_fetcher =
100 delivered_messages_event_loop.MakeFetcher<Timestamp>("/pi1/aos");
101 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
102 delivered_messages_event_loop.MakeFetcher<examples::Ping>("/test");
103 EXPECT_FALSE(ping_on_pi2_fetcher.Fetch());
104 EXPECT_FALSE(pi1_on_pi2_timestamp_fetcher.Fetch());
Austin Schuh7bc59052020-02-16 23:48:33 -0800105
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800106 // Count the pongs.
107 int pong_count = 0;
Austin Schuh8902fa52021-03-14 22:39:24 -0700108 pong_event_loop.MakeWatcher("/test", [&pong_count, &pong_event_loop,
109 this](const examples::Ping &ping) {
Kiran Mohan38648482024-03-15 15:56:14 -0700110 EXPECT_EQ(pong_event_loop.context().source_boot_uuid, pi1_.boot_uuid_);
Austin Schuh8902fa52021-03-14 22:39:24 -0700111 ++pong_count;
112 VLOG(1) << "Got ping back " << FlatbufferToJson(&ping);
113 });
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800114
115 FLAGS_override_hostname = "";
116
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800117 // Wait until we are connected, then send.
118 int ping_count = 0;
Austin Schuh7bc59052020-02-16 23:48:33 -0800119 int pi1_server_statistics_count = 0;
Philipp Schrader790cb542023-07-05 21:06:52 -0700120 ping_event_loop.MakeWatcher(
121 "/pi1/aos",
122 [this, &ping_count, &ping_sender, &pi1_server_statistics_count,
123 &long_data](const ServerStatistics &stats) {
124 VLOG(1) << "/pi1/aos ServerStatistics " << FlatbufferToJson(&stats);
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800125
Philipp Schrader790cb542023-07-05 21:06:52 -0700126 ASSERT_TRUE(stats.has_connections());
127 EXPECT_EQ(stats.connections()->size(), 1);
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800128
Philipp Schrader790cb542023-07-05 21:06:52 -0700129 bool connected = false;
130 for (const ServerConnection *connection : *stats.connections()) {
131 // Confirm that we are estimating the server time offset correctly. It
132 // should be about 0 since we are on the same machine here.
133 if (connection->has_monotonic_offset()) {
134 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
135 chrono::milliseconds(1));
136 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
137 chrono::milliseconds(-1));
138 ++pi1_server_statistics_count;
139 }
Austin Schuh7bc59052020-02-16 23:48:33 -0800140
Philipp Schrader790cb542023-07-05 21:06:52 -0700141 if (connection->node()->name()->string_view() ==
Kiran Mohan38648482024-03-15 15:56:14 -0700142 pi2_.client_event_loop_->node()->name()->string_view()) {
Philipp Schrader790cb542023-07-05 21:06:52 -0700143 if (connection->state() == State::CONNECTED) {
144 EXPECT_TRUE(connection->has_boot_uuid());
145 EXPECT_EQ(connection->connection_count(), 1u);
146 EXPECT_LT(monotonic_clock::time_point(chrono::nanoseconds(
147 connection->connected_since_time())),
148 monotonic_clock::now());
149 connected = true;
150 } else {
151 EXPECT_FALSE(connection->has_connection_count());
152 EXPECT_FALSE(connection->has_connected_since_time());
153 }
154 }
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800155 }
156
Philipp Schrader790cb542023-07-05 21:06:52 -0700157 if (connected) {
158 VLOG(1) << "Connected! Sent ping.";
159 auto builder = ping_sender.MakeBuilder();
160 builder.fbb()->CreateString(long_data);
161 examples::Ping::Builder ping_builder =
162 builder.MakeBuilder<examples::Ping>();
163 ping_builder.add_value(ping_count + 971);
164 EXPECT_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
165 ++ping_count;
166 }
167 });
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800168
Austin Schuh7bc59052020-02-16 23:48:33 -0800169 // Confirm both client and server statistics messages have decent offsets in
170 // them.
171 int pi2_server_statistics_count = 0;
Austin Schuh196a4452020-03-15 23:12:03 -0700172 pong_event_loop.MakeWatcher("/pi2/aos", [&pi2_server_statistics_count](
Austin Schuh7bc59052020-02-16 23:48:33 -0800173 const ServerStatistics &stats) {
Austin Schuh1ca49e92020-12-11 00:01:27 -0800174 VLOG(1) << "/pi2/aos ServerStatistics " << FlatbufferToJson(&stats);
Austin Schuh7bc59052020-02-16 23:48:33 -0800175 for (const ServerConnection *connection : *stats.connections()) {
176 if (connection->has_monotonic_offset()) {
177 ++pi2_server_statistics_count;
178 // Confirm that we are estimating the server time offset correctly. It
179 // should be about 0 since we are on the same machine here.
180 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
181 chrono::milliseconds(1));
182 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
183 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800184 EXPECT_TRUE(connection->has_boot_uuid());
Austin Schuh7bc59052020-02-16 23:48:33 -0800185 }
Austin Schuh367a7f42021-11-23 23:04:36 -0800186
187 if (connection->state() == State::CONNECTED) {
188 EXPECT_EQ(connection->connection_count(), 1u);
189 EXPECT_LT(monotonic_clock::time_point(
190 chrono::nanoseconds(connection->connected_since_time())),
191 monotonic_clock::now());
192 } else {
Austin Schuha4e616a2023-05-15 17:59:30 -0700193 // If we have been connected, we expect the connection count to stay
194 // around.
195 if (pi2_server_statistics_count > 0) {
196 EXPECT_TRUE(connection->has_connection_count());
197 EXPECT_EQ(connection->connection_count(), 1u);
198 } else {
199 EXPECT_FALSE(connection->has_connection_count());
200 }
Austin Schuh367a7f42021-11-23 23:04:36 -0800201 EXPECT_FALSE(connection->has_connected_since_time());
202 }
Austin Schuh7bc59052020-02-16 23:48:33 -0800203 }
204 });
205
206 int pi1_client_statistics_count = 0;
Austin Schuh367a7f42021-11-23 23:04:36 -0800207 int pi1_connected_client_statistics_count = 0;
208 ping_event_loop.MakeWatcher(
209 "/pi1/aos",
210 [&pi1_client_statistics_count,
211 &pi1_connected_client_statistics_count](const ClientStatistics &stats) {
212 VLOG(1) << "/pi1/aos ClientStatistics " << FlatbufferToJson(&stats);
Austin Schuh7bc59052020-02-16 23:48:33 -0800213
Austin Schuh367a7f42021-11-23 23:04:36 -0800214 for (const ClientConnection *connection : *stats.connections()) {
215 if (connection->has_monotonic_offset()) {
216 ++pi1_client_statistics_count;
217 // It takes at least 10 microseconds to send a message between the
218 // client and server. The min (filtered) time shouldn't be over 10
219 // milliseconds on localhost. This might have to bump up if this is
220 // proving flaky.
221 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
222 chrono::milliseconds(10))
223 << " " << connection->monotonic_offset()
224 << "ns vs 10000ns on iteration " << pi1_client_statistics_count;
225 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
226 chrono::microseconds(10))
227 << " " << connection->monotonic_offset()
228 << "ns vs 10000ns on iteration " << pi1_client_statistics_count;
229 }
230 if (connection->state() == State::CONNECTED) {
231 EXPECT_EQ(connection->connection_count(), 1u);
232 EXPECT_LT(monotonic_clock::time_point(chrono::nanoseconds(
233 connection->connected_since_time())),
234 monotonic_clock::now());
235 // The first Connected message may not have a UUID in it since no
236 // data has flown. That's fine.
237 if (pi1_connected_client_statistics_count > 0) {
238 EXPECT_TRUE(connection->has_boot_uuid())
239 << ": " << aos::FlatbufferToJson(connection);
240 }
241 ++pi1_connected_client_statistics_count;
242 } else {
243 EXPECT_FALSE(connection->has_connection_count());
244 EXPECT_FALSE(connection->has_connected_since_time());
245 }
246 }
247 });
Austin Schuh7bc59052020-02-16 23:48:33 -0800248
249 int pi2_client_statistics_count = 0;
Austin Schuh367a7f42021-11-23 23:04:36 -0800250 int pi2_connected_client_statistics_count = 0;
251 pong_event_loop.MakeWatcher(
252 "/pi2/aos",
253 [&pi2_client_statistics_count,
254 &pi2_connected_client_statistics_count](const ClientStatistics &stats) {
255 VLOG(1) << "/pi2/aos ClientStatistics " << FlatbufferToJson(&stats);
Austin Schuh7bc59052020-02-16 23:48:33 -0800256
Austin Schuh367a7f42021-11-23 23:04:36 -0800257 for (const ClientConnection *connection : *stats.connections()) {
258 if (connection->has_monotonic_offset()) {
259 ++pi2_client_statistics_count;
260 EXPECT_LT(chrono::nanoseconds(connection->monotonic_offset()),
261 chrono::milliseconds(10))
262 << ": got " << aos::FlatbufferToJson(connection);
263 EXPECT_GT(chrono::nanoseconds(connection->monotonic_offset()),
264 chrono::microseconds(10))
265 << ": got " << aos::FlatbufferToJson(connection);
266 }
267 if (connection->state() == State::CONNECTED) {
268 EXPECT_EQ(connection->connection_count(), 1u);
269 EXPECT_LT(monotonic_clock::time_point(chrono::nanoseconds(
270 connection->connected_since_time())),
271 monotonic_clock::now());
272 if (pi2_connected_client_statistics_count > 0) {
273 EXPECT_TRUE(connection->has_boot_uuid());
274 }
275 ++pi2_connected_client_statistics_count;
276 } else {
Austin Schuha4e616a2023-05-15 17:59:30 -0700277 if (pi2_connected_client_statistics_count == 0) {
278 EXPECT_FALSE(connection->has_connection_count())
279 << aos::FlatbufferToJson(&stats);
280 } else {
281 EXPECT_TRUE(connection->has_connection_count())
282 << aos::FlatbufferToJson(&stats);
283 EXPECT_EQ(connection->connection_count(), 1u);
284 }
Austin Schuh367a7f42021-11-23 23:04:36 -0800285 EXPECT_FALSE(connection->has_connected_since_time());
286 }
287 }
288 });
Austin Schuh7bc59052020-02-16 23:48:33 -0800289
Austin Schuh196a4452020-03-15 23:12:03 -0700290 ping_event_loop.MakeWatcher("/pi1/aos", [](const Timestamp &timestamp) {
Austin Schuh7bc59052020-02-16 23:48:33 -0800291 EXPECT_TRUE(timestamp.has_offsets());
Austin Schuh1ca49e92020-12-11 00:01:27 -0800292 VLOG(1) << "/pi1/aos Timestamp " << FlatbufferToJson(&timestamp);
Austin Schuh7bc59052020-02-16 23:48:33 -0800293 });
Austin Schuh196a4452020-03-15 23:12:03 -0700294 pong_event_loop.MakeWatcher("/pi2/aos", [](const Timestamp &timestamp) {
Austin Schuh7bc59052020-02-16 23:48:33 -0800295 EXPECT_TRUE(timestamp.has_offsets());
Austin Schuh1ca49e92020-12-11 00:01:27 -0800296 VLOG(1) << "/pi2/aos Timestamp " << FlatbufferToJson(&timestamp);
Austin Schuh7bc59052020-02-16 23:48:33 -0800297 });
298
Austin Schuh2f8fd752020-09-01 22:38:28 -0700299 // Find the channel index for both the /pi1/aos Timestamp channel and Ping
300 // channel.
301 const size_t pi1_timestamp_channel = configuration::ChannelIndex(
302 pong_event_loop.configuration(), pi1_on_pi2_timestamp_fetcher.channel());
303 const size_t ping_timestamp_channel =
304 configuration::ChannelIndex(delivered_messages_event_loop.configuration(),
305 ping_on_pi2_fetcher.channel());
306
307 for (const Channel *channel : *ping_event_loop.configuration()->channels()) {
308 VLOG(1) << "Channel "
309 << configuration::ChannelIndex(ping_event_loop.configuration(),
310 channel)
311 << " " << configuration::CleanedChannelToString(channel);
312 }
313
314 // For each remote timestamp we get back, confirm that it is either a ping
315 // message, or a timestamp we sent out. Also confirm that the timestamps are
316 // correct.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800317 for (std::pair<int, std::string> channel :
318 shared()
319 ? std::vector<std::pair<
320 int, std::string>>{{-1, "/pi1/aos/remote_timestamps/pi2"}}
321 : std::vector<std::pair<int, std::string>>{
322 {pi1_timestamp_channel,
323 "/pi1/aos/remote_timestamps/pi2/pi1/aos/"
324 "aos-message_bridge-Timestamp"},
325 {ping_timestamp_channel,
326 "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping"}}) {
327 ping_event_loop.MakeWatcher(
328 channel.second,
329 [pi1_timestamp_channel, ping_timestamp_channel, &ping_on_pi2_fetcher,
330 &ping_on_pi1_fetcher, &pi1_on_pi2_timestamp_fetcher,
331 &pi1_on_pi1_timestamp_fetcher,
332 channel_index = channel.first](const RemoteMessage &header) {
333 VLOG(1) << "/pi1/aos/remote_timestamps/pi2 RemoteMessage "
334 << aos::FlatbufferToJson(&header);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700335
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800336 EXPECT_TRUE(header.has_boot_uuid());
337 if (channel_index != -1) {
338 ASSERT_EQ(channel_index, header.channel_index());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700339 }
340
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800341 const aos::monotonic_clock::time_point header_monotonic_sent_time(
342 chrono::nanoseconds(header.monotonic_sent_time()));
343 const aos::realtime_clock::time_point header_realtime_sent_time(
344 chrono::nanoseconds(header.realtime_sent_time()));
345 const aos::monotonic_clock::time_point header_monotonic_remote_time(
346 chrono::nanoseconds(header.monotonic_remote_time()));
Austin Schuhac6d89e2024-03-27 14:56:09 -0700347 const aos::monotonic_clock::time_point
348 header_monotonic_remote_transmit_time(
349 chrono::nanoseconds(header.monotonic_remote_transmit_time()));
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800350 const aos::realtime_clock::time_point header_realtime_remote_time(
351 chrono::nanoseconds(header.realtime_remote_time()));
352
353 const Context *pi1_context = nullptr;
354 const Context *pi2_context = nullptr;
355
356 if (header.channel_index() == pi1_timestamp_channel) {
357 // Find the forwarded message.
358 while (pi1_on_pi2_timestamp_fetcher.context().monotonic_event_time <
359 header_monotonic_sent_time) {
360 ASSERT_TRUE(pi1_on_pi2_timestamp_fetcher.FetchNext());
361 }
362
363 // And the source message.
364 while (pi1_on_pi1_timestamp_fetcher.context().monotonic_event_time <
365 header_monotonic_remote_time) {
366 ASSERT_TRUE(pi1_on_pi1_timestamp_fetcher.FetchNext());
367 }
368
369 pi1_context = &pi1_on_pi1_timestamp_fetcher.context();
370 pi2_context = &pi1_on_pi2_timestamp_fetcher.context();
371 } else if (header.channel_index() == ping_timestamp_channel) {
372 // Find the forwarded message.
373 while (ping_on_pi2_fetcher.context().monotonic_event_time <
374 header_monotonic_sent_time) {
375 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
376 }
377
378 // And the source message.
379 while (ping_on_pi1_fetcher.context().monotonic_event_time <
380 header_monotonic_remote_time) {
381 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
382 }
383
384 pi1_context = &ping_on_pi1_fetcher.context();
385 pi2_context = &ping_on_pi2_fetcher.context();
386 } else {
387 LOG(FATAL) << "Unknown channel";
Austin Schuh2f8fd752020-09-01 22:38:28 -0700388 }
389
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800390 // Confirm the forwarded message has matching timestamps to the
391 // timestamps we got back.
392 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
393 EXPECT_EQ(pi2_context->monotonic_event_time,
394 header_monotonic_sent_time);
395 EXPECT_EQ(pi2_context->realtime_event_time,
396 header_realtime_sent_time);
397 EXPECT_EQ(pi2_context->realtime_remote_time,
398 header_realtime_remote_time);
399 EXPECT_EQ(pi2_context->monotonic_remote_time,
400 header_monotonic_remote_time);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700401
Austin Schuhac6d89e2024-03-27 14:56:09 -0700402 EXPECT_LT(header_monotonic_remote_transmit_time,
403 pi2_context->monotonic_event_time);
404 EXPECT_GT(header_monotonic_remote_transmit_time,
405 pi2_context->monotonic_remote_time);
406
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800407 // Confirm the forwarded message also matches the source message.
408 EXPECT_EQ(pi1_context->queue_index, header.queue_index());
409 EXPECT_EQ(pi1_context->monotonic_event_time,
410 header_monotonic_remote_time);
411 EXPECT_EQ(pi1_context->realtime_event_time,
412 header_realtime_remote_time);
Austin Schuhac6d89e2024-03-27 14:56:09 -0700413 EXPECT_EQ(header_monotonic_remote_transmit_time,
414 pi2_context->monotonic_remote_transmit_time);
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800415 });
416 }
Austin Schuh2f8fd752020-09-01 22:38:28 -0700417
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800418 // Start everything up. Pong is the only thing we don't know how to wait
419 // on, so start it first.
Austin Schuha4e616a2023-05-15 17:59:30 -0700420 ThreadedEventLoopRunner pong_thread(&pong_event_loop);
421 ThreadedEventLoopRunner ping_thread(&ping_event_loop);
Austin Schuh7bc59052020-02-16 23:48:33 -0800422
Kiran Mohan38648482024-03-15 15:56:14 -0700423 pi1_.StartServer();
424 pi1_.StartClient();
425 pi2_.StartClient();
426 pi2_.StartServer();
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800427
428 // And go!
Austin Schuha4e616a2023-05-15 17:59:30 -0700429 // Run for 5 seconds to make sure we have time to estimate the offset.
430 std::this_thread::sleep_for(chrono::milliseconds(5050));
Austin Schuh7bc59052020-02-16 23:48:33 -0800431
432 // Confirm that we are estimating a monotonic offset on the client.
433 ASSERT_TRUE(client_statistics_fetcher.Fetch());
434
435 EXPECT_EQ(client_statistics_fetcher->connections()->size(), 1u);
436 EXPECT_EQ(client_statistics_fetcher->connections()
437 ->Get(0)
438 ->node()
439 ->name()
440 ->string_view(),
441 "pi1");
442
443 // Make sure the offset in one direction is less than a second.
444 EXPECT_GT(
Austin Schuh2b159eb2021-07-31 19:42:21 -0700445 client_statistics_fetcher->connections()->Get(0)->monotonic_offset(), 0)
446 << aos::FlatbufferToJson(client_statistics_fetcher.get());
Austin Schuh7bc59052020-02-16 23:48:33 -0800447 EXPECT_LT(
448 client_statistics_fetcher->connections()->Get(0)->monotonic_offset(),
Austin Schuh2b159eb2021-07-31 19:42:21 -0700449 1000000000)
450 << aos::FlatbufferToJson(client_statistics_fetcher.get());
Austin Schuh7bc59052020-02-16 23:48:33 -0800451
Austin Schuha4e616a2023-05-15 17:59:30 -0700452 // Shut everyone else down before confirming everything actually ran.
453 ping_thread.Exit();
454 pong_thread.Exit();
Kiran Mohan38648482024-03-15 15:56:14 -0700455 pi1_.StopServer();
456 pi1_.StopClient();
457 pi2_.StopClient();
458 pi2_.StopServer();
Austin Schuha4e616a2023-05-15 17:59:30 -0700459
460 // Make sure we sent something.
461 EXPECT_GE(ping_count, 1);
462 // And got something back.
463 EXPECT_GE(pong_count, 1);
464
Austin Schuh7bc59052020-02-16 23:48:33 -0800465 EXPECT_GE(pi1_server_statistics_count, 2);
466 EXPECT_GE(pi2_server_statistics_count, 2);
467 EXPECT_GE(pi1_client_statistics_count, 2);
468 EXPECT_GE(pi2_client_statistics_count, 2);
Austin Schuh2f8fd752020-09-01 22:38:28 -0700469
470 // Confirm we got timestamps back!
471 EXPECT_TRUE(message_header_fetcher1.Fetch());
472 EXPECT_TRUE(message_header_fetcher2.Fetch());
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800473}
474
Austin Schuh5344c352020-04-12 17:04:26 -0700475// Test that the client disconnecting triggers the server offsets on both sides
476// to clear.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800477TEST_P(MessageBridgeParameterizedTest, ClientRestart) {
Austin Schuh5344c352020-04-12 17:04:26 -0700478 // This is rather annoying to set up. We need to start up a client and
479 // server, on the same node, but get them to think that they are on different
480 // nodes.
481 //
482 // We need the client to not post directly to "/test" like it would in a
483 // real system, otherwise we will re-send the ping message... So, use an
484 // application specific map to have the client post somewhere else.
485 //
486 // To top this all off, each of these needs to be done with a ShmEventLoop,
487 // which needs to run in a separate thread... And it is really hard to get
488 // everything started up reliably. So just be super generous on timeouts and
489 // hope for the best. We can be more generous in the future if we need to.
490 //
491 // We are faking the application names by passing in --application_name=foo
Kiran Mohan38648482024-03-15 15:56:14 -0700492 pi1_.OnPi();
Austin Schuh5344c352020-04-12 17:04:26 -0700493
Kiran Mohan38648482024-03-15 15:56:14 -0700494 pi1_.MakeServer();
495 pi1_.MakeClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700496
497 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -0700498 pi1_.MakeTest("test1", &pi2_);
Austin Schuh5344c352020-04-12 17:04:26 -0700499 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -0700500 pi1_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi1/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700501
502 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -0700503 pi2_.OnPi();
504 pi2_.MakeServer();
Austin Schuh5344c352020-04-12 17:04:26 -0700505
506 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -0700507 pi2_.MakeTest("test2", &pi1_);
Austin Schuh5344c352020-04-12 17:04:26 -0700508 aos::Fetcher<ServerStatistics> pi2_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -0700509 pi2_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi2/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700510
511 // Wait until we are connected, then send.
Austin Schuh5344c352020-04-12 17:04:26 -0700512
Kiran Mohan38648482024-03-15 15:56:14 -0700513 pi1_.StartTest();
514 pi2_.StartTest();
515 pi1_.StartServer();
516 pi1_.StartClient();
517 pi2_.StartServer();
Austin Schuh5344c352020-04-12 17:04:26 -0700518
519 {
Kiran Mohan38648482024-03-15 15:56:14 -0700520 pi2_.MakeClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700521
Kiran Mohan38648482024-03-15 15:56:14 -0700522 pi2_.RunClient(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700523
524 // Now confirm we are synchronized.
525 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
526 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
527
528 const ServerConnection *const pi1_connection =
529 pi1_server_statistics_fetcher->connections()->Get(0);
530 const ServerConnection *const pi2_connection =
531 pi2_server_statistics_fetcher->connections()->Get(0);
532
533 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
Austin Schuh367a7f42021-11-23 23:04:36 -0800534 EXPECT_EQ(pi1_connection->connection_count(), 1u);
535 EXPECT_TRUE(pi1_connection->has_connected_since_time());
Austin Schuh5344c352020-04-12 17:04:26 -0700536 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
537 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
538 chrono::milliseconds(1));
539 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
540 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800541 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700542
543 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
Austin Schuh367a7f42021-11-23 23:04:36 -0800544 EXPECT_EQ(pi2_connection->connection_count(), 1u);
545 EXPECT_TRUE(pi2_connection->has_connected_since_time());
Austin Schuh5344c352020-04-12 17:04:26 -0700546 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
547 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
548 chrono::milliseconds(1));
549 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
550 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800551 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800552
Kiran Mohan38648482024-03-15 15:56:14 -0700553 pi2_.StopClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700554 }
555
Austin Schuhd0d894e2021-10-24 17:13:11 -0700556 std::this_thread::sleep_for(SctpClientConnection::kReconnectTimeout +
557 std::chrono::seconds(1));
Austin Schuh5344c352020-04-12 17:04:26 -0700558
559 {
560 // Now confirm we are un-synchronized.
561 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
562 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
563 const ServerConnection *const pi1_connection =
564 pi1_server_statistics_fetcher->connections()->Get(0);
565 const ServerConnection *const pi2_connection =
566 pi2_server_statistics_fetcher->connections()->Get(0);
567
568 EXPECT_EQ(pi1_connection->state(), State::DISCONNECTED);
Austin Schuh367a7f42021-11-23 23:04:36 -0800569 EXPECT_EQ(pi1_connection->connection_count(), 1u);
570 EXPECT_FALSE(pi1_connection->has_connected_since_time());
Austin Schuh5344c352020-04-12 17:04:26 -0700571 EXPECT_FALSE(pi1_connection->has_monotonic_offset());
Austin Schuh20ac95d2020-12-05 17:24:19 -0800572 EXPECT_FALSE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700573 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
574 EXPECT_FALSE(pi2_connection->has_monotonic_offset());
Austin Schuh20ac95d2020-12-05 17:24:19 -0800575 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh367a7f42021-11-23 23:04:36 -0800576 EXPECT_EQ(pi2_connection->connection_count(), 1u);
577 EXPECT_TRUE(pi2_connection->has_connected_since_time());
Austin Schuh5344c352020-04-12 17:04:26 -0700578 }
579
580 {
Kiran Mohan38648482024-03-15 15:56:14 -0700581 pi2_.MakeClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700582 // And go!
Kiran Mohan38648482024-03-15 15:56:14 -0700583 pi2_.RunClient(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700584
585 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
586 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
587
588 // Now confirm we are synchronized again.
589 const ServerConnection *const pi1_connection =
590 pi1_server_statistics_fetcher->connections()->Get(0);
591 const ServerConnection *const pi2_connection =
592 pi2_server_statistics_fetcher->connections()->Get(0);
593
594 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
Austin Schuh367a7f42021-11-23 23:04:36 -0800595 EXPECT_EQ(pi1_connection->connection_count(), 2u);
596 EXPECT_TRUE(pi1_connection->has_connected_since_time());
Austin Schuh5344c352020-04-12 17:04:26 -0700597 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
598 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
Austin Schuh367a7f42021-11-23 23:04:36 -0800599 chrono::milliseconds(1))
600 << ": " << FlatbufferToJson(pi1_connection);
Austin Schuh5344c352020-04-12 17:04:26 -0700601 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
Austin Schuh367a7f42021-11-23 23:04:36 -0800602 chrono::milliseconds(-1))
603 << ": " << FlatbufferToJson(pi1_connection);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800604 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700605
606 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
Austin Schuh367a7f42021-11-23 23:04:36 -0800607 EXPECT_EQ(pi2_connection->connection_count(), 1u);
608 EXPECT_TRUE(pi2_connection->has_connected_since_time());
Austin Schuh5344c352020-04-12 17:04:26 -0700609 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
610 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
Austin Schuh367a7f42021-11-23 23:04:36 -0800611 chrono::milliseconds(1))
612 << ": " << FlatbufferToJson(pi2_connection);
Austin Schuh5344c352020-04-12 17:04:26 -0700613 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
Austin Schuh367a7f42021-11-23 23:04:36 -0800614 chrono::milliseconds(-1))
615 << ": " << FlatbufferToJson(pi2_connection);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800616 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800617
Kiran Mohan38648482024-03-15 15:56:14 -0700618 pi2_.StopClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700619 }
620
James Kuszmaul79b2f032023-06-02 21:02:27 -0700621 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -0700622 pi1_.StopServer();
623 pi1_.StopClient();
624 pi2_.StopServer();
625 pi1_.StopTest();
626 pi2_.StopTest();
Austin Schuh5344c352020-04-12 17:04:26 -0700627}
628
629// Test that the server disconnecting triggers the server offsets on the other
630// side to clear, along with the other client.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800631TEST_P(MessageBridgeParameterizedTest, ServerRestart) {
Austin Schuh5344c352020-04-12 17:04:26 -0700632 // This is rather annoying to set up. We need to start up a client and
633 // server, on the same node, but get them to think that they are on different
634 // nodes.
635 //
636 // We need the client to not post directly to "/test" like it would in a
637 // real system, otherwise we will re-send the ping message... So, use an
638 // application specific map to have the client post somewhere else.
639 //
640 // To top this all off, each of these needs to be done with a ShmEventLoop,
641 // which needs to run in a separate thread... And it is really hard to get
642 // everything started up reliably. So just be super generous on timeouts and
643 // hope for the best. We can be more generous in the future if we need to.
644 //
645 // We are faking the application names by passing in --application_name=foo
Austin Schuh5344c352020-04-12 17:04:26 -0700646 // Force ourselves to be "raspberrypi" and allocate everything.
Kiran Mohan38648482024-03-15 15:56:14 -0700647 pi1_.OnPi();
648 pi1_.MakeServer();
649 pi1_.MakeClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700650
651 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -0700652 pi1_.MakeTest("test1", &pi2_);
Austin Schuh5344c352020-04-12 17:04:26 -0700653 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -0700654 pi1_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi1/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700655 aos::Fetcher<ClientStatistics> pi1_client_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -0700656 pi1_.test_event_loop_->MakeFetcher<ClientStatistics>("/pi1/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700657
658 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -0700659 pi2_.OnPi();
660 pi2_.MakeClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700661
662 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -0700663 pi2_.MakeTest("test1", &pi1_);
Austin Schuh5344c352020-04-12 17:04:26 -0700664 aos::Fetcher<ServerStatistics> pi2_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -0700665 pi2_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi2/aos");
Austin Schuh5344c352020-04-12 17:04:26 -0700666
667 // Start everything up. Pong is the only thing we don't know how to wait on,
668 // so start it first.
Kiran Mohan38648482024-03-15 15:56:14 -0700669 pi1_.StartTest();
670 pi2_.StartTest();
671 pi1_.StartServer();
672 pi1_.StartClient();
673 pi2_.StartClient();
Austin Schuh5344c352020-04-12 17:04:26 -0700674
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800675 // Confirm both client and server statistics messages have decent offsets in
676 // them.
Austin Schuh5344c352020-04-12 17:04:26 -0700677
678 {
Kiran Mohan38648482024-03-15 15:56:14 -0700679 pi2_.MakeServer();
Austin Schuh5344c352020-04-12 17:04:26 -0700680
Kiran Mohan38648482024-03-15 15:56:14 -0700681 pi2_.RunServer(chrono::milliseconds(3050));
Austin Schuh5344c352020-04-12 17:04:26 -0700682
683 // Now confirm we are synchronized.
684 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
685 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
686
687 const ServerConnection *const pi1_connection =
688 pi1_server_statistics_fetcher->connections()->Get(0);
689 const ServerConnection *const pi2_connection =
690 pi2_server_statistics_fetcher->connections()->Get(0);
691
692 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
693 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
694 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
695 chrono::milliseconds(1));
696 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
697 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800698 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh367a7f42021-11-23 23:04:36 -0800699 EXPECT_TRUE(pi1_connection->has_connected_since_time());
700 EXPECT_EQ(pi1_connection->connection_count(), 1u);
Austin Schuh5344c352020-04-12 17:04:26 -0700701
702 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
703 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
704 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
705 chrono::milliseconds(1));
706 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
707 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800708 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh367a7f42021-11-23 23:04:36 -0800709 EXPECT_TRUE(pi2_connection->has_connected_since_time());
710 EXPECT_EQ(pi2_connection->connection_count(), 1u);
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800711
Kiran Mohan38648482024-03-15 15:56:14 -0700712 pi2_.StopServer();
Austin Schuh5344c352020-04-12 17:04:26 -0700713 }
714
715 std::this_thread::sleep_for(std::chrono::seconds(2));
716
717 {
718 // And confirm we are unsynchronized.
719 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
720 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
721
722 const ServerConnection *const pi1_server_connection =
723 pi1_server_statistics_fetcher->connections()->Get(0);
724 const ClientConnection *const pi1_client_connection =
725 pi1_client_statistics_fetcher->connections()->Get(0);
726
727 EXPECT_EQ(pi1_server_connection->state(), State::CONNECTED);
728 EXPECT_FALSE(pi1_server_connection->has_monotonic_offset());
Austin Schuh367a7f42021-11-23 23:04:36 -0800729 EXPECT_TRUE(pi1_server_connection->has_connected_since_time());
730 EXPECT_EQ(pi1_server_connection->connection_count(), 1u);
731
Austin Schuh20ac95d2020-12-05 17:24:19 -0800732 EXPECT_TRUE(pi1_server_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700733 EXPECT_EQ(pi1_client_connection->state(), State::DISCONNECTED);
734 EXPECT_FALSE(pi1_client_connection->has_monotonic_offset());
Austin Schuh367a7f42021-11-23 23:04:36 -0800735 EXPECT_FALSE(pi1_client_connection->has_connected_since_time());
736 EXPECT_EQ(pi1_client_connection->connection_count(), 1u);
737 EXPECT_FALSE(pi1_client_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700738 }
739
740 {
Kiran Mohan38648482024-03-15 15:56:14 -0700741 pi2_.MakeServer();
Austin Schuh5344c352020-04-12 17:04:26 -0700742
Austin Schuh5cd1d752023-08-18 17:31:46 -0700743 // Wait long enough for the client to connect again. It currently takes 3
744 // seconds of connection to estimate the time offset.
Kiran Mohan38648482024-03-15 15:56:14 -0700745 pi2_.RunServer(chrono::milliseconds(4050));
Austin Schuh5344c352020-04-12 17:04:26 -0700746
747 // And confirm we are synchronized again.
748 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
749 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
Austin Schuh367a7f42021-11-23 23:04:36 -0800750 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
Austin Schuh5344c352020-04-12 17:04:26 -0700751
752 const ServerConnection *const pi1_connection =
753 pi1_server_statistics_fetcher->connections()->Get(0);
754 const ServerConnection *const pi2_connection =
755 pi2_server_statistics_fetcher->connections()->Get(0);
Austin Schuh367a7f42021-11-23 23:04:36 -0800756 const ClientConnection *const pi1_client_connection =
757 pi1_client_statistics_fetcher->connections()->Get(0);
Austin Schuh5344c352020-04-12 17:04:26 -0700758
759 EXPECT_EQ(pi1_connection->state(), State::CONNECTED);
760 EXPECT_TRUE(pi1_connection->has_monotonic_offset());
761 EXPECT_LT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
762 chrono::milliseconds(1));
763 EXPECT_GT(chrono::nanoseconds(pi1_connection->monotonic_offset()),
764 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800765 EXPECT_TRUE(pi1_connection->has_boot_uuid());
Austin Schuh5344c352020-04-12 17:04:26 -0700766
Austin Schuh367a7f42021-11-23 23:04:36 -0800767 EXPECT_EQ(pi1_client_connection->state(), State::CONNECTED);
768 EXPECT_TRUE(pi1_client_connection->has_connected_since_time());
769 EXPECT_EQ(pi1_client_connection->connection_count(), 2u);
770 EXPECT_TRUE(pi1_client_connection->has_boot_uuid());
771
Austin Schuh5344c352020-04-12 17:04:26 -0700772 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
773 EXPECT_TRUE(pi2_connection->has_monotonic_offset());
774 EXPECT_LT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
775 chrono::milliseconds(1));
776 EXPECT_GT(chrono::nanoseconds(pi2_connection->monotonic_offset()),
777 chrono::milliseconds(-1));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800778 EXPECT_TRUE(pi2_connection->has_boot_uuid());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800779
Kiran Mohan38648482024-03-15 15:56:14 -0700780 pi2_.StopServer();
Austin Schuh5344c352020-04-12 17:04:26 -0700781 }
782
James Kuszmaul79b2f032023-06-02 21:02:27 -0700783 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -0700784 pi1_.StopServer();
785 pi1_.StopClient();
786 pi2_.StopClient();
787 pi1_.StopTest();
788 pi2_.StopTest();
Austin Schuh5344c352020-04-12 17:04:26 -0700789}
790
Austin Schuh4889b182020-11-18 19:11:56 -0800791// TODO(austin): The above test confirms that the external state does the right
Austin Schuh5344c352020-04-12 17:04:26 -0700792// thing, but doesn't confirm that the internal state does. We either need to
793// expose a way to check the state in a thread-safe way, or need a way to jump
794// time for one node to do that.
795
Austin Schuh4889b182020-11-18 19:11:56 -0800796void SendPing(aos::Sender<examples::Ping> *sender, int value) {
797 aos::Sender<examples::Ping>::Builder builder = sender->MakeBuilder();
798 examples::Ping::Builder ping_builder = builder.MakeBuilder<examples::Ping>();
799 ping_builder.add_value(value);
milind1f1dca32021-07-03 13:50:07 -0700800 builder.CheckOk(builder.Send(ping_builder.Finish()));
Austin Schuh4889b182020-11-18 19:11:56 -0800801}
802
803// Tests that when a message is sent before the bridge starts up, but is
804// configured as reliable, we forward it. Confirm this survives a client reset.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800805TEST_P(MessageBridgeParameterizedTest, ReliableSentBeforeClientStartup) {
Kiran Mohan38648482024-03-15 15:56:14 -0700806 pi1_.OnPi();
Austin Schuh4889b182020-11-18 19:11:56 -0800807
808 FLAGS_application_name = "sender";
Kiran Mohan38648482024-03-15 15:56:14 -0700809 aos::ShmEventLoop send_event_loop(&config_.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800810 aos::Sender<examples::Ping> ping_sender =
811 send_event_loop.MakeSender<examples::Ping>("/test");
812 SendPing(&ping_sender, 1);
813 aos::Sender<examples::Ping> unreliable_ping_sender =
814 send_event_loop.MakeSender<examples::Ping>("/unreliable");
815 SendPing(&unreliable_ping_sender, 1);
816
Kiran Mohan38648482024-03-15 15:56:14 -0700817 pi1_.MakeServer();
818 pi1_.MakeClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800819
820 FLAGS_application_name = "pi1_timestamp";
Kiran Mohan38648482024-03-15 15:56:14 -0700821 aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config_.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800822
823 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -0700824 pi2_.OnPi();
Austin Schuh4889b182020-11-18 19:11:56 -0800825
Kiran Mohan38648482024-03-15 15:56:14 -0700826 pi2_.MakeServer();
Austin Schuh4889b182020-11-18 19:11:56 -0800827
Kiran Mohan38648482024-03-15 15:56:14 -0700828 aos::ShmEventLoop receive_event_loop(&config_.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800829 aos::Fetcher<examples::Ping> ping_fetcher =
830 receive_event_loop.MakeFetcher<examples::Ping>("/test");
831 aos::Fetcher<examples::Ping> unreliable_ping_fetcher =
832 receive_event_loop.MakeFetcher<examples::Ping>("/unreliable");
833 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
834 receive_event_loop.MakeFetcher<ClientStatistics>("/pi2/aos");
835
836 const size_t ping_channel_index = configuration::ChannelIndex(
837 receive_event_loop.configuration(), ping_fetcher.channel());
838
James Kuszmaul79b2f032023-06-02 21:02:27 -0700839 // ping_timestamp_count is accessed from multiple threads (the Watcher that
840 // triggers it is in a separate thread), so make it atomic.
Austin Schuh4889b182020-11-18 19:11:56 -0800841 std::atomic<int> ping_timestamp_count{0};
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800842 const std::string channel_name =
843 shared() ? "/pi1/aos/remote_timestamps/pi2"
844 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping";
Austin Schuh4889b182020-11-18 19:11:56 -0800845 pi1_remote_timestamp_event_loop.MakeWatcher(
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800846 channel_name, [this, channel_name, ping_channel_index,
847 &ping_timestamp_count](const RemoteMessage &header) {
Austin Schuh61e973f2021-02-21 21:43:56 -0800848 VLOG(1) << channel_name << " RemoteMessage "
Austin Schuh0de30f32020-12-06 12:44:28 -0800849 << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800850 EXPECT_TRUE(header.has_boot_uuid());
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800851 if (shared() && header.channel_index() != ping_channel_index) {
852 return;
Austin Schuh4889b182020-11-18 19:11:56 -0800853 }
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800854 CHECK_EQ(header.channel_index(), ping_channel_index);
855 ++ping_timestamp_count;
Austin Schuh4889b182020-11-18 19:11:56 -0800856 });
857
858 // Before everything starts up, confirm there is no message.
859 EXPECT_FALSE(ping_fetcher.Fetch());
860 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
861
James Kuszmaul79b2f032023-06-02 21:02:27 -0700862 // Spin up the persistent pieces.
Kiran Mohan38648482024-03-15 15:56:14 -0700863 pi1_.StartServer();
864 pi1_.StartClient();
865 pi2_.StartServer();
Austin Schuh4889b182020-11-18 19:11:56 -0800866
867 // Event used to wait for the timestamp counting thread to start.
Austin Schuha4e616a2023-05-15 17:59:30 -0700868 std::unique_ptr<ThreadedEventLoopRunner> pi1_remote_timestamp_thread =
869 std::make_unique<ThreadedEventLoopRunner>(
870 &pi1_remote_timestamp_event_loop);
Austin Schuh4889b182020-11-18 19:11:56 -0800871
872 {
Austin Schuhac6d89e2024-03-27 14:56:09 -0700873 const aos::monotonic_clock::time_point startup_time =
874 aos::monotonic_clock::now();
James Kuszmaul79b2f032023-06-02 21:02:27 -0700875 // Now spin up a client for 2 seconds.
Kiran Mohan38648482024-03-15 15:56:14 -0700876 pi2_.MakeClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800877
Kiran Mohan38648482024-03-15 15:56:14 -0700878 pi2_.RunClient(chrono::milliseconds(2050));
Austin Schuh4889b182020-11-18 19:11:56 -0800879
880 // Confirm there is no detected duplicate packet.
881 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
882 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
883 ->Get(0)
884 ->duplicate_packets(),
885 0u);
886
Austin Schuhe61d4382021-03-31 21:33:02 -0700887 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
888 ->Get(0)
889 ->partial_deliveries(),
890 0u);
891
Austin Schuh4889b182020-11-18 19:11:56 -0800892 EXPECT_TRUE(ping_fetcher.Fetch());
Austin Schuhac6d89e2024-03-27 14:56:09 -0700893 EXPECT_GT(ping_fetcher.context().monotonic_remote_transmit_time,
894 startup_time);
895 EXPECT_LT(ping_fetcher.context().monotonic_remote_transmit_time,
896 aos::monotonic_clock::now());
Austin Schuh4889b182020-11-18 19:11:56 -0800897 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
898 EXPECT_EQ(ping_timestamp_count, 1);
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800899
Kiran Mohan38648482024-03-15 15:56:14 -0700900 pi2_.StopClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800901 }
902
903 {
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800904 // Now, spin up a client for 2 seconds.
Kiran Mohan38648482024-03-15 15:56:14 -0700905 pi2_.MakeClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800906
Kiran Mohan38648482024-03-15 15:56:14 -0700907 pi2_.RunClient(chrono::milliseconds(5050));
Austin Schuh4889b182020-11-18 19:11:56 -0800908
909 // Confirm we detect the duplicate packet correctly.
910 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
911 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
912 ->Get(0)
913 ->duplicate_packets(),
914 1u);
915
Austin Schuhe61d4382021-03-31 21:33:02 -0700916 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
917 ->Get(0)
918 ->partial_deliveries(),
919 0u);
920
Austin Schuh4889b182020-11-18 19:11:56 -0800921 EXPECT_EQ(ping_timestamp_count, 1);
922 EXPECT_FALSE(ping_fetcher.Fetch());
923 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
Austin Schuh0a2f12f2021-01-08 22:48:29 -0800924
Kiran Mohan38648482024-03-15 15:56:14 -0700925 pi2_.StopClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800926 }
927
James Kuszmaul79b2f032023-06-02 21:02:27 -0700928 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -0700929 pi1_.StopClient();
930 pi2_.StopServer();
Austin Schuha4e616a2023-05-15 17:59:30 -0700931 pi1_remote_timestamp_thread.reset();
Kiran Mohan38648482024-03-15 15:56:14 -0700932 pi1_.StopServer();
Austin Schuh4889b182020-11-18 19:11:56 -0800933}
934
935// Tests that when a message is sent before the bridge starts up, but is
936// configured as reliable, we forward it. Confirm this works across server
937// resets.
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800938TEST_P(MessageBridgeParameterizedTest, ReliableSentBeforeServerStartup) {
Austin Schuh4889b182020-11-18 19:11:56 -0800939 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -0700940 pi2_.OnPi();
Austin Schuh4889b182020-11-18 19:11:56 -0800941
Kiran Mohan38648482024-03-15 15:56:14 -0700942 pi2_.MakeServer();
943 pi2_.MakeClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800944
Kiran Mohan38648482024-03-15 15:56:14 -0700945 aos::ShmEventLoop receive_event_loop(&config_.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800946 aos::Fetcher<examples::Ping> ping_fetcher =
947 receive_event_loop.MakeFetcher<examples::Ping>("/test");
948 aos::Fetcher<examples::Ping> unreliable_ping_fetcher =
949 receive_event_loop.MakeFetcher<examples::Ping>("/unreliable");
950 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
951 receive_event_loop.MakeFetcher<ClientStatistics>("/pi2/aos");
952
Austin Schuh4889b182020-11-18 19:11:56 -0800953 // Force ourselves to be "raspberrypi" and allocate everything.
Kiran Mohan38648482024-03-15 15:56:14 -0700954 pi1_.OnPi();
Austin Schuh4889b182020-11-18 19:11:56 -0800955
956 FLAGS_application_name = "sender";
Kiran Mohan38648482024-03-15 15:56:14 -0700957 aos::ShmEventLoop send_event_loop(&config_.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800958 aos::Sender<examples::Ping> ping_sender =
959 send_event_loop.MakeSender<examples::Ping>("/test");
960 {
961 aos::Sender<examples::Ping>::Builder builder = ping_sender.MakeBuilder();
962 examples::Ping::Builder ping_builder =
963 builder.MakeBuilder<examples::Ping>();
964 ping_builder.add_value(1);
milind1f1dca32021-07-03 13:50:07 -0700965 builder.CheckOk(builder.Send(ping_builder.Finish()));
Austin Schuh4889b182020-11-18 19:11:56 -0800966 }
967
Kiran Mohan38648482024-03-15 15:56:14 -0700968 pi1_.MakeClient();
Austin Schuh4889b182020-11-18 19:11:56 -0800969
970 FLAGS_application_name = "pi1_timestamp";
Kiran Mohan38648482024-03-15 15:56:14 -0700971 aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config_.message());
Austin Schuh4889b182020-11-18 19:11:56 -0800972
973 const size_t ping_channel_index = configuration::ChannelIndex(
974 receive_event_loop.configuration(), ping_fetcher.channel());
975
James Kuszmaul79b2f032023-06-02 21:02:27 -0700976 // ping_timestamp_count is accessed from multiple threads (the Watcher that
977 // triggers it is in a separate thread), so make it atomic.
Austin Schuh4889b182020-11-18 19:11:56 -0800978 std::atomic<int> ping_timestamp_count{0};
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800979 const std::string channel_name =
980 shared() ? "/pi1/aos/remote_timestamps/pi2"
981 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping";
Austin Schuh4889b182020-11-18 19:11:56 -0800982 pi1_remote_timestamp_event_loop.MakeWatcher(
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800983 channel_name, [this, channel_name, ping_channel_index,
984 &ping_timestamp_count](const RemoteMessage &header) {
985 VLOG(1) << channel_name << " RemoteMessage "
Austin Schuh0de30f32020-12-06 12:44:28 -0800986 << aos::FlatbufferToJson(&header);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800987 EXPECT_TRUE(header.has_boot_uuid());
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800988 if (shared() && header.channel_index() != ping_channel_index) {
989 return;
Austin Schuh4889b182020-11-18 19:11:56 -0800990 }
Austin Schuh36a2c3e2021-02-18 22:28:38 -0800991 CHECK_EQ(header.channel_index(), ping_channel_index);
992 ++ping_timestamp_count;
Austin Schuh4889b182020-11-18 19:11:56 -0800993 });
994
995 // Before everything starts up, confirm there is no message.
996 EXPECT_FALSE(ping_fetcher.Fetch());
997 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
998
James Kuszmaul79b2f032023-06-02 21:02:27 -0700999 // Spin up the persistent pieces.
Kiran Mohan38648482024-03-15 15:56:14 -07001000 pi1_.StartClient();
1001 pi2_.StartServer();
1002 pi2_.StartClient();
Austin Schuh4889b182020-11-18 19:11:56 -08001003
Austin Schuha4e616a2023-05-15 17:59:30 -07001004 std::unique_ptr<ThreadedEventLoopRunner> pi1_remote_timestamp_thread =
1005 std::make_unique<ThreadedEventLoopRunner>(
1006 &pi1_remote_timestamp_event_loop);
Austin Schuh4889b182020-11-18 19:11:56 -08001007
1008 {
Austin Schuhac6d89e2024-03-27 14:56:09 -07001009 const aos::monotonic_clock::time_point startup_time =
1010 aos::monotonic_clock::now();
Austin Schuh4889b182020-11-18 19:11:56 -08001011 // Now, spin up a server for 2 seconds.
Kiran Mohan38648482024-03-15 15:56:14 -07001012 pi1_.MakeServer();
Austin Schuh4889b182020-11-18 19:11:56 -08001013
Kiran Mohan38648482024-03-15 15:56:14 -07001014 pi1_.RunServer(chrono::milliseconds(2050));
Austin Schuh4889b182020-11-18 19:11:56 -08001015
1016 // Confirm there is no detected duplicate packet.
1017 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1018 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1019 ->Get(0)
1020 ->duplicate_packets(),
1021 0u);
1022
Austin Schuhe61d4382021-03-31 21:33:02 -07001023 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1024 ->Get(0)
1025 ->partial_deliveries(),
1026 0u);
1027
Austin Schuh4889b182020-11-18 19:11:56 -08001028 EXPECT_TRUE(ping_fetcher.Fetch());
Austin Schuhac6d89e2024-03-27 14:56:09 -07001029 EXPECT_GT(ping_fetcher.context().monotonic_remote_transmit_time,
1030 startup_time);
1031 EXPECT_LT(ping_fetcher.context().monotonic_remote_transmit_time,
1032 aos::monotonic_clock::now());
1033
Austin Schuh4889b182020-11-18 19:11:56 -08001034 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
1035 EXPECT_EQ(ping_timestamp_count, 1);
1036 LOG(INFO) << "Shutting down first pi1 MessageBridgeServer";
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001037
Kiran Mohan38648482024-03-15 15:56:14 -07001038 pi1_.StopServer();
Austin Schuh4889b182020-11-18 19:11:56 -08001039 }
1040
1041 {
1042 // Now, spin up a second server for 2 seconds.
Kiran Mohan38648482024-03-15 15:56:14 -07001043 pi1_.MakeServer();
Austin Schuh4889b182020-11-18 19:11:56 -08001044
Kiran Mohan38648482024-03-15 15:56:14 -07001045 pi1_.RunServer(chrono::milliseconds(2050));
Austin Schuh4889b182020-11-18 19:11:56 -08001046
1047 // Confirm we detect the duplicate packet correctly.
1048 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1049 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1050 ->Get(0)
1051 ->duplicate_packets(),
1052 1u);
1053
Austin Schuhe61d4382021-03-31 21:33:02 -07001054 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1055 ->Get(0)
1056 ->partial_deliveries(),
1057 0u);
1058
Austin Schuh4889b182020-11-18 19:11:56 -08001059 EXPECT_EQ(ping_timestamp_count, 1);
1060 EXPECT_FALSE(ping_fetcher.Fetch());
1061 EXPECT_FALSE(unreliable_ping_fetcher.Fetch());
Austin Schuh0a2f12f2021-01-08 22:48:29 -08001062
Kiran Mohan38648482024-03-15 15:56:14 -07001063 pi1_.StopServer();
Austin Schuh4889b182020-11-18 19:11:56 -08001064 }
1065
James Kuszmaul79b2f032023-06-02 21:02:27 -07001066 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -07001067 pi1_.StopClient();
1068 pi2_.StopServer();
1069 pi2_.StopClient();
Austin Schuha4e616a2023-05-15 17:59:30 -07001070 pi1_remote_timestamp_thread.reset();
Austin Schuh4889b182020-11-18 19:11:56 -08001071}
1072
James Kuszmaul79b2f032023-06-02 21:02:27 -07001073// Tests that when multiple reliable messages are sent during a time when the
1074// client is restarting that only the final of those messages makes it to the
1075// client. This ensures that we handle a disconnecting & reconnecting client
1076// correctly in the server reliable connection retry logic.
1077TEST_P(MessageBridgeParameterizedTest, ReliableSentDuringClientReboot) {
Kiran Mohan38648482024-03-15 15:56:14 -07001078 pi1_.OnPi();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001079
1080 FLAGS_application_name = "sender";
Kiran Mohan38648482024-03-15 15:56:14 -07001081 aos::ShmEventLoop send_event_loop(&config_.message());
James Kuszmaul79b2f032023-06-02 21:02:27 -07001082 aos::Sender<examples::Ping> ping_sender =
1083 send_event_loop.MakeSender<examples::Ping>("/test");
1084 size_t ping_index = 0;
1085 SendPing(&ping_sender, ++ping_index);
1086
Kiran Mohan38648482024-03-15 15:56:14 -07001087 pi1_.MakeServer();
1088 pi1_.MakeClient();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001089
1090 FLAGS_application_name = "pi1_timestamp";
Kiran Mohan38648482024-03-15 15:56:14 -07001091 aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config_.message());
James Kuszmaul79b2f032023-06-02 21:02:27 -07001092
1093 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -07001094 pi2_.OnPi();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001095
Kiran Mohan38648482024-03-15 15:56:14 -07001096 pi2_.MakeServer();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001097
Kiran Mohan38648482024-03-15 15:56:14 -07001098 aos::ShmEventLoop receive_event_loop(&config_.message());
James Kuszmaul79b2f032023-06-02 21:02:27 -07001099 aos::Fetcher<examples::Ping> ping_fetcher =
1100 receive_event_loop.MakeFetcher<examples::Ping>("/test");
1101 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
1102 receive_event_loop.MakeFetcher<ClientStatistics>("/pi2/aos");
1103
1104 const size_t ping_channel_index = configuration::ChannelIndex(
1105 receive_event_loop.configuration(), ping_fetcher.channel());
1106
1107 // ping_timestamp_count is accessed from multiple threads (the Watcher that
1108 // triggers it is in a separate thread), so make it atomic.
1109 std::atomic<int> ping_timestamp_count{0};
1110 const std::string channel_name =
1111 shared() ? "/pi1/aos/remote_timestamps/pi2"
1112 : "/pi1/aos/remote_timestamps/pi2/test/aos-examples-Ping";
1113 pi1_remote_timestamp_event_loop.MakeWatcher(
1114 channel_name, [this, channel_name, ping_channel_index,
1115 &ping_timestamp_count](const RemoteMessage &header) {
1116 VLOG(1) << channel_name << " RemoteMessage "
1117 << aos::FlatbufferToJson(&header);
1118 EXPECT_TRUE(header.has_boot_uuid());
1119 if (shared() && header.channel_index() != ping_channel_index) {
1120 return;
1121 }
1122 CHECK_EQ(header.channel_index(), ping_channel_index);
1123 ++ping_timestamp_count;
1124 });
1125
1126 // Before everything starts up, confirm there is no message.
1127 EXPECT_FALSE(ping_fetcher.Fetch());
1128
1129 // Spin up the persistent pieces.
Kiran Mohan38648482024-03-15 15:56:14 -07001130 pi1_.StartServer();
1131 pi1_.StartClient();
1132 pi2_.StartServer();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001133
1134 // Event used to wait for the timestamp counting thread to start.
1135 std::unique_ptr<ThreadedEventLoopRunner> pi1_remote_timestamp_thread =
1136 std::make_unique<ThreadedEventLoopRunner>(
1137 &pi1_remote_timestamp_event_loop);
1138
1139 {
1140 // Now, spin up a client for 2 seconds.
Kiran Mohan38648482024-03-15 15:56:14 -07001141 pi2_.MakeClient();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001142
Kiran Mohan38648482024-03-15 15:56:14 -07001143 pi2_.RunClient(chrono::milliseconds(2050));
James Kuszmaul79b2f032023-06-02 21:02:27 -07001144
1145 // Confirm there is no detected duplicate packet.
1146 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1147 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1148 ->Get(0)
1149 ->duplicate_packets(),
1150 0u);
1151
1152 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1153 ->Get(0)
1154 ->partial_deliveries(),
1155 0u);
1156
1157 EXPECT_TRUE(ping_fetcher.Fetch());
1158 EXPECT_EQ(ping_timestamp_count, 1);
1159
Kiran Mohan38648482024-03-15 15:56:14 -07001160 pi2_.StopClient();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001161 }
1162
1163 // Send some reliable messages while the client is dead. Only the final one
1164 // should make it through.
1165 while (ping_index < 10) {
1166 SendPing(&ping_sender, ++ping_index);
1167 }
1168
1169 {
Austin Schuhac6d89e2024-03-27 14:56:09 -07001170 const aos::monotonic_clock::time_point startup_time =
1171 aos::monotonic_clock::now();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001172 // Now, spin up a client for 2 seconds.
Kiran Mohan38648482024-03-15 15:56:14 -07001173 pi2_.MakeClient();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001174
Kiran Mohan38648482024-03-15 15:56:14 -07001175 pi2_.RunClient(chrono::milliseconds(5050));
James Kuszmaul79b2f032023-06-02 21:02:27 -07001176
1177 // No duplicate packets should have appeared.
1178 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1179 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1180 ->Get(0)
1181 ->duplicate_packets(),
1182 0u);
1183
1184 EXPECT_EQ(pi2_client_statistics_fetcher->connections()
1185 ->Get(0)
1186 ->partial_deliveries(),
1187 0u);
1188
1189 EXPECT_EQ(ping_timestamp_count, 2);
1190 // We should have gotten precisely one more ping message--the latest one
1191 // sent should've made it, but no previous ones.
1192 EXPECT_TRUE(ping_fetcher.FetchNext());
Austin Schuhac6d89e2024-03-27 14:56:09 -07001193 EXPECT_GT(ping_fetcher.context().monotonic_remote_transmit_time,
1194 startup_time);
1195 EXPECT_LT(ping_fetcher.context().monotonic_remote_transmit_time,
1196 aos::monotonic_clock::now());
1197
James Kuszmaul79b2f032023-06-02 21:02:27 -07001198 EXPECT_EQ(ping_index, ping_fetcher->value());
1199 EXPECT_FALSE(ping_fetcher.FetchNext());
1200
Kiran Mohan38648482024-03-15 15:56:14 -07001201 pi2_.StopClient();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001202 }
1203
1204 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -07001205 pi1_.StopClient();
1206 pi2_.StopServer();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001207 pi1_remote_timestamp_thread.reset();
Kiran Mohan38648482024-03-15 15:56:14 -07001208 pi1_.StopServer();
James Kuszmaul79b2f032023-06-02 21:02:27 -07001209}
1210
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001211// Test that differing config sha256's result in no connection.
1212TEST_P(MessageBridgeParameterizedTest, MismatchedSha256) {
1213 // This is rather annoying to set up. We need to start up a client and
1214 // server, on the same node, but get them to think that they are on different
1215 // nodes.
1216 //
1217 // We need the client to not post directly to "/test" like it would in a
1218 // real system, otherwise we will re-send the ping message... So, use an
1219 // application specific map to have the client post somewhere else.
1220 //
1221 // To top this all off, each of these needs to be done with a ShmEventLoop,
1222 // which needs to run in a separate thread... And it is really hard to get
1223 // everything started up reliably. So just be super generous on timeouts and
1224 // hope for the best. We can be more generous in the future if we need to.
1225 //
1226 // We are faking the application names by passing in --application_name=foo
Kiran Mohan38648482024-03-15 15:56:14 -07001227 pi1_.OnPi();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001228
Kiran Mohan38648482024-03-15 15:56:14 -07001229 pi1_.MakeServer(
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001230 "dummy sha256 ");
Kiran Mohan38648482024-03-15 15:56:14 -07001231 pi1_.MakeClient();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001232
1233 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -07001234 pi1_.MakeTest("test1", &pi2_);
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001235 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001236 pi1_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi1/aos");
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001237 aos::Fetcher<ClientStatistics> pi1_client_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001238 pi1_.test_event_loop_->MakeFetcher<ClientStatistics>("/pi1/aos");
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001239
1240 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -07001241 pi2_.OnPi();
1242 pi2_.MakeServer();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001243
1244 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -07001245 pi2_.MakeTest("test1", &pi1_);
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001246 aos::Fetcher<ServerStatistics> pi2_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001247 pi2_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi2/aos");
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001248 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001249 pi2_.test_event_loop_->MakeFetcher<ClientStatistics>("/pi2/aos");
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001250
1251 // Wait until we are connected, then send.
1252
Kiran Mohan38648482024-03-15 15:56:14 -07001253 pi1_.StartTest();
1254 pi2_.StartTest();
1255 pi1_.StartServer();
1256 pi1_.StartClient();
1257 pi2_.StartServer();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001258
1259 {
Kiran Mohan38648482024-03-15 15:56:14 -07001260 pi2_.MakeClient();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001261
Kiran Mohan38648482024-03-15 15:56:14 -07001262 pi2_.RunClient(chrono::milliseconds(3050));
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001263
1264 // Now confirm we are synchronized.
1265 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1266 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1267 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
1268 EXPECT_TRUE(pi2_client_statistics_fetcher.Fetch());
1269
1270 const ServerConnection *const pi1_connection =
1271 pi1_server_statistics_fetcher->connections()->Get(0);
1272 const ClientConnection *const pi1_client_connection =
1273 pi1_client_statistics_fetcher->connections()->Get(0);
1274 const ServerConnection *const pi2_connection =
1275 pi2_server_statistics_fetcher->connections()->Get(0);
1276 const ClientConnection *const pi2_client_connection =
1277 pi2_client_statistics_fetcher->connections()->Get(0);
1278
1279 // Make sure one direction is disconnected with a bunch of connection
1280 // attempts and failures.
1281 EXPECT_EQ(pi1_connection->state(), State::DISCONNECTED);
1282 EXPECT_EQ(pi1_connection->connection_count(), 0u);
1283 EXPECT_GT(pi1_connection->invalid_connection_count(), 10u);
1284
1285 EXPECT_EQ(pi2_client_connection->state(), State::DISCONNECTED);
1286 EXPECT_GT(pi2_client_connection->connection_count(), 10u);
1287
1288 // And the other direction is happy.
1289 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
1290 EXPECT_EQ(pi2_connection->connection_count(), 1u);
1291 EXPECT_TRUE(pi2_connection->has_connected_since_time());
1292 EXPECT_FALSE(pi2_connection->has_monotonic_offset());
1293 EXPECT_TRUE(pi2_connection->has_boot_uuid());
1294
1295 EXPECT_EQ(pi1_client_connection->state(), State::CONNECTED);
1296 EXPECT_EQ(pi1_client_connection->connection_count(), 1u);
1297
1298 VLOG(1) << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1299 VLOG(1) << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
1300 VLOG(1) << aos::FlatbufferToJson(pi2_client_statistics_fetcher.get());
1301 VLOG(1) << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1302
Kiran Mohan38648482024-03-15 15:56:14 -07001303 pi2_.StopClient();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001304 }
1305
James Kuszmaul79b2f032023-06-02 21:02:27 -07001306 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -07001307 pi1_.StopServer();
1308 pi1_.StopClient();
1309 pi2_.StopServer();
1310 pi1_.StopTest();
1311 pi2_.StopTest();
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001312}
1313
Austin Schuh89f23e32023-05-15 17:06:43 -07001314// Test that a client which connects with too big a message gets disconnected
1315// without crashing.
1316TEST_P(MessageBridgeParameterizedTest, TooBigConnect) {
Austin Schuhb0e439d2023-05-15 10:55:40 -07001317 // This is rather annoying to set up. We need to start up a client and
1318 // server, on the same node, but get them to think that they are on different
1319 // nodes.
1320 //
1321 // We need the client to not post directly to "/test" like it would in a
1322 // real system, otherwise we will re-send the ping message... So, use an
1323 // application specific map to have the client post somewhere else.
1324 //
1325 // To top this all off, each of these needs to be done with a ShmEventLoop,
1326 // which needs to run in a separate thread... And it is really hard to get
1327 // everything started up reliably. So just be super generous on timeouts and
1328 // hope for the best. We can be more generous in the future if we need to.
1329 //
1330 // We are faking the application names by passing in --application_name=foo
Kiran Mohan38648482024-03-15 15:56:14 -07001331 pi1_.OnPi();
Austin Schuhb0e439d2023-05-15 10:55:40 -07001332
Kiran Mohan38648482024-03-15 15:56:14 -07001333 pi1_.MakeServer();
1334 pi1_.MakeClient();
Austin Schuhb0e439d2023-05-15 10:55:40 -07001335
1336 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -07001337 pi1_.MakeTest("test1", &pi2_);
Austin Schuhb0e439d2023-05-15 10:55:40 -07001338 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001339 pi1_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi1/aos");
Austin Schuhb0e439d2023-05-15 10:55:40 -07001340 aos::Fetcher<ClientStatistics> pi1_client_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001341 pi1_.test_event_loop_->MakeFetcher<ClientStatistics>("/pi1/aos");
Austin Schuhb0e439d2023-05-15 10:55:40 -07001342
1343 // Now do it for "raspberrypi2", the client.
Kiran Mohan38648482024-03-15 15:56:14 -07001344 pi2_.OnPi();
1345 pi2_.MakeServer();
Austin Schuhb0e439d2023-05-15 10:55:40 -07001346
1347 // And build the app for testing.
Kiran Mohan38648482024-03-15 15:56:14 -07001348 pi2_.MakeTest("test1", &pi1_);
Austin Schuhb0e439d2023-05-15 10:55:40 -07001349 aos::Fetcher<ServerStatistics> pi2_server_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001350 pi2_.test_event_loop_->MakeFetcher<ServerStatistics>("/pi2/aos");
Austin Schuhb0e439d2023-05-15 10:55:40 -07001351 aos::Fetcher<ClientStatistics> pi2_client_statistics_fetcher =
Kiran Mohan38648482024-03-15 15:56:14 -07001352 pi2_.test_event_loop_->MakeFetcher<ClientStatistics>("/pi2/aos");
Austin Schuhb0e439d2023-05-15 10:55:40 -07001353
1354 // Wait until we are connected, then send.
1355
Kiran Mohan38648482024-03-15 15:56:14 -07001356 pi1_.StartTest();
1357 pi2_.StartTest();
1358 pi1_.StartServer();
1359 pi1_.StartClient();
1360 pi2_.StartServer();
Austin Schuhb0e439d2023-05-15 10:55:40 -07001361
1362 {
Austin Schuh89f23e32023-05-15 17:06:43 -07001363 // Now, spin up a SctpClient and send a massive hunk of data. This should
1364 // trigger a disconnect, but no crash.
Kiran Mohan38648482024-03-15 15:56:14 -07001365 pi2_.OnPi();
Austin Schuh89f23e32023-05-15 17:06:43 -07001366 FLAGS_application_name = "pi2_message_bridge_client";
Kiran Mohan38648482024-03-15 15:56:14 -07001367 pi2_.client_event_loop_ =
1368 std::make_unique<aos::ShmEventLoop>(&config_.message());
1369 pi2_.client_event_loop_->SetRuntimeRealtimePriority(1);
Austin Schuh89f23e32023-05-15 17:06:43 -07001370
Austin Schuh6bdcc372024-06-27 14:49:11 -07001371 const aos::Node *const remote_node =
1372 configuration::GetNode(pi2_.client_event_loop_->configuration(), "pi1");
1373 CHECK(remote_node != nullptr);
Austin Schuh89f23e32023-05-15 17:06:43 -07001374
1375 const aos::FlatbufferDetachedBuffer<aos::message_bridge::Connect>
1376 connect_message(MakeConnectMessage(
Kiran Mohan38648482024-03-15 15:56:14 -07001377 pi2_.client_event_loop_->configuration(),
1378 pi2_.client_event_loop_->node(), "pi1",
1379 pi2_.client_event_loop_->boot_uuid(), config_sha256_));
Austin Schuh89f23e32023-05-15 17:06:43 -07001380
1381 SctpClient client(remote_node->hostname()->string_view(),
1382 remote_node->port(),
1383 connect_message.message().channels_to_transfer()->size() +
1384 kControlStreams(),
1385 "");
1386
Austin Schuh89f23e32023-05-15 17:06:43 -07001387 client.SetPoolSize(2u);
1388
Sarah Newman3a3b5b82023-05-26 15:56:53 -07001389 // Passes on a machine with:
1390 // 5.4.0-147-generic
1391 // net.core.wmem_default = 212992
1392 // net.core.wmem_max = 212992
1393 // net.core.rmem_default = 212992
1394 // net.core.rmem_max = 212992
1395 // If too large it appears the message is never delivered to the
1396 // application.
1397 constexpr size_t kBigMessageSize = 64000;
1398 client.SetMaxReadSize(kBigMessageSize);
1399 client.SetMaxWriteSize(kBigMessageSize);
1400
1401 const std::string big_data(kBigMessageSize, 'a');
Austin Schuh89f23e32023-05-15 17:06:43 -07001402
Kiran Mohan38648482024-03-15 15:56:14 -07001403 pi2_.client_event_loop_->epoll()->OnReadable(client.fd(), [&]() {
Austin Schuh89f23e32023-05-15 17:06:43 -07001404 aos::unique_c_ptr<Message> message = client.Read();
1405 client.FreeMessage(std::move(message));
1406 });
1407
Kiran Mohan38648482024-03-15 15:56:14 -07001408 aos::TimerHandler *const send_big_message =
1409 pi2_.client_event_loop_->AddTimer(
1410 [&]() { CHECK(client.Send(kConnectStream(), big_data, 0)); });
Austin Schuh89f23e32023-05-15 17:06:43 -07001411
Kiran Mohan38648482024-03-15 15:56:14 -07001412 pi2_.client_event_loop_->OnRun([this, send_big_message]() {
1413 send_big_message->Schedule(pi2_.client_event_loop_->monotonic_now() +
Austin Schuh89f23e32023-05-15 17:06:43 -07001414 chrono::seconds(1));
1415 });
Austin Schuhb0e439d2023-05-15 10:55:40 -07001416
Kiran Mohan38648482024-03-15 15:56:14 -07001417 pi2_.RunClient(chrono::milliseconds(3050));
Austin Schuhb0e439d2023-05-15 10:55:40 -07001418
1419 // Now confirm we are synchronized.
1420 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1421 EXPECT_TRUE(pi1_client_statistics_fetcher.Fetch());
1422 EXPECT_TRUE(pi2_server_statistics_fetcher.Fetch());
Austin Schuh89f23e32023-05-15 17:06:43 -07001423 EXPECT_FALSE(pi2_client_statistics_fetcher.Fetch());
Austin Schuhb0e439d2023-05-15 10:55:40 -07001424
1425 const ServerConnection *const pi1_connection =
1426 pi1_server_statistics_fetcher->connections()->Get(0);
1427 const ClientConnection *const pi1_client_connection =
1428 pi1_client_statistics_fetcher->connections()->Get(0);
1429 const ServerConnection *const pi2_connection =
1430 pi2_server_statistics_fetcher->connections()->Get(0);
Austin Schuhb0e439d2023-05-15 10:55:40 -07001431
Austin Schuh4f7cccc2023-05-17 09:20:33 -07001432 // Make sure the server we just sent a bunch of junk to is grumpy and
1433 // disconnected the bad client.
Austin Schuhb0e439d2023-05-15 10:55:40 -07001434 EXPECT_EQ(pi1_connection->state(), State::DISCONNECTED);
1435 EXPECT_EQ(pi1_connection->connection_count(), 0u);
Austin Schuh89f23e32023-05-15 17:06:43 -07001436 EXPECT_GE(pi1_server_statistics_fetcher->invalid_connection_count(), 1u);
Austin Schuhb0e439d2023-05-15 10:55:40 -07001437
1438 // And the other direction is happy.
1439 EXPECT_EQ(pi2_connection->state(), State::CONNECTED);
1440 EXPECT_EQ(pi2_connection->connection_count(), 1u);
1441 EXPECT_TRUE(pi2_connection->has_connected_since_time());
1442 EXPECT_FALSE(pi2_connection->has_monotonic_offset());
1443 EXPECT_TRUE(pi2_connection->has_boot_uuid());
1444
1445 EXPECT_EQ(pi1_client_connection->state(), State::CONNECTED);
1446 EXPECT_EQ(pi1_client_connection->connection_count(), 1u);
1447
1448 VLOG(1) << aos::FlatbufferToJson(pi2_server_statistics_fetcher.get());
1449 VLOG(1) << aos::FlatbufferToJson(pi1_server_statistics_fetcher.get());
Austin Schuhb0e439d2023-05-15 10:55:40 -07001450 VLOG(1) << aos::FlatbufferToJson(pi1_client_statistics_fetcher.get());
1451
Kiran Mohan38648482024-03-15 15:56:14 -07001452 pi2_.client_event_loop_->epoll()->DeleteFd(client.fd());
Austin Schuh89f23e32023-05-15 17:06:43 -07001453
Kiran Mohan38648482024-03-15 15:56:14 -07001454 pi2_.StopClient();
Austin Schuhb0e439d2023-05-15 10:55:40 -07001455 }
1456
James Kuszmaul79b2f032023-06-02 21:02:27 -07001457 // Shut everyone else down.
Kiran Mohan38648482024-03-15 15:56:14 -07001458 pi1_.StopServer();
1459 pi1_.StopClient();
1460 pi2_.StopServer();
1461 pi1_.StopTest();
1462 pi2_.StopTest();
Austin Schuhb0e439d2023-05-15 10:55:40 -07001463}
1464
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -07001465INSTANTIATE_TEST_SUITE_P(
Austin Schuh36a2c3e2021-02-18 22:28:38 -08001466 MessageBridgeTests, MessageBridgeParameterizedTest,
1467 ::testing::Values(
1468 Param{"message_bridge_test_combined_timestamps_common_config.json",
1469 true},
1470 Param{"message_bridge_test_common_config.json", false}));
1471
Kiran Mohan38648482024-03-15 15:56:14 -07001472// Tests the case in which the configurations for the server and client are
1473// different - specifically the case where the client's config allows it to
1474// "talk" to the server, while the server's config does not allow the client to
1475// "talk" to it. The expectation in such a case is that we don't crash or raise
1476// an exception.
1477TEST(MessageBridgeTests, MismatchedServerAndClientConfigs) {
1478 // Make a `MessageBridgeServer` with the config
1479 // `message_bridge_test_mismatched_configs_pi1_and_pi3_config.json`.
1480 // In this config, `pi1` talks to `pi3`, but does *not* talk to `pi2`.
1481 PiNode pi1("pi1", "raspberrypi", "pi1_message_bridge_server",
1482 "message_bridge_test_mismatched_configs_pi1_and_pi3_config.json");
1483 pi1.OnPi();
1484 pi1.MakeServer();
1485 aos::ShmEventLoop pi1_test_event_loop(&pi1.config_.message());
1486 aos::Fetcher<ServerStatistics> pi1_server_statistics_fetcher =
1487 pi1_test_event_loop.MakeFetcher<ServerStatistics>("/pi1/aos");
1488
1489 // Make a `MessageBridgeClient` with the config
1490 // `message_bridge_test_mismatched_configs_pi1_and_pi2_config.json`.
1491 // In this config, `pi1` talks to `pi2`.
1492 // Reasoning:
1493 // Due to this mismatch between the configs of the server and client,
1494 // when the client `pi2` sends a "connect" request to the server `pi1`,
1495 // there will be no server node placed in the
1496 // `MessageBridgeServerStatus::nodes_` vector at the index corresponding to
1497 // the client node's index. In such a case, we expect to not crash or raise an
1498 // exception.
1499 PiNode pi2("pi2", "raspberrypi2", "pi2_message_bridge_client",
1500 "message_bridge_test_mismatched_configs_pi1_and_pi2_config.json");
1501 pi2.OnPi();
1502 pi2.MakeClient();
1503
1504 // Put the server and client on 2 separate threaded runners and start running.
1505 pi1.StartServer();
1506 pi2.StartClient();
1507
1508 // Sleep here while the server and client threads run for 1 second.
1509 // During this time, the client will attempt to connect to the server.
1510 // We've set them up with mismatching configs such that the
1511 // server does not expect to talk to the client, but the client does
1512 // expect to connect to the server.
1513 // We expect that neither of the threads crashes/raises an exception.
1514 // If any of them does, the test terminates and the exception is reported
1515 // via the stack trace when running the test.
1516 std::this_thread::sleep_for(chrono::milliseconds(1000));
1517
1518 EXPECT_TRUE(pi1_server_statistics_fetcher.Fetch());
1519 // Since pi1's configuration is such that it expects to talk only to pi3,
1520 // we expect the number of connections to be 1, and the node to
1521 // be `pi3`.
1522 EXPECT_EQ(pi1_server_statistics_fetcher->connections()->size(), 1);
1523 const ServerConnection *const pi1_connection =
1524 pi1_server_statistics_fetcher->connections()->Get(0);
1525 EXPECT_EQ(pi1_connection->node()->name()->string_view(), "pi3");
1526 // Since we didn't really spawn a `pi3` node in this test, we expect
1527 // that the connection is disconnected, and the connection count is 0.
1528 EXPECT_EQ(pi1_connection->state(), State::DISCONNECTED);
1529 EXPECT_EQ(pi1_connection->connection_count(), 0u);
1530 // Also, since no connection was established, we expect that there is
1531 // no `connected_since_time` set.
1532 EXPECT_FALSE(pi1_connection->has_connected_since_time());
1533
1534 // If we got here, everything went well. Stop the threads.
1535 pi1.StopServer();
1536 pi2.StopClient();
1537}
1538
Stephan Pleinesf63bde82024-01-13 15:59:33 -08001539} // namespace aos::message_bridge::testing