blob: 3f0b182af4a888d436d06125794ff1002d8aefd9 [file] [log] [blame]
Austin Schuh6bb8a822021-03-31 23:04:39 -07001#include <sys/stat.h>
2
Alexei Strots01395492023-03-20 13:59:56 -07003#include <filesystem>
4
Austin Schuh315b96b2020-12-11 21:21:12 -08005#include "absl/strings/str_format.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07006#include "glog/logging.h"
7#include "gmock/gmock.h"
8#include "gtest/gtest.h"
9
Austin Schuhe309d2a2019-11-29 13:25:21 -080010#include "aos/events/event_loop.h"
Tyler Chatowb7c6eba2021-07-28 14:43:23 -070011#include "aos/events/logging/log_reader.h"
Austin Schuhb06f03b2021-02-17 22:00:37 -080012#include "aos/events/logging/log_writer.h"
milind1f1dca32021-07-03 13:50:07 -070013#include "aos/events/logging/snappy_encoder.h"
Austin Schuh01b4c352020-09-21 23:09:39 -070014#include "aos/events/message_counter.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080015#include "aos/events/ping_lib.h"
16#include "aos/events/pong_lib.h"
17#include "aos/events/simulated_event_loop.h"
Austin Schuh0de30f32020-12-06 12:44:28 -080018#include "aos/network/remote_message_generated.h"
Austin Schuh87dd3832021-01-01 23:07:31 -080019#include "aos/network/testing_time_converter.h"
Austin Schuh8d7e0bb2020-10-02 17:57:00 -070020#include "aos/network/timestamp_generated.h"
Austin Schuh373f1762021-06-02 21:07:09 -070021#include "aos/testing/path.h"
Austin Schuhc243b422020-10-11 15:35:08 -070022#include "aos/testing/tmpdir.h"
Austin Schuh2f8fd752020-09-01 22:38:28 -070023#include "aos/util/file.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080024
Austin Schuh3bd4c402020-11-06 18:19:06 -080025#ifdef LZMA
26#include "aos/events/logging/lzma_encoder.h"
27#endif
28
Stephan Pleinesf63bde82024-01-13 15:59:33 -080029namespace aos::logger::testing {
Austin Schuhe309d2a2019-11-29 13:25:21 -080030
31namespace chrono = std::chrono;
Austin Schuh0de30f32020-12-06 12:44:28 -080032using aos::message_bridge::RemoteMessage;
Naman Guptaa63aa132023-03-22 20:06:34 -070033using aos::testing::ArtifactPath;
Austin Schuh01b4c352020-09-21 23:09:39 -070034using aos::testing::MessageCounter;
Austin Schuhe309d2a2019-11-29 13:25:21 -080035
Austin Schuhee4713b2021-03-21 19:25:17 -070036constexpr std::string_view kSingleConfigSha256(
Austin Schuhb8bca732021-07-30 22:32:00 -070037 "bbe1b563139273b23a5405eebc2f2740cefcda5f96681acd0a84b8ff9ab93ea4");
Austin Schuh8c399962020-12-25 21:51:45 -080038
Austin Schuhe309d2a2019-11-29 13:25:21 -080039class LoggerTest : public ::testing::Test {
40 public:
41 LoggerTest()
Austin Schuh373f1762021-06-02 21:07:09 -070042 : config_(aos::configuration::ReadConfig(
43 ArtifactPath("aos/events/pingpong_config.json"))),
Austin Schuhe309d2a2019-11-29 13:25:21 -080044 event_loop_factory_(&config_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080045 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080046 ping_(ping_event_loop_.get()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080047 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080048 pong_(pong_event_loop_.get()) {}
49
50 // Config and factory.
51 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
52 SimulatedEventLoopFactory event_loop_factory_;
53
54 // Event loop and app for Ping
55 std::unique_ptr<EventLoop> ping_event_loop_;
56 Ping ping_;
57
58 // Event loop and app for Pong
59 std::unique_ptr<EventLoop> pong_event_loop_;
60 Pong pong_;
61};
62
Brian Silverman1f345222020-09-24 21:14:48 -070063using LoggerDeathTest = LoggerTest;
64
Austin Schuhe309d2a2019-11-29 13:25:21 -080065// Tests that we can startup at all. This confirms that the channels are all in
66// the config.
67TEST_F(LoggerTest, Starts) {
Austin Schuhc243b422020-10-11 15:35:08 -070068 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -070069 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -080070 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -070071 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -070072 const ::std::string logfile = base_name + "_data.part0.bfbs";
Austin Schuhe309d2a2019-11-29 13:25:21 -080073 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -080074 unlink(config.c_str());
Austin Schuhe309d2a2019-11-29 13:25:21 -080075 unlink(logfile.c_str());
76
77 LOG(INFO) << "Logging data to " << logfile;
78
79 {
Austin Schuhe309d2a2019-11-29 13:25:21 -080080 std::unique_ptr<EventLoop> logger_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080081 event_loop_factory_.MakeEventLoop("logger");
Austin Schuhe309d2a2019-11-29 13:25:21 -080082
83 event_loop_factory_.RunFor(chrono::milliseconds(95));
84
Brian Silverman1f345222020-09-24 21:14:48 -070085 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -080086 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -070087 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -070088 logger.StartLoggingOnRun(base_name);
Austin Schuhe309d2a2019-11-29 13:25:21 -080089 event_loop_factory_.RunFor(chrono::milliseconds(20000));
90 }
91
Alexei Strots01395492023-03-20 13:59:56 -070092 ASSERT_TRUE(std::filesystem::exists(logfile));
93
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080094 // Even though it doesn't make any difference here, exercise the logic for
95 // passing in a separate config.
96 LogReader reader(logfile, &config_.message());
Austin Schuhe309d2a2019-11-29 13:25:21 -080097
Austin Schuh15649d62019-12-28 16:36:38 -080098 // This sends out the fetched messages and advances time to the start of the
99 // log file.
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800100 reader.Register();
Austin Schuhe309d2a2019-11-29 13:25:21 -0800101
Austin Schuh07676622021-01-21 18:59:17 -0800102 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800103
Austin Schuhe309d2a2019-11-29 13:25:21 -0800104 std::unique_ptr<EventLoop> test_event_loop =
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800105 reader.event_loop_factory()->MakeEventLoop("log_reader");
Austin Schuhe309d2a2019-11-29 13:25:21 -0800106
107 int ping_count = 10;
108 int pong_count = 10;
109
Sanjay Narayanan5ec00232022-07-08 15:21:30 -0700110 // Confirm that the ping value matches.
111 test_event_loop->MakeWatcher("/test",
Austin Schuhe309d2a2019-11-29 13:25:21 -0800112 [&ping_count](const examples::Ping &ping) {
113 EXPECT_EQ(ping.value(), ping_count + 1);
114 ++ping_count;
115 });
116 // Confirm that the ping and pong counts both match, and the value also
117 // matches.
118 test_event_loop->MakeWatcher(
119 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
120 EXPECT_EQ(pong.value(), pong_count + 1);
121 ++pong_count;
122 EXPECT_EQ(ping_count, pong_count);
123 });
124
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800125 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
Austin Schuhe309d2a2019-11-29 13:25:21 -0800126 EXPECT_EQ(ping_count, 2010);
Sanjay Narayanan5ec00232022-07-08 15:21:30 -0700127 EXPECT_EQ(pong_count, ping_count);
Austin Schuhe309d2a2019-11-29 13:25:21 -0800128}
129
Eric Schmiedebergae00e732023-04-12 15:53:17 -0600130// Tests that we can mutate a message before sending
131TEST_F(LoggerTest, MutateCallback) {
132 const ::std::string tmpdir = aos::testing::TestTmpDir();
133 const ::std::string base_name = tmpdir + "/logfile";
134 const ::std::string config =
135 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
136 const ::std::string logfile = base_name + "_data.part0.bfbs";
137 // Remove it.
138 unlink(config.c_str());
139 unlink(logfile.c_str());
140
141 LOG(INFO) << "Logging data to " << logfile;
142
143 {
144 std::unique_ptr<EventLoop> logger_event_loop =
145 event_loop_factory_.MakeEventLoop("logger");
146
147 event_loop_factory_.RunFor(chrono::milliseconds(95));
148
149 Logger logger(logger_event_loop.get());
150 logger.set_separate_config(false);
151 logger.set_polling_period(std::chrono::milliseconds(100));
152 logger.StartLoggingOnRun(base_name);
153 event_loop_factory_.RunFor(chrono::milliseconds(20000));
154 }
155
156 // Even though it doesn't make any difference here, exercise the logic for
157 // passing in a separate config.
158 LogReader reader(logfile, &config_.message());
159
160 reader.AddBeforeSendCallback("/test", [](aos::examples::Ping *ping) {
161 ping->mutate_value(ping->value() + 1);
162 });
163
164 // This sends out the fetched messages and advances time to the start of the
165 // log file.
166 reader.Register();
167
168 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
169
170 std::unique_ptr<EventLoop> test_event_loop =
171 reader.event_loop_factory()->MakeEventLoop("log_reader");
172
173 // Confirm that the ping and pong counts both match, and the value also
174 // matches.
175 int ping_count = 10;
176 test_event_loop->MakeWatcher("/test",
177 [&ping_count](const examples::Ping &ping) {
178 ++ping_count;
179 EXPECT_EQ(ping.value(), ping_count);
180 });
181
182 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
183 EXPECT_EQ(ping_count, 2010);
184}
185
Brian Silverman1f345222020-09-24 21:14:48 -0700186// Tests calling StartLogging twice.
187TEST_F(LoggerDeathTest, ExtraStart) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800188 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700189 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800190 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700191 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700192 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700193 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800194 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700195 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700196 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700197 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800198 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700199 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800200 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700201
202 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
203
204 {
205 std::unique_ptr<EventLoop> logger_event_loop =
206 event_loop_factory_.MakeEventLoop("logger");
207
208 event_loop_factory_.RunFor(chrono::milliseconds(95));
209
210 Logger logger(logger_event_loop.get());
211 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700212 logger_event_loop->OnRun([base_name1, base_name2, &logger_event_loop,
213 &logger]() {
214 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
215 base_name1, logger_event_loop->configuration(),
216 logger_event_loop.get(), logger_event_loop->node()));
217 EXPECT_DEATH(logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
218 base_name2, logger_event_loop->configuration(),
219 logger_event_loop.get(), logger_event_loop->node())),
220 "Already logging");
221 });
Brian Silverman1f345222020-09-24 21:14:48 -0700222 event_loop_factory_.RunFor(chrono::milliseconds(20000));
223 }
224}
225
James Kuszmaul94ca5132022-07-19 09:11:08 -0700226// Tests that we die if the replayer attempts to send on a logged channel.
227TEST_F(LoggerDeathTest, DieOnDuplicateReplayChannels) {
228 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
229 aos::configuration::ReadConfig(
230 ArtifactPath("aos/events/pingpong_config.json"));
231 SimulatedEventLoopFactory event_loop_factory(&config.message());
232 const ::std::string tmpdir = aos::testing::TestTmpDir();
233 const ::std::string base_name = tmpdir + "/logfile";
234 const ::std::string config_file =
235 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700236 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul94ca5132022-07-19 09:11:08 -0700237 // Remove the log file.
238 unlink(config_file.c_str());
239 unlink(logfile.c_str());
240
241 LOG(INFO) << "Logging data to " << logfile;
242
243 {
244 std::unique_ptr<EventLoop> logger_event_loop =
245 event_loop_factory.MakeEventLoop("logger");
246
247 Logger logger(logger_event_loop.get());
248 logger.set_separate_config(false);
249 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700250 logger.StartLoggingOnRun(base_name);
James Kuszmaul94ca5132022-07-19 09:11:08 -0700251
252 event_loop_factory.RunFor(chrono::seconds(2));
253 }
254
255 LogReader reader(logfile);
256
257 reader.Register();
258
259 std::unique_ptr<EventLoop> test_event_loop =
260 reader.event_loop_factory()->MakeEventLoop("log_reader");
261
262 EXPECT_DEATH(test_event_loop->MakeSender<examples::Ping>("/test"),
263 "exclusive channel.*examples.Ping");
264}
265
Brian Silverman1f345222020-09-24 21:14:48 -0700266// Tests calling StopLogging twice.
267TEST_F(LoggerDeathTest, ExtraStop) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800268 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700269 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800270 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700271 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700272 const ::std::string logfile = base_name + ".part0.bfbs";
273 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800274 unlink(config.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700275 unlink(logfile.c_str());
276
277 LOG(INFO) << "Logging data to " << logfile;
278
279 {
280 std::unique_ptr<EventLoop> logger_event_loop =
281 event_loop_factory_.MakeEventLoop("logger");
282
283 event_loop_factory_.RunFor(chrono::milliseconds(95));
284
285 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800286 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700287 logger.set_polling_period(std::chrono::milliseconds(100));
288 logger_event_loop->OnRun([base_name, &logger_event_loop, &logger]() {
Alexei Strots01395492023-03-20 13:59:56 -0700289 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700290 base_name, logger_event_loop->configuration(),
291 logger_event_loop.get(), logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700292 logger.StopLogging(aos::monotonic_clock::min_time);
293 EXPECT_DEATH(logger.StopLogging(aos::monotonic_clock::min_time),
294 "Not logging right now");
295 });
296 event_loop_factory_.RunFor(chrono::milliseconds(20000));
297 }
298}
299
300// Tests that we can startup twice.
301TEST_F(LoggerTest, StartsTwice) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800302 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700303 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800304 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700305 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700306 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700307 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800308 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700309 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700310 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700311 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800312 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700313 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800314 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700315
316 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
317
318 {
319 std::unique_ptr<EventLoop> logger_event_loop =
320 event_loop_factory_.MakeEventLoop("logger");
321
322 event_loop_factory_.RunFor(chrono::milliseconds(95));
323
324 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800325 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700326 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700327 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700328 base_name1, logger_event_loop->configuration(), logger_event_loop.get(),
329 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700330 event_loop_factory_.RunFor(chrono::milliseconds(10000));
331 logger.StopLogging(logger_event_loop->monotonic_now());
332 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Alexei Strots01395492023-03-20 13:59:56 -0700333 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700334 base_name2, logger_event_loop->configuration(), logger_event_loop.get(),
335 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700336 event_loop_factory_.RunFor(chrono::milliseconds(10000));
337 }
338
339 for (const auto &logfile :
340 {std::make_tuple(logfile1, 10), std::make_tuple(logfile2, 2010)}) {
341 SCOPED_TRACE(std::get<0>(logfile));
342 LogReader reader(std::get<0>(logfile));
343 reader.Register();
344
Austin Schuh07676622021-01-21 18:59:17 -0800345 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Brian Silverman1f345222020-09-24 21:14:48 -0700346
347 std::unique_ptr<EventLoop> test_event_loop =
348 reader.event_loop_factory()->MakeEventLoop("log_reader");
349
350 int ping_count = std::get<1>(logfile);
351 int pong_count = std::get<1>(logfile);
352
353 // Confirm that the ping and pong counts both match, and the value also
354 // matches.
355 test_event_loop->MakeWatcher("/test",
356 [&ping_count](const examples::Ping &ping) {
357 EXPECT_EQ(ping.value(), ping_count + 1);
358 ++ping_count;
359 });
360 test_event_loop->MakeWatcher(
361 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
362 EXPECT_EQ(pong.value(), pong_count + 1);
363 ++pong_count;
364 EXPECT_EQ(ping_count, pong_count);
365 });
366
367 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
368 EXPECT_EQ(ping_count, std::get<1>(logfile) + 1000);
369 }
370}
371
Austin Schuhfa895892020-01-07 20:07:41 -0800372// Tests that we can read and write rotated log files.
373TEST_F(LoggerTest, RotatedLogFile) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800374 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700375 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800376 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700377 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700378 const ::std::string logfile0 = base_name + "_data.part0.bfbs";
379 const ::std::string logfile1 = base_name + "_data.part1.bfbs";
Austin Schuhfa895892020-01-07 20:07:41 -0800380 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800381 unlink(config.c_str());
Austin Schuhfa895892020-01-07 20:07:41 -0800382 unlink(logfile0.c_str());
383 unlink(logfile1.c_str());
384
385 LOG(INFO) << "Logging data to " << logfile0 << " and " << logfile1;
386
387 {
Austin Schuhfa895892020-01-07 20:07:41 -0800388 std::unique_ptr<EventLoop> logger_event_loop =
389 event_loop_factory_.MakeEventLoop("logger");
390
391 event_loop_factory_.RunFor(chrono::milliseconds(95));
392
Brian Silverman1f345222020-09-24 21:14:48 -0700393 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800394 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700395 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700396 logger.StartLoggingOnRun(base_name);
Austin Schuhfa895892020-01-07 20:07:41 -0800397 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700398 logger.Rotate();
Austin Schuhfa895892020-01-07 20:07:41 -0800399 event_loop_factory_.RunFor(chrono::milliseconds(10000));
400 }
401
Austin Schuh64fab802020-09-09 22:47:47 -0700402 {
403 // Confirm that the UUIDs match for both the parts and the logger, and the
404 // parts_index increments.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800405 std::vector<SizePrefixedFlatbufferVector<LogFileHeader>> log_header;
Austin Schuh64fab802020-09-09 22:47:47 -0700406 for (std::string_view f : {logfile0, logfile1}) {
Austin Schuh3bd4c402020-11-06 18:19:06 -0800407 log_header.emplace_back(ReadHeader(f).value());
Austin Schuh64fab802020-09-09 22:47:47 -0700408 }
409
Brian Silvermanae7c0332020-09-30 16:58:23 -0700410 EXPECT_EQ(log_header[0].message().log_event_uuid()->string_view(),
411 log_header[1].message().log_event_uuid()->string_view());
Austin Schuh64fab802020-09-09 22:47:47 -0700412 EXPECT_EQ(log_header[0].message().parts_uuid()->string_view(),
413 log_header[1].message().parts_uuid()->string_view());
414
415 EXPECT_EQ(log_header[0].message().parts_index(), 0);
416 EXPECT_EQ(log_header[1].message().parts_index(), 1);
417 }
418
Austin Schuhfa895892020-01-07 20:07:41 -0800419 // Even though it doesn't make any difference here, exercise the logic for
420 // passing in a separate config.
Austin Schuh287d43d2020-12-04 20:19:33 -0800421 LogReader reader(SortParts({logfile0, logfile1}), &config_.message());
Austin Schuhfa895892020-01-07 20:07:41 -0800422
423 // Confirm that we can remap logged channels to point to new buses.
424 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
425
426 // This sends out the fetched messages and advances time to the start of the
427 // log file.
428 reader.Register();
429
Austin Schuh07676622021-01-21 18:59:17 -0800430 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800431
432 std::unique_ptr<EventLoop> test_event_loop =
433 reader.event_loop_factory()->MakeEventLoop("log_reader");
434
435 int ping_count = 10;
436 int pong_count = 10;
437
438 // Confirm that the ping value matches in the remapped channel location.
439 test_event_loop->MakeWatcher("/original/test",
440 [&ping_count](const examples::Ping &ping) {
441 EXPECT_EQ(ping.value(), ping_count + 1);
442 ++ping_count;
443 });
444 // Confirm that the ping and pong counts both match, and the value also
445 // matches.
446 test_event_loop->MakeWatcher(
447 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
448 EXPECT_EQ(pong.value(), pong_count + 1);
449 ++pong_count;
450 EXPECT_EQ(ping_count, pong_count);
451 });
452
453 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
454 EXPECT_EQ(ping_count, 2010);
455}
456
Austin Schuh4c4e0092019-12-22 16:18:03 -0800457// Tests that a large number of messages per second doesn't overwhelm writev.
458TEST_F(LoggerTest, ManyMessages) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800459 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700460 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800461 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700462 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700463 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800464 // Remove the log file.
Austin Schuh25b46712021-01-03 00:04:38 -0800465 unlink(config.c_str());
Austin Schuh4c4e0092019-12-22 16:18:03 -0800466 unlink(logfile.c_str());
467
468 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700469 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800470
471 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800472 std::unique_ptr<EventLoop> logger_event_loop =
473 event_loop_factory_.MakeEventLoop("logger");
474
475 std::unique_ptr<EventLoop> ping_spammer_event_loop =
476 event_loop_factory_.MakeEventLoop("ping_spammer");
477 aos::Sender<examples::Ping> ping_sender =
478 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
479
480 aos::TimerHandler *timer_handler =
481 ping_spammer_event_loop->AddTimer([&ping_sender]() {
482 aos::Sender<examples::Ping>::Builder builder =
483 ping_sender.MakeBuilder();
484 examples::Ping::Builder ping_builder =
485 builder.MakeBuilder<examples::Ping>();
Austin Schuhbfe6c572022-01-27 20:48:20 -0800486 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800487 });
488
489 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
490 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700491 timer_handler->Schedule(ping_spammer_event_loop->monotonic_now(),
492 chrono::microseconds(50));
Austin Schuh4c4e0092019-12-22 16:18:03 -0800493 });
494
Brian Silverman1f345222020-09-24 21:14:48 -0700495 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800496 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700497 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700498 logger.StartLoggingOnRun(base_name);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800499
500 event_loop_factory_.RunFor(chrono::milliseconds(1000));
501 }
502}
503
James Kuszmaul890c2492022-04-06 14:59:31 -0700504// Tests that we can read a logfile that has channels which were sent too fast.
505TEST(SingleNodeLoggerNoFixtureTest, ReadTooFast) {
506 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
507 aos::configuration::ReadConfig(
508 ArtifactPath("aos/events/pingpong_config.json"));
509 SimulatedEventLoopFactory event_loop_factory(&config.message());
510 const ::std::string tmpdir = aos::testing::TestTmpDir();
511 const ::std::string base_name = tmpdir + "/logfile";
512 const ::std::string config_file =
513 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700514 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul890c2492022-04-06 14:59:31 -0700515 // Remove the log file.
516 unlink(config_file.c_str());
517 unlink(logfile.c_str());
518
519 LOG(INFO) << "Logging data to " << logfile;
520
521 int sent_messages = 0;
522
523 {
524 std::unique_ptr<EventLoop> logger_event_loop =
525 event_loop_factory.MakeEventLoop("logger");
526
527 std::unique_ptr<EventLoop> ping_spammer_event_loop =
528 event_loop_factory.GetNodeEventLoopFactory(nullptr)->MakeEventLoop(
529 "ping_spammer", {NodeEventLoopFactory::CheckSentTooFast::kNo,
James Kuszmaul94ca5132022-07-19 09:11:08 -0700530 NodeEventLoopFactory::ExclusiveSenders::kNo,
531 {}});
James Kuszmaul890c2492022-04-06 14:59:31 -0700532 aos::Sender<examples::Ping> ping_sender =
533 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
534
535 aos::TimerHandler *timer_handler =
536 ping_spammer_event_loop->AddTimer([&ping_sender, &sent_messages]() {
537 aos::Sender<examples::Ping>::Builder builder =
538 ping_sender.MakeBuilder();
539 examples::Ping::Builder ping_builder =
540 builder.MakeBuilder<examples::Ping>();
541 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
542 ++sent_messages;
543 });
544
545 constexpr std::chrono::microseconds kSendPeriod{10};
Austin Schuhfff9c3a2023-06-16 18:48:23 -0700546 const int max_legal_messages = configuration::QueueSize(
547 event_loop_factory.configuration(), ping_sender.channel());
James Kuszmaul890c2492022-04-06 14:59:31 -0700548
549 ping_spammer_event_loop->OnRun(
550 [&ping_spammer_event_loop, kSendPeriod, timer_handler]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700551 timer_handler->Schedule(
James Kuszmaul890c2492022-04-06 14:59:31 -0700552 ping_spammer_event_loop->monotonic_now() + kSendPeriod / 2,
553 kSendPeriod);
554 });
555
556 Logger logger(logger_event_loop.get());
557 logger.set_separate_config(false);
558 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700559 logger.StartLoggingOnRun(base_name);
James Kuszmaul890c2492022-04-06 14:59:31 -0700560
561 event_loop_factory.RunFor(kSendPeriod * max_legal_messages * 2);
562 }
563
564 LogReader reader(logfile);
565
566 reader.Register();
567
568 std::unique_ptr<EventLoop> test_event_loop =
569 reader.event_loop_factory()->MakeEventLoop("log_reader");
570
571 int replay_count = 0;
572
573 test_event_loop->MakeWatcher(
574 "/test", [&replay_count](const examples::Ping &) { ++replay_count; });
575
576 reader.event_loop_factory()->Run();
577 EXPECT_EQ(replay_count, sent_messages);
578}
579
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800580} // namespace aos::logger::testing