blob: a28891e9da922c9843c79702c0830ca3f4a1bdaf [file] [log] [blame]
James Kuszmaul38735e82019-12-07 16:42:06 -08001#include "aos/events/logging/logger.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -08002
Austin Schuh315b96b2020-12-11 21:21:12 -08003#include "absl/strings/str_format.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -08004#include "aos/events/event_loop.h"
Austin Schuh01b4c352020-09-21 23:09:39 -07005#include "aos/events/message_counter.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -08006#include "aos/events/ping_lib.h"
7#include "aos/events/pong_lib.h"
8#include "aos/events/simulated_event_loop.h"
Austin Schuh0de30f32020-12-06 12:44:28 -08009#include "aos/network/remote_message_generated.h"
Austin Schuh87dd3832021-01-01 23:07:31 -080010#include "aos/network/testing_time_converter.h"
Austin Schuh8d7e0bb2020-10-02 17:57:00 -070011#include "aos/network/timestamp_generated.h"
Austin Schuhc243b422020-10-11 15:35:08 -070012#include "aos/testing/tmpdir.h"
Austin Schuh2f8fd752020-09-01 22:38:28 -070013#include "aos/util/file.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080014#include "glog/logging.h"
Austin Schuh6f3babe2020-01-26 20:34:50 -080015#include "gmock/gmock.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080016#include "gtest/gtest.h"
17
Austin Schuh3bd4c402020-11-06 18:19:06 -080018#ifdef LZMA
19#include "aos/events/logging/lzma_encoder.h"
20#endif
21
Austin Schuhe309d2a2019-11-29 13:25:21 -080022namespace aos {
23namespace logger {
24namespace testing {
25
26namespace chrono = std::chrono;
Austin Schuh0de30f32020-12-06 12:44:28 -080027using aos::message_bridge::RemoteMessage;
Austin Schuh01b4c352020-09-21 23:09:39 -070028using aos::testing::MessageCounter;
Austin Schuhe309d2a2019-11-29 13:25:21 -080029
Austin Schuh25b46712021-01-03 00:04:38 -080030constexpr std::string_view kSingleConfigSha1(
31 "bc8c9c2e31589eae6f0e36d766f6a437643e861d9568b7483106841cf7504dea");
Austin Schuh8c399962020-12-25 21:51:45 -080032constexpr std::string_view kConfigSha1(
Austin Schuh532656d2021-01-11 10:17:18 -080033 "47511a1906dbb59cf9f8ad98ad08e568c718a4deb204c8bbce81ff76cef9095c");
Austin Schuh8c399962020-12-25 21:51:45 -080034
Austin Schuhe309d2a2019-11-29 13:25:21 -080035class LoggerTest : public ::testing::Test {
36 public:
37 LoggerTest()
38 : config_(
39 aos::configuration::ReadConfig("aos/events/pingpong_config.json")),
40 event_loop_factory_(&config_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080041 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080042 ping_(ping_event_loop_.get()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080043 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080044 pong_(pong_event_loop_.get()) {}
45
46 // Config and factory.
47 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
48 SimulatedEventLoopFactory event_loop_factory_;
49
50 // Event loop and app for Ping
51 std::unique_ptr<EventLoop> ping_event_loop_;
52 Ping ping_;
53
54 // Event loop and app for Pong
55 std::unique_ptr<EventLoop> pong_event_loop_;
56 Pong pong_;
57};
58
Brian Silverman1f345222020-09-24 21:14:48 -070059using LoggerDeathTest = LoggerTest;
60
Austin Schuhe309d2a2019-11-29 13:25:21 -080061// Tests that we can startup at all. This confirms that the channels are all in
62// the config.
63TEST_F(LoggerTest, Starts) {
Austin Schuhc243b422020-10-11 15:35:08 -070064 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -070065 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -080066 const ::std::string config =
67 absl::StrCat(base_name, kSingleConfigSha1, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -070068 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuhe309d2a2019-11-29 13:25:21 -080069 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -080070 unlink(config.c_str());
Austin Schuhe309d2a2019-11-29 13:25:21 -080071 unlink(logfile.c_str());
72
73 LOG(INFO) << "Logging data to " << logfile;
74
75 {
Austin Schuhe309d2a2019-11-29 13:25:21 -080076 std::unique_ptr<EventLoop> logger_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080077 event_loop_factory_.MakeEventLoop("logger");
Austin Schuhe309d2a2019-11-29 13:25:21 -080078
79 event_loop_factory_.RunFor(chrono::milliseconds(95));
80
Brian Silverman1f345222020-09-24 21:14:48 -070081 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -080082 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -070083 logger.set_polling_period(std::chrono::milliseconds(100));
84 logger.StartLoggingLocalNamerOnRun(base_name);
Austin Schuhe309d2a2019-11-29 13:25:21 -080085 event_loop_factory_.RunFor(chrono::milliseconds(20000));
86 }
87
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080088 // Even though it doesn't make any difference here, exercise the logic for
89 // passing in a separate config.
90 LogReader reader(logfile, &config_.message());
Austin Schuhe309d2a2019-11-29 13:25:21 -080091
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080092 // Confirm that we can remap logged channels to point to new buses.
93 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
Austin Schuhe309d2a2019-11-29 13:25:21 -080094
Austin Schuh15649d62019-12-28 16:36:38 -080095 // This sends out the fetched messages and advances time to the start of the
96 // log file.
James Kuszmaul84ff3e52020-01-03 19:48:53 -080097 reader.Register();
Austin Schuhe309d2a2019-11-29 13:25:21 -080098
Austin Schuh6f3babe2020-01-26 20:34:50 -080099 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(nullptr));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800100
Austin Schuhe309d2a2019-11-29 13:25:21 -0800101 std::unique_ptr<EventLoop> test_event_loop =
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800102 reader.event_loop_factory()->MakeEventLoop("log_reader");
Austin Schuhe309d2a2019-11-29 13:25:21 -0800103
104 int ping_count = 10;
105 int pong_count = 10;
106
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -0800107 // Confirm that the ping value matches in the remapped channel location.
108 test_event_loop->MakeWatcher("/original/test",
Austin Schuhe309d2a2019-11-29 13:25:21 -0800109 [&ping_count](const examples::Ping &ping) {
110 EXPECT_EQ(ping.value(), ping_count + 1);
111 ++ping_count;
112 });
113 // Confirm that the ping and pong counts both match, and the value also
114 // matches.
115 test_event_loop->MakeWatcher(
116 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
117 EXPECT_EQ(pong.value(), pong_count + 1);
118 ++pong_count;
119 EXPECT_EQ(ping_count, pong_count);
120 });
121
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800122 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
Austin Schuhe309d2a2019-11-29 13:25:21 -0800123 EXPECT_EQ(ping_count, 2010);
Austin Schuhe309d2a2019-11-29 13:25:21 -0800124}
125
Brian Silverman1f345222020-09-24 21:14:48 -0700126// Tests calling StartLogging twice.
127TEST_F(LoggerDeathTest, ExtraStart) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800128 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700129 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800130 const ::std::string config1 =
131 absl::StrCat(base_name1, kSingleConfigSha1, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700132 const ::std::string logfile1 = base_name1 + ".part0.bfbs";
133 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800134 const ::std::string config2 =
135 absl::StrCat(base_name2, kSingleConfigSha1, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700136 const ::std::string logfile2 = base_name2 + ".part0.bfbs";
137 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800138 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700139 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800140 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700141
142 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
143
144 {
145 std::unique_ptr<EventLoop> logger_event_loop =
146 event_loop_factory_.MakeEventLoop("logger");
147
148 event_loop_factory_.RunFor(chrono::milliseconds(95));
149
150 Logger logger(logger_event_loop.get());
151 logger.set_polling_period(std::chrono::milliseconds(100));
152 logger_event_loop->OnRun(
153 [base_name1, base_name2, &logger_event_loop, &logger]() {
154 logger.StartLogging(std::make_unique<LocalLogNamer>(
155 base_name1, logger_event_loop->node()));
156 EXPECT_DEATH(logger.StartLogging(std::make_unique<LocalLogNamer>(
157 base_name2, logger_event_loop->node())),
158 "Already logging");
159 });
160 event_loop_factory_.RunFor(chrono::milliseconds(20000));
161 }
162}
163
164// Tests calling StopLogging twice.
165TEST_F(LoggerDeathTest, ExtraStop) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800166 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700167 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800168 const ::std::string config =
169 absl::StrCat(base_name, kSingleConfigSha1, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700170 const ::std::string logfile = base_name + ".part0.bfbs";
171 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800172 unlink(config.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700173 unlink(logfile.c_str());
174
175 LOG(INFO) << "Logging data to " << logfile;
176
177 {
178 std::unique_ptr<EventLoop> logger_event_loop =
179 event_loop_factory_.MakeEventLoop("logger");
180
181 event_loop_factory_.RunFor(chrono::milliseconds(95));
182
183 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800184 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700185 logger.set_polling_period(std::chrono::milliseconds(100));
186 logger_event_loop->OnRun([base_name, &logger_event_loop, &logger]() {
187 logger.StartLogging(std::make_unique<LocalLogNamer>(
188 base_name, logger_event_loop->node()));
189 logger.StopLogging(aos::monotonic_clock::min_time);
190 EXPECT_DEATH(logger.StopLogging(aos::monotonic_clock::min_time),
191 "Not logging right now");
192 });
193 event_loop_factory_.RunFor(chrono::milliseconds(20000));
194 }
195}
196
197// Tests that we can startup twice.
198TEST_F(LoggerTest, StartsTwice) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800199 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700200 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800201 const ::std::string config1 =
202 absl::StrCat(base_name1, kSingleConfigSha1, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700203 const ::std::string logfile1 = base_name1 + ".part0.bfbs";
204 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800205 const ::std::string config2 =
206 absl::StrCat(base_name2, kSingleConfigSha1, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700207 const ::std::string logfile2 = base_name2 + ".part0.bfbs";
208 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800209 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700210 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800211 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700212
213 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
214
215 {
216 std::unique_ptr<EventLoop> logger_event_loop =
217 event_loop_factory_.MakeEventLoop("logger");
218
219 event_loop_factory_.RunFor(chrono::milliseconds(95));
220
221 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800222 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700223 logger.set_polling_period(std::chrono::milliseconds(100));
224 logger.StartLogging(
225 std::make_unique<LocalLogNamer>(base_name1, logger_event_loop->node()));
226 event_loop_factory_.RunFor(chrono::milliseconds(10000));
227 logger.StopLogging(logger_event_loop->monotonic_now());
228 event_loop_factory_.RunFor(chrono::milliseconds(10000));
229 logger.StartLogging(
230 std::make_unique<LocalLogNamer>(base_name2, logger_event_loop->node()));
231 event_loop_factory_.RunFor(chrono::milliseconds(10000));
232 }
233
234 for (const auto &logfile :
235 {std::make_tuple(logfile1, 10), std::make_tuple(logfile2, 2010)}) {
236 SCOPED_TRACE(std::get<0>(logfile));
237 LogReader reader(std::get<0>(logfile));
238 reader.Register();
239
240 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(nullptr));
241
242 std::unique_ptr<EventLoop> test_event_loop =
243 reader.event_loop_factory()->MakeEventLoop("log_reader");
244
245 int ping_count = std::get<1>(logfile);
246 int pong_count = std::get<1>(logfile);
247
248 // Confirm that the ping and pong counts both match, and the value also
249 // matches.
250 test_event_loop->MakeWatcher("/test",
251 [&ping_count](const examples::Ping &ping) {
252 EXPECT_EQ(ping.value(), ping_count + 1);
253 ++ping_count;
254 });
255 test_event_loop->MakeWatcher(
256 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
257 EXPECT_EQ(pong.value(), pong_count + 1);
258 ++pong_count;
259 EXPECT_EQ(ping_count, pong_count);
260 });
261
262 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
263 EXPECT_EQ(ping_count, std::get<1>(logfile) + 1000);
264 }
265}
266
Austin Schuhfa895892020-01-07 20:07:41 -0800267// Tests that we can read and write rotated log files.
268TEST_F(LoggerTest, RotatedLogFile) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800269 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700270 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800271 const ::std::string config =
272 absl::StrCat(base_name, kSingleConfigSha1, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700273 const ::std::string logfile0 = base_name + ".part0.bfbs";
274 const ::std::string logfile1 = base_name + ".part1.bfbs";
Austin Schuhfa895892020-01-07 20:07:41 -0800275 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800276 unlink(config.c_str());
Austin Schuhfa895892020-01-07 20:07:41 -0800277 unlink(logfile0.c_str());
278 unlink(logfile1.c_str());
279
280 LOG(INFO) << "Logging data to " << logfile0 << " and " << logfile1;
281
282 {
Austin Schuhfa895892020-01-07 20:07:41 -0800283 std::unique_ptr<EventLoop> logger_event_loop =
284 event_loop_factory_.MakeEventLoop("logger");
285
286 event_loop_factory_.RunFor(chrono::milliseconds(95));
287
Brian Silverman1f345222020-09-24 21:14:48 -0700288 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800289 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700290 logger.set_polling_period(std::chrono::milliseconds(100));
291 logger.StartLoggingLocalNamerOnRun(base_name);
Austin Schuhfa895892020-01-07 20:07:41 -0800292 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700293 logger.Rotate();
Austin Schuhfa895892020-01-07 20:07:41 -0800294 event_loop_factory_.RunFor(chrono::milliseconds(10000));
295 }
296
Austin Schuh64fab802020-09-09 22:47:47 -0700297 {
298 // Confirm that the UUIDs match for both the parts and the logger, and the
299 // parts_index increments.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800300 std::vector<SizePrefixedFlatbufferVector<LogFileHeader>> log_header;
Austin Schuh64fab802020-09-09 22:47:47 -0700301 for (std::string_view f : {logfile0, logfile1}) {
Austin Schuh3bd4c402020-11-06 18:19:06 -0800302 log_header.emplace_back(ReadHeader(f).value());
Austin Schuh64fab802020-09-09 22:47:47 -0700303 }
304
Brian Silvermanae7c0332020-09-30 16:58:23 -0700305 EXPECT_EQ(log_header[0].message().log_event_uuid()->string_view(),
306 log_header[1].message().log_event_uuid()->string_view());
Austin Schuh64fab802020-09-09 22:47:47 -0700307 EXPECT_EQ(log_header[0].message().parts_uuid()->string_view(),
308 log_header[1].message().parts_uuid()->string_view());
309
310 EXPECT_EQ(log_header[0].message().parts_index(), 0);
311 EXPECT_EQ(log_header[1].message().parts_index(), 1);
312 }
313
Austin Schuhfa895892020-01-07 20:07:41 -0800314 // Even though it doesn't make any difference here, exercise the logic for
315 // passing in a separate config.
Austin Schuh287d43d2020-12-04 20:19:33 -0800316 LogReader reader(SortParts({logfile0, logfile1}), &config_.message());
Austin Schuhfa895892020-01-07 20:07:41 -0800317
318 // Confirm that we can remap logged channels to point to new buses.
319 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
320
321 // This sends out the fetched messages and advances time to the start of the
322 // log file.
323 reader.Register();
324
Austin Schuh6f3babe2020-01-26 20:34:50 -0800325 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800326
327 std::unique_ptr<EventLoop> test_event_loop =
328 reader.event_loop_factory()->MakeEventLoop("log_reader");
329
330 int ping_count = 10;
331 int pong_count = 10;
332
333 // Confirm that the ping value matches in the remapped channel location.
334 test_event_loop->MakeWatcher("/original/test",
335 [&ping_count](const examples::Ping &ping) {
336 EXPECT_EQ(ping.value(), ping_count + 1);
337 ++ping_count;
338 });
339 // Confirm that the ping and pong counts both match, and the value also
340 // matches.
341 test_event_loop->MakeWatcher(
342 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
343 EXPECT_EQ(pong.value(), pong_count + 1);
344 ++pong_count;
345 EXPECT_EQ(ping_count, pong_count);
346 });
347
348 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
349 EXPECT_EQ(ping_count, 2010);
350}
351
Austin Schuh4c4e0092019-12-22 16:18:03 -0800352// Tests that a large number of messages per second doesn't overwhelm writev.
353TEST_F(LoggerTest, ManyMessages) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800354 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700355 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800356 const ::std::string config =
357 absl::StrCat(base_name, kSingleConfigSha1, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700358 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800359 // Remove the log file.
Austin Schuh25b46712021-01-03 00:04:38 -0800360 unlink(config.c_str());
Austin Schuh4c4e0092019-12-22 16:18:03 -0800361 unlink(logfile.c_str());
362
363 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700364 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800365
366 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800367 std::unique_ptr<EventLoop> logger_event_loop =
368 event_loop_factory_.MakeEventLoop("logger");
369
370 std::unique_ptr<EventLoop> ping_spammer_event_loop =
371 event_loop_factory_.MakeEventLoop("ping_spammer");
372 aos::Sender<examples::Ping> ping_sender =
373 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
374
375 aos::TimerHandler *timer_handler =
376 ping_spammer_event_loop->AddTimer([&ping_sender]() {
377 aos::Sender<examples::Ping>::Builder builder =
378 ping_sender.MakeBuilder();
379 examples::Ping::Builder ping_builder =
380 builder.MakeBuilder<examples::Ping>();
381 CHECK(builder.Send(ping_builder.Finish()));
382 });
383
384 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
385 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
386 timer_handler->Setup(ping_spammer_event_loop->monotonic_now(),
387 chrono::microseconds(50));
388 });
389
Brian Silverman1f345222020-09-24 21:14:48 -0700390 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800391 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700392 logger.set_polling_period(std::chrono::milliseconds(100));
393 logger.StartLoggingLocalNamerOnRun(base_name);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800394
395 event_loop_factory_.RunFor(chrono::milliseconds(1000));
396 }
397}
398
Austin Schuh25b46712021-01-03 00:04:38 -0800399std::vector<std::string> MakeLogFiles(std::string logfile_base1,
400 std::string logfile_base2) {
Austin Schuh315b96b2020-12-11 21:21:12 -0800401 return std::vector<std::string>(
Austin Schuh8c399962020-12-25 21:51:45 -0800402 {logfile_base1 + "_pi1_data.part0.bfbs",
403 logfile_base1 + "_pi2_data/test/aos.examples.Pong.part0.bfbs",
404 logfile_base1 + "_pi2_data/test/aos.examples.Pong.part1.bfbs",
405 logfile_base2 + "_pi2_data.part0.bfbs",
406 logfile_base1 + "_timestamps/pi1/aos/remote_timestamps/pi2/"
407 "aos.message_bridge.RemoteMessage.part0.bfbs",
408 logfile_base1 + "_timestamps/pi1/aos/remote_timestamps/pi2/"
409 "aos.message_bridge.RemoteMessage.part1.bfbs",
410 logfile_base2 + "_timestamps/pi2/aos/remote_timestamps/pi1/"
411 "aos.message_bridge.RemoteMessage.part0.bfbs",
412 logfile_base2 + "_timestamps/pi2/aos/remote_timestamps/pi1/"
413 "aos.message_bridge.RemoteMessage.part1.bfbs",
414 logfile_base2 +
Austin Schuh315b96b2020-12-11 21:21:12 -0800415 "_pi1_data/pi1/aos/aos.message_bridge.Timestamp.part0.bfbs",
Austin Schuh8c399962020-12-25 21:51:45 -0800416 logfile_base2 +
Austin Schuh315b96b2020-12-11 21:21:12 -0800417 "_pi1_data/pi1/aos/aos.message_bridge.Timestamp.part1.bfbs",
Austin Schuh8c399962020-12-25 21:51:45 -0800418 logfile_base1 +
Austin Schuh315b96b2020-12-11 21:21:12 -0800419 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part0.bfbs",
Austin Schuh8c399962020-12-25 21:51:45 -0800420 logfile_base1 +
421 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part1.bfbs",
422 absl::StrCat(logfile_base1, "_", kConfigSha1, ".bfbs"),
423 absl::StrCat(logfile_base2, "_", kConfigSha1, ".bfbs")});
Austin Schuh315b96b2020-12-11 21:21:12 -0800424}
425
Austin Schuh15649d62019-12-28 16:36:38 -0800426class MultinodeLoggerTest : public ::testing::Test {
427 public:
428 MultinodeLoggerTest()
429 : config_(aos::configuration::ReadConfig(
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800430 "aos/events/logging/multinode_pingpong_config.json")),
Austin Schuh87dd3832021-01-01 23:07:31 -0800431 time_converter_(configuration::NodesCount(&config_.message())),
Austin Schuhac0771c2020-01-07 18:36:30 -0800432 event_loop_factory_(&config_.message()),
Austin Schuhcde938c2020-02-02 17:30:07 -0800433 pi1_(
434 configuration::GetNode(event_loop_factory_.configuration(), "pi1")),
Austin Schuh87dd3832021-01-01 23:07:31 -0800435 pi1_index_(configuration::GetNodeIndex(
436 event_loop_factory_.configuration(), pi1_)),
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700437 pi2_(
438 configuration::GetNode(event_loop_factory_.configuration(), "pi2")),
Austin Schuh87dd3832021-01-01 23:07:31 -0800439 pi2_index_(configuration::GetNodeIndex(
440 event_loop_factory_.configuration(), pi2_)),
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800441 tmp_dir_(aos::testing::TestTmpDir()),
Austin Schuh8c399962020-12-25 21:51:45 -0800442 logfile_base1_(tmp_dir_ + "/multi_logfile1"),
443 logfile_base2_(tmp_dir_ + "/multi_logfile2"),
Austin Schuh315b96b2020-12-11 21:21:12 -0800444 pi1_reboot_logfiles_(
Austin Schuh8c399962020-12-25 21:51:45 -0800445 {logfile_base1_ + "_pi1_data.part0.bfbs",
446 logfile_base1_ + "_pi2_data/test/aos.examples.Pong.part0.bfbs",
447 logfile_base1_ + "_pi2_data/test/aos.examples.Pong.part1.bfbs",
448 logfile_base1_ + "_pi2_data/test/aos.examples.Pong.part2.bfbs",
449 logfile_base1_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
450 "aos.message_bridge.RemoteMessage.part0.bfbs",
451 logfile_base1_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
452 "aos.message_bridge.RemoteMessage.part1.bfbs",
453 logfile_base1_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
454 "aos.message_bridge.RemoteMessage.part2.bfbs",
455 logfile_base1_ +
Austin Schuh2f8fd752020-09-01 22:38:28 -0700456 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part0.bfbs",
Austin Schuh8c399962020-12-25 21:51:45 -0800457 logfile_base1_ +
Austin Schuh315b96b2020-12-11 21:21:12 -0800458 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part1.bfbs",
Austin Schuh8c399962020-12-25 21:51:45 -0800459 logfile_base1_ +
460 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part2.bfbs",
461 absl::StrCat(logfile_base1_, "_", kConfigSha1, ".bfbs")}),
462 logfiles_(MakeLogFiles(logfile_base1_, logfile_base2_)),
Austin Schuhc9049732020-12-21 22:27:15 -0800463 pi1_single_direction_logfiles_(
Austin Schuh8c399962020-12-25 21:51:45 -0800464 {logfile_base1_ + "_pi1_data.part0.bfbs",
465 logfile_base1_ + "_pi2_data/test/aos.examples.Pong.part0.bfbs",
466 logfile_base1_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
467 "aos.message_bridge.RemoteMessage.part0.bfbs",
468 logfile_base1_ +
469 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part0.bfbs",
470 absl::StrCat(logfile_base1_, "_", kConfigSha1, ".bfbs")}),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700471 structured_logfiles_{
472 std::vector<std::string>{logfiles_[0]},
473 std::vector<std::string>{logfiles_[1], logfiles_[2]},
474 std::vector<std::string>{logfiles_[3]},
475 std::vector<std::string>{logfiles_[4], logfiles_[5]},
476 std::vector<std::string>{logfiles_[6], logfiles_[7]},
477 std::vector<std::string>{logfiles_[8], logfiles_[9]},
478 std::vector<std::string>{logfiles_[10], logfiles_[11]}},
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700479 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping", pi1_)),
480 ping_(ping_event_loop_.get()),
481 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong", pi2_)),
482 pong_(pong_event_loop_.get()) {
Austin Schuh87dd3832021-01-01 23:07:31 -0800483 event_loop_factory_.SetTimeConverter(&time_converter_);
484
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700485 // Go through and remove the logfiles if they already exist.
486 for (const auto file : logfiles_) {
487 unlink(file.c_str());
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800488 unlink((file + ".xz").c_str());
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700489 }
490
Austin Schuh25b46712021-01-03 00:04:38 -0800491 for (const auto file :
492 MakeLogFiles(tmp_dir_ + "/relogged1", tmp_dir_ + "/relogged2")) {
Austin Schuh315b96b2020-12-11 21:21:12 -0800493 unlink(file.c_str());
494 }
495
496 for (const auto file : pi1_reboot_logfiles_) {
497 unlink(file.c_str());
498 }
499
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700500 LOG(INFO) << "Logging data to " << logfiles_[0] << ", " << logfiles_[1]
501 << " and " << logfiles_[2];
502 }
503
504 struct LoggerState {
505 std::unique_ptr<EventLoop> event_loop;
506 std::unique_ptr<Logger> logger;
507 };
508
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700509 LoggerState MakeLogger(const Node *node,
510 SimulatedEventLoopFactory *factory = nullptr) {
511 if (factory == nullptr) {
512 factory = &event_loop_factory_;
513 }
514 return {factory->MakeEventLoop("logger", node), {}};
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700515 }
516
Austin Schuh3bd4c402020-11-06 18:19:06 -0800517 void StartLogger(LoggerState *logger, std::string logfile_base = "",
518 bool compress = false) {
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700519 if (logfile_base.empty()) {
Austin Schuh8c399962020-12-25 21:51:45 -0800520 if (logger->event_loop->node()->name()->string_view() == "pi1") {
521 logfile_base = logfile_base1_;
522 } else {
523 logfile_base = logfile_base2_;
524 }
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700525 }
526
Brian Silverman1f345222020-09-24 21:14:48 -0700527 logger->logger = std::make_unique<Logger>(logger->event_loop.get());
528 logger->logger->set_polling_period(std::chrono::milliseconds(100));
Austin Schuh0ca51f32020-12-25 21:51:45 -0800529 logger->logger->set_name(absl::StrCat(
530 "name_prefix_", logger->event_loop->node()->name()->str()));
Austin Schuh3bd4c402020-11-06 18:19:06 -0800531 logger->event_loop->OnRun([logger, logfile_base, compress]() {
532 std::unique_ptr<MultiNodeLogNamer> namer =
533 std::make_unique<MultiNodeLogNamer>(
534 logfile_base, logger->event_loop->configuration(),
535 logger->event_loop->node());
536 if (compress) {
537#ifdef LZMA
538 namer->set_extension(".xz");
539 namer->set_encoder_factory(
540 []() { return std::make_unique<aos::logger::LzmaEncoder>(3); });
541#else
542 LOG(FATAL) << "Compression unsupported";
543#endif
544 }
545
546 logger->logger->StartLogging(std::move(namer));
Brian Silverman1f345222020-09-24 21:14:48 -0700547 });
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700548 }
Austin Schuh15649d62019-12-28 16:36:38 -0800549
Austin Schuh3bd4c402020-11-06 18:19:06 -0800550 void VerifyParts(const std::vector<LogFile> &sorted_parts,
551 const std::vector<std::string> &corrupted_parts = {}) {
552 EXPECT_EQ(sorted_parts.size(), 2u);
553
554 // Count up the number of UUIDs and make sure they are what we expect as a
555 // sanity check.
556 std::set<std::string> log_event_uuids;
557 std::set<std::string> parts_uuids;
558 std::set<std::string> both_uuids;
559
560 size_t missing_rt_count = 0;
561
562 std::vector<std::string> logger_nodes;
563 for (const LogFile &log_file : sorted_parts) {
564 EXPECT_FALSE(log_file.log_event_uuid.empty());
565 log_event_uuids.insert(log_file.log_event_uuid);
566 logger_nodes.emplace_back(log_file.logger_node);
567 both_uuids.insert(log_file.log_event_uuid);
Austin Schuh0ca51f32020-12-25 21:51:45 -0800568 EXPECT_TRUE(log_file.config);
569 EXPECT_EQ(log_file.name,
570 absl::StrCat("name_prefix_", log_file.logger_node));
Austin Schuh3bd4c402020-11-06 18:19:06 -0800571
572 for (const LogParts &part : log_file.parts) {
573 EXPECT_NE(part.monotonic_start_time, aos::monotonic_clock::min_time)
574 << ": " << part;
575 missing_rt_count +=
576 part.realtime_start_time == aos::realtime_clock::min_time;
577
578 EXPECT_TRUE(log_event_uuids.find(part.log_event_uuid) !=
579 log_event_uuids.end());
580 EXPECT_NE(part.node, "");
Austin Schuh0ca51f32020-12-25 21:51:45 -0800581 EXPECT_TRUE(log_file.config);
Austin Schuh3bd4c402020-11-06 18:19:06 -0800582 parts_uuids.insert(part.parts_uuid);
583 both_uuids.insert(part.parts_uuid);
584 }
585 }
586
587 // We won't have RT timestamps for 5 log files. We don't log the RT start
588 // time on remote nodes because we don't know it and would be guessing. And
589 // the log reader can actually do a better job.
590 EXPECT_EQ(missing_rt_count, 5u);
591
592 EXPECT_EQ(log_event_uuids.size(), 2u);
593 EXPECT_EQ(parts_uuids.size(), ToLogReaderVector(sorted_parts).size());
594 EXPECT_EQ(log_event_uuids.size() + parts_uuids.size(), both_uuids.size());
595
596 // Test that each list of parts is in order. Don't worry about the ordering
597 // between part file lists though.
598 // (inner vectors all need to be in order, but outer one doesn't matter).
599 EXPECT_THAT(ToLogReaderVector(sorted_parts),
600 ::testing::UnorderedElementsAreArray(structured_logfiles_));
601
602 EXPECT_THAT(logger_nodes, ::testing::UnorderedElementsAre("pi1", "pi2"));
603
604 EXPECT_NE(sorted_parts[0].realtime_start_time,
605 aos::realtime_clock::min_time);
606 EXPECT_NE(sorted_parts[1].realtime_start_time,
607 aos::realtime_clock::min_time);
608
609 EXPECT_NE(sorted_parts[0].monotonic_start_time,
610 aos::monotonic_clock::min_time);
611 EXPECT_NE(sorted_parts[1].monotonic_start_time,
612 aos::monotonic_clock::min_time);
613
614 EXPECT_THAT(sorted_parts[0].corrupted, ::testing::Eq(corrupted_parts));
615 EXPECT_THAT(sorted_parts[1].corrupted, ::testing::Eq(corrupted_parts));
616 }
617
Austin Schuhc9049732020-12-21 22:27:15 -0800618 void ConfirmReadable(const std::vector<std::string> &files) {
619 LogReader reader(SortParts(files));
620
621 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
622 reader.Register(&log_reader_factory);
623
624 log_reader_factory.Run();
625
626 reader.Deregister();
627 }
628
Austin Schuh3bd4c402020-11-06 18:19:06 -0800629 void AddExtension(std::string_view extension) {
630 std::transform(logfiles_.begin(), logfiles_.end(), logfiles_.begin(),
631 [extension](const std::string &in) {
632 return absl::StrCat(in, extension);
633 });
634
635 std::transform(structured_logfiles_.begin(), structured_logfiles_.end(),
636 structured_logfiles_.begin(),
637 [extension](std::vector<std::string> in) {
638 std::transform(in.begin(), in.end(), in.begin(),
639 [extension](const std::string &in_str) {
640 return absl::StrCat(in_str, extension);
641 });
642 return in;
643 });
644 }
645
Austin Schuh15649d62019-12-28 16:36:38 -0800646 // Config and factory.
647 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
Austin Schuh87dd3832021-01-01 23:07:31 -0800648 message_bridge::TestingTimeConverter time_converter_;
Austin Schuh15649d62019-12-28 16:36:38 -0800649 SimulatedEventLoopFactory event_loop_factory_;
650
Austin Schuh87dd3832021-01-01 23:07:31 -0800651 const Node *const pi1_;
652 const size_t pi1_index_;
653 const Node *const pi2_;
654 const size_t pi2_index_;
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700655
656 std::string tmp_dir_;
Austin Schuh8c399962020-12-25 21:51:45 -0800657 std::string logfile_base1_;
658 std::string logfile_base2_;
Austin Schuh315b96b2020-12-11 21:21:12 -0800659 std::vector<std::string> pi1_reboot_logfiles_;
Austin Schuh2f8fd752020-09-01 22:38:28 -0700660 std::vector<std::string> logfiles_;
Austin Schuhc9049732020-12-21 22:27:15 -0800661 std::vector<std::string> pi1_single_direction_logfiles_;
Austin Schuh2f8fd752020-09-01 22:38:28 -0700662
663 std::vector<std::vector<std::string>> structured_logfiles_;
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700664
665 std::unique_ptr<EventLoop> ping_event_loop_;
666 Ping ping_;
667 std::unique_ptr<EventLoop> pong_event_loop_;
668 Pong pong_;
Austin Schuh15649d62019-12-28 16:36:38 -0800669};
670
Austin Schuh391e3172020-09-01 22:48:18 -0700671// Counts the number of messages on a channel. Returns (channel name, channel
672// type, count) for every message matching matcher()
673std::vector<std::tuple<std::string, std::string, int>> CountChannelsMatching(
Austin Schuh25b46712021-01-03 00:04:38 -0800674 std::shared_ptr<const aos::Configuration> config, std::string_view filename,
Austin Schuh6f3babe2020-01-26 20:34:50 -0800675 std::function<bool(const MessageHeader *)> matcher) {
676 MessageReader message_reader(filename);
Austin Schuh8c399962020-12-25 21:51:45 -0800677 std::vector<int> counts(config->channels()->size(), 0);
Austin Schuh15649d62019-12-28 16:36:38 -0800678
Austin Schuh6f3babe2020-01-26 20:34:50 -0800679 while (true) {
Austin Schuhadd6eb32020-11-09 21:24:26 -0800680 std::optional<SizePrefixedFlatbufferVector<MessageHeader>> msg =
Austin Schuh6f3babe2020-01-26 20:34:50 -0800681 message_reader.ReadMessage();
682 if (!msg) {
683 break;
684 }
685
686 if (matcher(&msg.value().message())) {
687 counts[msg.value().message().channel_index()]++;
688 }
689 }
690
Austin Schuh391e3172020-09-01 22:48:18 -0700691 std::vector<std::tuple<std::string, std::string, int>> result;
Austin Schuh6f3babe2020-01-26 20:34:50 -0800692 int channel = 0;
693 for (size_t i = 0; i < counts.size(); ++i) {
694 if (counts[i] != 0) {
Austin Schuh8c399962020-12-25 21:51:45 -0800695 const Channel *channel = config->channels()->Get(i);
Austin Schuh391e3172020-09-01 22:48:18 -0700696 result.push_back(std::make_tuple(channel->name()->str(),
697 channel->type()->str(), counts[i]));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800698 }
699 ++channel;
700 }
701
702 return result;
703}
704
705// Counts the number of messages (channel, count) for all data messages.
Austin Schuh391e3172020-09-01 22:48:18 -0700706std::vector<std::tuple<std::string, std::string, int>> CountChannelsData(
Austin Schuh8c399962020-12-25 21:51:45 -0800707 std::shared_ptr<const aos::Configuration> config,
Austin Schuh391e3172020-09-01 22:48:18 -0700708 std::string_view filename) {
Austin Schuh8c399962020-12-25 21:51:45 -0800709 return CountChannelsMatching(config, filename, [](const MessageHeader *msg) {
Austin Schuh6f3babe2020-01-26 20:34:50 -0800710 if (msg->has_data()) {
711 CHECK(!msg->has_monotonic_remote_time());
712 CHECK(!msg->has_realtime_remote_time());
713 CHECK(!msg->has_remote_queue_index());
714 return true;
715 }
716 return false;
717 });
718}
719
720// Counts the number of messages (channel, count) for all timestamp messages.
Austin Schuh391e3172020-09-01 22:48:18 -0700721std::vector<std::tuple<std::string, std::string, int>> CountChannelsTimestamp(
Austin Schuh8c399962020-12-25 21:51:45 -0800722 std::shared_ptr<const aos::Configuration> config,
Austin Schuh6f3babe2020-01-26 20:34:50 -0800723 std::string_view filename) {
Austin Schuh8c399962020-12-25 21:51:45 -0800724 return CountChannelsMatching(config, filename, [](const MessageHeader *msg) {
Austin Schuh6f3babe2020-01-26 20:34:50 -0800725 if (!msg->has_data()) {
726 CHECK(msg->has_monotonic_remote_time());
727 CHECK(msg->has_realtime_remote_time());
728 CHECK(msg->has_remote_queue_index());
729 return true;
730 }
731 return false;
732 });
733}
734
Austin Schuhcde938c2020-02-02 17:30:07 -0800735// Tests that we can write and read simple multi-node log files.
736TEST_F(MultinodeLoggerTest, SimpleMultiNode) {
Austin Schuh87dd3832021-01-01 23:07:31 -0800737 time_converter_.StartEqual();
Austin Schuh15649d62019-12-28 16:36:38 -0800738 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700739 LoggerState pi1_logger = MakeLogger(pi1_);
740 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuh15649d62019-12-28 16:36:38 -0800741
742 event_loop_factory_.RunFor(chrono::milliseconds(95));
743
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700744 StartLogger(&pi1_logger);
745 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800746
Austin Schuh15649d62019-12-28 16:36:38 -0800747 event_loop_factory_.RunFor(chrono::milliseconds(20000));
748 }
749
Austin Schuh6f3babe2020-01-26 20:34:50 -0800750 {
Austin Schuh64fab802020-09-09 22:47:47 -0700751 std::set<std::string> logfile_uuids;
752 std::set<std::string> parts_uuids;
753 // Confirm that we have the expected number of UUIDs for both the logfile
754 // UUIDs and parts UUIDs.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800755 std::vector<SizePrefixedFlatbufferVector<LogFileHeader>> log_header;
Austin Schuh64fab802020-09-09 22:47:47 -0700756 for (std::string_view f : logfiles_) {
Austin Schuh3bd4c402020-11-06 18:19:06 -0800757 log_header.emplace_back(ReadHeader(f).value());
Austin Schuh8c399962020-12-25 21:51:45 -0800758 if (!log_header.back().message().has_configuration()) {
759 logfile_uuids.insert(
760 log_header.back().message().log_event_uuid()->str());
761 parts_uuids.insert(log_header.back().message().parts_uuid()->str());
762 }
Austin Schuh64fab802020-09-09 22:47:47 -0700763 }
Austin Schuh15649d62019-12-28 16:36:38 -0800764
Austin Schuh64fab802020-09-09 22:47:47 -0700765 EXPECT_EQ(logfile_uuids.size(), 2u);
766 EXPECT_EQ(parts_uuids.size(), 7u);
767
768 // And confirm everything is on the correct node.
769 EXPECT_EQ(log_header[0].message().node()->name()->string_view(), "pi1");
770 EXPECT_EQ(log_header[1].message().node()->name()->string_view(), "pi2");
771 EXPECT_EQ(log_header[2].message().node()->name()->string_view(), "pi2");
772 EXPECT_EQ(log_header[3].message().node()->name()->string_view(), "pi2");
773 EXPECT_EQ(log_header[4].message().node()->name()->string_view(), "pi2");
774 EXPECT_EQ(log_header[5].message().node()->name()->string_view(), "pi2");
775 EXPECT_EQ(log_header[6].message().node()->name()->string_view(), "pi1");
776 EXPECT_EQ(log_header[7].message().node()->name()->string_view(), "pi1");
777 EXPECT_EQ(log_header[8].message().node()->name()->string_view(), "pi1");
778 EXPECT_EQ(log_header[9].message().node()->name()->string_view(), "pi1");
779 EXPECT_EQ(log_header[10].message().node()->name()->string_view(), "pi2");
780 EXPECT_EQ(log_header[11].message().node()->name()->string_view(), "pi2");
781
782 // And the parts index matches.
783 EXPECT_EQ(log_header[0].message().parts_index(), 0);
784 EXPECT_EQ(log_header[1].message().parts_index(), 0);
785 EXPECT_EQ(log_header[2].message().parts_index(), 1);
786 EXPECT_EQ(log_header[3].message().parts_index(), 0);
787 EXPECT_EQ(log_header[4].message().parts_index(), 0);
788 EXPECT_EQ(log_header[5].message().parts_index(), 1);
789 EXPECT_EQ(log_header[6].message().parts_index(), 0);
790 EXPECT_EQ(log_header[7].message().parts_index(), 1);
791 EXPECT_EQ(log_header[8].message().parts_index(), 0);
792 EXPECT_EQ(log_header[9].message().parts_index(), 1);
793 EXPECT_EQ(log_header[10].message().parts_index(), 0);
794 EXPECT_EQ(log_header[11].message().parts_index(), 1);
795 }
796
Austin Schuh8c399962020-12-25 21:51:45 -0800797 const std::vector<LogFile> sorted_log_files = SortParts(logfiles_);
Austin Schuh64fab802020-09-09 22:47:47 -0700798 {
Austin Schuh391e3172020-09-01 22:48:18 -0700799 using ::testing::UnorderedElementsAre;
Austin Schuh8c399962020-12-25 21:51:45 -0800800 std::shared_ptr<const aos::Configuration> config =
801 sorted_log_files[0].config;
Austin Schuh391e3172020-09-01 22:48:18 -0700802
Austin Schuh6f3babe2020-01-26 20:34:50 -0800803 // Timing reports, pings
Austin Schuh2f8fd752020-09-01 22:38:28 -0700804 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800805 CountChannelsData(config, logfiles_[0]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700806 UnorderedElementsAre(
807 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 200),
James Kuszmaul4f106fb2021-01-05 20:53:02 -0800808 std::make_tuple("/pi1/aos", "aos.message_bridge.ServerStatistics",
809 21),
810 std::make_tuple("/pi1/aos", "aos.message_bridge.ClientStatistics",
811 200),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700812 std::make_tuple("/pi1/aos", "aos.timing.Report", 40),
Austin Schuh20ac95d2020-12-05 17:24:19 -0800813 std::make_tuple("/test", "aos.examples.Ping", 2001)))
814 << " : " << logfiles_[0];
Austin Schuh6f3babe2020-01-26 20:34:50 -0800815 // Timestamps for pong
Austin Schuh2f8fd752020-09-01 22:38:28 -0700816 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800817 CountChannelsTimestamp(config, logfiles_[0]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700818 UnorderedElementsAre(
819 std::make_tuple("/test", "aos.examples.Pong", 2001),
Austin Schuh20ac95d2020-12-05 17:24:19 -0800820 std::make_tuple("/pi2/aos", "aos.message_bridge.Timestamp", 200)))
821 << " : " << logfiles_[0];
Austin Schuh6f3babe2020-01-26 20:34:50 -0800822
823 // Pong data.
Austin Schuh20ac95d2020-12-05 17:24:19 -0800824 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800825 CountChannelsData(config, logfiles_[1]),
Austin Schuh20ac95d2020-12-05 17:24:19 -0800826 UnorderedElementsAre(std::make_tuple("/test", "aos.examples.Pong", 91)))
827 << " : " << logfiles_[1];
Austin Schuh8c399962020-12-25 21:51:45 -0800828 EXPECT_THAT(CountChannelsData(config, logfiles_[2]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700829 UnorderedElementsAre(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800830 std::make_tuple("/test", "aos.examples.Pong", 1910)))
831 << " : " << logfiles_[1];
Austin Schuh391e3172020-09-01 22:48:18 -0700832
Austin Schuh6f3babe2020-01-26 20:34:50 -0800833 // No timestamps
Austin Schuh25b46712021-01-03 00:04:38 -0800834 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[1]),
835 UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800836 << " : " << logfiles_[1];
Austin Schuh25b46712021-01-03 00:04:38 -0800837 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[2]),
838 UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800839 << " : " << logfiles_[2];
Austin Schuh6f3babe2020-01-26 20:34:50 -0800840
841 // Timing reports and pongs.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700842 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800843 CountChannelsData(config, logfiles_[3]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700844 UnorderedElementsAre(
845 std::make_tuple("/pi2/aos", "aos.message_bridge.Timestamp", 200),
James Kuszmaul4f106fb2021-01-05 20:53:02 -0800846 std::make_tuple("/pi2/aos", "aos.message_bridge.ServerStatistics",
847 21),
848 std::make_tuple("/pi2/aos", "aos.message_bridge.ClientStatistics",
849 200),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700850 std::make_tuple("/pi2/aos", "aos.timing.Report", 40),
Austin Schuh20ac95d2020-12-05 17:24:19 -0800851 std::make_tuple("/test", "aos.examples.Pong", 2001)))
852 << " : " << logfiles_[3];
Austin Schuh6f3babe2020-01-26 20:34:50 -0800853 // And ping timestamps.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700854 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800855 CountChannelsTimestamp(config, logfiles_[3]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700856 UnorderedElementsAre(
857 std::make_tuple("/test", "aos.examples.Ping", 2001),
Austin Schuh20ac95d2020-12-05 17:24:19 -0800858 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 200)))
859 << " : " << logfiles_[3];
Austin Schuh2f8fd752020-09-01 22:38:28 -0700860
861 // Timestamps from pi2 on pi1, and the other way.
Austin Schuh8c399962020-12-25 21:51:45 -0800862 EXPECT_THAT(CountChannelsData(config, logfiles_[4]), UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800863 << " : " << logfiles_[4];
Austin Schuh8c399962020-12-25 21:51:45 -0800864 EXPECT_THAT(CountChannelsData(config, logfiles_[5]), UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800865 << " : " << logfiles_[5];
Austin Schuh8c399962020-12-25 21:51:45 -0800866 EXPECT_THAT(CountChannelsData(config, logfiles_[6]), UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800867 << " : " << logfiles_[6];
Austin Schuh8c399962020-12-25 21:51:45 -0800868 EXPECT_THAT(CountChannelsData(config, logfiles_[7]), UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800869 << " : " << logfiles_[7];
Austin Schuh2f8fd752020-09-01 22:38:28 -0700870 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800871 CountChannelsTimestamp(config, logfiles_[4]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700872 UnorderedElementsAre(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800873 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 9),
874 std::make_tuple("/test", "aos.examples.Ping", 91)))
875 << " : " << logfiles_[4];
Austin Schuh2f8fd752020-09-01 22:38:28 -0700876 EXPECT_THAT(
Austin Schuh8c399962020-12-25 21:51:45 -0800877 CountChannelsTimestamp(config, logfiles_[5]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700878 UnorderedElementsAre(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800879 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 191),
880 std::make_tuple("/test", "aos.examples.Ping", 1910)))
881 << " : " << logfiles_[5];
Austin Schuh8c399962020-12-25 21:51:45 -0800882 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[6]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700883 UnorderedElementsAre(std::make_tuple(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800884 "/pi2/aos", "aos.message_bridge.Timestamp", 9)))
885 << " : " << logfiles_[6];
Austin Schuh8c399962020-12-25 21:51:45 -0800886 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[7]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700887 UnorderedElementsAre(std::make_tuple(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800888 "/pi2/aos", "aos.message_bridge.Timestamp", 191)))
889 << " : " << logfiles_[7];
Austin Schuh2f8fd752020-09-01 22:38:28 -0700890
891 // And then test that the remotely logged timestamp data files only have
892 // timestamps in them.
Austin Schuh25b46712021-01-03 00:04:38 -0800893 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[8]),
894 UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800895 << " : " << logfiles_[8];
Austin Schuh25b46712021-01-03 00:04:38 -0800896 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[9]),
897 UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800898 << " : " << logfiles_[9];
Austin Schuh25b46712021-01-03 00:04:38 -0800899 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[10]),
900 UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800901 << " : " << logfiles_[10];
Austin Schuh25b46712021-01-03 00:04:38 -0800902 EXPECT_THAT(CountChannelsTimestamp(config, logfiles_[11]),
903 UnorderedElementsAre())
Austin Schuh20ac95d2020-12-05 17:24:19 -0800904 << " : " << logfiles_[11];
Austin Schuh2f8fd752020-09-01 22:38:28 -0700905
Austin Schuh8c399962020-12-25 21:51:45 -0800906 EXPECT_THAT(CountChannelsData(config, logfiles_[8]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700907 UnorderedElementsAre(std::make_tuple(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800908 "/pi1/aos", "aos.message_bridge.Timestamp", 9)))
909 << " : " << logfiles_[8];
Austin Schuh8c399962020-12-25 21:51:45 -0800910 EXPECT_THAT(CountChannelsData(config, logfiles_[9]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700911 UnorderedElementsAre(std::make_tuple(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800912 "/pi1/aos", "aos.message_bridge.Timestamp", 191)))
913 << " : " << logfiles_[9];
Austin Schuh2f8fd752020-09-01 22:38:28 -0700914
Austin Schuh8c399962020-12-25 21:51:45 -0800915 EXPECT_THAT(CountChannelsData(config, logfiles_[10]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700916 UnorderedElementsAre(std::make_tuple(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800917 "/pi2/aos", "aos.message_bridge.Timestamp", 9)))
918 << " : " << logfiles_[10];
Austin Schuh8c399962020-12-25 21:51:45 -0800919 EXPECT_THAT(CountChannelsData(config, logfiles_[11]),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700920 UnorderedElementsAre(std::make_tuple(
Austin Schuh20ac95d2020-12-05 17:24:19 -0800921 "/pi2/aos", "aos.message_bridge.Timestamp", 191)))
922 << " : " << logfiles_[11];
Austin Schuh6f3babe2020-01-26 20:34:50 -0800923 }
924
Austin Schuh8c399962020-12-25 21:51:45 -0800925 LogReader reader(sorted_log_files);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800926
Austin Schuh8d7e0bb2020-10-02 17:57:00 -0700927 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
Austin Schuh6331ef92020-01-07 18:28:09 -0800928 log_reader_factory.set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800929
930 // This sends out the fetched messages and advances time to the start of the
931 // log file.
Austin Schuh6331ef92020-01-07 18:28:09 -0800932 reader.Register(&log_reader_factory);
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800933
Austin Schuhac0771c2020-01-07 18:36:30 -0800934 const Node *pi1 =
935 configuration::GetNode(log_reader_factory.configuration(), "pi1");
Austin Schuh6f3babe2020-01-26 20:34:50 -0800936 const Node *pi2 =
937 configuration::GetNode(log_reader_factory.configuration(), "pi2");
Austin Schuhac0771c2020-01-07 18:36:30 -0800938
Austin Schuh2f8fd752020-09-01 22:38:28 -0700939 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
940 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
941 LOG(INFO) << "now pi1 "
942 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
943 LOG(INFO) << "now pi2 "
944 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
945
Austin Schuh6f3babe2020-01-26 20:34:50 -0800946 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800947
948 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800949
Austin Schuh6f3babe2020-01-26 20:34:50 -0800950 std::unique_ptr<EventLoop> pi1_event_loop =
Austin Schuhac0771c2020-01-07 18:36:30 -0800951 log_reader_factory.MakeEventLoop("test", pi1);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800952 std::unique_ptr<EventLoop> pi2_event_loop =
953 log_reader_factory.MakeEventLoop("test", pi2);
Austin Schuh15649d62019-12-28 16:36:38 -0800954
Austin Schuh6f3babe2020-01-26 20:34:50 -0800955 int pi1_ping_count = 10;
956 int pi2_ping_count = 10;
957 int pi1_pong_count = 10;
958 int pi2_pong_count = 10;
Austin Schuh15649d62019-12-28 16:36:38 -0800959
960 // Confirm that the ping value matches.
Austin Schuh6f3babe2020-01-26 20:34:50 -0800961 pi1_event_loop->MakeWatcher(
962 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700963 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800964 << pi1_event_loop->context().monotonic_remote_time << " -> "
965 << pi1_event_loop->context().monotonic_event_time;
966 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
967 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
968 pi1_ping_count * chrono::milliseconds(10) +
969 monotonic_clock::epoch());
970 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
971 pi1_ping_count * chrono::milliseconds(10) +
972 realtime_clock::epoch());
973 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
974 pi1_event_loop->context().monotonic_event_time);
975 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
976 pi1_event_loop->context().realtime_event_time);
Austin Schuh15649d62019-12-28 16:36:38 -0800977
Austin Schuh6f3babe2020-01-26 20:34:50 -0800978 ++pi1_ping_count;
979 });
980 pi2_event_loop->MakeWatcher(
981 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700982 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800983 << pi2_event_loop->context().monotonic_remote_time << " -> "
984 << pi2_event_loop->context().monotonic_event_time;
985 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
986
987 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
988 pi2_ping_count * chrono::milliseconds(10) +
989 monotonic_clock::epoch());
990 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
991 pi2_ping_count * chrono::milliseconds(10) +
992 realtime_clock::epoch());
993 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time +
994 chrono::microseconds(150),
995 pi2_event_loop->context().monotonic_event_time);
996 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time +
997 chrono::microseconds(150),
998 pi2_event_loop->context().realtime_event_time);
999 ++pi2_ping_count;
Austin Schuh15649d62019-12-28 16:36:38 -08001000 });
1001
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001002 constexpr ssize_t kQueueIndexOffset = -9;
Austin Schuh6f3babe2020-01-26 20:34:50 -08001003 // Confirm that the ping and pong counts both match, and the value also
1004 // matches.
1005 pi1_event_loop->MakeWatcher(
1006 "/test", [&pi1_event_loop, &pi1_ping_count,
1007 &pi1_pong_count](const examples::Pong &pong) {
1008 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
1009 << pi1_event_loop->context().monotonic_remote_time << " -> "
1010 << pi1_event_loop->context().monotonic_event_time;
1011
1012 EXPECT_EQ(pi1_event_loop->context().remote_queue_index,
1013 pi1_pong_count + kQueueIndexOffset);
1014 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
1015 chrono::microseconds(200) +
1016 pi1_pong_count * chrono::milliseconds(10) +
1017 monotonic_clock::epoch());
1018 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
1019 chrono::microseconds(200) +
1020 pi1_pong_count * chrono::milliseconds(10) +
1021 realtime_clock::epoch());
1022
1023 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time +
1024 chrono::microseconds(150),
1025 pi1_event_loop->context().monotonic_event_time);
1026 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time +
1027 chrono::microseconds(150),
1028 pi1_event_loop->context().realtime_event_time);
1029
1030 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
1031 ++pi1_pong_count;
1032 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
1033 });
1034 pi2_event_loop->MakeWatcher(
1035 "/test", [&pi2_event_loop, &pi2_ping_count,
1036 &pi2_pong_count](const examples::Pong &pong) {
1037 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
1038 << pi2_event_loop->context().monotonic_remote_time << " -> "
1039 << pi2_event_loop->context().monotonic_event_time;
1040
1041 EXPECT_EQ(pi2_event_loop->context().remote_queue_index,
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001042 pi2_pong_count + kQueueIndexOffset);
Austin Schuh6f3babe2020-01-26 20:34:50 -08001043
1044 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
1045 chrono::microseconds(200) +
1046 pi2_pong_count * chrono::milliseconds(10) +
1047 monotonic_clock::epoch());
1048 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
1049 chrono::microseconds(200) +
1050 pi2_pong_count * chrono::milliseconds(10) +
1051 realtime_clock::epoch());
1052
1053 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
1054 pi2_event_loop->context().monotonic_event_time);
1055 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
1056 pi2_event_loop->context().realtime_event_time);
1057
1058 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
1059 ++pi2_pong_count;
1060 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
1061 });
1062
1063 log_reader_factory.Run();
1064 EXPECT_EQ(pi1_ping_count, 2010);
1065 EXPECT_EQ(pi2_ping_count, 2010);
1066 EXPECT_EQ(pi1_pong_count, 2010);
1067 EXPECT_EQ(pi2_pong_count, 2010);
Austin Schuh6331ef92020-01-07 18:28:09 -08001068
1069 reader.Deregister();
Austin Schuh15649d62019-12-28 16:36:38 -08001070}
1071
James Kuszmaul46d82582020-05-09 19:50:09 -07001072typedef MultinodeLoggerTest MultinodeLoggerDeathTest;
1073
1074// Test that if we feed the replay with a mismatched node list that we die on
1075// the LogReader constructor.
1076TEST_F(MultinodeLoggerDeathTest, MultiNodeBadReplayConfig) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001077 time_converter_.StartEqual();
James Kuszmaul46d82582020-05-09 19:50:09 -07001078 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001079 LoggerState pi1_logger = MakeLogger(pi1_);
1080 LoggerState pi2_logger = MakeLogger(pi2_);
James Kuszmaul46d82582020-05-09 19:50:09 -07001081
1082 event_loop_factory_.RunFor(chrono::milliseconds(95));
1083
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001084 StartLogger(&pi1_logger);
1085 StartLogger(&pi2_logger);
James Kuszmaul46d82582020-05-09 19:50:09 -07001086
James Kuszmaul46d82582020-05-09 19:50:09 -07001087 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1088 }
1089
1090 // Test that, if we add an additional node to the replay config that the
1091 // logger complains about the mismatch in number of nodes.
1092 FlatbufferDetachedBuffer<Configuration> extra_nodes_config =
1093 configuration::MergeWithConfig(&config_.message(), R"({
1094 "nodes": [
1095 {
1096 "name": "extra-node"
1097 }
1098 ]
1099 }
1100 )");
1101
Austin Schuh287d43d2020-12-04 20:19:33 -08001102 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1103 EXPECT_DEATH(LogReader(sorted_parts, &extra_nodes_config.message()),
James Kuszmaul46d82582020-05-09 19:50:09 -07001104 "Log file and replay config need to have matching nodes lists.");
James Kuszmaul46d82582020-05-09 19:50:09 -07001105}
1106
Austin Schuhcde938c2020-02-02 17:30:07 -08001107// Tests that we can read log files where they don't start at the same monotonic
1108// time.
1109TEST_F(MultinodeLoggerTest, StaggeredStart) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001110 time_converter_.StartEqual();
Austin Schuhcde938c2020-02-02 17:30:07 -08001111 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001112 LoggerState pi1_logger = MakeLogger(pi1_);
1113 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuhcde938c2020-02-02 17:30:07 -08001114
1115 event_loop_factory_.RunFor(chrono::milliseconds(95));
1116
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001117 StartLogger(&pi1_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -08001118
1119 event_loop_factory_.RunFor(chrono::milliseconds(200));
1120
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001121 StartLogger(&pi2_logger);
1122
Austin Schuhcde938c2020-02-02 17:30:07 -08001123 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1124 }
1125
Austin Schuh287d43d2020-12-04 20:19:33 -08001126 LogReader reader(SortParts(logfiles_));
Austin Schuhcde938c2020-02-02 17:30:07 -08001127
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001128 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
Austin Schuhcde938c2020-02-02 17:30:07 -08001129 log_reader_factory.set_send_delay(chrono::microseconds(0));
1130
1131 // This sends out the fetched messages and advances time to the start of the
1132 // log file.
1133 reader.Register(&log_reader_factory);
1134
1135 const Node *pi1 =
1136 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1137 const Node *pi2 =
1138 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1139
1140 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
1141
1142 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
1143
1144 std::unique_ptr<EventLoop> pi1_event_loop =
1145 log_reader_factory.MakeEventLoop("test", pi1);
1146 std::unique_ptr<EventLoop> pi2_event_loop =
1147 log_reader_factory.MakeEventLoop("test", pi2);
1148
1149 int pi1_ping_count = 30;
1150 int pi2_ping_count = 30;
1151 int pi1_pong_count = 30;
1152 int pi2_pong_count = 30;
1153
1154 // Confirm that the ping value matches.
1155 pi1_event_loop->MakeWatcher(
1156 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
1157 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
1158 << pi1_event_loop->context().monotonic_remote_time << " -> "
1159 << pi1_event_loop->context().monotonic_event_time;
1160 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
1161
1162 ++pi1_ping_count;
1163 });
1164 pi2_event_loop->MakeWatcher(
1165 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
1166 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
1167 << pi2_event_loop->context().monotonic_remote_time << " -> "
1168 << pi2_event_loop->context().monotonic_event_time;
1169 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
1170
1171 ++pi2_ping_count;
1172 });
1173
1174 // Confirm that the ping and pong counts both match, and the value also
1175 // matches.
1176 pi1_event_loop->MakeWatcher(
1177 "/test", [&pi1_event_loop, &pi1_ping_count,
1178 &pi1_pong_count](const examples::Pong &pong) {
1179 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
1180 << pi1_event_loop->context().monotonic_remote_time << " -> "
1181 << pi1_event_loop->context().monotonic_event_time;
1182
1183 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
1184 ++pi1_pong_count;
1185 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
1186 });
1187 pi2_event_loop->MakeWatcher(
1188 "/test", [&pi2_event_loop, &pi2_ping_count,
1189 &pi2_pong_count](const examples::Pong &pong) {
1190 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
1191 << pi2_event_loop->context().monotonic_remote_time << " -> "
1192 << pi2_event_loop->context().monotonic_event_time;
1193
1194 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
1195 ++pi2_pong_count;
1196 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
1197 });
1198
1199 log_reader_factory.Run();
1200 EXPECT_EQ(pi1_ping_count, 2030);
1201 EXPECT_EQ(pi2_ping_count, 2030);
1202 EXPECT_EQ(pi1_pong_count, 2030);
1203 EXPECT_EQ(pi2_pong_count, 2030);
1204
1205 reader.Deregister();
1206}
Austin Schuh6f3babe2020-01-26 20:34:50 -08001207
Austin Schuh8bd96322020-02-13 21:18:22 -08001208// Tests that we can read log files where the monotonic clocks drift and don't
1209// match correctly. While we are here, also test that different ending times
1210// also is readable.
1211TEST_F(MultinodeLoggerTest, MismatchedClocks) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001212 // TODO(austin): Negate...
1213 const chrono::nanoseconds initial_pi2_offset = chrono::seconds(1000);
1214
1215 time_converter_.AddMonotonic({monotonic_clock::epoch(),
1216 monotonic_clock::epoch() + initial_pi2_offset});
1217 // Wait for 95 ms, (~0.1 seconds - 1/2 of the ping/pong period), and set the
1218 // skew to be 200 uS/s
1219 const chrono::nanoseconds startup_sleep1 = time_converter_.AddMonotonic(
1220 {chrono::milliseconds(95),
1221 chrono::milliseconds(95) - chrono::nanoseconds(200) * 95});
1222 // Run another 200 ms to have one logger start first.
1223 const chrono::nanoseconds startup_sleep2 = time_converter_.AddMonotonic(
1224 {chrono::milliseconds(200), chrono::milliseconds(200)});
1225 // Slew one way then the other at the same 200 uS/S slew rate. Make sure we
1226 // go far enough to cause problems if this isn't accounted for.
1227 const chrono::nanoseconds logger_run1 = time_converter_.AddMonotonic(
1228 {chrono::milliseconds(20000),
1229 chrono::milliseconds(20000) - chrono::nanoseconds(200) * 20000});
1230 const chrono::nanoseconds logger_run2 = time_converter_.AddMonotonic(
1231 {chrono::milliseconds(40000),
1232 chrono::milliseconds(40000) + chrono::nanoseconds(200) * 40000});
1233 const chrono::nanoseconds logger_run3 = time_converter_.AddMonotonic(
1234 {chrono::milliseconds(400), chrono::milliseconds(400)});
1235
Austin Schuhcde938c2020-02-02 17:30:07 -08001236 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001237 LoggerState pi2_logger = MakeLogger(pi2_);
1238
Austin Schuh87dd3832021-01-01 23:07:31 -08001239 NodeEventLoopFactory *pi1 =
1240 event_loop_factory_.GetNodeEventLoopFactory(pi1_);
Austin Schuh8bd96322020-02-13 21:18:22 -08001241 NodeEventLoopFactory *pi2 =
1242 event_loop_factory_.GetNodeEventLoopFactory(pi2_);
1243 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
1244 << pi2->realtime_now() << " distributed "
1245 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -08001246
Austin Schuh8bd96322020-02-13 21:18:22 -08001247 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
1248 << pi2->realtime_now() << " distributed "
1249 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -08001250
Austin Schuh87dd3832021-01-01 23:07:31 -08001251 event_loop_factory_.RunFor(startup_sleep1);
Austin Schuhcde938c2020-02-02 17:30:07 -08001252
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001253 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -08001254
Austin Schuh87dd3832021-01-01 23:07:31 -08001255 event_loop_factory_.RunFor(startup_sleep2);
Austin Schuhcde938c2020-02-02 17:30:07 -08001256
Austin Schuh8bd96322020-02-13 21:18:22 -08001257 {
1258 // Run pi1's logger for only part of the time.
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001259 LoggerState pi1_logger = MakeLogger(pi1_);
Austin Schuh8bd96322020-02-13 21:18:22 -08001260
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001261 StartLogger(&pi1_logger);
Austin Schuh87dd3832021-01-01 23:07:31 -08001262 event_loop_factory_.RunFor(logger_run1);
Austin Schuh8bd96322020-02-13 21:18:22 -08001263
Austin Schuh87dd3832021-01-01 23:07:31 -08001264 // Make sure we slewed time far enough so that the difference is greater
1265 // than the network delay. This confirms that if we sort incorrectly, it
1266 // would show in the results.
1267 EXPECT_LT(
1268 (pi2->monotonic_now() - pi1->monotonic_now()) - initial_pi2_offset,
1269 -event_loop_factory_.send_delay() -
1270 event_loop_factory_.network_delay());
Austin Schuh8bd96322020-02-13 21:18:22 -08001271
Austin Schuh87dd3832021-01-01 23:07:31 -08001272 event_loop_factory_.RunFor(logger_run2);
Austin Schuh8bd96322020-02-13 21:18:22 -08001273
Austin Schuh87dd3832021-01-01 23:07:31 -08001274 // And now check that we went far enough the other way to make sure we
1275 // cover both problems.
1276 EXPECT_GT(
1277 (pi2->monotonic_now() - pi1->monotonic_now()) - initial_pi2_offset,
1278 event_loop_factory_.send_delay() +
1279 event_loop_factory_.network_delay());
Austin Schuh8bd96322020-02-13 21:18:22 -08001280 }
1281
1282 // And log a bit more on pi2.
Austin Schuh87dd3832021-01-01 23:07:31 -08001283 event_loop_factory_.RunFor(logger_run3);
Austin Schuhcde938c2020-02-02 17:30:07 -08001284 }
1285
Austin Schuh287d43d2020-12-04 20:19:33 -08001286 LogReader reader(SortParts(logfiles_));
Austin Schuhcde938c2020-02-02 17:30:07 -08001287
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001288 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
Austin Schuhcde938c2020-02-02 17:30:07 -08001289 log_reader_factory.set_send_delay(chrono::microseconds(0));
1290
Austin Schuhcde938c2020-02-02 17:30:07 -08001291 const Node *pi1 =
1292 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1293 const Node *pi2 =
1294 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1295
Austin Schuh2f8fd752020-09-01 22:38:28 -07001296 // This sends out the fetched messages and advances time to the start of the
1297 // log file.
1298 reader.Register(&log_reader_factory);
1299
1300 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
1301 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
1302 LOG(INFO) << "now pi1 "
1303 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
1304 LOG(INFO) << "now pi2 "
1305 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
1306
Austin Schuhcde938c2020-02-02 17:30:07 -08001307 LOG(INFO) << "Done registering (pi1) "
Austin Schuh391e3172020-09-01 22:48:18 -07001308 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now()
1309 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -08001310 << log_reader_factory.GetNodeEventLoopFactory(pi1)->realtime_now();
1311 LOG(INFO) << "Done registering (pi2) "
Austin Schuh391e3172020-09-01 22:48:18 -07001312 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now()
1313 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -08001314 << log_reader_factory.GetNodeEventLoopFactory(pi2)->realtime_now();
1315
1316 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
1317
1318 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
1319
1320 std::unique_ptr<EventLoop> pi1_event_loop =
1321 log_reader_factory.MakeEventLoop("test", pi1);
1322 std::unique_ptr<EventLoop> pi2_event_loop =
1323 log_reader_factory.MakeEventLoop("test", pi2);
1324
1325 int pi1_ping_count = 30;
1326 int pi2_ping_count = 30;
1327 int pi1_pong_count = 30;
1328 int pi2_pong_count = 30;
1329
1330 // Confirm that the ping value matches.
1331 pi1_event_loop->MakeWatcher(
1332 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
1333 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
1334 << pi1_event_loop->context().monotonic_remote_time << " -> "
1335 << pi1_event_loop->context().monotonic_event_time;
1336 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
1337
1338 ++pi1_ping_count;
1339 });
1340 pi2_event_loop->MakeWatcher(
1341 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
1342 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
1343 << pi2_event_loop->context().monotonic_remote_time << " -> "
1344 << pi2_event_loop->context().monotonic_event_time;
1345 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
1346
1347 ++pi2_ping_count;
1348 });
1349
1350 // Confirm that the ping and pong counts both match, and the value also
1351 // matches.
1352 pi1_event_loop->MakeWatcher(
1353 "/test", [&pi1_event_loop, &pi1_ping_count,
1354 &pi1_pong_count](const examples::Pong &pong) {
1355 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
1356 << pi1_event_loop->context().monotonic_remote_time << " -> "
1357 << pi1_event_loop->context().monotonic_event_time;
1358
1359 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
1360 ++pi1_pong_count;
1361 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
1362 });
1363 pi2_event_loop->MakeWatcher(
1364 "/test", [&pi2_event_loop, &pi2_ping_count,
1365 &pi2_pong_count](const examples::Pong &pong) {
1366 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
1367 << pi2_event_loop->context().monotonic_remote_time << " -> "
1368 << pi2_event_loop->context().monotonic_event_time;
1369
1370 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
1371 ++pi2_pong_count;
1372 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
1373 });
1374
1375 log_reader_factory.Run();
Austin Schuh8bd96322020-02-13 21:18:22 -08001376 EXPECT_EQ(pi1_ping_count, 6030);
1377 EXPECT_EQ(pi2_ping_count, 6030);
1378 EXPECT_EQ(pi1_pong_count, 6030);
1379 EXPECT_EQ(pi2_pong_count, 6030);
Austin Schuhcde938c2020-02-02 17:30:07 -08001380
1381 reader.Deregister();
1382}
1383
Austin Schuh5212cad2020-09-09 23:12:09 -07001384// Tests that we can sort a bunch of parts into the pre-determined sorted parts.
1385TEST_F(MultinodeLoggerTest, SortParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001386 time_converter_.StartEqual();
Austin Schuh5212cad2020-09-09 23:12:09 -07001387 // Make a bunch of parts.
1388 {
1389 LoggerState pi1_logger = MakeLogger(pi1_);
1390 LoggerState pi2_logger = MakeLogger(pi2_);
1391
1392 event_loop_factory_.RunFor(chrono::milliseconds(95));
1393
1394 StartLogger(&pi1_logger);
1395 StartLogger(&pi2_logger);
1396
1397 event_loop_factory_.RunFor(chrono::milliseconds(2000));
1398 }
1399
Austin Schuh11d43732020-09-21 17:28:30 -07001400 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
Austin Schuh3bd4c402020-11-06 18:19:06 -08001401 VerifyParts(sorted_parts);
1402}
Austin Schuh11d43732020-09-21 17:28:30 -07001403
Austin Schuh3bd4c402020-11-06 18:19:06 -08001404// Tests that we can sort a bunch of parts with an empty part. We should ignore
1405// it and remove it from the sorted list.
1406TEST_F(MultinodeLoggerTest, SortEmptyParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001407 time_converter_.StartEqual();
Austin Schuh3bd4c402020-11-06 18:19:06 -08001408 // Make a bunch of parts.
1409 {
1410 LoggerState pi1_logger = MakeLogger(pi1_);
1411 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuh11d43732020-09-21 17:28:30 -07001412
Austin Schuh3bd4c402020-11-06 18:19:06 -08001413 event_loop_factory_.RunFor(chrono::milliseconds(95));
Austin Schuh11d43732020-09-21 17:28:30 -07001414
Austin Schuh3bd4c402020-11-06 18:19:06 -08001415 StartLogger(&pi1_logger);
1416 StartLogger(&pi2_logger);
Austin Schuh11d43732020-09-21 17:28:30 -07001417
Austin Schuh3bd4c402020-11-06 18:19:06 -08001418 event_loop_factory_.RunFor(chrono::milliseconds(2000));
Austin Schuh11d43732020-09-21 17:28:30 -07001419 }
1420
Austin Schuh3bd4c402020-11-06 18:19:06 -08001421 // TODO(austin): Should we flip out if the file can't open?
1422 const std::string kEmptyFile("foobarinvalidfiledoesnotexist.bfbs");
Austin Schuh11d43732020-09-21 17:28:30 -07001423
Austin Schuh3bd4c402020-11-06 18:19:06 -08001424 aos::util::WriteStringToFileOrDie(kEmptyFile, "");
1425 logfiles_.emplace_back(kEmptyFile);
Austin Schuh5212cad2020-09-09 23:12:09 -07001426
Austin Schuh3bd4c402020-11-06 18:19:06 -08001427 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1428 VerifyParts(sorted_parts, {kEmptyFile});
Austin Schuh5212cad2020-09-09 23:12:09 -07001429}
1430
Austin Schuh3bd4c402020-11-06 18:19:06 -08001431#ifdef LZMA
1432// Tests that we can sort a bunch of parts with an empty .xz file in there. The
1433// empty file should be ignored.
1434TEST_F(MultinodeLoggerTest, SortEmptyCompressedParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001435 time_converter_.StartEqual();
Austin Schuh3bd4c402020-11-06 18:19:06 -08001436 // Make a bunch of parts.
1437 {
1438 LoggerState pi1_logger = MakeLogger(pi1_);
1439 LoggerState pi2_logger = MakeLogger(pi2_);
1440
1441 event_loop_factory_.RunFor(chrono::milliseconds(95));
1442
1443 StartLogger(&pi1_logger, "", true);
1444 StartLogger(&pi2_logger, "", true);
1445
1446 event_loop_factory_.RunFor(chrono::milliseconds(2000));
1447 }
1448
1449 // TODO(austin): Should we flip out if the file can't open?
1450 const std::string kEmptyFile("foobarinvalidfiledoesnotexist.bfbs.xz");
1451
1452 AddExtension(".xz");
1453
1454 aos::util::WriteStringToFileOrDie(kEmptyFile, "");
1455 logfiles_.emplace_back(kEmptyFile);
1456
1457 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1458 VerifyParts(sorted_parts, {kEmptyFile});
1459}
1460
1461// Tests that we can sort a bunch of parts with the end missing off a compressed
1462// file. We should use the part we can read.
1463TEST_F(MultinodeLoggerTest, SortTruncatedCompressedParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001464 time_converter_.StartEqual();
Austin Schuh3bd4c402020-11-06 18:19:06 -08001465 // Make a bunch of parts.
1466 {
1467 LoggerState pi1_logger = MakeLogger(pi1_);
1468 LoggerState pi2_logger = MakeLogger(pi2_);
1469
1470 event_loop_factory_.RunFor(chrono::milliseconds(95));
1471
1472 StartLogger(&pi1_logger, "", true);
1473 StartLogger(&pi2_logger, "", true);
1474
1475 event_loop_factory_.RunFor(chrono::milliseconds(2000));
1476 }
1477
1478 // Append everything with .xz.
1479 AddExtension(".xz");
1480
1481 // Strip off the end of one of the files. Pick one with a lot of data.
1482 ::std::string compressed_contents =
1483 aos::util::ReadFileToStringOrDie(logfiles_[0]);
1484
1485 aos::util::WriteStringToFileOrDie(
1486 logfiles_[0],
1487 compressed_contents.substr(0, compressed_contents.size() - 100));
1488
1489 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1490 VerifyParts(sorted_parts);
1491}
1492#endif
1493
Austin Schuh01b4c352020-09-21 23:09:39 -07001494// Tests that if we remap a remapped channel, it shows up correctly.
1495TEST_F(MultinodeLoggerTest, RemapLoggedChannel) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001496 time_converter_.StartEqual();
Austin Schuh01b4c352020-09-21 23:09:39 -07001497 {
1498 LoggerState pi1_logger = MakeLogger(pi1_);
1499 LoggerState pi2_logger = MakeLogger(pi2_);
1500
1501 event_loop_factory_.RunFor(chrono::milliseconds(95));
1502
1503 StartLogger(&pi1_logger);
1504 StartLogger(&pi2_logger);
1505
1506 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1507 }
1508
Austin Schuh287d43d2020-12-04 20:19:33 -08001509 LogReader reader(SortParts(logfiles_));
Austin Schuh01b4c352020-09-21 23:09:39 -07001510
1511 // Remap just on pi1.
1512 reader.RemapLoggedChannel<aos::timing::Report>(
1513 "/aos", configuration::GetNode(reader.configuration(), "pi1"));
1514
1515 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
1516 log_reader_factory.set_send_delay(chrono::microseconds(0));
1517
1518 reader.Register(&log_reader_factory);
1519
1520 const Node *pi1 =
1521 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1522 const Node *pi2 =
1523 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1524
1525 // Confirm we can read the data on the remapped channel, just for pi1. Nothing
1526 // else should have moved.
1527 std::unique_ptr<EventLoop> pi1_event_loop =
1528 log_reader_factory.MakeEventLoop("test", pi1);
1529 pi1_event_loop->SkipTimingReport();
1530 std::unique_ptr<EventLoop> full_pi1_event_loop =
1531 log_reader_factory.MakeEventLoop("test", pi1);
1532 full_pi1_event_loop->SkipTimingReport();
1533 std::unique_ptr<EventLoop> pi2_event_loop =
1534 log_reader_factory.MakeEventLoop("test", pi2);
1535 pi2_event_loop->SkipTimingReport();
1536
1537 MessageCounter<aos::timing::Report> pi1_timing_report(pi1_event_loop.get(),
1538 "/aos");
1539 MessageCounter<aos::timing::Report> full_pi1_timing_report(
1540 full_pi1_event_loop.get(), "/pi1/aos");
1541 MessageCounter<aos::timing::Report> pi1_original_timing_report(
1542 pi1_event_loop.get(), "/original/aos");
1543 MessageCounter<aos::timing::Report> full_pi1_original_timing_report(
1544 full_pi1_event_loop.get(), "/original/pi1/aos");
1545 MessageCounter<aos::timing::Report> pi2_timing_report(pi2_event_loop.get(),
1546 "/aos");
1547
1548 log_reader_factory.Run();
1549
1550 EXPECT_EQ(pi1_timing_report.count(), 0u);
1551 EXPECT_EQ(full_pi1_timing_report.count(), 0u);
1552 EXPECT_NE(pi1_original_timing_report.count(), 0u);
1553 EXPECT_NE(full_pi1_original_timing_report.count(), 0u);
1554 EXPECT_NE(pi2_timing_report.count(), 0u);
1555
1556 reader.Deregister();
1557}
1558
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001559// Tests that we properly recreate forwarded timestamps when replaying a log.
1560// This should be enough that we can then re-run the logger and get a valid log
1561// back.
1562TEST_F(MultinodeLoggerTest, MessageHeader) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001563 time_converter_.StartEqual();
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001564 {
1565 LoggerState pi1_logger = MakeLogger(pi1_);
1566 LoggerState pi2_logger = MakeLogger(pi2_);
1567
1568 event_loop_factory_.RunFor(chrono::milliseconds(95));
1569
1570 StartLogger(&pi1_logger);
1571 StartLogger(&pi2_logger);
1572
1573 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1574 }
1575
Austin Schuh287d43d2020-12-04 20:19:33 -08001576 LogReader reader(SortParts(logfiles_));
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001577
1578 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
1579 log_reader_factory.set_send_delay(chrono::microseconds(0));
1580
1581 // This sends out the fetched messages and advances time to the start of the
1582 // log file.
1583 reader.Register(&log_reader_factory);
1584
1585 const Node *pi1 =
1586 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1587 const Node *pi2 =
1588 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1589
1590 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
1591 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
1592 LOG(INFO) << "now pi1 "
1593 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
1594 LOG(INFO) << "now pi2 "
1595 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
1596
1597 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
1598
1599 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
1600
1601 std::unique_ptr<EventLoop> pi1_event_loop =
1602 log_reader_factory.MakeEventLoop("test", pi1);
1603 std::unique_ptr<EventLoop> pi2_event_loop =
1604 log_reader_factory.MakeEventLoop("test", pi2);
1605
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001606 aos::Fetcher<message_bridge::Timestamp> pi1_timestamp_on_pi1_fetcher =
1607 pi1_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi1/aos");
1608 aos::Fetcher<message_bridge::Timestamp> pi1_timestamp_on_pi2_fetcher =
1609 pi2_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi1/aos");
1610
1611 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
1612 pi1_event_loop->MakeFetcher<examples::Ping>("/test");
1613 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
1614 pi2_event_loop->MakeFetcher<examples::Ping>("/test");
1615
1616 aos::Fetcher<message_bridge::Timestamp> pi2_timestamp_on_pi2_fetcher =
1617 pi2_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi2/aos");
1618 aos::Fetcher<message_bridge::Timestamp> pi2_timestamp_on_pi1_fetcher =
1619 pi1_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi2/aos");
1620
1621 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
1622 pi2_event_loop->MakeFetcher<examples::Pong>("/test");
1623 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
1624 pi1_event_loop->MakeFetcher<examples::Pong>("/test");
1625
1626 const size_t pi1_timestamp_channel = configuration::ChannelIndex(
1627 pi1_event_loop->configuration(), pi1_timestamp_on_pi1_fetcher.channel());
1628 const size_t ping_timestamp_channel = configuration::ChannelIndex(
1629 pi2_event_loop->configuration(), ping_on_pi2_fetcher.channel());
1630
1631 const size_t pi2_timestamp_channel = configuration::ChannelIndex(
1632 pi2_event_loop->configuration(), pi2_timestamp_on_pi2_fetcher.channel());
1633 const size_t pong_timestamp_channel = configuration::ChannelIndex(
1634 pi1_event_loop->configuration(), pong_on_pi1_fetcher.channel());
1635
Austin Schuh969cd602021-01-03 00:09:45 -08001636 const chrono::nanoseconds network_delay = event_loop_factory_.network_delay();
Austin Schuh816e5d62021-01-05 23:42:20 -08001637 const chrono::nanoseconds send_delay = event_loop_factory_.send_delay();
Austin Schuh969cd602021-01-03 00:09:45 -08001638
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001639 pi1_event_loop->MakeWatcher(
1640 "/aos/remote_timestamps/pi2",
Austin Schuh315b96b2020-12-11 21:21:12 -08001641 [&pi1_event_loop, &pi2_event_loop, pi1_timestamp_channel,
1642 ping_timestamp_channel, &pi1_timestamp_on_pi1_fetcher,
1643 &pi1_timestamp_on_pi2_fetcher, &ping_on_pi1_fetcher,
Austin Schuh816e5d62021-01-05 23:42:20 -08001644 &ping_on_pi2_fetcher, network_delay,
1645 send_delay](const RemoteMessage &header) {
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001646 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1647 chrono::nanoseconds(header.monotonic_sent_time()));
1648 const aos::realtime_clock::time_point header_realtime_sent_time(
1649 chrono::nanoseconds(header.realtime_sent_time()));
1650 const aos::monotonic_clock::time_point header_monotonic_remote_time(
1651 chrono::nanoseconds(header.monotonic_remote_time()));
1652 const aos::realtime_clock::time_point header_realtime_remote_time(
1653 chrono::nanoseconds(header.realtime_remote_time()));
1654
1655 const Context *pi1_context = nullptr;
1656 const Context *pi2_context = nullptr;
1657
1658 if (header.channel_index() == pi1_timestamp_channel) {
1659 ASSERT_TRUE(pi1_timestamp_on_pi1_fetcher.FetchNext());
1660 ASSERT_TRUE(pi1_timestamp_on_pi2_fetcher.FetchNext());
1661 pi1_context = &pi1_timestamp_on_pi1_fetcher.context();
1662 pi2_context = &pi1_timestamp_on_pi2_fetcher.context();
1663 } else if (header.channel_index() == ping_timestamp_channel) {
1664 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
1665 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
1666 pi1_context = &ping_on_pi1_fetcher.context();
1667 pi2_context = &ping_on_pi2_fetcher.context();
1668 } else {
1669 LOG(FATAL) << "Unknown channel " << FlatbufferToJson(&header) << " "
1670 << configuration::CleanedChannelToString(
1671 pi1_event_loop->configuration()->channels()->Get(
1672 header.channel_index()));
1673 }
1674
Austin Schuh315b96b2020-12-11 21:21:12 -08001675 ASSERT_TRUE(header.has_boot_uuid());
1676 EXPECT_EQ(header.boot_uuid()->string_view(),
1677 pi2_event_loop->boot_uuid().string_view());
1678
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001679 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
1680 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
1681 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
1682
1683 EXPECT_EQ(pi2_context->monotonic_event_time,
1684 header_monotonic_sent_time);
1685 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
1686 EXPECT_EQ(pi2_context->realtime_remote_time,
1687 header_realtime_remote_time);
1688 EXPECT_EQ(pi2_context->monotonic_remote_time,
1689 header_monotonic_remote_time);
1690
1691 EXPECT_EQ(pi1_context->realtime_event_time,
1692 header_realtime_remote_time);
1693 EXPECT_EQ(pi1_context->monotonic_event_time,
1694 header_monotonic_remote_time);
Austin Schuh969cd602021-01-03 00:09:45 -08001695
Austin Schuh816e5d62021-01-05 23:42:20 -08001696 // Time estimation isn't perfect, but we know the clocks were identical
1697 // when logged, so we know when this should have come back. Confirm we
1698 // got it when we expected.
1699 EXPECT_EQ(
1700 pi1_event_loop->context().monotonic_event_time,
1701 pi1_context->monotonic_event_time + 2 * network_delay + send_delay);
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001702 });
1703 pi2_event_loop->MakeWatcher(
1704 "/aos/remote_timestamps/pi1",
Austin Schuh315b96b2020-12-11 21:21:12 -08001705 [&pi2_event_loop, &pi1_event_loop, pi2_timestamp_channel,
1706 pong_timestamp_channel, &pi2_timestamp_on_pi2_fetcher,
1707 &pi2_timestamp_on_pi1_fetcher, &pong_on_pi2_fetcher,
Austin Schuh816e5d62021-01-05 23:42:20 -08001708 &pong_on_pi1_fetcher, network_delay,
1709 send_delay](const RemoteMessage &header) {
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001710 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1711 chrono::nanoseconds(header.monotonic_sent_time()));
1712 const aos::realtime_clock::time_point header_realtime_sent_time(
1713 chrono::nanoseconds(header.realtime_sent_time()));
1714 const aos::monotonic_clock::time_point header_monotonic_remote_time(
1715 chrono::nanoseconds(header.monotonic_remote_time()));
1716 const aos::realtime_clock::time_point header_realtime_remote_time(
1717 chrono::nanoseconds(header.realtime_remote_time()));
1718
1719 const Context *pi2_context = nullptr;
1720 const Context *pi1_context = nullptr;
1721
1722 if (header.channel_index() == pi2_timestamp_channel) {
1723 ASSERT_TRUE(pi2_timestamp_on_pi2_fetcher.FetchNext());
1724 ASSERT_TRUE(pi2_timestamp_on_pi1_fetcher.FetchNext());
1725 pi2_context = &pi2_timestamp_on_pi2_fetcher.context();
1726 pi1_context = &pi2_timestamp_on_pi1_fetcher.context();
1727 } else if (header.channel_index() == pong_timestamp_channel) {
1728 ASSERT_TRUE(pong_on_pi2_fetcher.FetchNext());
1729 ASSERT_TRUE(pong_on_pi1_fetcher.FetchNext());
1730 pi2_context = &pong_on_pi2_fetcher.context();
1731 pi1_context = &pong_on_pi1_fetcher.context();
1732 } else {
1733 LOG(FATAL) << "Unknown channel " << FlatbufferToJson(&header) << " "
1734 << configuration::CleanedChannelToString(
1735 pi2_event_loop->configuration()->channels()->Get(
1736 header.channel_index()));
1737 }
1738
Austin Schuh315b96b2020-12-11 21:21:12 -08001739 ASSERT_TRUE(header.has_boot_uuid());
1740 EXPECT_EQ(header.boot_uuid()->string_view(),
1741 pi1_event_loop->boot_uuid().string_view());
1742
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001743 EXPECT_EQ(pi2_context->queue_index, header.remote_queue_index());
1744 EXPECT_EQ(pi1_context->remote_queue_index, header.remote_queue_index());
1745 EXPECT_EQ(pi1_context->queue_index, header.queue_index());
1746
1747 EXPECT_EQ(pi1_context->monotonic_event_time,
1748 header_monotonic_sent_time);
1749 EXPECT_EQ(pi1_context->realtime_event_time, header_realtime_sent_time);
1750 EXPECT_EQ(pi1_context->realtime_remote_time,
1751 header_realtime_remote_time);
1752 EXPECT_EQ(pi1_context->monotonic_remote_time,
1753 header_monotonic_remote_time);
1754
1755 EXPECT_EQ(pi2_context->realtime_event_time,
1756 header_realtime_remote_time);
1757 EXPECT_EQ(pi2_context->monotonic_event_time,
1758 header_monotonic_remote_time);
Austin Schuh969cd602021-01-03 00:09:45 -08001759
Austin Schuh816e5d62021-01-05 23:42:20 -08001760 // Time estimation isn't perfect, but we know the clocks were identical
1761 // when logged, so we know when this should have come back. Confirm we
1762 // got it when we expected.
1763 EXPECT_EQ(
1764 pi2_event_loop->context().monotonic_event_time,
1765 pi2_context->monotonic_event_time + 2 * network_delay + send_delay);
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001766 });
1767
1768 // And confirm we can re-create a log again, while checking the contents.
1769 {
1770 LoggerState pi1_logger = MakeLogger(
1771 configuration::GetNode(log_reader_factory.configuration(), pi1_),
1772 &log_reader_factory);
1773 LoggerState pi2_logger = MakeLogger(
1774 configuration::GetNode(log_reader_factory.configuration(), pi2_),
1775 &log_reader_factory);
1776
Austin Schuh25b46712021-01-03 00:04:38 -08001777 StartLogger(&pi1_logger, tmp_dir_ + "/relogged1");
1778 StartLogger(&pi2_logger, tmp_dir_ + "/relogged2");
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001779
1780 log_reader_factory.Run();
1781 }
1782
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001783 reader.Deregister();
James Kuszmaul4f106fb2021-01-05 20:53:02 -08001784
1785 // And verify that we can run the LogReader over the relogged files without
1786 // hitting any fatal errors.
1787 {
1788 LogReader relogged_reader(SortParts(
1789 MakeLogFiles(tmp_dir_ + "/relogged1", tmp_dir_ + "/relogged2")));
1790 relogged_reader.Register();
1791
1792 relogged_reader.event_loop_factory()->Run();
1793 }
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001794}
1795
Austin Schuh315b96b2020-12-11 21:21:12 -08001796// Tests that we properly populate and extract the logger_start time by setting
1797// up a clock difference between 2 nodes and looking at the resulting parts.
1798TEST_F(MultinodeLoggerTest, LoggerStartTime) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001799 time_converter_.AddMonotonic(
1800 {monotonic_clock::epoch(),
1801 monotonic_clock::epoch() + chrono::seconds(1000)});
Austin Schuh315b96b2020-12-11 21:21:12 -08001802 {
1803 LoggerState pi1_logger = MakeLogger(pi1_);
1804 LoggerState pi2_logger = MakeLogger(pi2_);
1805
Austin Schuh315b96b2020-12-11 21:21:12 -08001806 StartLogger(&pi1_logger);
1807 StartLogger(&pi2_logger);
1808
1809 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1810 }
1811
1812 for (const LogFile &log_file : SortParts(logfiles_)) {
1813 for (const LogParts &log_part : log_file.parts) {
1814 if (log_part.node == log_file.logger_node) {
1815 EXPECT_EQ(log_part.logger_monotonic_start_time,
1816 aos::monotonic_clock::min_time);
1817 EXPECT_EQ(log_part.logger_realtime_start_time,
1818 aos::realtime_clock::min_time);
1819 } else {
1820 const chrono::seconds offset = log_file.logger_node == "pi1"
1821 ? -chrono::seconds(1000)
1822 : chrono::seconds(1000);
1823 EXPECT_EQ(log_part.logger_monotonic_start_time,
1824 log_part.monotonic_start_time + offset);
1825 EXPECT_EQ(log_part.logger_realtime_start_time,
1826 log_file.realtime_start_time +
1827 (log_part.logger_monotonic_start_time -
1828 log_file.monotonic_start_time));
1829 }
1830 }
1831 }
1832}
1833
Austin Schuh8bd96322020-02-13 21:18:22 -08001834// TODO(austin): We can write a test which recreates a logfile and confirms that
1835// we get it back. That is the ultimate test.
1836
Austin Schuh315b96b2020-12-11 21:21:12 -08001837// Tests that we properly recreate forwarded timestamps when replaying a log.
1838// This should be enough that we can then re-run the logger and get a valid log
1839// back.
1840TEST_F(MultinodeLoggerDeathTest, RemoteReboot) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001841 time_converter_.StartEqual();
Austin Schuh315b96b2020-12-11 21:21:12 -08001842 std::string pi2_boot1;
1843 std::string pi2_boot2;
1844 {
1845 pi2_boot1 = event_loop_factory_.GetNodeEventLoopFactory(pi2_)
1846 ->boot_uuid()
1847 .string_view();
1848 LoggerState pi1_logger = MakeLogger(pi1_);
1849
1850 event_loop_factory_.RunFor(chrono::milliseconds(95));
1851
1852 StartLogger(&pi1_logger);
1853
1854 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1855
1856 event_loop_factory_.GetNodeEventLoopFactory(pi2_)->Reboot();
1857
1858 pi2_boot2 = event_loop_factory_.GetNodeEventLoopFactory(pi2_)
1859 ->boot_uuid()
1860 .string_view();
1861
1862 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1863 }
1864
1865 // Confirm that we refuse to replay logs with missing boot uuids.
1866 EXPECT_DEATH(
1867 {
1868 LogReader reader(SortParts(pi1_reboot_logfiles_));
1869
1870 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
1871 log_reader_factory.set_send_delay(chrono::microseconds(0));
1872
1873 // This sends out the fetched messages and advances time to the start of
1874 // the log file.
1875 reader.Register(&log_reader_factory);
1876 },
1877 absl::StrFormat("(%s|%s).*(%s|%s).*Found parts from different boots",
1878 pi2_boot1, pi2_boot2, pi2_boot2, pi2_boot1));
1879}
1880
Austin Schuhc9049732020-12-21 22:27:15 -08001881// Tests that we properly handle one direction of message_bridge being
1882// unavailable.
1883TEST_F(MultinodeLoggerTest, OneDirectionWithNegativeSlope) {
1884 event_loop_factory_.GetNodeEventLoopFactory(pi1_)->Disconnect(pi2_);
Austin Schuh87dd3832021-01-01 23:07:31 -08001885 time_converter_.AddMonotonic(
1886 {monotonic_clock::epoch(),
1887 monotonic_clock::epoch() + chrono::seconds(1000)});
1888
1889 time_converter_.AddMonotonic(
1890 {chrono::milliseconds(10000),
1891 chrono::milliseconds(10000) - chrono::milliseconds(1)});
Austin Schuhc9049732020-12-21 22:27:15 -08001892 {
1893 LoggerState pi1_logger = MakeLogger(pi1_);
1894
1895 event_loop_factory_.RunFor(chrono::milliseconds(95));
1896
1897 StartLogger(&pi1_logger);
1898
1899 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1900 }
1901
1902 // Confirm that we can parse the result. LogReader has enough internal CHECKs
1903 // to confirm the right thing happened.
1904 ConfirmReadable(pi1_single_direction_logfiles_);
1905}
1906
1907// Tests that we properly handle one direction of message_bridge being
1908// unavailable.
1909TEST_F(MultinodeLoggerTest, OneDirectionWithPositiveSlope) {
1910 event_loop_factory_.GetNodeEventLoopFactory(pi1_)->Disconnect(pi2_);
Austin Schuh87dd3832021-01-01 23:07:31 -08001911 time_converter_.AddMonotonic(
1912 {monotonic_clock::epoch(),
1913 monotonic_clock::epoch() + chrono::seconds(500)});
1914
1915 time_converter_.AddMonotonic(
1916 {chrono::milliseconds(10000),
1917 chrono::milliseconds(10000) + chrono::milliseconds(1)});
1918 {
1919 LoggerState pi1_logger = MakeLogger(pi1_);
1920
1921 event_loop_factory_.RunFor(chrono::milliseconds(95));
1922
1923 StartLogger(&pi1_logger);
1924
1925 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1926 }
1927
1928 // Confirm that we can parse the result. LogReader has enough internal CHECKs
1929 // to confirm the right thing happened.
1930 ConfirmReadable(pi1_single_direction_logfiles_);
1931}
1932
1933// Tests that we properly handle a dead node. Do this by just disconnecting it
1934// and only using one nodes of logs.
1935TEST_F(MultinodeLoggerTest, DeadNode) {
1936 event_loop_factory_.GetNodeEventLoopFactory(pi1_)->Disconnect(pi2_);
1937 event_loop_factory_.GetNodeEventLoopFactory(pi2_)->Disconnect(pi1_);
1938 time_converter_.AddMonotonic(
1939 {monotonic_clock::epoch(),
1940 monotonic_clock::epoch() + chrono::seconds(1000)});
Austin Schuhc9049732020-12-21 22:27:15 -08001941 {
1942 LoggerState pi1_logger = MakeLogger(pi1_);
1943
1944 event_loop_factory_.RunFor(chrono::milliseconds(95));
1945
1946 StartLogger(&pi1_logger);
1947
1948 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1949 }
1950
1951 // Confirm that we can parse the result. LogReader has enough internal CHECKs
1952 // to confirm the right thing happened.
1953 ConfirmReadable(pi1_single_direction_logfiles_);
1954}
1955
Austin Schuhe309d2a2019-11-29 13:25:21 -08001956} // namespace testing
1957} // namespace logger
1958} // namespace aos