blob: 5f18e294ffd968538cc6135bcbf9a62edf2d60bb [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 Schuh07676622021-01-21 18:59:17 -080099 EXPECT_THAT(reader.LoggedNodes(), ::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
Austin Schuh07676622021-01-21 18:59:17 -0800240 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Brian Silverman1f345222020-09-24 21:14:48 -0700241
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 Schuh07676622021-01-21 18:59:17 -0800325 EXPECT_THAT(reader.LoggedNodes(), ::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 Schuh07676622021-01-21 18:59:17 -0800946 EXPECT_THAT(reader.LoggedNodes(),
947 ::testing::ElementsAre(
948 configuration::GetNode(reader.logged_configuration(), pi1),
949 configuration::GetNode(reader.logged_configuration(), pi2)));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800950
951 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800952
Austin Schuh6f3babe2020-01-26 20:34:50 -0800953 std::unique_ptr<EventLoop> pi1_event_loop =
Austin Schuhac0771c2020-01-07 18:36:30 -0800954 log_reader_factory.MakeEventLoop("test", pi1);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800955 std::unique_ptr<EventLoop> pi2_event_loop =
956 log_reader_factory.MakeEventLoop("test", pi2);
Austin Schuh15649d62019-12-28 16:36:38 -0800957
Austin Schuh6f3babe2020-01-26 20:34:50 -0800958 int pi1_ping_count = 10;
959 int pi2_ping_count = 10;
960 int pi1_pong_count = 10;
961 int pi2_pong_count = 10;
Austin Schuh15649d62019-12-28 16:36:38 -0800962
963 // Confirm that the ping value matches.
Austin Schuh6f3babe2020-01-26 20:34:50 -0800964 pi1_event_loop->MakeWatcher(
965 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700966 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800967 << pi1_event_loop->context().monotonic_remote_time << " -> "
968 << pi1_event_loop->context().monotonic_event_time;
969 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
970 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
971 pi1_ping_count * chrono::milliseconds(10) +
972 monotonic_clock::epoch());
973 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
974 pi1_ping_count * chrono::milliseconds(10) +
975 realtime_clock::epoch());
976 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
977 pi1_event_loop->context().monotonic_event_time);
978 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
979 pi1_event_loop->context().realtime_event_time);
Austin Schuh15649d62019-12-28 16:36:38 -0800980
Austin Schuh6f3babe2020-01-26 20:34:50 -0800981 ++pi1_ping_count;
982 });
983 pi2_event_loop->MakeWatcher(
984 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700985 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800986 << pi2_event_loop->context().monotonic_remote_time << " -> "
987 << pi2_event_loop->context().monotonic_event_time;
988 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
989
990 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
991 pi2_ping_count * chrono::milliseconds(10) +
992 monotonic_clock::epoch());
993 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
994 pi2_ping_count * chrono::milliseconds(10) +
995 realtime_clock::epoch());
996 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time +
997 chrono::microseconds(150),
998 pi2_event_loop->context().monotonic_event_time);
999 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time +
1000 chrono::microseconds(150),
1001 pi2_event_loop->context().realtime_event_time);
1002 ++pi2_ping_count;
Austin Schuh15649d62019-12-28 16:36:38 -08001003 });
1004
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001005 constexpr ssize_t kQueueIndexOffset = -9;
Austin Schuh6f3babe2020-01-26 20:34:50 -08001006 // Confirm that the ping and pong counts both match, and the value also
1007 // matches.
1008 pi1_event_loop->MakeWatcher(
1009 "/test", [&pi1_event_loop, &pi1_ping_count,
1010 &pi1_pong_count](const examples::Pong &pong) {
1011 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
1012 << pi1_event_loop->context().monotonic_remote_time << " -> "
1013 << pi1_event_loop->context().monotonic_event_time;
1014
1015 EXPECT_EQ(pi1_event_loop->context().remote_queue_index,
1016 pi1_pong_count + kQueueIndexOffset);
1017 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
1018 chrono::microseconds(200) +
1019 pi1_pong_count * chrono::milliseconds(10) +
1020 monotonic_clock::epoch());
1021 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
1022 chrono::microseconds(200) +
1023 pi1_pong_count * chrono::milliseconds(10) +
1024 realtime_clock::epoch());
1025
1026 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time +
1027 chrono::microseconds(150),
1028 pi1_event_loop->context().monotonic_event_time);
1029 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time +
1030 chrono::microseconds(150),
1031 pi1_event_loop->context().realtime_event_time);
1032
1033 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
1034 ++pi1_pong_count;
1035 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
1036 });
1037 pi2_event_loop->MakeWatcher(
1038 "/test", [&pi2_event_loop, &pi2_ping_count,
1039 &pi2_pong_count](const examples::Pong &pong) {
1040 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
1041 << pi2_event_loop->context().monotonic_remote_time << " -> "
1042 << pi2_event_loop->context().monotonic_event_time;
1043
1044 EXPECT_EQ(pi2_event_loop->context().remote_queue_index,
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001045 pi2_pong_count + kQueueIndexOffset);
Austin Schuh6f3babe2020-01-26 20:34:50 -08001046
1047 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
1048 chrono::microseconds(200) +
1049 pi2_pong_count * chrono::milliseconds(10) +
1050 monotonic_clock::epoch());
1051 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
1052 chrono::microseconds(200) +
1053 pi2_pong_count * chrono::milliseconds(10) +
1054 realtime_clock::epoch());
1055
1056 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
1057 pi2_event_loop->context().monotonic_event_time);
1058 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
1059 pi2_event_loop->context().realtime_event_time);
1060
1061 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
1062 ++pi2_pong_count;
1063 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
1064 });
1065
1066 log_reader_factory.Run();
1067 EXPECT_EQ(pi1_ping_count, 2010);
1068 EXPECT_EQ(pi2_ping_count, 2010);
1069 EXPECT_EQ(pi1_pong_count, 2010);
1070 EXPECT_EQ(pi2_pong_count, 2010);
Austin Schuh6331ef92020-01-07 18:28:09 -08001071
1072 reader.Deregister();
Austin Schuh15649d62019-12-28 16:36:38 -08001073}
1074
James Kuszmaul46d82582020-05-09 19:50:09 -07001075typedef MultinodeLoggerTest MultinodeLoggerDeathTest;
1076
1077// Test that if we feed the replay with a mismatched node list that we die on
1078// the LogReader constructor.
1079TEST_F(MultinodeLoggerDeathTest, MultiNodeBadReplayConfig) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001080 time_converter_.StartEqual();
James Kuszmaul46d82582020-05-09 19:50:09 -07001081 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001082 LoggerState pi1_logger = MakeLogger(pi1_);
1083 LoggerState pi2_logger = MakeLogger(pi2_);
James Kuszmaul46d82582020-05-09 19:50:09 -07001084
1085 event_loop_factory_.RunFor(chrono::milliseconds(95));
1086
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001087 StartLogger(&pi1_logger);
1088 StartLogger(&pi2_logger);
James Kuszmaul46d82582020-05-09 19:50:09 -07001089
James Kuszmaul46d82582020-05-09 19:50:09 -07001090 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1091 }
1092
1093 // Test that, if we add an additional node to the replay config that the
1094 // logger complains about the mismatch in number of nodes.
1095 FlatbufferDetachedBuffer<Configuration> extra_nodes_config =
1096 configuration::MergeWithConfig(&config_.message(), R"({
1097 "nodes": [
1098 {
1099 "name": "extra-node"
1100 }
1101 ]
1102 }
1103 )");
1104
Austin Schuh287d43d2020-12-04 20:19:33 -08001105 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1106 EXPECT_DEATH(LogReader(sorted_parts, &extra_nodes_config.message()),
James Kuszmaul46d82582020-05-09 19:50:09 -07001107 "Log file and replay config need to have matching nodes lists.");
James Kuszmaul46d82582020-05-09 19:50:09 -07001108}
1109
Austin Schuhcde938c2020-02-02 17:30:07 -08001110// Tests that we can read log files where they don't start at the same monotonic
1111// time.
1112TEST_F(MultinodeLoggerTest, StaggeredStart) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001113 time_converter_.StartEqual();
Austin Schuhcde938c2020-02-02 17:30:07 -08001114 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001115 LoggerState pi1_logger = MakeLogger(pi1_);
1116 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuhcde938c2020-02-02 17:30:07 -08001117
1118 event_loop_factory_.RunFor(chrono::milliseconds(95));
1119
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001120 StartLogger(&pi1_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -08001121
1122 event_loop_factory_.RunFor(chrono::milliseconds(200));
1123
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001124 StartLogger(&pi2_logger);
1125
Austin Schuhcde938c2020-02-02 17:30:07 -08001126 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1127 }
1128
Austin Schuh287d43d2020-12-04 20:19:33 -08001129 LogReader reader(SortParts(logfiles_));
Austin Schuhcde938c2020-02-02 17:30:07 -08001130
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001131 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
Austin Schuhcde938c2020-02-02 17:30:07 -08001132 log_reader_factory.set_send_delay(chrono::microseconds(0));
1133
1134 // This sends out the fetched messages and advances time to the start of the
1135 // log file.
1136 reader.Register(&log_reader_factory);
1137
1138 const Node *pi1 =
1139 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1140 const Node *pi2 =
1141 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1142
Austin Schuh07676622021-01-21 18:59:17 -08001143 EXPECT_THAT(reader.LoggedNodes(),
1144 ::testing::ElementsAre(
1145 configuration::GetNode(reader.logged_configuration(), pi1),
1146 configuration::GetNode(reader.logged_configuration(), pi2)));
Austin Schuhcde938c2020-02-02 17:30:07 -08001147
1148 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
1149
1150 std::unique_ptr<EventLoop> pi1_event_loop =
1151 log_reader_factory.MakeEventLoop("test", pi1);
1152 std::unique_ptr<EventLoop> pi2_event_loop =
1153 log_reader_factory.MakeEventLoop("test", pi2);
1154
1155 int pi1_ping_count = 30;
1156 int pi2_ping_count = 30;
1157 int pi1_pong_count = 30;
1158 int pi2_pong_count = 30;
1159
1160 // Confirm that the ping value matches.
1161 pi1_event_loop->MakeWatcher(
1162 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
1163 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
1164 << pi1_event_loop->context().monotonic_remote_time << " -> "
1165 << pi1_event_loop->context().monotonic_event_time;
1166 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
1167
1168 ++pi1_ping_count;
1169 });
1170 pi2_event_loop->MakeWatcher(
1171 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
1172 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
1173 << pi2_event_loop->context().monotonic_remote_time << " -> "
1174 << pi2_event_loop->context().monotonic_event_time;
1175 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
1176
1177 ++pi2_ping_count;
1178 });
1179
1180 // Confirm that the ping and pong counts both match, and the value also
1181 // matches.
1182 pi1_event_loop->MakeWatcher(
1183 "/test", [&pi1_event_loop, &pi1_ping_count,
1184 &pi1_pong_count](const examples::Pong &pong) {
1185 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
1186 << pi1_event_loop->context().monotonic_remote_time << " -> "
1187 << pi1_event_loop->context().monotonic_event_time;
1188
1189 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
1190 ++pi1_pong_count;
1191 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
1192 });
1193 pi2_event_loop->MakeWatcher(
1194 "/test", [&pi2_event_loop, &pi2_ping_count,
1195 &pi2_pong_count](const examples::Pong &pong) {
1196 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
1197 << pi2_event_loop->context().monotonic_remote_time << " -> "
1198 << pi2_event_loop->context().monotonic_event_time;
1199
1200 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
1201 ++pi2_pong_count;
1202 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
1203 });
1204
1205 log_reader_factory.Run();
1206 EXPECT_EQ(pi1_ping_count, 2030);
1207 EXPECT_EQ(pi2_ping_count, 2030);
1208 EXPECT_EQ(pi1_pong_count, 2030);
1209 EXPECT_EQ(pi2_pong_count, 2030);
1210
1211 reader.Deregister();
1212}
Austin Schuh6f3babe2020-01-26 20:34:50 -08001213
Austin Schuh8bd96322020-02-13 21:18:22 -08001214// Tests that we can read log files where the monotonic clocks drift and don't
1215// match correctly. While we are here, also test that different ending times
1216// also is readable.
1217TEST_F(MultinodeLoggerTest, MismatchedClocks) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001218 // TODO(austin): Negate...
1219 const chrono::nanoseconds initial_pi2_offset = chrono::seconds(1000);
1220
1221 time_converter_.AddMonotonic({monotonic_clock::epoch(),
1222 monotonic_clock::epoch() + initial_pi2_offset});
1223 // Wait for 95 ms, (~0.1 seconds - 1/2 of the ping/pong period), and set the
1224 // skew to be 200 uS/s
1225 const chrono::nanoseconds startup_sleep1 = time_converter_.AddMonotonic(
1226 {chrono::milliseconds(95),
1227 chrono::milliseconds(95) - chrono::nanoseconds(200) * 95});
1228 // Run another 200 ms to have one logger start first.
1229 const chrono::nanoseconds startup_sleep2 = time_converter_.AddMonotonic(
1230 {chrono::milliseconds(200), chrono::milliseconds(200)});
1231 // Slew one way then the other at the same 200 uS/S slew rate. Make sure we
1232 // go far enough to cause problems if this isn't accounted for.
1233 const chrono::nanoseconds logger_run1 = time_converter_.AddMonotonic(
1234 {chrono::milliseconds(20000),
1235 chrono::milliseconds(20000) - chrono::nanoseconds(200) * 20000});
1236 const chrono::nanoseconds logger_run2 = time_converter_.AddMonotonic(
1237 {chrono::milliseconds(40000),
1238 chrono::milliseconds(40000) + chrono::nanoseconds(200) * 40000});
1239 const chrono::nanoseconds logger_run3 = time_converter_.AddMonotonic(
1240 {chrono::milliseconds(400), chrono::milliseconds(400)});
1241
Austin Schuhcde938c2020-02-02 17:30:07 -08001242 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001243 LoggerState pi2_logger = MakeLogger(pi2_);
1244
Austin Schuh87dd3832021-01-01 23:07:31 -08001245 NodeEventLoopFactory *pi1 =
1246 event_loop_factory_.GetNodeEventLoopFactory(pi1_);
Austin Schuh8bd96322020-02-13 21:18:22 -08001247 NodeEventLoopFactory *pi2 =
1248 event_loop_factory_.GetNodeEventLoopFactory(pi2_);
1249 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
1250 << pi2->realtime_now() << " distributed "
1251 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -08001252
Austin Schuh8bd96322020-02-13 21:18:22 -08001253 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
1254 << pi2->realtime_now() << " distributed "
1255 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -08001256
Austin Schuh87dd3832021-01-01 23:07:31 -08001257 event_loop_factory_.RunFor(startup_sleep1);
Austin Schuhcde938c2020-02-02 17:30:07 -08001258
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001259 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -08001260
Austin Schuh87dd3832021-01-01 23:07:31 -08001261 event_loop_factory_.RunFor(startup_sleep2);
Austin Schuhcde938c2020-02-02 17:30:07 -08001262
Austin Schuh8bd96322020-02-13 21:18:22 -08001263 {
1264 // Run pi1's logger for only part of the time.
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001265 LoggerState pi1_logger = MakeLogger(pi1_);
Austin Schuh8bd96322020-02-13 21:18:22 -08001266
James Kuszmaulbb28ef22020-05-09 22:30:38 -07001267 StartLogger(&pi1_logger);
Austin Schuh87dd3832021-01-01 23:07:31 -08001268 event_loop_factory_.RunFor(logger_run1);
Austin Schuh8bd96322020-02-13 21:18:22 -08001269
Austin Schuh87dd3832021-01-01 23:07:31 -08001270 // Make sure we slewed time far enough so that the difference is greater
1271 // than the network delay. This confirms that if we sort incorrectly, it
1272 // would show in the results.
1273 EXPECT_LT(
1274 (pi2->monotonic_now() - pi1->monotonic_now()) - initial_pi2_offset,
1275 -event_loop_factory_.send_delay() -
1276 event_loop_factory_.network_delay());
Austin Schuh8bd96322020-02-13 21:18:22 -08001277
Austin Schuh87dd3832021-01-01 23:07:31 -08001278 event_loop_factory_.RunFor(logger_run2);
Austin Schuh8bd96322020-02-13 21:18:22 -08001279
Austin Schuh87dd3832021-01-01 23:07:31 -08001280 // And now check that we went far enough the other way to make sure we
1281 // cover both problems.
1282 EXPECT_GT(
1283 (pi2->monotonic_now() - pi1->monotonic_now()) - initial_pi2_offset,
1284 event_loop_factory_.send_delay() +
1285 event_loop_factory_.network_delay());
Austin Schuh8bd96322020-02-13 21:18:22 -08001286 }
1287
1288 // And log a bit more on pi2.
Austin Schuh87dd3832021-01-01 23:07:31 -08001289 event_loop_factory_.RunFor(logger_run3);
Austin Schuhcde938c2020-02-02 17:30:07 -08001290 }
1291
Austin Schuh287d43d2020-12-04 20:19:33 -08001292 LogReader reader(SortParts(logfiles_));
Austin Schuhcde938c2020-02-02 17:30:07 -08001293
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001294 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
Austin Schuhcde938c2020-02-02 17:30:07 -08001295 log_reader_factory.set_send_delay(chrono::microseconds(0));
1296
Austin Schuhcde938c2020-02-02 17:30:07 -08001297 const Node *pi1 =
1298 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1299 const Node *pi2 =
1300 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1301
Austin Schuh2f8fd752020-09-01 22:38:28 -07001302 // This sends out the fetched messages and advances time to the start of the
1303 // log file.
1304 reader.Register(&log_reader_factory);
1305
1306 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
1307 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
1308 LOG(INFO) << "now pi1 "
1309 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
1310 LOG(INFO) << "now pi2 "
1311 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
1312
Austin Schuhcde938c2020-02-02 17:30:07 -08001313 LOG(INFO) << "Done registering (pi1) "
Austin Schuh391e3172020-09-01 22:48:18 -07001314 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now()
1315 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -08001316 << log_reader_factory.GetNodeEventLoopFactory(pi1)->realtime_now();
1317 LOG(INFO) << "Done registering (pi2) "
Austin Schuh391e3172020-09-01 22:48:18 -07001318 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now()
1319 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -08001320 << log_reader_factory.GetNodeEventLoopFactory(pi2)->realtime_now();
1321
Austin Schuh07676622021-01-21 18:59:17 -08001322 EXPECT_THAT(reader.LoggedNodes(),
1323 ::testing::ElementsAre(
1324 configuration::GetNode(reader.logged_configuration(), pi1),
1325 configuration::GetNode(reader.logged_configuration(), pi2)));
Austin Schuhcde938c2020-02-02 17:30:07 -08001326
1327 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
1328
1329 std::unique_ptr<EventLoop> pi1_event_loop =
1330 log_reader_factory.MakeEventLoop("test", pi1);
1331 std::unique_ptr<EventLoop> pi2_event_loop =
1332 log_reader_factory.MakeEventLoop("test", pi2);
1333
1334 int pi1_ping_count = 30;
1335 int pi2_ping_count = 30;
1336 int pi1_pong_count = 30;
1337 int pi2_pong_count = 30;
1338
1339 // Confirm that the ping value matches.
1340 pi1_event_loop->MakeWatcher(
1341 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
1342 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
1343 << pi1_event_loop->context().monotonic_remote_time << " -> "
1344 << pi1_event_loop->context().monotonic_event_time;
1345 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
1346
1347 ++pi1_ping_count;
1348 });
1349 pi2_event_loop->MakeWatcher(
1350 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
1351 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
1352 << pi2_event_loop->context().monotonic_remote_time << " -> "
1353 << pi2_event_loop->context().monotonic_event_time;
1354 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
1355
1356 ++pi2_ping_count;
1357 });
1358
1359 // Confirm that the ping and pong counts both match, and the value also
1360 // matches.
1361 pi1_event_loop->MakeWatcher(
1362 "/test", [&pi1_event_loop, &pi1_ping_count,
1363 &pi1_pong_count](const examples::Pong &pong) {
1364 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
1365 << pi1_event_loop->context().monotonic_remote_time << " -> "
1366 << pi1_event_loop->context().monotonic_event_time;
1367
1368 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
1369 ++pi1_pong_count;
1370 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
1371 });
1372 pi2_event_loop->MakeWatcher(
1373 "/test", [&pi2_event_loop, &pi2_ping_count,
1374 &pi2_pong_count](const examples::Pong &pong) {
1375 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
1376 << pi2_event_loop->context().monotonic_remote_time << " -> "
1377 << pi2_event_loop->context().monotonic_event_time;
1378
1379 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
1380 ++pi2_pong_count;
1381 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
1382 });
1383
1384 log_reader_factory.Run();
Austin Schuh8bd96322020-02-13 21:18:22 -08001385 EXPECT_EQ(pi1_ping_count, 6030);
1386 EXPECT_EQ(pi2_ping_count, 6030);
1387 EXPECT_EQ(pi1_pong_count, 6030);
1388 EXPECT_EQ(pi2_pong_count, 6030);
Austin Schuhcde938c2020-02-02 17:30:07 -08001389
1390 reader.Deregister();
1391}
1392
Austin Schuh5212cad2020-09-09 23:12:09 -07001393// Tests that we can sort a bunch of parts into the pre-determined sorted parts.
1394TEST_F(MultinodeLoggerTest, SortParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001395 time_converter_.StartEqual();
Austin Schuh5212cad2020-09-09 23:12:09 -07001396 // Make a bunch of parts.
1397 {
1398 LoggerState pi1_logger = MakeLogger(pi1_);
1399 LoggerState pi2_logger = MakeLogger(pi2_);
1400
1401 event_loop_factory_.RunFor(chrono::milliseconds(95));
1402
1403 StartLogger(&pi1_logger);
1404 StartLogger(&pi2_logger);
1405
1406 event_loop_factory_.RunFor(chrono::milliseconds(2000));
1407 }
1408
Austin Schuh11d43732020-09-21 17:28:30 -07001409 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
Austin Schuh3bd4c402020-11-06 18:19:06 -08001410 VerifyParts(sorted_parts);
1411}
Austin Schuh11d43732020-09-21 17:28:30 -07001412
Austin Schuh3bd4c402020-11-06 18:19:06 -08001413// Tests that we can sort a bunch of parts with an empty part. We should ignore
1414// it and remove it from the sorted list.
1415TEST_F(MultinodeLoggerTest, SortEmptyParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001416 time_converter_.StartEqual();
Austin Schuh3bd4c402020-11-06 18:19:06 -08001417 // Make a bunch of parts.
1418 {
1419 LoggerState pi1_logger = MakeLogger(pi1_);
1420 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuh11d43732020-09-21 17:28:30 -07001421
Austin Schuh3bd4c402020-11-06 18:19:06 -08001422 event_loop_factory_.RunFor(chrono::milliseconds(95));
Austin Schuh11d43732020-09-21 17:28:30 -07001423
Austin Schuh3bd4c402020-11-06 18:19:06 -08001424 StartLogger(&pi1_logger);
1425 StartLogger(&pi2_logger);
Austin Schuh11d43732020-09-21 17:28:30 -07001426
Austin Schuh3bd4c402020-11-06 18:19:06 -08001427 event_loop_factory_.RunFor(chrono::milliseconds(2000));
Austin Schuh11d43732020-09-21 17:28:30 -07001428 }
1429
Austin Schuh3bd4c402020-11-06 18:19:06 -08001430 // TODO(austin): Should we flip out if the file can't open?
1431 const std::string kEmptyFile("foobarinvalidfiledoesnotexist.bfbs");
Austin Schuh11d43732020-09-21 17:28:30 -07001432
Austin Schuh3bd4c402020-11-06 18:19:06 -08001433 aos::util::WriteStringToFileOrDie(kEmptyFile, "");
1434 logfiles_.emplace_back(kEmptyFile);
Austin Schuh5212cad2020-09-09 23:12:09 -07001435
Austin Schuh3bd4c402020-11-06 18:19:06 -08001436 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1437 VerifyParts(sorted_parts, {kEmptyFile});
Austin Schuh5212cad2020-09-09 23:12:09 -07001438}
1439
Austin Schuh3bd4c402020-11-06 18:19:06 -08001440#ifdef LZMA
1441// Tests that we can sort a bunch of parts with an empty .xz file in there. The
1442// empty file should be ignored.
1443TEST_F(MultinodeLoggerTest, SortEmptyCompressedParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001444 time_converter_.StartEqual();
Austin Schuh3bd4c402020-11-06 18:19:06 -08001445 // Make a bunch of parts.
1446 {
1447 LoggerState pi1_logger = MakeLogger(pi1_);
1448 LoggerState pi2_logger = MakeLogger(pi2_);
1449
1450 event_loop_factory_.RunFor(chrono::milliseconds(95));
1451
1452 StartLogger(&pi1_logger, "", true);
1453 StartLogger(&pi2_logger, "", true);
1454
1455 event_loop_factory_.RunFor(chrono::milliseconds(2000));
1456 }
1457
1458 // TODO(austin): Should we flip out if the file can't open?
1459 const std::string kEmptyFile("foobarinvalidfiledoesnotexist.bfbs.xz");
1460
1461 AddExtension(".xz");
1462
1463 aos::util::WriteStringToFileOrDie(kEmptyFile, "");
1464 logfiles_.emplace_back(kEmptyFile);
1465
1466 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1467 VerifyParts(sorted_parts, {kEmptyFile});
1468}
1469
1470// Tests that we can sort a bunch of parts with the end missing off a compressed
1471// file. We should use the part we can read.
1472TEST_F(MultinodeLoggerTest, SortTruncatedCompressedParts) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001473 time_converter_.StartEqual();
Austin Schuh3bd4c402020-11-06 18:19:06 -08001474 // Make a bunch of parts.
1475 {
1476 LoggerState pi1_logger = MakeLogger(pi1_);
1477 LoggerState pi2_logger = MakeLogger(pi2_);
1478
1479 event_loop_factory_.RunFor(chrono::milliseconds(95));
1480
1481 StartLogger(&pi1_logger, "", true);
1482 StartLogger(&pi2_logger, "", true);
1483
1484 event_loop_factory_.RunFor(chrono::milliseconds(2000));
1485 }
1486
1487 // Append everything with .xz.
1488 AddExtension(".xz");
1489
1490 // Strip off the end of one of the files. Pick one with a lot of data.
1491 ::std::string compressed_contents =
1492 aos::util::ReadFileToStringOrDie(logfiles_[0]);
1493
1494 aos::util::WriteStringToFileOrDie(
1495 logfiles_[0],
1496 compressed_contents.substr(0, compressed_contents.size() - 100));
1497
1498 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
1499 VerifyParts(sorted_parts);
1500}
1501#endif
1502
Austin Schuh01b4c352020-09-21 23:09:39 -07001503// Tests that if we remap a remapped channel, it shows up correctly.
1504TEST_F(MultinodeLoggerTest, RemapLoggedChannel) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001505 time_converter_.StartEqual();
Austin Schuh01b4c352020-09-21 23:09:39 -07001506 {
1507 LoggerState pi1_logger = MakeLogger(pi1_);
1508 LoggerState pi2_logger = MakeLogger(pi2_);
1509
1510 event_loop_factory_.RunFor(chrono::milliseconds(95));
1511
1512 StartLogger(&pi1_logger);
1513 StartLogger(&pi2_logger);
1514
1515 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1516 }
1517
Austin Schuh287d43d2020-12-04 20:19:33 -08001518 LogReader reader(SortParts(logfiles_));
Austin Schuh01b4c352020-09-21 23:09:39 -07001519
1520 // Remap just on pi1.
1521 reader.RemapLoggedChannel<aos::timing::Report>(
1522 "/aos", configuration::GetNode(reader.configuration(), "pi1"));
1523
1524 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
1525 log_reader_factory.set_send_delay(chrono::microseconds(0));
1526
1527 reader.Register(&log_reader_factory);
1528
1529 const Node *pi1 =
1530 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1531 const Node *pi2 =
1532 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1533
1534 // Confirm we can read the data on the remapped channel, just for pi1. Nothing
1535 // else should have moved.
1536 std::unique_ptr<EventLoop> pi1_event_loop =
1537 log_reader_factory.MakeEventLoop("test", pi1);
1538 pi1_event_loop->SkipTimingReport();
1539 std::unique_ptr<EventLoop> full_pi1_event_loop =
1540 log_reader_factory.MakeEventLoop("test", pi1);
1541 full_pi1_event_loop->SkipTimingReport();
1542 std::unique_ptr<EventLoop> pi2_event_loop =
1543 log_reader_factory.MakeEventLoop("test", pi2);
1544 pi2_event_loop->SkipTimingReport();
1545
1546 MessageCounter<aos::timing::Report> pi1_timing_report(pi1_event_loop.get(),
1547 "/aos");
1548 MessageCounter<aos::timing::Report> full_pi1_timing_report(
1549 full_pi1_event_loop.get(), "/pi1/aos");
1550 MessageCounter<aos::timing::Report> pi1_original_timing_report(
1551 pi1_event_loop.get(), "/original/aos");
1552 MessageCounter<aos::timing::Report> full_pi1_original_timing_report(
1553 full_pi1_event_loop.get(), "/original/pi1/aos");
1554 MessageCounter<aos::timing::Report> pi2_timing_report(pi2_event_loop.get(),
1555 "/aos");
1556
1557 log_reader_factory.Run();
1558
1559 EXPECT_EQ(pi1_timing_report.count(), 0u);
1560 EXPECT_EQ(full_pi1_timing_report.count(), 0u);
1561 EXPECT_NE(pi1_original_timing_report.count(), 0u);
1562 EXPECT_NE(full_pi1_original_timing_report.count(), 0u);
1563 EXPECT_NE(pi2_timing_report.count(), 0u);
1564
1565 reader.Deregister();
1566}
1567
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001568// Tests that we properly recreate forwarded timestamps when replaying a log.
1569// This should be enough that we can then re-run the logger and get a valid log
1570// back.
1571TEST_F(MultinodeLoggerTest, MessageHeader) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001572 time_converter_.StartEqual();
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001573 {
1574 LoggerState pi1_logger = MakeLogger(pi1_);
1575 LoggerState pi2_logger = MakeLogger(pi2_);
1576
1577 event_loop_factory_.RunFor(chrono::milliseconds(95));
1578
1579 StartLogger(&pi1_logger);
1580 StartLogger(&pi2_logger);
1581
1582 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1583 }
1584
Austin Schuh287d43d2020-12-04 20:19:33 -08001585 LogReader reader(SortParts(logfiles_));
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001586
1587 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
1588 log_reader_factory.set_send_delay(chrono::microseconds(0));
1589
1590 // This sends out the fetched messages and advances time to the start of the
1591 // log file.
1592 reader.Register(&log_reader_factory);
1593
1594 const Node *pi1 =
1595 configuration::GetNode(log_reader_factory.configuration(), "pi1");
1596 const Node *pi2 =
1597 configuration::GetNode(log_reader_factory.configuration(), "pi2");
1598
1599 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
1600 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
1601 LOG(INFO) << "now pi1 "
1602 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
1603 LOG(INFO) << "now pi2 "
1604 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
1605
Austin Schuh07676622021-01-21 18:59:17 -08001606 EXPECT_THAT(reader.LoggedNodes(),
1607 ::testing::ElementsAre(
1608 configuration::GetNode(reader.logged_configuration(), pi1),
1609 configuration::GetNode(reader.logged_configuration(), pi2)));
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001610
1611 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
1612
1613 std::unique_ptr<EventLoop> pi1_event_loop =
1614 log_reader_factory.MakeEventLoop("test", pi1);
1615 std::unique_ptr<EventLoop> pi2_event_loop =
1616 log_reader_factory.MakeEventLoop("test", pi2);
1617
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001618 aos::Fetcher<message_bridge::Timestamp> pi1_timestamp_on_pi1_fetcher =
1619 pi1_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi1/aos");
1620 aos::Fetcher<message_bridge::Timestamp> pi1_timestamp_on_pi2_fetcher =
1621 pi2_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi1/aos");
1622
1623 aos::Fetcher<examples::Ping> ping_on_pi1_fetcher =
1624 pi1_event_loop->MakeFetcher<examples::Ping>("/test");
1625 aos::Fetcher<examples::Ping> ping_on_pi2_fetcher =
1626 pi2_event_loop->MakeFetcher<examples::Ping>("/test");
1627
1628 aos::Fetcher<message_bridge::Timestamp> pi2_timestamp_on_pi2_fetcher =
1629 pi2_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi2/aos");
1630 aos::Fetcher<message_bridge::Timestamp> pi2_timestamp_on_pi1_fetcher =
1631 pi1_event_loop->MakeFetcher<message_bridge::Timestamp>("/pi2/aos");
1632
1633 aos::Fetcher<examples::Pong> pong_on_pi2_fetcher =
1634 pi2_event_loop->MakeFetcher<examples::Pong>("/test");
1635 aos::Fetcher<examples::Pong> pong_on_pi1_fetcher =
1636 pi1_event_loop->MakeFetcher<examples::Pong>("/test");
1637
1638 const size_t pi1_timestamp_channel = configuration::ChannelIndex(
1639 pi1_event_loop->configuration(), pi1_timestamp_on_pi1_fetcher.channel());
1640 const size_t ping_timestamp_channel = configuration::ChannelIndex(
1641 pi2_event_loop->configuration(), ping_on_pi2_fetcher.channel());
1642
1643 const size_t pi2_timestamp_channel = configuration::ChannelIndex(
1644 pi2_event_loop->configuration(), pi2_timestamp_on_pi2_fetcher.channel());
1645 const size_t pong_timestamp_channel = configuration::ChannelIndex(
1646 pi1_event_loop->configuration(), pong_on_pi1_fetcher.channel());
1647
Austin Schuh969cd602021-01-03 00:09:45 -08001648 const chrono::nanoseconds network_delay = event_loop_factory_.network_delay();
Austin Schuh816e5d62021-01-05 23:42:20 -08001649 const chrono::nanoseconds send_delay = event_loop_factory_.send_delay();
Austin Schuh969cd602021-01-03 00:09:45 -08001650
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001651 pi1_event_loop->MakeWatcher(
1652 "/aos/remote_timestamps/pi2",
Austin Schuh315b96b2020-12-11 21:21:12 -08001653 [&pi1_event_loop, &pi2_event_loop, pi1_timestamp_channel,
1654 ping_timestamp_channel, &pi1_timestamp_on_pi1_fetcher,
1655 &pi1_timestamp_on_pi2_fetcher, &ping_on_pi1_fetcher,
Austin Schuh816e5d62021-01-05 23:42:20 -08001656 &ping_on_pi2_fetcher, network_delay,
1657 send_delay](const RemoteMessage &header) {
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001658 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1659 chrono::nanoseconds(header.monotonic_sent_time()));
1660 const aos::realtime_clock::time_point header_realtime_sent_time(
1661 chrono::nanoseconds(header.realtime_sent_time()));
1662 const aos::monotonic_clock::time_point header_monotonic_remote_time(
1663 chrono::nanoseconds(header.monotonic_remote_time()));
1664 const aos::realtime_clock::time_point header_realtime_remote_time(
1665 chrono::nanoseconds(header.realtime_remote_time()));
1666
1667 const Context *pi1_context = nullptr;
1668 const Context *pi2_context = nullptr;
1669
1670 if (header.channel_index() == pi1_timestamp_channel) {
1671 ASSERT_TRUE(pi1_timestamp_on_pi1_fetcher.FetchNext());
1672 ASSERT_TRUE(pi1_timestamp_on_pi2_fetcher.FetchNext());
1673 pi1_context = &pi1_timestamp_on_pi1_fetcher.context();
1674 pi2_context = &pi1_timestamp_on_pi2_fetcher.context();
1675 } else if (header.channel_index() == ping_timestamp_channel) {
1676 ASSERT_TRUE(ping_on_pi1_fetcher.FetchNext());
1677 ASSERT_TRUE(ping_on_pi2_fetcher.FetchNext());
1678 pi1_context = &ping_on_pi1_fetcher.context();
1679 pi2_context = &ping_on_pi2_fetcher.context();
1680 } else {
1681 LOG(FATAL) << "Unknown channel " << FlatbufferToJson(&header) << " "
1682 << configuration::CleanedChannelToString(
1683 pi1_event_loop->configuration()->channels()->Get(
1684 header.channel_index()));
1685 }
1686
Austin Schuh315b96b2020-12-11 21:21:12 -08001687 ASSERT_TRUE(header.has_boot_uuid());
1688 EXPECT_EQ(header.boot_uuid()->string_view(),
1689 pi2_event_loop->boot_uuid().string_view());
1690
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001691 EXPECT_EQ(pi1_context->queue_index, header.remote_queue_index());
1692 EXPECT_EQ(pi2_context->remote_queue_index, header.remote_queue_index());
1693 EXPECT_EQ(pi2_context->queue_index, header.queue_index());
1694
1695 EXPECT_EQ(pi2_context->monotonic_event_time,
1696 header_monotonic_sent_time);
1697 EXPECT_EQ(pi2_context->realtime_event_time, header_realtime_sent_time);
1698 EXPECT_EQ(pi2_context->realtime_remote_time,
1699 header_realtime_remote_time);
1700 EXPECT_EQ(pi2_context->monotonic_remote_time,
1701 header_monotonic_remote_time);
1702
1703 EXPECT_EQ(pi1_context->realtime_event_time,
1704 header_realtime_remote_time);
1705 EXPECT_EQ(pi1_context->monotonic_event_time,
1706 header_monotonic_remote_time);
Austin Schuh969cd602021-01-03 00:09:45 -08001707
Austin Schuh816e5d62021-01-05 23:42:20 -08001708 // Time estimation isn't perfect, but we know the clocks were identical
1709 // when logged, so we know when this should have come back. Confirm we
1710 // got it when we expected.
1711 EXPECT_EQ(
1712 pi1_event_loop->context().monotonic_event_time,
1713 pi1_context->monotonic_event_time + 2 * network_delay + send_delay);
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001714 });
1715 pi2_event_loop->MakeWatcher(
1716 "/aos/remote_timestamps/pi1",
Austin Schuh315b96b2020-12-11 21:21:12 -08001717 [&pi2_event_loop, &pi1_event_loop, pi2_timestamp_channel,
1718 pong_timestamp_channel, &pi2_timestamp_on_pi2_fetcher,
1719 &pi2_timestamp_on_pi1_fetcher, &pong_on_pi2_fetcher,
Austin Schuh816e5d62021-01-05 23:42:20 -08001720 &pong_on_pi1_fetcher, network_delay,
1721 send_delay](const RemoteMessage &header) {
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001722 const aos::monotonic_clock::time_point header_monotonic_sent_time(
1723 chrono::nanoseconds(header.monotonic_sent_time()));
1724 const aos::realtime_clock::time_point header_realtime_sent_time(
1725 chrono::nanoseconds(header.realtime_sent_time()));
1726 const aos::monotonic_clock::time_point header_monotonic_remote_time(
1727 chrono::nanoseconds(header.monotonic_remote_time()));
1728 const aos::realtime_clock::time_point header_realtime_remote_time(
1729 chrono::nanoseconds(header.realtime_remote_time()));
1730
1731 const Context *pi2_context = nullptr;
1732 const Context *pi1_context = nullptr;
1733
1734 if (header.channel_index() == pi2_timestamp_channel) {
1735 ASSERT_TRUE(pi2_timestamp_on_pi2_fetcher.FetchNext());
1736 ASSERT_TRUE(pi2_timestamp_on_pi1_fetcher.FetchNext());
1737 pi2_context = &pi2_timestamp_on_pi2_fetcher.context();
1738 pi1_context = &pi2_timestamp_on_pi1_fetcher.context();
1739 } else if (header.channel_index() == pong_timestamp_channel) {
1740 ASSERT_TRUE(pong_on_pi2_fetcher.FetchNext());
1741 ASSERT_TRUE(pong_on_pi1_fetcher.FetchNext());
1742 pi2_context = &pong_on_pi2_fetcher.context();
1743 pi1_context = &pong_on_pi1_fetcher.context();
1744 } else {
1745 LOG(FATAL) << "Unknown channel " << FlatbufferToJson(&header) << " "
1746 << configuration::CleanedChannelToString(
1747 pi2_event_loop->configuration()->channels()->Get(
1748 header.channel_index()));
1749 }
1750
Austin Schuh315b96b2020-12-11 21:21:12 -08001751 ASSERT_TRUE(header.has_boot_uuid());
1752 EXPECT_EQ(header.boot_uuid()->string_view(),
1753 pi1_event_loop->boot_uuid().string_view());
1754
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001755 EXPECT_EQ(pi2_context->queue_index, header.remote_queue_index());
1756 EXPECT_EQ(pi1_context->remote_queue_index, header.remote_queue_index());
1757 EXPECT_EQ(pi1_context->queue_index, header.queue_index());
1758
1759 EXPECT_EQ(pi1_context->monotonic_event_time,
1760 header_monotonic_sent_time);
1761 EXPECT_EQ(pi1_context->realtime_event_time, header_realtime_sent_time);
1762 EXPECT_EQ(pi1_context->realtime_remote_time,
1763 header_realtime_remote_time);
1764 EXPECT_EQ(pi1_context->monotonic_remote_time,
1765 header_monotonic_remote_time);
1766
1767 EXPECT_EQ(pi2_context->realtime_event_time,
1768 header_realtime_remote_time);
1769 EXPECT_EQ(pi2_context->monotonic_event_time,
1770 header_monotonic_remote_time);
Austin Schuh969cd602021-01-03 00:09:45 -08001771
Austin Schuh816e5d62021-01-05 23:42:20 -08001772 // Time estimation isn't perfect, but we know the clocks were identical
1773 // when logged, so we know when this should have come back. Confirm we
1774 // got it when we expected.
1775 EXPECT_EQ(
1776 pi2_event_loop->context().monotonic_event_time,
1777 pi2_context->monotonic_event_time + 2 * network_delay + send_delay);
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001778 });
1779
1780 // And confirm we can re-create a log again, while checking the contents.
1781 {
1782 LoggerState pi1_logger = MakeLogger(
1783 configuration::GetNode(log_reader_factory.configuration(), pi1_),
1784 &log_reader_factory);
1785 LoggerState pi2_logger = MakeLogger(
1786 configuration::GetNode(log_reader_factory.configuration(), pi2_),
1787 &log_reader_factory);
1788
Austin Schuh25b46712021-01-03 00:04:38 -08001789 StartLogger(&pi1_logger, tmp_dir_ + "/relogged1");
1790 StartLogger(&pi2_logger, tmp_dir_ + "/relogged2");
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001791
1792 log_reader_factory.Run();
1793 }
1794
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001795 reader.Deregister();
James Kuszmaul4f106fb2021-01-05 20:53:02 -08001796
1797 // And verify that we can run the LogReader over the relogged files without
1798 // hitting any fatal errors.
1799 {
1800 LogReader relogged_reader(SortParts(
1801 MakeLogFiles(tmp_dir_ + "/relogged1", tmp_dir_ + "/relogged2")));
1802 relogged_reader.Register();
1803
1804 relogged_reader.event_loop_factory()->Run();
1805 }
Austin Schuh8d7e0bb2020-10-02 17:57:00 -07001806}
1807
Austin Schuh315b96b2020-12-11 21:21:12 -08001808// Tests that we properly populate and extract the logger_start time by setting
1809// up a clock difference between 2 nodes and looking at the resulting parts.
1810TEST_F(MultinodeLoggerTest, LoggerStartTime) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001811 time_converter_.AddMonotonic(
1812 {monotonic_clock::epoch(),
1813 monotonic_clock::epoch() + chrono::seconds(1000)});
Austin Schuh315b96b2020-12-11 21:21:12 -08001814 {
1815 LoggerState pi1_logger = MakeLogger(pi1_);
1816 LoggerState pi2_logger = MakeLogger(pi2_);
1817
Austin Schuh315b96b2020-12-11 21:21:12 -08001818 StartLogger(&pi1_logger);
1819 StartLogger(&pi2_logger);
1820
1821 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1822 }
1823
1824 for (const LogFile &log_file : SortParts(logfiles_)) {
1825 for (const LogParts &log_part : log_file.parts) {
1826 if (log_part.node == log_file.logger_node) {
1827 EXPECT_EQ(log_part.logger_monotonic_start_time,
1828 aos::monotonic_clock::min_time);
1829 EXPECT_EQ(log_part.logger_realtime_start_time,
1830 aos::realtime_clock::min_time);
1831 } else {
1832 const chrono::seconds offset = log_file.logger_node == "pi1"
1833 ? -chrono::seconds(1000)
1834 : chrono::seconds(1000);
1835 EXPECT_EQ(log_part.logger_monotonic_start_time,
1836 log_part.monotonic_start_time + offset);
1837 EXPECT_EQ(log_part.logger_realtime_start_time,
1838 log_file.realtime_start_time +
1839 (log_part.logger_monotonic_start_time -
1840 log_file.monotonic_start_time));
1841 }
1842 }
1843 }
1844}
1845
Austin Schuh8bd96322020-02-13 21:18:22 -08001846// TODO(austin): We can write a test which recreates a logfile and confirms that
1847// we get it back. That is the ultimate test.
1848
Austin Schuh315b96b2020-12-11 21:21:12 -08001849// Tests that we properly recreate forwarded timestamps when replaying a log.
1850// This should be enough that we can then re-run the logger and get a valid log
1851// back.
1852TEST_F(MultinodeLoggerDeathTest, RemoteReboot) {
Austin Schuh87dd3832021-01-01 23:07:31 -08001853 time_converter_.StartEqual();
Austin Schuh315b96b2020-12-11 21:21:12 -08001854 std::string pi2_boot1;
1855 std::string pi2_boot2;
1856 {
1857 pi2_boot1 = event_loop_factory_.GetNodeEventLoopFactory(pi2_)
1858 ->boot_uuid()
1859 .string_view();
1860 LoggerState pi1_logger = MakeLogger(pi1_);
1861
1862 event_loop_factory_.RunFor(chrono::milliseconds(95));
1863
1864 StartLogger(&pi1_logger);
1865
1866 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1867
1868 event_loop_factory_.GetNodeEventLoopFactory(pi2_)->Reboot();
1869
1870 pi2_boot2 = event_loop_factory_.GetNodeEventLoopFactory(pi2_)
1871 ->boot_uuid()
1872 .string_view();
1873
1874 event_loop_factory_.RunFor(chrono::milliseconds(20000));
1875 }
1876
1877 // Confirm that we refuse to replay logs with missing boot uuids.
1878 EXPECT_DEATH(
1879 {
1880 LogReader reader(SortParts(pi1_reboot_logfiles_));
1881
1882 SimulatedEventLoopFactory log_reader_factory(reader.configuration());
1883 log_reader_factory.set_send_delay(chrono::microseconds(0));
1884
1885 // This sends out the fetched messages and advances time to the start of
1886 // the log file.
1887 reader.Register(&log_reader_factory);
1888 },
1889 absl::StrFormat("(%s|%s).*(%s|%s).*Found parts from different boots",
1890 pi2_boot1, pi2_boot2, pi2_boot2, pi2_boot1));
1891}
1892
Austin Schuhc9049732020-12-21 22:27:15 -08001893// Tests that we properly handle one direction of message_bridge being
1894// unavailable.
1895TEST_F(MultinodeLoggerTest, OneDirectionWithNegativeSlope) {
1896 event_loop_factory_.GetNodeEventLoopFactory(pi1_)->Disconnect(pi2_);
Austin Schuh87dd3832021-01-01 23:07:31 -08001897 time_converter_.AddMonotonic(
1898 {monotonic_clock::epoch(),
1899 monotonic_clock::epoch() + chrono::seconds(1000)});
1900
1901 time_converter_.AddMonotonic(
1902 {chrono::milliseconds(10000),
1903 chrono::milliseconds(10000) - chrono::milliseconds(1)});
Austin Schuhc9049732020-12-21 22:27:15 -08001904 {
1905 LoggerState pi1_logger = MakeLogger(pi1_);
1906
1907 event_loop_factory_.RunFor(chrono::milliseconds(95));
1908
1909 StartLogger(&pi1_logger);
1910
1911 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1912 }
1913
1914 // Confirm that we can parse the result. LogReader has enough internal CHECKs
1915 // to confirm the right thing happened.
1916 ConfirmReadable(pi1_single_direction_logfiles_);
1917}
1918
1919// Tests that we properly handle one direction of message_bridge being
1920// unavailable.
1921TEST_F(MultinodeLoggerTest, OneDirectionWithPositiveSlope) {
1922 event_loop_factory_.GetNodeEventLoopFactory(pi1_)->Disconnect(pi2_);
Austin Schuh87dd3832021-01-01 23:07:31 -08001923 time_converter_.AddMonotonic(
1924 {monotonic_clock::epoch(),
1925 monotonic_clock::epoch() + chrono::seconds(500)});
1926
1927 time_converter_.AddMonotonic(
1928 {chrono::milliseconds(10000),
1929 chrono::milliseconds(10000) + chrono::milliseconds(1)});
1930 {
1931 LoggerState pi1_logger = MakeLogger(pi1_);
1932
1933 event_loop_factory_.RunFor(chrono::milliseconds(95));
1934
1935 StartLogger(&pi1_logger);
1936
1937 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1938 }
1939
1940 // Confirm that we can parse the result. LogReader has enough internal CHECKs
1941 // to confirm the right thing happened.
1942 ConfirmReadable(pi1_single_direction_logfiles_);
1943}
1944
1945// Tests that we properly handle a dead node. Do this by just disconnecting it
1946// and only using one nodes of logs.
1947TEST_F(MultinodeLoggerTest, DeadNode) {
1948 event_loop_factory_.GetNodeEventLoopFactory(pi1_)->Disconnect(pi2_);
1949 event_loop_factory_.GetNodeEventLoopFactory(pi2_)->Disconnect(pi1_);
1950 time_converter_.AddMonotonic(
1951 {monotonic_clock::epoch(),
1952 monotonic_clock::epoch() + chrono::seconds(1000)});
Austin Schuhc9049732020-12-21 22:27:15 -08001953 {
1954 LoggerState pi1_logger = MakeLogger(pi1_);
1955
1956 event_loop_factory_.RunFor(chrono::milliseconds(95));
1957
1958 StartLogger(&pi1_logger);
1959
1960 event_loop_factory_.RunFor(chrono::milliseconds(10000));
1961 }
1962
1963 // Confirm that we can parse the result. LogReader has enough internal CHECKs
1964 // to confirm the right thing happened.
1965 ConfirmReadable(pi1_single_direction_logfiles_);
1966}
1967
Austin Schuhe309d2a2019-11-29 13:25:21 -08001968} // namespace testing
1969} // namespace logger
1970} // namespace aos