blob: 5990a7a663a0d0c8d3469beebbf50ee67c922134 [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
Austin Schuhe309d2a2019-11-29 13:25:21 -080029namespace aos {
30namespace logger {
31namespace testing {
32
33namespace chrono = std::chrono;
Austin Schuh0de30f32020-12-06 12:44:28 -080034using aos::message_bridge::RemoteMessage;
Naman Guptaa63aa132023-03-22 20:06:34 -070035using aos::testing::ArtifactPath;
Austin Schuh01b4c352020-09-21 23:09:39 -070036using aos::testing::MessageCounter;
Austin Schuhe309d2a2019-11-29 13:25:21 -080037
Austin Schuhee4713b2021-03-21 19:25:17 -070038constexpr std::string_view kSingleConfigSha256(
Austin Schuhb8bca732021-07-30 22:32:00 -070039 "bbe1b563139273b23a5405eebc2f2740cefcda5f96681acd0a84b8ff9ab93ea4");
Austin Schuh8c399962020-12-25 21:51:45 -080040
Austin Schuhe309d2a2019-11-29 13:25:21 -080041class LoggerTest : public ::testing::Test {
42 public:
43 LoggerTest()
Austin Schuh373f1762021-06-02 21:07:09 -070044 : config_(aos::configuration::ReadConfig(
45 ArtifactPath("aos/events/pingpong_config.json"))),
Austin Schuhe309d2a2019-11-29 13:25:21 -080046 event_loop_factory_(&config_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080047 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080048 ping_(ping_event_loop_.get()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080049 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080050 pong_(pong_event_loop_.get()) {}
51
52 // Config and factory.
53 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
54 SimulatedEventLoopFactory event_loop_factory_;
55
56 // Event loop and app for Ping
57 std::unique_ptr<EventLoop> ping_event_loop_;
58 Ping ping_;
59
60 // Event loop and app for Pong
61 std::unique_ptr<EventLoop> pong_event_loop_;
62 Pong pong_;
63};
64
Brian Silverman1f345222020-09-24 21:14:48 -070065using LoggerDeathTest = LoggerTest;
66
Austin Schuhe309d2a2019-11-29 13:25:21 -080067// Tests that we can startup at all. This confirms that the channels are all in
68// the config.
69TEST_F(LoggerTest, Starts) {
Austin Schuhc243b422020-10-11 15:35:08 -070070 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -070071 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -080072 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -070073 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -070074 const ::std::string logfile = base_name + "_data.part0.bfbs";
Austin Schuhe309d2a2019-11-29 13:25:21 -080075 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -080076 unlink(config.c_str());
Austin Schuhe309d2a2019-11-29 13:25:21 -080077 unlink(logfile.c_str());
78
79 LOG(INFO) << "Logging data to " << logfile;
80
81 {
Austin Schuhe309d2a2019-11-29 13:25:21 -080082 std::unique_ptr<EventLoop> logger_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080083 event_loop_factory_.MakeEventLoop("logger");
Austin Schuhe309d2a2019-11-29 13:25:21 -080084
85 event_loop_factory_.RunFor(chrono::milliseconds(95));
86
Brian Silverman1f345222020-09-24 21:14:48 -070087 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -080088 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -070089 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -070090 logger.StartLoggingOnRun(base_name);
Austin Schuhe309d2a2019-11-29 13:25:21 -080091 event_loop_factory_.RunFor(chrono::milliseconds(20000));
92 }
93
Alexei Strots01395492023-03-20 13:59:56 -070094 ASSERT_TRUE(std::filesystem::exists(logfile));
95
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080096 // Even though it doesn't make any difference here, exercise the logic for
97 // passing in a separate config.
98 LogReader reader(logfile, &config_.message());
Austin Schuhe309d2a2019-11-29 13:25:21 -080099
Austin Schuh15649d62019-12-28 16:36:38 -0800100 // This sends out the fetched messages and advances time to the start of the
101 // log file.
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800102 reader.Register();
Austin Schuhe309d2a2019-11-29 13:25:21 -0800103
Austin Schuh07676622021-01-21 18:59:17 -0800104 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800105
Austin Schuhe309d2a2019-11-29 13:25:21 -0800106 std::unique_ptr<EventLoop> test_event_loop =
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800107 reader.event_loop_factory()->MakeEventLoop("log_reader");
Austin Schuhe309d2a2019-11-29 13:25:21 -0800108
109 int ping_count = 10;
110 int pong_count = 10;
111
Sanjay Narayanan5ec00232022-07-08 15:21:30 -0700112 // Confirm that the ping value matches.
113 test_event_loop->MakeWatcher("/test",
Austin Schuhe309d2a2019-11-29 13:25:21 -0800114 [&ping_count](const examples::Ping &ping) {
115 EXPECT_EQ(ping.value(), ping_count + 1);
116 ++ping_count;
117 });
118 // Confirm that the ping and pong counts both match, and the value also
119 // matches.
120 test_event_loop->MakeWatcher(
121 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
122 EXPECT_EQ(pong.value(), pong_count + 1);
123 ++pong_count;
124 EXPECT_EQ(ping_count, pong_count);
125 });
126
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800127 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
Austin Schuhe309d2a2019-11-29 13:25:21 -0800128 EXPECT_EQ(ping_count, 2010);
Sanjay Narayanan5ec00232022-07-08 15:21:30 -0700129 EXPECT_EQ(pong_count, ping_count);
Austin Schuhe309d2a2019-11-29 13:25:21 -0800130}
131
Eric Schmiedebergae00e732023-04-12 15:53:17 -0600132// Tests that we can mutate a message before sending
133TEST_F(LoggerTest, MutateCallback) {
134 const ::std::string tmpdir = aos::testing::TestTmpDir();
135 const ::std::string base_name = tmpdir + "/logfile";
136 const ::std::string config =
137 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
138 const ::std::string logfile = base_name + "_data.part0.bfbs";
139 // Remove it.
140 unlink(config.c_str());
141 unlink(logfile.c_str());
142
143 LOG(INFO) << "Logging data to " << logfile;
144
145 {
146 std::unique_ptr<EventLoop> logger_event_loop =
147 event_loop_factory_.MakeEventLoop("logger");
148
149 event_loop_factory_.RunFor(chrono::milliseconds(95));
150
151 Logger logger(logger_event_loop.get());
152 logger.set_separate_config(false);
153 logger.set_polling_period(std::chrono::milliseconds(100));
154 logger.StartLoggingOnRun(base_name);
155 event_loop_factory_.RunFor(chrono::milliseconds(20000));
156 }
157
158 // Even though it doesn't make any difference here, exercise the logic for
159 // passing in a separate config.
160 LogReader reader(logfile, &config_.message());
161
162 reader.AddBeforeSendCallback("/test", [](aos::examples::Ping *ping) {
163 ping->mutate_value(ping->value() + 1);
164 });
165
166 // This sends out the fetched messages and advances time to the start of the
167 // log file.
168 reader.Register();
169
170 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
171
172 std::unique_ptr<EventLoop> test_event_loop =
173 reader.event_loop_factory()->MakeEventLoop("log_reader");
174
175 // Confirm that the ping and pong counts both match, and the value also
176 // matches.
177 int ping_count = 10;
178 test_event_loop->MakeWatcher("/test",
179 [&ping_count](const examples::Ping &ping) {
180 ++ping_count;
181 EXPECT_EQ(ping.value(), ping_count);
182 });
183
184 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
185 EXPECT_EQ(ping_count, 2010);
186}
187
Brian Silverman1f345222020-09-24 21:14:48 -0700188// Tests calling StartLogging twice.
189TEST_F(LoggerDeathTest, ExtraStart) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800190 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700191 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800192 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700193 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700194 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700195 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800196 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700197 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700198 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700199 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800200 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700201 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800202 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700203
204 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
205
206 {
207 std::unique_ptr<EventLoop> logger_event_loop =
208 event_loop_factory_.MakeEventLoop("logger");
209
210 event_loop_factory_.RunFor(chrono::milliseconds(95));
211
212 Logger logger(logger_event_loop.get());
213 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700214 logger_event_loop->OnRun([base_name1, base_name2, &logger_event_loop,
215 &logger]() {
216 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
217 base_name1, logger_event_loop->configuration(),
218 logger_event_loop.get(), logger_event_loop->node()));
219 EXPECT_DEATH(logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
220 base_name2, logger_event_loop->configuration(),
221 logger_event_loop.get(), logger_event_loop->node())),
222 "Already logging");
223 });
Brian Silverman1f345222020-09-24 21:14:48 -0700224 event_loop_factory_.RunFor(chrono::milliseconds(20000));
225 }
226}
227
James Kuszmaul94ca5132022-07-19 09:11:08 -0700228// Tests that we die if the replayer attempts to send on a logged channel.
229TEST_F(LoggerDeathTest, DieOnDuplicateReplayChannels) {
230 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
231 aos::configuration::ReadConfig(
232 ArtifactPath("aos/events/pingpong_config.json"));
233 SimulatedEventLoopFactory event_loop_factory(&config.message());
234 const ::std::string tmpdir = aos::testing::TestTmpDir();
235 const ::std::string base_name = tmpdir + "/logfile";
236 const ::std::string config_file =
237 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700238 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul94ca5132022-07-19 09:11:08 -0700239 // Remove the log file.
240 unlink(config_file.c_str());
241 unlink(logfile.c_str());
242
243 LOG(INFO) << "Logging data to " << logfile;
244
245 {
246 std::unique_ptr<EventLoop> logger_event_loop =
247 event_loop_factory.MakeEventLoop("logger");
248
249 Logger logger(logger_event_loop.get());
250 logger.set_separate_config(false);
251 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700252 logger.StartLoggingOnRun(base_name);
James Kuszmaul94ca5132022-07-19 09:11:08 -0700253
254 event_loop_factory.RunFor(chrono::seconds(2));
255 }
256
257 LogReader reader(logfile);
258
259 reader.Register();
260
261 std::unique_ptr<EventLoop> test_event_loop =
262 reader.event_loop_factory()->MakeEventLoop("log_reader");
263
264 EXPECT_DEATH(test_event_loop->MakeSender<examples::Ping>("/test"),
265 "exclusive channel.*examples.Ping");
266}
267
Brian Silverman1f345222020-09-24 21:14:48 -0700268// Tests calling StopLogging twice.
269TEST_F(LoggerDeathTest, ExtraStop) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800270 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700271 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800272 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700273 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700274 const ::std::string logfile = base_name + ".part0.bfbs";
275 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800276 unlink(config.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700277 unlink(logfile.c_str());
278
279 LOG(INFO) << "Logging data to " << logfile;
280
281 {
282 std::unique_ptr<EventLoop> logger_event_loop =
283 event_loop_factory_.MakeEventLoop("logger");
284
285 event_loop_factory_.RunFor(chrono::milliseconds(95));
286
287 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800288 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700289 logger.set_polling_period(std::chrono::milliseconds(100));
290 logger_event_loop->OnRun([base_name, &logger_event_loop, &logger]() {
Alexei Strots01395492023-03-20 13:59:56 -0700291 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700292 base_name, logger_event_loop->configuration(),
293 logger_event_loop.get(), logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700294 logger.StopLogging(aos::monotonic_clock::min_time);
295 EXPECT_DEATH(logger.StopLogging(aos::monotonic_clock::min_time),
296 "Not logging right now");
297 });
298 event_loop_factory_.RunFor(chrono::milliseconds(20000));
299 }
300}
301
302// Tests that we can startup twice.
303TEST_F(LoggerTest, StartsTwice) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800304 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700305 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800306 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700307 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700308 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700309 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800310 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700311 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700312 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700313 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800314 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700315 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800316 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700317
318 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
319
320 {
321 std::unique_ptr<EventLoop> logger_event_loop =
322 event_loop_factory_.MakeEventLoop("logger");
323
324 event_loop_factory_.RunFor(chrono::milliseconds(95));
325
326 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800327 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700328 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700329 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700330 base_name1, logger_event_loop->configuration(), logger_event_loop.get(),
331 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700332 event_loop_factory_.RunFor(chrono::milliseconds(10000));
333 logger.StopLogging(logger_event_loop->monotonic_now());
334 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Alexei Strots01395492023-03-20 13:59:56 -0700335 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700336 base_name2, logger_event_loop->configuration(), logger_event_loop.get(),
337 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700338 event_loop_factory_.RunFor(chrono::milliseconds(10000));
339 }
340
341 for (const auto &logfile :
342 {std::make_tuple(logfile1, 10), std::make_tuple(logfile2, 2010)}) {
343 SCOPED_TRACE(std::get<0>(logfile));
344 LogReader reader(std::get<0>(logfile));
345 reader.Register();
346
Austin Schuh07676622021-01-21 18:59:17 -0800347 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Brian Silverman1f345222020-09-24 21:14:48 -0700348
349 std::unique_ptr<EventLoop> test_event_loop =
350 reader.event_loop_factory()->MakeEventLoop("log_reader");
351
352 int ping_count = std::get<1>(logfile);
353 int pong_count = std::get<1>(logfile);
354
355 // Confirm that the ping and pong counts both match, and the value also
356 // matches.
357 test_event_loop->MakeWatcher("/test",
358 [&ping_count](const examples::Ping &ping) {
359 EXPECT_EQ(ping.value(), ping_count + 1);
360 ++ping_count;
361 });
362 test_event_loop->MakeWatcher(
363 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
364 EXPECT_EQ(pong.value(), pong_count + 1);
365 ++pong_count;
366 EXPECT_EQ(ping_count, pong_count);
367 });
368
369 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
370 EXPECT_EQ(ping_count, std::get<1>(logfile) + 1000);
371 }
372}
373
Austin Schuhfa895892020-01-07 20:07:41 -0800374// Tests that we can read and write rotated log files.
375TEST_F(LoggerTest, RotatedLogFile) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800376 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700377 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800378 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700379 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700380 const ::std::string logfile0 = base_name + "_data.part0.bfbs";
381 const ::std::string logfile1 = base_name + "_data.part1.bfbs";
Austin Schuhfa895892020-01-07 20:07:41 -0800382 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800383 unlink(config.c_str());
Austin Schuhfa895892020-01-07 20:07:41 -0800384 unlink(logfile0.c_str());
385 unlink(logfile1.c_str());
386
387 LOG(INFO) << "Logging data to " << logfile0 << " and " << logfile1;
388
389 {
Austin Schuhfa895892020-01-07 20:07:41 -0800390 std::unique_ptr<EventLoop> logger_event_loop =
391 event_loop_factory_.MakeEventLoop("logger");
392
393 event_loop_factory_.RunFor(chrono::milliseconds(95));
394
Brian Silverman1f345222020-09-24 21:14:48 -0700395 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800396 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700397 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700398 logger.StartLoggingOnRun(base_name);
Austin Schuhfa895892020-01-07 20:07:41 -0800399 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700400 logger.Rotate();
Austin Schuhfa895892020-01-07 20:07:41 -0800401 event_loop_factory_.RunFor(chrono::milliseconds(10000));
402 }
403
Austin Schuh64fab802020-09-09 22:47:47 -0700404 {
405 // Confirm that the UUIDs match for both the parts and the logger, and the
406 // parts_index increments.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800407 std::vector<SizePrefixedFlatbufferVector<LogFileHeader>> log_header;
Austin Schuh64fab802020-09-09 22:47:47 -0700408 for (std::string_view f : {logfile0, logfile1}) {
Austin Schuh3bd4c402020-11-06 18:19:06 -0800409 log_header.emplace_back(ReadHeader(f).value());
Austin Schuh64fab802020-09-09 22:47:47 -0700410 }
411
Brian Silvermanae7c0332020-09-30 16:58:23 -0700412 EXPECT_EQ(log_header[0].message().log_event_uuid()->string_view(),
413 log_header[1].message().log_event_uuid()->string_view());
Austin Schuh64fab802020-09-09 22:47:47 -0700414 EXPECT_EQ(log_header[0].message().parts_uuid()->string_view(),
415 log_header[1].message().parts_uuid()->string_view());
416
417 EXPECT_EQ(log_header[0].message().parts_index(), 0);
418 EXPECT_EQ(log_header[1].message().parts_index(), 1);
419 }
420
Austin Schuhfa895892020-01-07 20:07:41 -0800421 // Even though it doesn't make any difference here, exercise the logic for
422 // passing in a separate config.
Austin Schuh287d43d2020-12-04 20:19:33 -0800423 LogReader reader(SortParts({logfile0, logfile1}), &config_.message());
Austin Schuhfa895892020-01-07 20:07:41 -0800424
425 // Confirm that we can remap logged channels to point to new buses.
426 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
427
428 // This sends out the fetched messages and advances time to the start of the
429 // log file.
430 reader.Register();
431
Austin Schuh07676622021-01-21 18:59:17 -0800432 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800433
434 std::unique_ptr<EventLoop> test_event_loop =
435 reader.event_loop_factory()->MakeEventLoop("log_reader");
436
437 int ping_count = 10;
438 int pong_count = 10;
439
440 // Confirm that the ping value matches in the remapped channel location.
441 test_event_loop->MakeWatcher("/original/test",
442 [&ping_count](const examples::Ping &ping) {
443 EXPECT_EQ(ping.value(), ping_count + 1);
444 ++ping_count;
445 });
446 // Confirm that the ping and pong counts both match, and the value also
447 // matches.
448 test_event_loop->MakeWatcher(
449 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
450 EXPECT_EQ(pong.value(), pong_count + 1);
451 ++pong_count;
452 EXPECT_EQ(ping_count, pong_count);
453 });
454
455 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
456 EXPECT_EQ(ping_count, 2010);
457}
458
Austin Schuh4c4e0092019-12-22 16:18:03 -0800459// Tests that a large number of messages per second doesn't overwhelm writev.
460TEST_F(LoggerTest, ManyMessages) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800461 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700462 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800463 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700464 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700465 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800466 // Remove the log file.
Austin Schuh25b46712021-01-03 00:04:38 -0800467 unlink(config.c_str());
Austin Schuh4c4e0092019-12-22 16:18:03 -0800468 unlink(logfile.c_str());
469
470 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700471 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800472
473 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800474 std::unique_ptr<EventLoop> logger_event_loop =
475 event_loop_factory_.MakeEventLoop("logger");
476
477 std::unique_ptr<EventLoop> ping_spammer_event_loop =
478 event_loop_factory_.MakeEventLoop("ping_spammer");
479 aos::Sender<examples::Ping> ping_sender =
480 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
481
482 aos::TimerHandler *timer_handler =
483 ping_spammer_event_loop->AddTimer([&ping_sender]() {
484 aos::Sender<examples::Ping>::Builder builder =
485 ping_sender.MakeBuilder();
486 examples::Ping::Builder ping_builder =
487 builder.MakeBuilder<examples::Ping>();
Austin Schuhbfe6c572022-01-27 20:48:20 -0800488 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800489 });
490
491 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
492 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700493 timer_handler->Schedule(ping_spammer_event_loop->monotonic_now(),
494 chrono::microseconds(50));
Austin Schuh4c4e0092019-12-22 16:18:03 -0800495 });
496
Brian Silverman1f345222020-09-24 21:14:48 -0700497 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800498 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700499 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700500 logger.StartLoggingOnRun(base_name);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800501
502 event_loop_factory_.RunFor(chrono::milliseconds(1000));
503 }
504}
505
James Kuszmaul890c2492022-04-06 14:59:31 -0700506// Tests that we can read a logfile that has channels which were sent too fast.
507TEST(SingleNodeLoggerNoFixtureTest, ReadTooFast) {
508 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
509 aos::configuration::ReadConfig(
510 ArtifactPath("aos/events/pingpong_config.json"));
511 SimulatedEventLoopFactory event_loop_factory(&config.message());
512 const ::std::string tmpdir = aos::testing::TestTmpDir();
513 const ::std::string base_name = tmpdir + "/logfile";
514 const ::std::string config_file =
515 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700516 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul890c2492022-04-06 14:59:31 -0700517 // Remove the log file.
518 unlink(config_file.c_str());
519 unlink(logfile.c_str());
520
521 LOG(INFO) << "Logging data to " << logfile;
522
523 int sent_messages = 0;
524
525 {
526 std::unique_ptr<EventLoop> logger_event_loop =
527 event_loop_factory.MakeEventLoop("logger");
528
529 std::unique_ptr<EventLoop> ping_spammer_event_loop =
530 event_loop_factory.GetNodeEventLoopFactory(nullptr)->MakeEventLoop(
531 "ping_spammer", {NodeEventLoopFactory::CheckSentTooFast::kNo,
James Kuszmaul94ca5132022-07-19 09:11:08 -0700532 NodeEventLoopFactory::ExclusiveSenders::kNo,
533 {}});
James Kuszmaul890c2492022-04-06 14:59:31 -0700534 aos::Sender<examples::Ping> ping_sender =
535 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
536
537 aos::TimerHandler *timer_handler =
538 ping_spammer_event_loop->AddTimer([&ping_sender, &sent_messages]() {
539 aos::Sender<examples::Ping>::Builder builder =
540 ping_sender.MakeBuilder();
541 examples::Ping::Builder ping_builder =
542 builder.MakeBuilder<examples::Ping>();
543 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
544 ++sent_messages;
545 });
546
547 constexpr std::chrono::microseconds kSendPeriod{10};
Austin Schuhfff9c3a2023-06-16 18:48:23 -0700548 const int max_legal_messages = configuration::QueueSize(
549 event_loop_factory.configuration(), ping_sender.channel());
James Kuszmaul890c2492022-04-06 14:59:31 -0700550
551 ping_spammer_event_loop->OnRun(
552 [&ping_spammer_event_loop, kSendPeriod, timer_handler]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700553 timer_handler->Schedule(
James Kuszmaul890c2492022-04-06 14:59:31 -0700554 ping_spammer_event_loop->monotonic_now() + kSendPeriod / 2,
555 kSendPeriod);
556 });
557
558 Logger logger(logger_event_loop.get());
559 logger.set_separate_config(false);
560 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700561 logger.StartLoggingOnRun(base_name);
James Kuszmaul890c2492022-04-06 14:59:31 -0700562
563 event_loop_factory.RunFor(kSendPeriod * max_legal_messages * 2);
564 }
565
566 LogReader reader(logfile);
567
568 reader.Register();
569
570 std::unique_ptr<EventLoop> test_event_loop =
571 reader.event_loop_factory()->MakeEventLoop("log_reader");
572
573 int replay_count = 0;
574
575 test_event_loop->MakeWatcher(
576 "/test", [&replay_count](const examples::Ping &) { ++replay_count; });
577
578 reader.event_loop_factory()->Run();
579 EXPECT_EQ(replay_count, sent_messages);
580}
581
Austin Schuhe309d2a2019-11-29 13:25:21 -0800582} // namespace testing
583} // namespace logger
584} // namespace aos