blob: be77f38dc7679c0863f72f96f5f77d3fc428aed4 [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
3#include "aos/events/event_loop.h"
4#include "aos/events/ping_lib.h"
5#include "aos/events/pong_lib.h"
6#include "aos/events/simulated_event_loop.h"
Austin Schuh2f8fd752020-09-01 22:38:28 -07007#include "aos/util/file.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -08008#include "glog/logging.h"
Austin Schuh6f3babe2020-01-26 20:34:50 -08009#include "gmock/gmock.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080010#include "gtest/gtest.h"
11
12namespace aos {
13namespace logger {
14namespace testing {
15
16namespace chrono = std::chrono;
17
18class LoggerTest : public ::testing::Test {
19 public:
20 LoggerTest()
21 : config_(
22 aos::configuration::ReadConfig("aos/events/pingpong_config.json")),
23 event_loop_factory_(&config_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080024 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080025 ping_(ping_event_loop_.get()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080026 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080027 pong_(pong_event_loop_.get()) {}
28
29 // Config and factory.
30 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
31 SimulatedEventLoopFactory event_loop_factory_;
32
33 // Event loop and app for Ping
34 std::unique_ptr<EventLoop> ping_event_loop_;
35 Ping ping_;
36
37 // Event loop and app for Pong
38 std::unique_ptr<EventLoop> pong_event_loop_;
39 Pong pong_;
40};
41
42// Tests that we can startup at all. This confirms that the channels are all in
43// the config.
44TEST_F(LoggerTest, Starts) {
45 const ::std::string tmpdir(getenv("TEST_TMPDIR"));
Austin Schuh2f8fd752020-09-01 22:38:28 -070046 const ::std::string base_name = tmpdir + "/logfile";
47 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuhe309d2a2019-11-29 13:25:21 -080048 // Remove it.
49 unlink(logfile.c_str());
50
51 LOG(INFO) << "Logging data to " << logfile;
52
53 {
Austin Schuhe309d2a2019-11-29 13:25:21 -080054 std::unique_ptr<EventLoop> logger_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080055 event_loop_factory_.MakeEventLoop("logger");
Austin Schuhe309d2a2019-11-29 13:25:21 -080056
57 event_loop_factory_.RunFor(chrono::milliseconds(95));
58
Austin Schuh2f8fd752020-09-01 22:38:28 -070059 Logger logger(base_name, logger_event_loop.get(),
Austin Schuhe309d2a2019-11-29 13:25:21 -080060 std::chrono::milliseconds(100));
61 event_loop_factory_.RunFor(chrono::milliseconds(20000));
62 }
63
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080064 // Even though it doesn't make any difference here, exercise the logic for
65 // passing in a separate config.
66 LogReader reader(logfile, &config_.message());
Austin Schuhe309d2a2019-11-29 13:25:21 -080067
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080068 // Confirm that we can remap logged channels to point to new buses.
69 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
Austin Schuhe309d2a2019-11-29 13:25:21 -080070
Austin Schuh15649d62019-12-28 16:36:38 -080071 // This sends out the fetched messages and advances time to the start of the
72 // log file.
James Kuszmaul84ff3e52020-01-03 19:48:53 -080073 reader.Register();
Austin Schuhe309d2a2019-11-29 13:25:21 -080074
Austin Schuh6f3babe2020-01-26 20:34:50 -080075 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(nullptr));
James Kuszmaul84ff3e52020-01-03 19:48:53 -080076
Austin Schuhe309d2a2019-11-29 13:25:21 -080077 std::unique_ptr<EventLoop> test_event_loop =
James Kuszmaul84ff3e52020-01-03 19:48:53 -080078 reader.event_loop_factory()->MakeEventLoop("log_reader");
Austin Schuhe309d2a2019-11-29 13:25:21 -080079
80 int ping_count = 10;
81 int pong_count = 10;
82
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080083 // Confirm that the ping value matches in the remapped channel location.
84 test_event_loop->MakeWatcher("/original/test",
Austin Schuhe309d2a2019-11-29 13:25:21 -080085 [&ping_count](const examples::Ping &ping) {
86 EXPECT_EQ(ping.value(), ping_count + 1);
87 ++ping_count;
88 });
89 // Confirm that the ping and pong counts both match, and the value also
90 // matches.
91 test_event_loop->MakeWatcher(
92 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
93 EXPECT_EQ(pong.value(), pong_count + 1);
94 ++pong_count;
95 EXPECT_EQ(ping_count, pong_count);
96 });
97
James Kuszmaul84ff3e52020-01-03 19:48:53 -080098 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
Austin Schuhe309d2a2019-11-29 13:25:21 -080099 EXPECT_EQ(ping_count, 2010);
Austin Schuhe309d2a2019-11-29 13:25:21 -0800100}
101
Austin Schuhfa895892020-01-07 20:07:41 -0800102// Tests that we can read and write rotated log files.
103TEST_F(LoggerTest, RotatedLogFile) {
104 const ::std::string tmpdir(getenv("TEST_TMPDIR"));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700105 const ::std::string base_name = tmpdir + "/logfile";
106 const ::std::string logfile0 = base_name + ".part0.bfbs";
107 const ::std::string logfile1 = base_name + ".part1.bfbs";
Austin Schuhfa895892020-01-07 20:07:41 -0800108 // Remove it.
109 unlink(logfile0.c_str());
110 unlink(logfile1.c_str());
111
112 LOG(INFO) << "Logging data to " << logfile0 << " and " << logfile1;
113
114 {
Austin Schuhfa895892020-01-07 20:07:41 -0800115 std::unique_ptr<EventLoop> logger_event_loop =
116 event_loop_factory_.MakeEventLoop("logger");
117
118 event_loop_factory_.RunFor(chrono::milliseconds(95));
119
Austin Schuh2f8fd752020-09-01 22:38:28 -0700120 Logger logger(
121 std::make_unique<LocalLogNamer>(base_name, logger_event_loop->node()),
122 logger_event_loop.get(), std::chrono::milliseconds(100));
Austin Schuhfa895892020-01-07 20:07:41 -0800123 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700124 logger.Rotate();
Austin Schuhfa895892020-01-07 20:07:41 -0800125 event_loop_factory_.RunFor(chrono::milliseconds(10000));
126 }
127
Austin Schuh64fab802020-09-09 22:47:47 -0700128 {
129 // Confirm that the UUIDs match for both the parts and the logger, and the
130 // parts_index increments.
131 std::vector<FlatbufferVector<LogFileHeader>> log_header;
132 for (std::string_view f : {logfile0, logfile1}) {
133 log_header.emplace_back(ReadHeader(f));
134 }
135
136 EXPECT_EQ(log_header[0].message().logger_uuid()->string_view(),
137 log_header[1].message().logger_uuid()->string_view());
138 EXPECT_EQ(log_header[0].message().parts_uuid()->string_view(),
139 log_header[1].message().parts_uuid()->string_view());
140
141 EXPECT_EQ(log_header[0].message().parts_index(), 0);
142 EXPECT_EQ(log_header[1].message().parts_index(), 1);
143 }
144
Austin Schuhfa895892020-01-07 20:07:41 -0800145 // Even though it doesn't make any difference here, exercise the logic for
146 // passing in a separate config.
147 LogReader reader(std::vector<std::string>{logfile0, logfile1},
148 &config_.message());
149
150 // Confirm that we can remap logged channels to point to new buses.
151 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
152
153 // This sends out the fetched messages and advances time to the start of the
154 // log file.
155 reader.Register();
156
Austin Schuh6f3babe2020-01-26 20:34:50 -0800157 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800158
159 std::unique_ptr<EventLoop> test_event_loop =
160 reader.event_loop_factory()->MakeEventLoop("log_reader");
161
162 int ping_count = 10;
163 int pong_count = 10;
164
165 // Confirm that the ping value matches in the remapped channel location.
166 test_event_loop->MakeWatcher("/original/test",
167 [&ping_count](const examples::Ping &ping) {
168 EXPECT_EQ(ping.value(), ping_count + 1);
169 ++ping_count;
170 });
171 // Confirm that the ping and pong counts both match, and the value also
172 // matches.
173 test_event_loop->MakeWatcher(
174 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
175 EXPECT_EQ(pong.value(), pong_count + 1);
176 ++pong_count;
177 EXPECT_EQ(ping_count, pong_count);
178 });
179
180 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
181 EXPECT_EQ(ping_count, 2010);
182}
183
Austin Schuh4c4e0092019-12-22 16:18:03 -0800184// Tests that a large number of messages per second doesn't overwhelm writev.
185TEST_F(LoggerTest, ManyMessages) {
186 const ::std::string tmpdir(getenv("TEST_TMPDIR"));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700187 const ::std::string base_name = tmpdir + "/logfile";
188 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800189 // Remove the log file.
190 unlink(logfile.c_str());
191
192 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700193 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800194
195 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800196 std::unique_ptr<EventLoop> logger_event_loop =
197 event_loop_factory_.MakeEventLoop("logger");
198
199 std::unique_ptr<EventLoop> ping_spammer_event_loop =
200 event_loop_factory_.MakeEventLoop("ping_spammer");
201 aos::Sender<examples::Ping> ping_sender =
202 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
203
204 aos::TimerHandler *timer_handler =
205 ping_spammer_event_loop->AddTimer([&ping_sender]() {
206 aos::Sender<examples::Ping>::Builder builder =
207 ping_sender.MakeBuilder();
208 examples::Ping::Builder ping_builder =
209 builder.MakeBuilder<examples::Ping>();
210 CHECK(builder.Send(ping_builder.Finish()));
211 });
212
213 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
214 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
215 timer_handler->Setup(ping_spammer_event_loop->monotonic_now(),
216 chrono::microseconds(50));
217 });
218
Austin Schuh2f8fd752020-09-01 22:38:28 -0700219 Logger logger(base_name, logger_event_loop.get(),
Austin Schuh4c4e0092019-12-22 16:18:03 -0800220 std::chrono::milliseconds(100));
221
222 event_loop_factory_.RunFor(chrono::milliseconds(1000));
223 }
224}
225
Austin Schuh15649d62019-12-28 16:36:38 -0800226class MultinodeLoggerTest : public ::testing::Test {
227 public:
228 MultinodeLoggerTest()
229 : config_(aos::configuration::ReadConfig(
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800230 "aos/events/logging/multinode_pingpong_config.json")),
Austin Schuhac0771c2020-01-07 18:36:30 -0800231 event_loop_factory_(&config_.message()),
Austin Schuhcde938c2020-02-02 17:30:07 -0800232 pi1_(
233 configuration::GetNode(event_loop_factory_.configuration(), "pi1")),
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700234 pi2_(
235 configuration::GetNode(event_loop_factory_.configuration(), "pi2")),
236 tmp_dir_(getenv("TEST_TMPDIR")),
237 logfile_base_(tmp_dir_ + "/multi_logfile"),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700238 logfiles_(
239 {logfile_base_ + "_pi1_data.part0.bfbs",
240 logfile_base_ + "_pi2_data/test/aos.examples.Pong.part0.bfbs",
241 logfile_base_ + "_pi2_data/test/aos.examples.Pong.part1.bfbs",
242 logfile_base_ + "_pi2_data.part0.bfbs",
243 logfile_base_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
244 "aos.logger.MessageHeader.part0.bfbs",
245 logfile_base_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
246 "aos.logger.MessageHeader.part1.bfbs",
247 logfile_base_ + "_timestamps/pi2/aos/remote_timestamps/pi1/"
248 "aos.logger.MessageHeader.part0.bfbs",
249 logfile_base_ + "_timestamps/pi2/aos/remote_timestamps/pi1/"
250 "aos.logger.MessageHeader.part1.bfbs",
251 logfile_base_ +
252 "_pi1_data/pi1/aos/aos.message_bridge.Timestamp.part0.bfbs",
253 logfile_base_ +
254 "_pi1_data/pi1/aos/aos.message_bridge.Timestamp.part1.bfbs",
255 logfile_base_ +
256 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part0.bfbs",
257 logfile_base_ +
258 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part1.bfbs"}),
259 structured_logfiles_{
260 std::vector<std::string>{logfiles_[0]},
261 std::vector<std::string>{logfiles_[1], logfiles_[2]},
262 std::vector<std::string>{logfiles_[3]},
263 std::vector<std::string>{logfiles_[4], logfiles_[5]},
264 std::vector<std::string>{logfiles_[6], logfiles_[7]},
265 std::vector<std::string>{logfiles_[8], logfiles_[9]},
266 std::vector<std::string>{logfiles_[10], logfiles_[11]}},
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700267 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping", pi1_)),
268 ping_(ping_event_loop_.get()),
269 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong", pi2_)),
270 pong_(pong_event_loop_.get()) {
271 // Go through and remove the logfiles if they already exist.
272 for (const auto file : logfiles_) {
273 unlink(file.c_str());
274 }
275
276 LOG(INFO) << "Logging data to " << logfiles_[0] << ", " << logfiles_[1]
277 << " and " << logfiles_[2];
278 }
279
280 struct LoggerState {
281 std::unique_ptr<EventLoop> event_loop;
282 std::unique_ptr<Logger> logger;
283 };
284
285 LoggerState MakeLogger(const Node *node) {
286 return {event_loop_factory_.MakeEventLoop("logger", node), {}};
287 }
288
289 void StartLogger(LoggerState *logger) {
290 logger->logger = std::make_unique<Logger>(
291 std::make_unique<MultiNodeLogNamer>(logfile_base_,
292 logger->event_loop->configuration(),
293 logger->event_loop->node()),
294 logger->event_loop.get(), chrono::milliseconds(100));
295 }
Austin Schuh15649d62019-12-28 16:36:38 -0800296
297 // Config and factory.
298 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
299 SimulatedEventLoopFactory event_loop_factory_;
300
Austin Schuhcde938c2020-02-02 17:30:07 -0800301 const Node *pi1_;
302 const Node *pi2_;
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700303
304 std::string tmp_dir_;
305 std::string logfile_base_;
Austin Schuh2f8fd752020-09-01 22:38:28 -0700306 std::vector<std::string> logfiles_;
307
308 std::vector<std::vector<std::string>> structured_logfiles_;
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700309
310 std::unique_ptr<EventLoop> ping_event_loop_;
311 Ping ping_;
312 std::unique_ptr<EventLoop> pong_event_loop_;
313 Pong pong_;
Austin Schuh15649d62019-12-28 16:36:38 -0800314};
315
Austin Schuh391e3172020-09-01 22:48:18 -0700316// Counts the number of messages on a channel. Returns (channel name, channel
317// type, count) for every message matching matcher()
318std::vector<std::tuple<std::string, std::string, int>> CountChannelsMatching(
Austin Schuh6f3babe2020-01-26 20:34:50 -0800319 std::string_view filename,
320 std::function<bool(const MessageHeader *)> matcher) {
321 MessageReader message_reader(filename);
322 std::vector<int> counts(
323 message_reader.log_file_header()->configuration()->channels()->size(), 0);
Austin Schuh15649d62019-12-28 16:36:38 -0800324
Austin Schuh6f3babe2020-01-26 20:34:50 -0800325 while (true) {
326 std::optional<FlatbufferVector<MessageHeader>> msg =
327 message_reader.ReadMessage();
328 if (!msg) {
329 break;
330 }
331
332 if (matcher(&msg.value().message())) {
333 counts[msg.value().message().channel_index()]++;
334 }
335 }
336
Austin Schuh391e3172020-09-01 22:48:18 -0700337 std::vector<std::tuple<std::string, std::string, int>> result;
Austin Schuh6f3babe2020-01-26 20:34:50 -0800338 int channel = 0;
339 for (size_t i = 0; i < counts.size(); ++i) {
340 if (counts[i] != 0) {
Austin Schuh391e3172020-09-01 22:48:18 -0700341 const Channel *channel =
342 message_reader.log_file_header()->configuration()->channels()->Get(i);
343 result.push_back(std::make_tuple(channel->name()->str(),
344 channel->type()->str(), counts[i]));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800345 }
346 ++channel;
347 }
348
349 return result;
350}
351
352// Counts the number of messages (channel, count) for all data messages.
Austin Schuh391e3172020-09-01 22:48:18 -0700353std::vector<std::tuple<std::string, std::string, int>> CountChannelsData(
354 std::string_view filename) {
Austin Schuh6f3babe2020-01-26 20:34:50 -0800355 return CountChannelsMatching(filename, [](const MessageHeader *msg) {
356 if (msg->has_data()) {
357 CHECK(!msg->has_monotonic_remote_time());
358 CHECK(!msg->has_realtime_remote_time());
359 CHECK(!msg->has_remote_queue_index());
360 return true;
361 }
362 return false;
363 });
364}
365
366// Counts the number of messages (channel, count) for all timestamp messages.
Austin Schuh391e3172020-09-01 22:48:18 -0700367std::vector<std::tuple<std::string, std::string, int>> CountChannelsTimestamp(
Austin Schuh6f3babe2020-01-26 20:34:50 -0800368 std::string_view filename) {
369 return CountChannelsMatching(filename, [](const MessageHeader *msg) {
370 if (!msg->has_data()) {
371 CHECK(msg->has_monotonic_remote_time());
372 CHECK(msg->has_realtime_remote_time());
373 CHECK(msg->has_remote_queue_index());
374 return true;
375 }
376 return false;
377 });
378}
379
Austin Schuhcde938c2020-02-02 17:30:07 -0800380// Tests that we can write and read simple multi-node log files.
381TEST_F(MultinodeLoggerTest, SimpleMultiNode) {
Austin Schuh15649d62019-12-28 16:36:38 -0800382 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700383 LoggerState pi1_logger = MakeLogger(pi1_);
384 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuh15649d62019-12-28 16:36:38 -0800385
386 event_loop_factory_.RunFor(chrono::milliseconds(95));
387
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700388 StartLogger(&pi1_logger);
389 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800390
Austin Schuh15649d62019-12-28 16:36:38 -0800391 event_loop_factory_.RunFor(chrono::milliseconds(20000));
392 }
393
Austin Schuh6f3babe2020-01-26 20:34:50 -0800394 {
Austin Schuh64fab802020-09-09 22:47:47 -0700395 std::set<std::string> logfile_uuids;
396 std::set<std::string> parts_uuids;
397 // Confirm that we have the expected number of UUIDs for both the logfile
398 // UUIDs and parts UUIDs.
399 std::vector<FlatbufferVector<LogFileHeader>> log_header;
400 for (std::string_view f : logfiles_) {
401 log_header.emplace_back(ReadHeader(f));
402 logfile_uuids.insert(log_header.back().message().logger_uuid()->str());
403 parts_uuids.insert(log_header.back().message().parts_uuid()->str());
404 }
Austin Schuh15649d62019-12-28 16:36:38 -0800405
Austin Schuh64fab802020-09-09 22:47:47 -0700406 EXPECT_EQ(logfile_uuids.size(), 2u);
407 EXPECT_EQ(parts_uuids.size(), 7u);
408
409 // And confirm everything is on the correct node.
410 EXPECT_EQ(log_header[0].message().node()->name()->string_view(), "pi1");
411 EXPECT_EQ(log_header[1].message().node()->name()->string_view(), "pi2");
412 EXPECT_EQ(log_header[2].message().node()->name()->string_view(), "pi2");
413 EXPECT_EQ(log_header[3].message().node()->name()->string_view(), "pi2");
414 EXPECT_EQ(log_header[4].message().node()->name()->string_view(), "pi2");
415 EXPECT_EQ(log_header[5].message().node()->name()->string_view(), "pi2");
416 EXPECT_EQ(log_header[6].message().node()->name()->string_view(), "pi1");
417 EXPECT_EQ(log_header[7].message().node()->name()->string_view(), "pi1");
418 EXPECT_EQ(log_header[8].message().node()->name()->string_view(), "pi1");
419 EXPECT_EQ(log_header[9].message().node()->name()->string_view(), "pi1");
420 EXPECT_EQ(log_header[10].message().node()->name()->string_view(), "pi2");
421 EXPECT_EQ(log_header[11].message().node()->name()->string_view(), "pi2");
422
423 // And the parts index matches.
424 EXPECT_EQ(log_header[0].message().parts_index(), 0);
425 EXPECT_EQ(log_header[1].message().parts_index(), 0);
426 EXPECT_EQ(log_header[2].message().parts_index(), 1);
427 EXPECT_EQ(log_header[3].message().parts_index(), 0);
428 EXPECT_EQ(log_header[4].message().parts_index(), 0);
429 EXPECT_EQ(log_header[5].message().parts_index(), 1);
430 EXPECT_EQ(log_header[6].message().parts_index(), 0);
431 EXPECT_EQ(log_header[7].message().parts_index(), 1);
432 EXPECT_EQ(log_header[8].message().parts_index(), 0);
433 EXPECT_EQ(log_header[9].message().parts_index(), 1);
434 EXPECT_EQ(log_header[10].message().parts_index(), 0);
435 EXPECT_EQ(log_header[11].message().parts_index(), 1);
436 }
437
438 {
Austin Schuh391e3172020-09-01 22:48:18 -0700439 using ::testing::UnorderedElementsAre;
440
Austin Schuh6f3babe2020-01-26 20:34:50 -0800441 // Timing reports, pings
Austin Schuh2f8fd752020-09-01 22:38:28 -0700442 EXPECT_THAT(
443 CountChannelsData(logfiles_[0]),
444 UnorderedElementsAre(
445 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 200),
446 std::make_tuple("/pi1/aos", "aos.timing.Report", 40),
447 std::make_tuple("/test", "aos.examples.Ping", 2001)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800448 // Timestamps for pong
Austin Schuh2f8fd752020-09-01 22:38:28 -0700449 EXPECT_THAT(
450 CountChannelsTimestamp(logfiles_[0]),
451 UnorderedElementsAre(
452 std::make_tuple("/test", "aos.examples.Pong", 2001),
453 std::make_tuple("/pi2/aos", "aos.message_bridge.Timestamp", 200)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800454
455 // Pong data.
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700456 EXPECT_THAT(CountChannelsData(logfiles_[1]),
Austin Schuh391e3172020-09-01 22:48:18 -0700457 UnorderedElementsAre(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700458 std::make_tuple("/test", "aos.examples.Pong", 101)));
459 EXPECT_THAT(CountChannelsData(logfiles_[2]),
460 UnorderedElementsAre(
461 std::make_tuple("/test", "aos.examples.Pong", 1900)));
Austin Schuh391e3172020-09-01 22:48:18 -0700462
Austin Schuh6f3babe2020-01-26 20:34:50 -0800463 // No timestamps
Austin Schuh391e3172020-09-01 22:48:18 -0700464 EXPECT_THAT(CountChannelsTimestamp(logfiles_[1]), UnorderedElementsAre());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700465 EXPECT_THAT(CountChannelsTimestamp(logfiles_[2]), UnorderedElementsAre());
Austin Schuh6f3babe2020-01-26 20:34:50 -0800466
467 // Timing reports and pongs.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700468 EXPECT_THAT(
469 CountChannelsData(logfiles_[3]),
470 UnorderedElementsAre(
471 std::make_tuple("/pi2/aos", "aos.message_bridge.Timestamp", 200),
472 std::make_tuple("/pi2/aos", "aos.timing.Report", 40),
473 std::make_tuple("/test", "aos.examples.Pong", 2001)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800474 // And ping timestamps.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700475 EXPECT_THAT(
476 CountChannelsTimestamp(logfiles_[3]),
477 UnorderedElementsAre(
478 std::make_tuple("/test", "aos.examples.Ping", 2001),
479 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 200)));
480
481 // Timestamps from pi2 on pi1, and the other way.
482 EXPECT_THAT(CountChannelsData(logfiles_[4]), UnorderedElementsAre());
483 EXPECT_THAT(CountChannelsData(logfiles_[5]), UnorderedElementsAre());
484 EXPECT_THAT(CountChannelsData(logfiles_[6]), UnorderedElementsAre());
485 EXPECT_THAT(CountChannelsData(logfiles_[7]), UnorderedElementsAre());
486 EXPECT_THAT(
487 CountChannelsTimestamp(logfiles_[4]),
488 UnorderedElementsAre(
489 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 10),
490 std::make_tuple("/test", "aos.examples.Ping", 101)));
491 EXPECT_THAT(
492 CountChannelsTimestamp(logfiles_[5]),
493 UnorderedElementsAre(
494 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 190),
495 std::make_tuple("/test", "aos.examples.Ping", 1900)));
496 EXPECT_THAT(CountChannelsTimestamp(logfiles_[6]),
497 UnorderedElementsAre(std::make_tuple(
498 "/pi2/aos", "aos.message_bridge.Timestamp", 10)));
499 EXPECT_THAT(CountChannelsTimestamp(logfiles_[7]),
500 UnorderedElementsAre(std::make_tuple(
501 "/pi2/aos", "aos.message_bridge.Timestamp", 190)));
502
503 // And then test that the remotely logged timestamp data files only have
504 // timestamps in them.
505 EXPECT_THAT(CountChannelsTimestamp(logfiles_[8]), UnorderedElementsAre());
506 EXPECT_THAT(CountChannelsTimestamp(logfiles_[9]), UnorderedElementsAre());
507 EXPECT_THAT(CountChannelsTimestamp(logfiles_[10]), UnorderedElementsAre());
508 EXPECT_THAT(CountChannelsTimestamp(logfiles_[11]), UnorderedElementsAre());
509
510 EXPECT_THAT(CountChannelsData(logfiles_[8]),
511 UnorderedElementsAre(std::make_tuple(
512 "/pi1/aos", "aos.message_bridge.Timestamp", 10)));
513 EXPECT_THAT(CountChannelsData(logfiles_[9]),
514 UnorderedElementsAre(std::make_tuple(
515 "/pi1/aos", "aos.message_bridge.Timestamp", 190)));
516
517 EXPECT_THAT(CountChannelsData(logfiles_[10]),
518 UnorderedElementsAre(std::make_tuple(
519 "/pi2/aos", "aos.message_bridge.Timestamp", 10)));
520 EXPECT_THAT(CountChannelsData(logfiles_[11]),
521 UnorderedElementsAre(std::make_tuple(
522 "/pi2/aos", "aos.message_bridge.Timestamp", 190)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800523 }
524
Austin Schuh2f8fd752020-09-01 22:38:28 -0700525 LogReader reader(structured_logfiles_);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800526
Austin Schuhac0771c2020-01-07 18:36:30 -0800527 SimulatedEventLoopFactory log_reader_factory(reader.logged_configuration());
Austin Schuh6331ef92020-01-07 18:28:09 -0800528 log_reader_factory.set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800529
530 // This sends out the fetched messages and advances time to the start of the
531 // log file.
Austin Schuh6331ef92020-01-07 18:28:09 -0800532 reader.Register(&log_reader_factory);
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800533
Austin Schuhac0771c2020-01-07 18:36:30 -0800534 const Node *pi1 =
535 configuration::GetNode(log_reader_factory.configuration(), "pi1");
Austin Schuh6f3babe2020-01-26 20:34:50 -0800536 const Node *pi2 =
537 configuration::GetNode(log_reader_factory.configuration(), "pi2");
Austin Schuhac0771c2020-01-07 18:36:30 -0800538
Austin Schuh2f8fd752020-09-01 22:38:28 -0700539 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
540 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
541 LOG(INFO) << "now pi1 "
542 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
543 LOG(INFO) << "now pi2 "
544 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
545
Austin Schuh6f3babe2020-01-26 20:34:50 -0800546 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800547
548 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800549
Austin Schuh6f3babe2020-01-26 20:34:50 -0800550 std::unique_ptr<EventLoop> pi1_event_loop =
Austin Schuhac0771c2020-01-07 18:36:30 -0800551 log_reader_factory.MakeEventLoop("test", pi1);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800552 std::unique_ptr<EventLoop> pi2_event_loop =
553 log_reader_factory.MakeEventLoop("test", pi2);
Austin Schuh15649d62019-12-28 16:36:38 -0800554
Austin Schuh6f3babe2020-01-26 20:34:50 -0800555 int pi1_ping_count = 10;
556 int pi2_ping_count = 10;
557 int pi1_pong_count = 10;
558 int pi2_pong_count = 10;
Austin Schuh15649d62019-12-28 16:36:38 -0800559
560 // Confirm that the ping value matches.
Austin Schuh6f3babe2020-01-26 20:34:50 -0800561 pi1_event_loop->MakeWatcher(
562 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700563 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800564 << pi1_event_loop->context().monotonic_remote_time << " -> "
565 << pi1_event_loop->context().monotonic_event_time;
566 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
567 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
568 pi1_ping_count * chrono::milliseconds(10) +
569 monotonic_clock::epoch());
570 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
571 pi1_ping_count * chrono::milliseconds(10) +
572 realtime_clock::epoch());
573 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
574 pi1_event_loop->context().monotonic_event_time);
575 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
576 pi1_event_loop->context().realtime_event_time);
Austin Schuh15649d62019-12-28 16:36:38 -0800577
Austin Schuh6f3babe2020-01-26 20:34:50 -0800578 ++pi1_ping_count;
579 });
580 pi2_event_loop->MakeWatcher(
581 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700582 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800583 << pi2_event_loop->context().monotonic_remote_time << " -> "
584 << pi2_event_loop->context().monotonic_event_time;
585 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
586
587 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
588 pi2_ping_count * chrono::milliseconds(10) +
589 monotonic_clock::epoch());
590 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
591 pi2_ping_count * chrono::milliseconds(10) +
592 realtime_clock::epoch());
593 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time +
594 chrono::microseconds(150),
595 pi2_event_loop->context().monotonic_event_time);
596 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time +
597 chrono::microseconds(150),
598 pi2_event_loop->context().realtime_event_time);
599 ++pi2_ping_count;
Austin Schuh15649d62019-12-28 16:36:38 -0800600 });
601
Austin Schuh6f3babe2020-01-26 20:34:50 -0800602 constexpr ssize_t kQueueIndexOffset = 0;
603 // Confirm that the ping and pong counts both match, and the value also
604 // matches.
605 pi1_event_loop->MakeWatcher(
606 "/test", [&pi1_event_loop, &pi1_ping_count,
607 &pi1_pong_count](const examples::Pong &pong) {
608 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
609 << pi1_event_loop->context().monotonic_remote_time << " -> "
610 << pi1_event_loop->context().monotonic_event_time;
611
612 EXPECT_EQ(pi1_event_loop->context().remote_queue_index,
613 pi1_pong_count + kQueueIndexOffset);
614 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
615 chrono::microseconds(200) +
616 pi1_pong_count * chrono::milliseconds(10) +
617 monotonic_clock::epoch());
618 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
619 chrono::microseconds(200) +
620 pi1_pong_count * chrono::milliseconds(10) +
621 realtime_clock::epoch());
622
623 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time +
624 chrono::microseconds(150),
625 pi1_event_loop->context().monotonic_event_time);
626 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time +
627 chrono::microseconds(150),
628 pi1_event_loop->context().realtime_event_time);
629
630 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
631 ++pi1_pong_count;
632 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
633 });
634 pi2_event_loop->MakeWatcher(
635 "/test", [&pi2_event_loop, &pi2_ping_count,
636 &pi2_pong_count](const examples::Pong &pong) {
637 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
638 << pi2_event_loop->context().monotonic_remote_time << " -> "
639 << pi2_event_loop->context().monotonic_event_time;
640
641 EXPECT_EQ(pi2_event_loop->context().remote_queue_index,
642 pi2_pong_count + kQueueIndexOffset - 9);
643
644 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
645 chrono::microseconds(200) +
646 pi2_pong_count * chrono::milliseconds(10) +
647 monotonic_clock::epoch());
648 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
649 chrono::microseconds(200) +
650 pi2_pong_count * chrono::milliseconds(10) +
651 realtime_clock::epoch());
652
653 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
654 pi2_event_loop->context().monotonic_event_time);
655 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
656 pi2_event_loop->context().realtime_event_time);
657
658 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
659 ++pi2_pong_count;
660 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
661 });
662
663 log_reader_factory.Run();
664 EXPECT_EQ(pi1_ping_count, 2010);
665 EXPECT_EQ(pi2_ping_count, 2010);
666 EXPECT_EQ(pi1_pong_count, 2010);
667 EXPECT_EQ(pi2_pong_count, 2010);
Austin Schuh6331ef92020-01-07 18:28:09 -0800668
669 reader.Deregister();
Austin Schuh15649d62019-12-28 16:36:38 -0800670}
671
James Kuszmaul46d82582020-05-09 19:50:09 -0700672typedef MultinodeLoggerTest MultinodeLoggerDeathTest;
673
674// Test that if we feed the replay with a mismatched node list that we die on
675// the LogReader constructor.
676TEST_F(MultinodeLoggerDeathTest, MultiNodeBadReplayConfig) {
James Kuszmaul46d82582020-05-09 19:50:09 -0700677 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700678 LoggerState pi1_logger = MakeLogger(pi1_);
679 LoggerState pi2_logger = MakeLogger(pi2_);
James Kuszmaul46d82582020-05-09 19:50:09 -0700680
681 event_loop_factory_.RunFor(chrono::milliseconds(95));
682
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700683 StartLogger(&pi1_logger);
684 StartLogger(&pi2_logger);
James Kuszmaul46d82582020-05-09 19:50:09 -0700685
James Kuszmaul46d82582020-05-09 19:50:09 -0700686 event_loop_factory_.RunFor(chrono::milliseconds(20000));
687 }
688
689 // Test that, if we add an additional node to the replay config that the
690 // logger complains about the mismatch in number of nodes.
691 FlatbufferDetachedBuffer<Configuration> extra_nodes_config =
692 configuration::MergeWithConfig(&config_.message(), R"({
693 "nodes": [
694 {
695 "name": "extra-node"
696 }
697 ]
698 }
699 )");
700
Austin Schuh2f8fd752020-09-01 22:38:28 -0700701 EXPECT_DEATH(LogReader(structured_logfiles_, &extra_nodes_config.message()),
James Kuszmaul46d82582020-05-09 19:50:09 -0700702 "Log file and replay config need to have matching nodes lists.");
James Kuszmaul46d82582020-05-09 19:50:09 -0700703}
704
Austin Schuhcde938c2020-02-02 17:30:07 -0800705// Tests that we can read log files where they don't start at the same monotonic
706// time.
707TEST_F(MultinodeLoggerTest, StaggeredStart) {
Austin Schuhcde938c2020-02-02 17:30:07 -0800708 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700709 LoggerState pi1_logger = MakeLogger(pi1_);
710 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuhcde938c2020-02-02 17:30:07 -0800711
712 event_loop_factory_.RunFor(chrono::milliseconds(95));
713
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700714 StartLogger(&pi1_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800715
716 event_loop_factory_.RunFor(chrono::milliseconds(200));
717
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700718 StartLogger(&pi2_logger);
719
Austin Schuhcde938c2020-02-02 17:30:07 -0800720 event_loop_factory_.RunFor(chrono::milliseconds(20000));
721 }
722
Austin Schuh2f8fd752020-09-01 22:38:28 -0700723 LogReader reader(structured_logfiles_);
Austin Schuhcde938c2020-02-02 17:30:07 -0800724
725 SimulatedEventLoopFactory log_reader_factory(reader.logged_configuration());
726 log_reader_factory.set_send_delay(chrono::microseconds(0));
727
728 // This sends out the fetched messages and advances time to the start of the
729 // log file.
730 reader.Register(&log_reader_factory);
731
732 const Node *pi1 =
733 configuration::GetNode(log_reader_factory.configuration(), "pi1");
734 const Node *pi2 =
735 configuration::GetNode(log_reader_factory.configuration(), "pi2");
736
737 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
738
739 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
740
741 std::unique_ptr<EventLoop> pi1_event_loop =
742 log_reader_factory.MakeEventLoop("test", pi1);
743 std::unique_ptr<EventLoop> pi2_event_loop =
744 log_reader_factory.MakeEventLoop("test", pi2);
745
746 int pi1_ping_count = 30;
747 int pi2_ping_count = 30;
748 int pi1_pong_count = 30;
749 int pi2_pong_count = 30;
750
751 // Confirm that the ping value matches.
752 pi1_event_loop->MakeWatcher(
753 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
754 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
755 << pi1_event_loop->context().monotonic_remote_time << " -> "
756 << pi1_event_loop->context().monotonic_event_time;
757 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
758
759 ++pi1_ping_count;
760 });
761 pi2_event_loop->MakeWatcher(
762 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
763 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
764 << pi2_event_loop->context().monotonic_remote_time << " -> "
765 << pi2_event_loop->context().monotonic_event_time;
766 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
767
768 ++pi2_ping_count;
769 });
770
771 // Confirm that the ping and pong counts both match, and the value also
772 // matches.
773 pi1_event_loop->MakeWatcher(
774 "/test", [&pi1_event_loop, &pi1_ping_count,
775 &pi1_pong_count](const examples::Pong &pong) {
776 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
777 << pi1_event_loop->context().monotonic_remote_time << " -> "
778 << pi1_event_loop->context().monotonic_event_time;
779
780 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
781 ++pi1_pong_count;
782 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
783 });
784 pi2_event_loop->MakeWatcher(
785 "/test", [&pi2_event_loop, &pi2_ping_count,
786 &pi2_pong_count](const examples::Pong &pong) {
787 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
788 << pi2_event_loop->context().monotonic_remote_time << " -> "
789 << pi2_event_loop->context().monotonic_event_time;
790
791 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
792 ++pi2_pong_count;
793 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
794 });
795
796 log_reader_factory.Run();
797 EXPECT_EQ(pi1_ping_count, 2030);
798 EXPECT_EQ(pi2_ping_count, 2030);
799 EXPECT_EQ(pi1_pong_count, 2030);
800 EXPECT_EQ(pi2_pong_count, 2030);
801
802 reader.Deregister();
803}
Austin Schuh6f3babe2020-01-26 20:34:50 -0800804
Austin Schuh8bd96322020-02-13 21:18:22 -0800805// Tests that we can read log files where the monotonic clocks drift and don't
806// match correctly. While we are here, also test that different ending times
807// also is readable.
808TEST_F(MultinodeLoggerTest, MismatchedClocks) {
Austin Schuhcde938c2020-02-02 17:30:07 -0800809 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700810 LoggerState pi2_logger = MakeLogger(pi2_);
811
Austin Schuh8bd96322020-02-13 21:18:22 -0800812 NodeEventLoopFactory *pi2 =
813 event_loop_factory_.GetNodeEventLoopFactory(pi2_);
814 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
815 << pi2->realtime_now() << " distributed "
816 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -0800817
Austin Schuh8bd96322020-02-13 21:18:22 -0800818 const chrono::nanoseconds initial_pi2_offset = -chrono::seconds(1000);
819 chrono::nanoseconds pi2_offset = initial_pi2_offset;
Austin Schuhcde938c2020-02-02 17:30:07 -0800820
Austin Schuhbe69cf32020-08-27 11:38:33 -0700821 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800822 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
823 << pi2->realtime_now() << " distributed "
824 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -0800825
Austin Schuh8bd96322020-02-13 21:18:22 -0800826 for (int i = 0; i < 95; ++i) {
827 pi2_offset += chrono::nanoseconds(200);
Austin Schuhbe69cf32020-08-27 11:38:33 -0700828 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800829 event_loop_factory_.RunFor(chrono::milliseconds(1));
830 }
Austin Schuhcde938c2020-02-02 17:30:07 -0800831
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700832 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800833
Austin Schuh8bd96322020-02-13 21:18:22 -0800834 event_loop_factory_.RunFor(chrono::milliseconds(200));
Austin Schuhcde938c2020-02-02 17:30:07 -0800835
Austin Schuh8bd96322020-02-13 21:18:22 -0800836 {
837 // Run pi1's logger for only part of the time.
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700838 LoggerState pi1_logger = MakeLogger(pi1_);
Austin Schuh8bd96322020-02-13 21:18:22 -0800839
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700840 StartLogger(&pi1_logger);
Austin Schuh8bd96322020-02-13 21:18:22 -0800841
842 for (int i = 0; i < 20000; ++i) {
843 pi2_offset += chrono::nanoseconds(200);
Austin Schuhbe69cf32020-08-27 11:38:33 -0700844 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800845 event_loop_factory_.RunFor(chrono::milliseconds(1));
846 }
847
848 EXPECT_GT(pi2_offset - initial_pi2_offset,
849 event_loop_factory_.send_delay() +
850 event_loop_factory_.network_delay());
851
852 for (int i = 0; i < 40000; ++i) {
853 pi2_offset -= chrono::nanoseconds(200);
Austin Schuhbe69cf32020-08-27 11:38:33 -0700854 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800855 event_loop_factory_.RunFor(chrono::milliseconds(1));
856 }
857 }
858
859 // And log a bit more on pi2.
860 event_loop_factory_.RunFor(chrono::milliseconds(400));
Austin Schuhcde938c2020-02-02 17:30:07 -0800861 }
862
Austin Schuh2f8fd752020-09-01 22:38:28 -0700863 LogReader reader(structured_logfiles_);
Austin Schuhcde938c2020-02-02 17:30:07 -0800864
865 SimulatedEventLoopFactory log_reader_factory(reader.logged_configuration());
866 log_reader_factory.set_send_delay(chrono::microseconds(0));
867
Austin Schuhcde938c2020-02-02 17:30:07 -0800868 const Node *pi1 =
869 configuration::GetNode(log_reader_factory.configuration(), "pi1");
870 const Node *pi2 =
871 configuration::GetNode(log_reader_factory.configuration(), "pi2");
872
Austin Schuh2f8fd752020-09-01 22:38:28 -0700873 // This sends out the fetched messages and advances time to the start of the
874 // log file.
875 reader.Register(&log_reader_factory);
876
877 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
878 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
879 LOG(INFO) << "now pi1 "
880 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
881 LOG(INFO) << "now pi2 "
882 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
883
Austin Schuhcde938c2020-02-02 17:30:07 -0800884 LOG(INFO) << "Done registering (pi1) "
Austin Schuh391e3172020-09-01 22:48:18 -0700885 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now()
886 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -0800887 << log_reader_factory.GetNodeEventLoopFactory(pi1)->realtime_now();
888 LOG(INFO) << "Done registering (pi2) "
Austin Schuh391e3172020-09-01 22:48:18 -0700889 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now()
890 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -0800891 << log_reader_factory.GetNodeEventLoopFactory(pi2)->realtime_now();
892
893 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
894
895 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
896
897 std::unique_ptr<EventLoop> pi1_event_loop =
898 log_reader_factory.MakeEventLoop("test", pi1);
899 std::unique_ptr<EventLoop> pi2_event_loop =
900 log_reader_factory.MakeEventLoop("test", pi2);
901
902 int pi1_ping_count = 30;
903 int pi2_ping_count = 30;
904 int pi1_pong_count = 30;
905 int pi2_pong_count = 30;
906
907 // Confirm that the ping value matches.
908 pi1_event_loop->MakeWatcher(
909 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
910 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
911 << pi1_event_loop->context().monotonic_remote_time << " -> "
912 << pi1_event_loop->context().monotonic_event_time;
913 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
914
915 ++pi1_ping_count;
916 });
917 pi2_event_loop->MakeWatcher(
918 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
919 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
920 << pi2_event_loop->context().monotonic_remote_time << " -> "
921 << pi2_event_loop->context().monotonic_event_time;
922 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
923
924 ++pi2_ping_count;
925 });
926
927 // Confirm that the ping and pong counts both match, and the value also
928 // matches.
929 pi1_event_loop->MakeWatcher(
930 "/test", [&pi1_event_loop, &pi1_ping_count,
931 &pi1_pong_count](const examples::Pong &pong) {
932 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
933 << pi1_event_loop->context().monotonic_remote_time << " -> "
934 << pi1_event_loop->context().monotonic_event_time;
935
936 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
937 ++pi1_pong_count;
938 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
939 });
940 pi2_event_loop->MakeWatcher(
941 "/test", [&pi2_event_loop, &pi2_ping_count,
942 &pi2_pong_count](const examples::Pong &pong) {
943 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
944 << pi2_event_loop->context().monotonic_remote_time << " -> "
945 << pi2_event_loop->context().monotonic_event_time;
946
947 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
948 ++pi2_pong_count;
949 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
950 });
951
952 log_reader_factory.Run();
Austin Schuh8bd96322020-02-13 21:18:22 -0800953 EXPECT_EQ(pi1_ping_count, 6030);
954 EXPECT_EQ(pi2_ping_count, 6030);
955 EXPECT_EQ(pi1_pong_count, 6030);
956 EXPECT_EQ(pi2_pong_count, 6030);
Austin Schuhcde938c2020-02-02 17:30:07 -0800957
958 reader.Deregister();
959}
960
Austin Schuh5212cad2020-09-09 23:12:09 -0700961// Tests that we can sort a bunch of parts into the pre-determined sorted parts.
962TEST_F(MultinodeLoggerTest, SortParts) {
963 // Make a bunch of parts.
964 {
965 LoggerState pi1_logger = MakeLogger(pi1_);
966 LoggerState pi2_logger = MakeLogger(pi2_);
967
968 event_loop_factory_.RunFor(chrono::milliseconds(95));
969
970 StartLogger(&pi1_logger);
971 StartLogger(&pi2_logger);
972
973 event_loop_factory_.RunFor(chrono::milliseconds(2000));
974 }
975
Austin Schuh11d43732020-09-21 17:28:30 -0700976 const std::vector<LogFile> sorted_parts = SortParts(logfiles_);
977
978 EXPECT_EQ(sorted_parts.size(), 2u);
979
980 // Count up the number of UUIDs and make sure they are what we expect as a
981 // sanity check.
982 std::set<std::string> logger_uuids;
983 std::set<std::string> parts_uuids;
984 std::set<std::string> both_uuids;
985
986 size_t missing_rt_count = 0;
987
988 for (const LogFile &log_file : sorted_parts) {
989 EXPECT_FALSE(log_file.logger_uuid.empty());
990 logger_uuids.insert(log_file.logger_uuid);
991 both_uuids.insert(log_file.logger_uuid);
992
993 for (const LogParts &part : log_file.parts) {
994 EXPECT_NE(part.monotonic_start_time, aos::monotonic_clock::min_time)
995 << ": " << part;
996 missing_rt_count += part.realtime_start_time == aos::realtime_clock::min_time;
997
998 EXPECT_TRUE(logger_uuids.find(part.logger_uuid) != logger_uuids.end());
999 EXPECT_NE(part.node, "");
1000 parts_uuids.insert(part.parts_uuid);
1001 both_uuids.insert(part.parts_uuid);
1002 }
1003 }
1004
1005 // We won't have RT timestamps for 5 log files. We don't log the RT start
1006 // time on remote nodes because we don't know it and would be guessing. And
1007 // the log reader can actually do a better job.
1008 EXPECT_EQ(missing_rt_count, 5u);
1009
1010 EXPECT_EQ(logger_uuids.size(), 2u);
1011 EXPECT_EQ(parts_uuids.size(), ToLogReaderVector(sorted_parts).size());
1012 EXPECT_EQ(logger_uuids.size() + parts_uuids.size(), both_uuids.size());
Austin Schuh5212cad2020-09-09 23:12:09 -07001013
1014 // Test that each list of parts is in order. Don't worry about the ordering
1015 // between part file lists though.
1016 // (inner vectors all need to be in order, but outer one doesn't matter).
Austin Schuh11d43732020-09-21 17:28:30 -07001017 EXPECT_THAT(ToLogReaderVector(sorted_parts),
Austin Schuh5212cad2020-09-09 23:12:09 -07001018 ::testing::UnorderedElementsAreArray(structured_logfiles_));
1019}
1020
Austin Schuh8bd96322020-02-13 21:18:22 -08001021// TODO(austin): We can write a test which recreates a logfile and confirms that
1022// we get it back. That is the ultimate test.
1023
Austin Schuhe309d2a2019-11-29 13:25:21 -08001024} // namespace testing
1025} // namespace logger
1026} // namespace aos