blob: ab5f02c807eaf74c76243b22a20e924517db8930 [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
128 // Even though it doesn't make any difference here, exercise the logic for
129 // passing in a separate config.
130 LogReader reader(std::vector<std::string>{logfile0, logfile1},
131 &config_.message());
132
133 // Confirm that we can remap logged channels to point to new buses.
134 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
135
136 // This sends out the fetched messages and advances time to the start of the
137 // log file.
138 reader.Register();
139
Austin Schuh6f3babe2020-01-26 20:34:50 -0800140 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800141
142 std::unique_ptr<EventLoop> test_event_loop =
143 reader.event_loop_factory()->MakeEventLoop("log_reader");
144
145 int ping_count = 10;
146 int pong_count = 10;
147
148 // Confirm that the ping value matches in the remapped channel location.
149 test_event_loop->MakeWatcher("/original/test",
150 [&ping_count](const examples::Ping &ping) {
151 EXPECT_EQ(ping.value(), ping_count + 1);
152 ++ping_count;
153 });
154 // Confirm that the ping and pong counts both match, and the value also
155 // matches.
156 test_event_loop->MakeWatcher(
157 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
158 EXPECT_EQ(pong.value(), pong_count + 1);
159 ++pong_count;
160 EXPECT_EQ(ping_count, pong_count);
161 });
162
163 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
164 EXPECT_EQ(ping_count, 2010);
165}
166
Austin Schuh4c4e0092019-12-22 16:18:03 -0800167// Tests that a large number of messages per second doesn't overwhelm writev.
168TEST_F(LoggerTest, ManyMessages) {
169 const ::std::string tmpdir(getenv("TEST_TMPDIR"));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700170 const ::std::string base_name = tmpdir + "/logfile";
171 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800172 // Remove the log file.
173 unlink(logfile.c_str());
174
175 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700176 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800177
178 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800179 std::unique_ptr<EventLoop> logger_event_loop =
180 event_loop_factory_.MakeEventLoop("logger");
181
182 std::unique_ptr<EventLoop> ping_spammer_event_loop =
183 event_loop_factory_.MakeEventLoop("ping_spammer");
184 aos::Sender<examples::Ping> ping_sender =
185 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
186
187 aos::TimerHandler *timer_handler =
188 ping_spammer_event_loop->AddTimer([&ping_sender]() {
189 aos::Sender<examples::Ping>::Builder builder =
190 ping_sender.MakeBuilder();
191 examples::Ping::Builder ping_builder =
192 builder.MakeBuilder<examples::Ping>();
193 CHECK(builder.Send(ping_builder.Finish()));
194 });
195
196 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
197 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
198 timer_handler->Setup(ping_spammer_event_loop->monotonic_now(),
199 chrono::microseconds(50));
200 });
201
Austin Schuh2f8fd752020-09-01 22:38:28 -0700202 Logger logger(base_name, logger_event_loop.get(),
Austin Schuh4c4e0092019-12-22 16:18:03 -0800203 std::chrono::milliseconds(100));
204
205 event_loop_factory_.RunFor(chrono::milliseconds(1000));
206 }
207}
208
Austin Schuh15649d62019-12-28 16:36:38 -0800209class MultinodeLoggerTest : public ::testing::Test {
210 public:
211 MultinodeLoggerTest()
212 : config_(aos::configuration::ReadConfig(
Austin Schuhe84c3ed2019-12-14 15:29:48 -0800213 "aos/events/logging/multinode_pingpong_config.json")),
Austin Schuhac0771c2020-01-07 18:36:30 -0800214 event_loop_factory_(&config_.message()),
Austin Schuhcde938c2020-02-02 17:30:07 -0800215 pi1_(
216 configuration::GetNode(event_loop_factory_.configuration(), "pi1")),
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700217 pi2_(
218 configuration::GetNode(event_loop_factory_.configuration(), "pi2")),
219 tmp_dir_(getenv("TEST_TMPDIR")),
220 logfile_base_(tmp_dir_ + "/multi_logfile"),
Austin Schuh2f8fd752020-09-01 22:38:28 -0700221 logfiles_(
222 {logfile_base_ + "_pi1_data.part0.bfbs",
223 logfile_base_ + "_pi2_data/test/aos.examples.Pong.part0.bfbs",
224 logfile_base_ + "_pi2_data/test/aos.examples.Pong.part1.bfbs",
225 logfile_base_ + "_pi2_data.part0.bfbs",
226 logfile_base_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
227 "aos.logger.MessageHeader.part0.bfbs",
228 logfile_base_ + "_timestamps/pi1/aos/remote_timestamps/pi2/"
229 "aos.logger.MessageHeader.part1.bfbs",
230 logfile_base_ + "_timestamps/pi2/aos/remote_timestamps/pi1/"
231 "aos.logger.MessageHeader.part0.bfbs",
232 logfile_base_ + "_timestamps/pi2/aos/remote_timestamps/pi1/"
233 "aos.logger.MessageHeader.part1.bfbs",
234 logfile_base_ +
235 "_pi1_data/pi1/aos/aos.message_bridge.Timestamp.part0.bfbs",
236 logfile_base_ +
237 "_pi1_data/pi1/aos/aos.message_bridge.Timestamp.part1.bfbs",
238 logfile_base_ +
239 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part0.bfbs",
240 logfile_base_ +
241 "_pi2_data/pi2/aos/aos.message_bridge.Timestamp.part1.bfbs"}),
242 structured_logfiles_{
243 std::vector<std::string>{logfiles_[0]},
244 std::vector<std::string>{logfiles_[1], logfiles_[2]},
245 std::vector<std::string>{logfiles_[3]},
246 std::vector<std::string>{logfiles_[4], logfiles_[5]},
247 std::vector<std::string>{logfiles_[6], logfiles_[7]},
248 std::vector<std::string>{logfiles_[8], logfiles_[9]},
249 std::vector<std::string>{logfiles_[10], logfiles_[11]}},
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700250 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping", pi1_)),
251 ping_(ping_event_loop_.get()),
252 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong", pi2_)),
253 pong_(pong_event_loop_.get()) {
254 // Go through and remove the logfiles if they already exist.
255 for (const auto file : logfiles_) {
256 unlink(file.c_str());
257 }
258
259 LOG(INFO) << "Logging data to " << logfiles_[0] << ", " << logfiles_[1]
260 << " and " << logfiles_[2];
261 }
262
263 struct LoggerState {
264 std::unique_ptr<EventLoop> event_loop;
265 std::unique_ptr<Logger> logger;
266 };
267
268 LoggerState MakeLogger(const Node *node) {
269 return {event_loop_factory_.MakeEventLoop("logger", node), {}};
270 }
271
272 void StartLogger(LoggerState *logger) {
273 logger->logger = std::make_unique<Logger>(
274 std::make_unique<MultiNodeLogNamer>(logfile_base_,
275 logger->event_loop->configuration(),
276 logger->event_loop->node()),
277 logger->event_loop.get(), chrono::milliseconds(100));
278 }
Austin Schuh15649d62019-12-28 16:36:38 -0800279
280 // Config and factory.
281 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
282 SimulatedEventLoopFactory event_loop_factory_;
283
Austin Schuhcde938c2020-02-02 17:30:07 -0800284 const Node *pi1_;
285 const Node *pi2_;
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700286
287 std::string tmp_dir_;
288 std::string logfile_base_;
Austin Schuh2f8fd752020-09-01 22:38:28 -0700289 std::vector<std::string> logfiles_;
290
291 std::vector<std::vector<std::string>> structured_logfiles_;
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700292
293 std::unique_ptr<EventLoop> ping_event_loop_;
294 Ping ping_;
295 std::unique_ptr<EventLoop> pong_event_loop_;
296 Pong pong_;
Austin Schuh15649d62019-12-28 16:36:38 -0800297};
298
Austin Schuh391e3172020-09-01 22:48:18 -0700299// Counts the number of messages on a channel. Returns (channel name, channel
300// type, count) for every message matching matcher()
301std::vector<std::tuple<std::string, std::string, int>> CountChannelsMatching(
Austin Schuh6f3babe2020-01-26 20:34:50 -0800302 std::string_view filename,
303 std::function<bool(const MessageHeader *)> matcher) {
304 MessageReader message_reader(filename);
305 std::vector<int> counts(
306 message_reader.log_file_header()->configuration()->channels()->size(), 0);
Austin Schuh15649d62019-12-28 16:36:38 -0800307
Austin Schuh6f3babe2020-01-26 20:34:50 -0800308 while (true) {
309 std::optional<FlatbufferVector<MessageHeader>> msg =
310 message_reader.ReadMessage();
311 if (!msg) {
312 break;
313 }
314
315 if (matcher(&msg.value().message())) {
316 counts[msg.value().message().channel_index()]++;
317 }
318 }
319
Austin Schuh391e3172020-09-01 22:48:18 -0700320 std::vector<std::tuple<std::string, std::string, int>> result;
Austin Schuh6f3babe2020-01-26 20:34:50 -0800321 int channel = 0;
322 for (size_t i = 0; i < counts.size(); ++i) {
323 if (counts[i] != 0) {
Austin Schuh391e3172020-09-01 22:48:18 -0700324 const Channel *channel =
325 message_reader.log_file_header()->configuration()->channels()->Get(i);
326 result.push_back(std::make_tuple(channel->name()->str(),
327 channel->type()->str(), counts[i]));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800328 }
329 ++channel;
330 }
331
332 return result;
333}
334
335// Counts the number of messages (channel, count) for all data messages.
Austin Schuh391e3172020-09-01 22:48:18 -0700336std::vector<std::tuple<std::string, std::string, int>> CountChannelsData(
337 std::string_view filename) {
Austin Schuh6f3babe2020-01-26 20:34:50 -0800338 return CountChannelsMatching(filename, [](const MessageHeader *msg) {
339 if (msg->has_data()) {
340 CHECK(!msg->has_monotonic_remote_time());
341 CHECK(!msg->has_realtime_remote_time());
342 CHECK(!msg->has_remote_queue_index());
343 return true;
344 }
345 return false;
346 });
347}
348
349// Counts the number of messages (channel, count) for all timestamp messages.
Austin Schuh391e3172020-09-01 22:48:18 -0700350std::vector<std::tuple<std::string, std::string, int>> CountChannelsTimestamp(
Austin Schuh6f3babe2020-01-26 20:34:50 -0800351 std::string_view filename) {
352 return CountChannelsMatching(filename, [](const MessageHeader *msg) {
353 if (!msg->has_data()) {
354 CHECK(msg->has_monotonic_remote_time());
355 CHECK(msg->has_realtime_remote_time());
356 CHECK(msg->has_remote_queue_index());
357 return true;
358 }
359 return false;
360 });
361}
362
Austin Schuhcde938c2020-02-02 17:30:07 -0800363// Tests that we can write and read simple multi-node log files.
364TEST_F(MultinodeLoggerTest, SimpleMultiNode) {
Austin Schuh15649d62019-12-28 16:36:38 -0800365 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700366 LoggerState pi1_logger = MakeLogger(pi1_);
367 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuh15649d62019-12-28 16:36:38 -0800368
369 event_loop_factory_.RunFor(chrono::milliseconds(95));
370
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700371 StartLogger(&pi1_logger);
372 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800373
Austin Schuh15649d62019-12-28 16:36:38 -0800374 event_loop_factory_.RunFor(chrono::milliseconds(20000));
375 }
376
Austin Schuh6f3babe2020-01-26 20:34:50 -0800377 {
378 // Confirm that the headers are all for the correct nodes.
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700379 FlatbufferVector<LogFileHeader> logheader1 = ReadHeader(logfiles_[0]);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800380 EXPECT_EQ(logheader1.message().node()->name()->string_view(), "pi1");
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700381 FlatbufferVector<LogFileHeader> logheader2 = ReadHeader(logfiles_[1]);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800382 EXPECT_EQ(logheader2.message().node()->name()->string_view(), "pi2");
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700383 FlatbufferVector<LogFileHeader> logheader3 = ReadHeader(logfiles_[2]);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800384 EXPECT_EQ(logheader3.message().node()->name()->string_view(), "pi2");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700385 FlatbufferVector<LogFileHeader> logheader4 = ReadHeader(logfiles_[3]);
386 EXPECT_EQ(logheader4.message().node()->name()->string_view(), "pi2");
Austin Schuh15649d62019-12-28 16:36:38 -0800387
Austin Schuh391e3172020-09-01 22:48:18 -0700388 using ::testing::UnorderedElementsAre;
389
Austin Schuh6f3babe2020-01-26 20:34:50 -0800390 // Timing reports, pings
Austin Schuh2f8fd752020-09-01 22:38:28 -0700391 EXPECT_THAT(
392 CountChannelsData(logfiles_[0]),
393 UnorderedElementsAre(
394 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 200),
395 std::make_tuple("/pi1/aos", "aos.timing.Report", 40),
396 std::make_tuple("/test", "aos.examples.Ping", 2001)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800397 // Timestamps for pong
Austin Schuh2f8fd752020-09-01 22:38:28 -0700398 EXPECT_THAT(
399 CountChannelsTimestamp(logfiles_[0]),
400 UnorderedElementsAre(
401 std::make_tuple("/test", "aos.examples.Pong", 2001),
402 std::make_tuple("/pi2/aos", "aos.message_bridge.Timestamp", 200)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800403
404 // Pong data.
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700405 EXPECT_THAT(CountChannelsData(logfiles_[1]),
Austin Schuh391e3172020-09-01 22:48:18 -0700406 UnorderedElementsAre(
Austin Schuh2f8fd752020-09-01 22:38:28 -0700407 std::make_tuple("/test", "aos.examples.Pong", 101)));
408 EXPECT_THAT(CountChannelsData(logfiles_[2]),
409 UnorderedElementsAre(
410 std::make_tuple("/test", "aos.examples.Pong", 1900)));
Austin Schuh391e3172020-09-01 22:48:18 -0700411
Austin Schuh6f3babe2020-01-26 20:34:50 -0800412 // No timestamps
Austin Schuh391e3172020-09-01 22:48:18 -0700413 EXPECT_THAT(CountChannelsTimestamp(logfiles_[1]), UnorderedElementsAre());
Austin Schuh2f8fd752020-09-01 22:38:28 -0700414 EXPECT_THAT(CountChannelsTimestamp(logfiles_[2]), UnorderedElementsAre());
Austin Schuh6f3babe2020-01-26 20:34:50 -0800415
416 // Timing reports and pongs.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700417 EXPECT_THAT(
418 CountChannelsData(logfiles_[3]),
419 UnorderedElementsAre(
420 std::make_tuple("/pi2/aos", "aos.message_bridge.Timestamp", 200),
421 std::make_tuple("/pi2/aos", "aos.timing.Report", 40),
422 std::make_tuple("/test", "aos.examples.Pong", 2001)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800423 // And ping timestamps.
Austin Schuh2f8fd752020-09-01 22:38:28 -0700424 EXPECT_THAT(
425 CountChannelsTimestamp(logfiles_[3]),
426 UnorderedElementsAre(
427 std::make_tuple("/test", "aos.examples.Ping", 2001),
428 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 200)));
429
430 // Timestamps from pi2 on pi1, and the other way.
431 EXPECT_THAT(CountChannelsData(logfiles_[4]), UnorderedElementsAre());
432 EXPECT_THAT(CountChannelsData(logfiles_[5]), UnorderedElementsAre());
433 EXPECT_THAT(CountChannelsData(logfiles_[6]), UnorderedElementsAre());
434 EXPECT_THAT(CountChannelsData(logfiles_[7]), UnorderedElementsAre());
435 EXPECT_THAT(
436 CountChannelsTimestamp(logfiles_[4]),
437 UnorderedElementsAre(
438 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 10),
439 std::make_tuple("/test", "aos.examples.Ping", 101)));
440 EXPECT_THAT(
441 CountChannelsTimestamp(logfiles_[5]),
442 UnorderedElementsAre(
443 std::make_tuple("/pi1/aos", "aos.message_bridge.Timestamp", 190),
444 std::make_tuple("/test", "aos.examples.Ping", 1900)));
445 EXPECT_THAT(CountChannelsTimestamp(logfiles_[6]),
446 UnorderedElementsAre(std::make_tuple(
447 "/pi2/aos", "aos.message_bridge.Timestamp", 10)));
448 EXPECT_THAT(CountChannelsTimestamp(logfiles_[7]),
449 UnorderedElementsAre(std::make_tuple(
450 "/pi2/aos", "aos.message_bridge.Timestamp", 190)));
451
452 // And then test that the remotely logged timestamp data files only have
453 // timestamps in them.
454 EXPECT_THAT(CountChannelsTimestamp(logfiles_[8]), UnorderedElementsAre());
455 EXPECT_THAT(CountChannelsTimestamp(logfiles_[9]), UnorderedElementsAre());
456 EXPECT_THAT(CountChannelsTimestamp(logfiles_[10]), UnorderedElementsAre());
457 EXPECT_THAT(CountChannelsTimestamp(logfiles_[11]), UnorderedElementsAre());
458
459 EXPECT_THAT(CountChannelsData(logfiles_[8]),
460 UnorderedElementsAre(std::make_tuple(
461 "/pi1/aos", "aos.message_bridge.Timestamp", 10)));
462 EXPECT_THAT(CountChannelsData(logfiles_[9]),
463 UnorderedElementsAre(std::make_tuple(
464 "/pi1/aos", "aos.message_bridge.Timestamp", 190)));
465
466 EXPECT_THAT(CountChannelsData(logfiles_[10]),
467 UnorderedElementsAre(std::make_tuple(
468 "/pi2/aos", "aos.message_bridge.Timestamp", 10)));
469 EXPECT_THAT(CountChannelsData(logfiles_[11]),
470 UnorderedElementsAre(std::make_tuple(
471 "/pi2/aos", "aos.message_bridge.Timestamp", 190)));
Austin Schuh6f3babe2020-01-26 20:34:50 -0800472 }
473
Austin Schuh2f8fd752020-09-01 22:38:28 -0700474 LogReader reader(structured_logfiles_);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800475
Austin Schuhac0771c2020-01-07 18:36:30 -0800476 SimulatedEventLoopFactory log_reader_factory(reader.logged_configuration());
Austin Schuh6331ef92020-01-07 18:28:09 -0800477 log_reader_factory.set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800478
479 // This sends out the fetched messages and advances time to the start of the
480 // log file.
Austin Schuh6331ef92020-01-07 18:28:09 -0800481 reader.Register(&log_reader_factory);
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800482
Austin Schuhac0771c2020-01-07 18:36:30 -0800483 const Node *pi1 =
484 configuration::GetNode(log_reader_factory.configuration(), "pi1");
Austin Schuh6f3babe2020-01-26 20:34:50 -0800485 const Node *pi2 =
486 configuration::GetNode(log_reader_factory.configuration(), "pi2");
Austin Schuhac0771c2020-01-07 18:36:30 -0800487
Austin Schuh2f8fd752020-09-01 22:38:28 -0700488 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
489 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
490 LOG(INFO) << "now pi1 "
491 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
492 LOG(INFO) << "now pi2 "
493 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
494
Austin Schuh6f3babe2020-01-26 20:34:50 -0800495 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800496
497 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
Austin Schuh15649d62019-12-28 16:36:38 -0800498
Austin Schuh6f3babe2020-01-26 20:34:50 -0800499 std::unique_ptr<EventLoop> pi1_event_loop =
Austin Schuhac0771c2020-01-07 18:36:30 -0800500 log_reader_factory.MakeEventLoop("test", pi1);
Austin Schuh6f3babe2020-01-26 20:34:50 -0800501 std::unique_ptr<EventLoop> pi2_event_loop =
502 log_reader_factory.MakeEventLoop("test", pi2);
Austin Schuh15649d62019-12-28 16:36:38 -0800503
Austin Schuh6f3babe2020-01-26 20:34:50 -0800504 int pi1_ping_count = 10;
505 int pi2_ping_count = 10;
506 int pi1_pong_count = 10;
507 int pi2_pong_count = 10;
Austin Schuh15649d62019-12-28 16:36:38 -0800508
509 // Confirm that the ping value matches.
Austin Schuh6f3babe2020-01-26 20:34:50 -0800510 pi1_event_loop->MakeWatcher(
511 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700512 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800513 << pi1_event_loop->context().monotonic_remote_time << " -> "
514 << pi1_event_loop->context().monotonic_event_time;
515 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
516 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
517 pi1_ping_count * chrono::milliseconds(10) +
518 monotonic_clock::epoch());
519 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
520 pi1_ping_count * chrono::milliseconds(10) +
521 realtime_clock::epoch());
522 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
523 pi1_event_loop->context().monotonic_event_time);
524 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
525 pi1_event_loop->context().realtime_event_time);
Austin Schuh15649d62019-12-28 16:36:38 -0800526
Austin Schuh6f3babe2020-01-26 20:34:50 -0800527 ++pi1_ping_count;
528 });
529 pi2_event_loop->MakeWatcher(
530 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
Austin Schuh2f8fd752020-09-01 22:38:28 -0700531 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping) << " at "
Austin Schuh6f3babe2020-01-26 20:34:50 -0800532 << pi2_event_loop->context().monotonic_remote_time << " -> "
533 << pi2_event_loop->context().monotonic_event_time;
534 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
535
536 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
537 pi2_ping_count * chrono::milliseconds(10) +
538 monotonic_clock::epoch());
539 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
540 pi2_ping_count * chrono::milliseconds(10) +
541 realtime_clock::epoch());
542 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time +
543 chrono::microseconds(150),
544 pi2_event_loop->context().monotonic_event_time);
545 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time +
546 chrono::microseconds(150),
547 pi2_event_loop->context().realtime_event_time);
548 ++pi2_ping_count;
Austin Schuh15649d62019-12-28 16:36:38 -0800549 });
550
Austin Schuh6f3babe2020-01-26 20:34:50 -0800551 constexpr ssize_t kQueueIndexOffset = 0;
552 // Confirm that the ping and pong counts both match, and the value also
553 // matches.
554 pi1_event_loop->MakeWatcher(
555 "/test", [&pi1_event_loop, &pi1_ping_count,
556 &pi1_pong_count](const examples::Pong &pong) {
557 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
558 << pi1_event_loop->context().monotonic_remote_time << " -> "
559 << pi1_event_loop->context().monotonic_event_time;
560
561 EXPECT_EQ(pi1_event_loop->context().remote_queue_index,
562 pi1_pong_count + kQueueIndexOffset);
563 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time,
564 chrono::microseconds(200) +
565 pi1_pong_count * chrono::milliseconds(10) +
566 monotonic_clock::epoch());
567 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time,
568 chrono::microseconds(200) +
569 pi1_pong_count * chrono::milliseconds(10) +
570 realtime_clock::epoch());
571
572 EXPECT_EQ(pi1_event_loop->context().monotonic_remote_time +
573 chrono::microseconds(150),
574 pi1_event_loop->context().monotonic_event_time);
575 EXPECT_EQ(pi1_event_loop->context().realtime_remote_time +
576 chrono::microseconds(150),
577 pi1_event_loop->context().realtime_event_time);
578
579 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
580 ++pi1_pong_count;
581 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
582 });
583 pi2_event_loop->MakeWatcher(
584 "/test", [&pi2_event_loop, &pi2_ping_count,
585 &pi2_pong_count](const examples::Pong &pong) {
586 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
587 << pi2_event_loop->context().monotonic_remote_time << " -> "
588 << pi2_event_loop->context().monotonic_event_time;
589
590 EXPECT_EQ(pi2_event_loop->context().remote_queue_index,
591 pi2_pong_count + kQueueIndexOffset - 9);
592
593 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
594 chrono::microseconds(200) +
595 pi2_pong_count * chrono::milliseconds(10) +
596 monotonic_clock::epoch());
597 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
598 chrono::microseconds(200) +
599 pi2_pong_count * chrono::milliseconds(10) +
600 realtime_clock::epoch());
601
602 EXPECT_EQ(pi2_event_loop->context().monotonic_remote_time,
603 pi2_event_loop->context().monotonic_event_time);
604 EXPECT_EQ(pi2_event_loop->context().realtime_remote_time,
605 pi2_event_loop->context().realtime_event_time);
606
607 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
608 ++pi2_pong_count;
609 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
610 });
611
612 log_reader_factory.Run();
613 EXPECT_EQ(pi1_ping_count, 2010);
614 EXPECT_EQ(pi2_ping_count, 2010);
615 EXPECT_EQ(pi1_pong_count, 2010);
616 EXPECT_EQ(pi2_pong_count, 2010);
Austin Schuh6331ef92020-01-07 18:28:09 -0800617
618 reader.Deregister();
Austin Schuh15649d62019-12-28 16:36:38 -0800619}
620
James Kuszmaul46d82582020-05-09 19:50:09 -0700621typedef MultinodeLoggerTest MultinodeLoggerDeathTest;
622
623// Test that if we feed the replay with a mismatched node list that we die on
624// the LogReader constructor.
625TEST_F(MultinodeLoggerDeathTest, MultiNodeBadReplayConfig) {
James Kuszmaul46d82582020-05-09 19:50:09 -0700626 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700627 LoggerState pi1_logger = MakeLogger(pi1_);
628 LoggerState pi2_logger = MakeLogger(pi2_);
James Kuszmaul46d82582020-05-09 19:50:09 -0700629
630 event_loop_factory_.RunFor(chrono::milliseconds(95));
631
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700632 StartLogger(&pi1_logger);
633 StartLogger(&pi2_logger);
James Kuszmaul46d82582020-05-09 19:50:09 -0700634
James Kuszmaul46d82582020-05-09 19:50:09 -0700635 event_loop_factory_.RunFor(chrono::milliseconds(20000));
636 }
637
638 // Test that, if we add an additional node to the replay config that the
639 // logger complains about the mismatch in number of nodes.
640 FlatbufferDetachedBuffer<Configuration> extra_nodes_config =
641 configuration::MergeWithConfig(&config_.message(), R"({
642 "nodes": [
643 {
644 "name": "extra-node"
645 }
646 ]
647 }
648 )");
649
Austin Schuh2f8fd752020-09-01 22:38:28 -0700650 EXPECT_DEATH(LogReader(structured_logfiles_, &extra_nodes_config.message()),
James Kuszmaul46d82582020-05-09 19:50:09 -0700651 "Log file and replay config need to have matching nodes lists.");
James Kuszmaul46d82582020-05-09 19:50:09 -0700652}
653
Austin Schuhcde938c2020-02-02 17:30:07 -0800654// Tests that we can read log files where they don't start at the same monotonic
655// time.
656TEST_F(MultinodeLoggerTest, StaggeredStart) {
Austin Schuhcde938c2020-02-02 17:30:07 -0800657 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700658 LoggerState pi1_logger = MakeLogger(pi1_);
659 LoggerState pi2_logger = MakeLogger(pi2_);
Austin Schuhcde938c2020-02-02 17:30:07 -0800660
661 event_loop_factory_.RunFor(chrono::milliseconds(95));
662
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700663 StartLogger(&pi1_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800664
665 event_loop_factory_.RunFor(chrono::milliseconds(200));
666
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700667 StartLogger(&pi2_logger);
668
Austin Schuhcde938c2020-02-02 17:30:07 -0800669 event_loop_factory_.RunFor(chrono::milliseconds(20000));
670 }
671
Austin Schuh2f8fd752020-09-01 22:38:28 -0700672 LogReader reader(structured_logfiles_);
Austin Schuhcde938c2020-02-02 17:30:07 -0800673
674 SimulatedEventLoopFactory log_reader_factory(reader.logged_configuration());
675 log_reader_factory.set_send_delay(chrono::microseconds(0));
676
677 // This sends out the fetched messages and advances time to the start of the
678 // log file.
679 reader.Register(&log_reader_factory);
680
681 const Node *pi1 =
682 configuration::GetNode(log_reader_factory.configuration(), "pi1");
683 const Node *pi2 =
684 configuration::GetNode(log_reader_factory.configuration(), "pi2");
685
686 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
687
688 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
689
690 std::unique_ptr<EventLoop> pi1_event_loop =
691 log_reader_factory.MakeEventLoop("test", pi1);
692 std::unique_ptr<EventLoop> pi2_event_loop =
693 log_reader_factory.MakeEventLoop("test", pi2);
694
695 int pi1_ping_count = 30;
696 int pi2_ping_count = 30;
697 int pi1_pong_count = 30;
698 int pi2_pong_count = 30;
699
700 // Confirm that the ping value matches.
701 pi1_event_loop->MakeWatcher(
702 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
703 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
704 << pi1_event_loop->context().monotonic_remote_time << " -> "
705 << pi1_event_loop->context().monotonic_event_time;
706 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
707
708 ++pi1_ping_count;
709 });
710 pi2_event_loop->MakeWatcher(
711 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
712 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
713 << pi2_event_loop->context().monotonic_remote_time << " -> "
714 << pi2_event_loop->context().monotonic_event_time;
715 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
716
717 ++pi2_ping_count;
718 });
719
720 // Confirm that the ping and pong counts both match, and the value also
721 // matches.
722 pi1_event_loop->MakeWatcher(
723 "/test", [&pi1_event_loop, &pi1_ping_count,
724 &pi1_pong_count](const examples::Pong &pong) {
725 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
726 << pi1_event_loop->context().monotonic_remote_time << " -> "
727 << pi1_event_loop->context().monotonic_event_time;
728
729 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
730 ++pi1_pong_count;
731 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
732 });
733 pi2_event_loop->MakeWatcher(
734 "/test", [&pi2_event_loop, &pi2_ping_count,
735 &pi2_pong_count](const examples::Pong &pong) {
736 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
737 << pi2_event_loop->context().monotonic_remote_time << " -> "
738 << pi2_event_loop->context().monotonic_event_time;
739
740 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
741 ++pi2_pong_count;
742 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
743 });
744
745 log_reader_factory.Run();
746 EXPECT_EQ(pi1_ping_count, 2030);
747 EXPECT_EQ(pi2_ping_count, 2030);
748 EXPECT_EQ(pi1_pong_count, 2030);
749 EXPECT_EQ(pi2_pong_count, 2030);
750
751 reader.Deregister();
752}
Austin Schuh6f3babe2020-01-26 20:34:50 -0800753
Austin Schuh8bd96322020-02-13 21:18:22 -0800754// Tests that we can read log files where the monotonic clocks drift and don't
755// match correctly. While we are here, also test that different ending times
756// also is readable.
757TEST_F(MultinodeLoggerTest, MismatchedClocks) {
Austin Schuhcde938c2020-02-02 17:30:07 -0800758 {
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700759 LoggerState pi2_logger = MakeLogger(pi2_);
760
Austin Schuh8bd96322020-02-13 21:18:22 -0800761 NodeEventLoopFactory *pi2 =
762 event_loop_factory_.GetNodeEventLoopFactory(pi2_);
763 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
764 << pi2->realtime_now() << " distributed "
765 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -0800766
Austin Schuh8bd96322020-02-13 21:18:22 -0800767 const chrono::nanoseconds initial_pi2_offset = -chrono::seconds(1000);
768 chrono::nanoseconds pi2_offset = initial_pi2_offset;
Austin Schuhcde938c2020-02-02 17:30:07 -0800769
Austin Schuhbe69cf32020-08-27 11:38:33 -0700770 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800771 LOG(INFO) << "pi2 times: " << pi2->monotonic_now() << " "
772 << pi2->realtime_now() << " distributed "
773 << pi2->ToDistributedClock(pi2->monotonic_now());
Austin Schuhcde938c2020-02-02 17:30:07 -0800774
Austin Schuh8bd96322020-02-13 21:18:22 -0800775 for (int i = 0; i < 95; ++i) {
776 pi2_offset += chrono::nanoseconds(200);
Austin Schuhbe69cf32020-08-27 11:38:33 -0700777 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800778 event_loop_factory_.RunFor(chrono::milliseconds(1));
779 }
Austin Schuhcde938c2020-02-02 17:30:07 -0800780
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700781 StartLogger(&pi2_logger);
Austin Schuhcde938c2020-02-02 17:30:07 -0800782
Austin Schuh8bd96322020-02-13 21:18:22 -0800783 event_loop_factory_.RunFor(chrono::milliseconds(200));
Austin Schuhcde938c2020-02-02 17:30:07 -0800784
Austin Schuh8bd96322020-02-13 21:18:22 -0800785 {
786 // Run pi1's logger for only part of the time.
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700787 LoggerState pi1_logger = MakeLogger(pi1_);
Austin Schuh8bd96322020-02-13 21:18:22 -0800788
James Kuszmaulbb28ef22020-05-09 22:30:38 -0700789 StartLogger(&pi1_logger);
Austin Schuh8bd96322020-02-13 21:18:22 -0800790
791 for (int i = 0; i < 20000; ++i) {
792 pi2_offset += chrono::nanoseconds(200);
Austin Schuhbe69cf32020-08-27 11:38:33 -0700793 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800794 event_loop_factory_.RunFor(chrono::milliseconds(1));
795 }
796
797 EXPECT_GT(pi2_offset - initial_pi2_offset,
798 event_loop_factory_.send_delay() +
799 event_loop_factory_.network_delay());
800
801 for (int i = 0; i < 40000; ++i) {
802 pi2_offset -= chrono::nanoseconds(200);
Austin Schuhbe69cf32020-08-27 11:38:33 -0700803 pi2->SetDistributedOffset(-pi2_offset, 1.0);
Austin Schuh8bd96322020-02-13 21:18:22 -0800804 event_loop_factory_.RunFor(chrono::milliseconds(1));
805 }
806 }
807
808 // And log a bit more on pi2.
809 event_loop_factory_.RunFor(chrono::milliseconds(400));
Austin Schuhcde938c2020-02-02 17:30:07 -0800810 }
811
Austin Schuh2f8fd752020-09-01 22:38:28 -0700812 LogReader reader(structured_logfiles_);
Austin Schuhcde938c2020-02-02 17:30:07 -0800813
814 SimulatedEventLoopFactory log_reader_factory(reader.logged_configuration());
815 log_reader_factory.set_send_delay(chrono::microseconds(0));
816
Austin Schuhcde938c2020-02-02 17:30:07 -0800817 const Node *pi1 =
818 configuration::GetNode(log_reader_factory.configuration(), "pi1");
819 const Node *pi2 =
820 configuration::GetNode(log_reader_factory.configuration(), "pi2");
821
Austin Schuh2f8fd752020-09-01 22:38:28 -0700822 // This sends out the fetched messages and advances time to the start of the
823 // log file.
824 reader.Register(&log_reader_factory);
825
826 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi1) << " pi1";
827 LOG(INFO) << "Start time " << reader.monotonic_start_time(pi2) << " pi2";
828 LOG(INFO) << "now pi1 "
829 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now();
830 LOG(INFO) << "now pi2 "
831 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now();
832
Austin Schuhcde938c2020-02-02 17:30:07 -0800833 LOG(INFO) << "Done registering (pi1) "
Austin Schuh391e3172020-09-01 22:48:18 -0700834 << log_reader_factory.GetNodeEventLoopFactory(pi1)->monotonic_now()
835 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -0800836 << log_reader_factory.GetNodeEventLoopFactory(pi1)->realtime_now();
837 LOG(INFO) << "Done registering (pi2) "
Austin Schuh391e3172020-09-01 22:48:18 -0700838 << log_reader_factory.GetNodeEventLoopFactory(pi2)->monotonic_now()
839 << " "
Austin Schuhcde938c2020-02-02 17:30:07 -0800840 << log_reader_factory.GetNodeEventLoopFactory(pi2)->realtime_now();
841
842 EXPECT_THAT(reader.Nodes(), ::testing::ElementsAre(pi1, pi2));
843
844 reader.event_loop_factory()->set_send_delay(chrono::microseconds(0));
845
846 std::unique_ptr<EventLoop> pi1_event_loop =
847 log_reader_factory.MakeEventLoop("test", pi1);
848 std::unique_ptr<EventLoop> pi2_event_loop =
849 log_reader_factory.MakeEventLoop("test", pi2);
850
851 int pi1_ping_count = 30;
852 int pi2_ping_count = 30;
853 int pi1_pong_count = 30;
854 int pi2_pong_count = 30;
855
856 // Confirm that the ping value matches.
857 pi1_event_loop->MakeWatcher(
858 "/test", [&pi1_ping_count, &pi1_event_loop](const examples::Ping &ping) {
859 VLOG(1) << "Pi1 ping " << FlatbufferToJson(&ping)
860 << pi1_event_loop->context().monotonic_remote_time << " -> "
861 << pi1_event_loop->context().monotonic_event_time;
862 EXPECT_EQ(ping.value(), pi1_ping_count + 1);
863
864 ++pi1_ping_count;
865 });
866 pi2_event_loop->MakeWatcher(
867 "/test", [&pi2_ping_count, &pi2_event_loop](const examples::Ping &ping) {
868 VLOG(1) << "Pi2 ping " << FlatbufferToJson(&ping)
869 << pi2_event_loop->context().monotonic_remote_time << " -> "
870 << pi2_event_loop->context().monotonic_event_time;
871 EXPECT_EQ(ping.value(), pi2_ping_count + 1);
872
873 ++pi2_ping_count;
874 });
875
876 // Confirm that the ping and pong counts both match, and the value also
877 // matches.
878 pi1_event_loop->MakeWatcher(
879 "/test", [&pi1_event_loop, &pi1_ping_count,
880 &pi1_pong_count](const examples::Pong &pong) {
881 VLOG(1) << "Pi1 pong " << FlatbufferToJson(&pong) << " at "
882 << pi1_event_loop->context().monotonic_remote_time << " -> "
883 << pi1_event_loop->context().monotonic_event_time;
884
885 EXPECT_EQ(pong.value(), pi1_pong_count + 1);
886 ++pi1_pong_count;
887 EXPECT_EQ(pi1_ping_count, pi1_pong_count);
888 });
889 pi2_event_loop->MakeWatcher(
890 "/test", [&pi2_event_loop, &pi2_ping_count,
891 &pi2_pong_count](const examples::Pong &pong) {
892 VLOG(1) << "Pi2 pong " << FlatbufferToJson(&pong) << " at "
893 << pi2_event_loop->context().monotonic_remote_time << " -> "
894 << pi2_event_loop->context().monotonic_event_time;
895
896 EXPECT_EQ(pong.value(), pi2_pong_count + 1);
897 ++pi2_pong_count;
898 EXPECT_EQ(pi2_ping_count, pi2_pong_count);
899 });
900
901 log_reader_factory.Run();
Austin Schuh8bd96322020-02-13 21:18:22 -0800902 EXPECT_EQ(pi1_ping_count, 6030);
903 EXPECT_EQ(pi2_ping_count, 6030);
904 EXPECT_EQ(pi1_pong_count, 6030);
905 EXPECT_EQ(pi2_pong_count, 6030);
Austin Schuhcde938c2020-02-02 17:30:07 -0800906
907 reader.Deregister();
908}
909
Austin Schuh8bd96322020-02-13 21:18:22 -0800910// TODO(austin): We can write a test which recreates a logfile and confirms that
911// we get it back. That is the ultimate test.
912
Austin Schuhe309d2a2019-11-29 13:25:21 -0800913} // namespace testing
914} // namespace logger
915} // namespace aos