blob: fcbd77bcaf12531b66b030b5d0db1561cf1de1fd [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"
Austin Schuhe309d2a2019-11-29 13:25:21 -08006#include "aos/events/event_loop.h"
Tyler Chatowb7c6eba2021-07-28 14:43:23 -07007#include "aos/events/logging/log_reader.h"
Austin Schuhb06f03b2021-02-17 22:00:37 -08008#include "aos/events/logging/log_writer.h"
milind1f1dca32021-07-03 13:50:07 -07009#include "aos/events/logging/snappy_encoder.h"
Austin Schuh01b4c352020-09-21 23:09:39 -070010#include "aos/events/message_counter.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080011#include "aos/events/ping_lib.h"
12#include "aos/events/pong_lib.h"
13#include "aos/events/simulated_event_loop.h"
Austin Schuh0de30f32020-12-06 12:44:28 -080014#include "aos/network/remote_message_generated.h"
Austin Schuh87dd3832021-01-01 23:07:31 -080015#include "aos/network/testing_time_converter.h"
Austin Schuh8d7e0bb2020-10-02 17:57:00 -070016#include "aos/network/timestamp_generated.h"
Austin Schuh373f1762021-06-02 21:07:09 -070017#include "aos/testing/path.h"
Austin Schuhc243b422020-10-11 15:35:08 -070018#include "aos/testing/tmpdir.h"
Austin Schuh2f8fd752020-09-01 22:38:28 -070019#include "aos/util/file.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080020#include "glog/logging.h"
Austin Schuh6f3babe2020-01-26 20:34:50 -080021#include "gmock/gmock.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080022#include "gtest/gtest.h"
23
Austin Schuh3bd4c402020-11-06 18:19:06 -080024#ifdef LZMA
25#include "aos/events/logging/lzma_encoder.h"
26#endif
27
Austin Schuhe309d2a2019-11-29 13:25:21 -080028namespace aos {
29namespace logger {
30namespace testing {
31
32namespace chrono = std::chrono;
Austin Schuh0de30f32020-12-06 12:44:28 -080033using aos::message_bridge::RemoteMessage;
Naman Guptaa63aa132023-03-22 20:06:34 -070034using aos::testing::ArtifactPath;
Austin Schuh01b4c352020-09-21 23:09:39 -070035using aos::testing::MessageCounter;
Austin Schuhe309d2a2019-11-29 13:25:21 -080036
Austin Schuhee4713b2021-03-21 19:25:17 -070037constexpr std::string_view kSingleConfigSha256(
Austin Schuhb8bca732021-07-30 22:32:00 -070038 "bbe1b563139273b23a5405eebc2f2740cefcda5f96681acd0a84b8ff9ab93ea4");
Austin Schuh8c399962020-12-25 21:51:45 -080039
Austin Schuhe309d2a2019-11-29 13:25:21 -080040class LoggerTest : public ::testing::Test {
41 public:
42 LoggerTest()
Austin Schuh373f1762021-06-02 21:07:09 -070043 : config_(aos::configuration::ReadConfig(
44 ArtifactPath("aos/events/pingpong_config.json"))),
Austin Schuhe309d2a2019-11-29 13:25:21 -080045 event_loop_factory_(&config_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080046 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080047 ping_(ping_event_loop_.get()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080048 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080049 pong_(pong_event_loop_.get()) {}
50
51 // Config and factory.
52 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
53 SimulatedEventLoopFactory event_loop_factory_;
54
55 // Event loop and app for Ping
56 std::unique_ptr<EventLoop> ping_event_loop_;
57 Ping ping_;
58
59 // Event loop and app for Pong
60 std::unique_ptr<EventLoop> pong_event_loop_;
61 Pong pong_;
62};
63
Brian Silverman1f345222020-09-24 21:14:48 -070064using LoggerDeathTest = LoggerTest;
65
Austin Schuhe309d2a2019-11-29 13:25:21 -080066// Tests that we can startup at all. This confirms that the channels are all in
67// the config.
68TEST_F(LoggerTest, Starts) {
Austin Schuhc243b422020-10-11 15:35:08 -070069 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -070070 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -080071 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -070072 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -070073 const ::std::string logfile = base_name + "_data.part0.bfbs";
Austin Schuhe309d2a2019-11-29 13:25:21 -080074 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -080075 unlink(config.c_str());
Austin Schuhe309d2a2019-11-29 13:25:21 -080076 unlink(logfile.c_str());
77
78 LOG(INFO) << "Logging data to " << logfile;
79
80 {
Austin Schuhe309d2a2019-11-29 13:25:21 -080081 std::unique_ptr<EventLoop> logger_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080082 event_loop_factory_.MakeEventLoop("logger");
Austin Schuhe309d2a2019-11-29 13:25:21 -080083
84 event_loop_factory_.RunFor(chrono::milliseconds(95));
85
Brian Silverman1f345222020-09-24 21:14:48 -070086 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -080087 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -070088 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -070089 logger.StartLoggingOnRun(base_name);
Austin Schuhe309d2a2019-11-29 13:25:21 -080090 event_loop_factory_.RunFor(chrono::milliseconds(20000));
91 }
92
Alexei Strots01395492023-03-20 13:59:56 -070093 ASSERT_TRUE(std::filesystem::exists(logfile));
94
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080095 // Even though it doesn't make any difference here, exercise the logic for
96 // passing in a separate config.
97 LogReader reader(logfile, &config_.message());
Austin Schuhe309d2a2019-11-29 13:25:21 -080098
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080099 // Confirm that we can remap logged channels to point to new buses.
100 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
Austin Schuhe309d2a2019-11-29 13:25:21 -0800101
Austin Schuh15649d62019-12-28 16:36:38 -0800102 // This sends out the fetched messages and advances time to the start of the
103 // log file.
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800104 reader.Register();
Austin Schuhe309d2a2019-11-29 13:25:21 -0800105
Austin Schuh07676622021-01-21 18:59:17 -0800106 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800107
Austin Schuhe309d2a2019-11-29 13:25:21 -0800108 std::unique_ptr<EventLoop> test_event_loop =
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800109 reader.event_loop_factory()->MakeEventLoop("log_reader");
Austin Schuhe309d2a2019-11-29 13:25:21 -0800110
111 int ping_count = 10;
112 int pong_count = 10;
113
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -0800114 // Confirm that the ping value matches in the remapped channel location.
115 test_event_loop->MakeWatcher("/original/test",
Austin Schuhe309d2a2019-11-29 13:25:21 -0800116 [&ping_count](const examples::Ping &ping) {
117 EXPECT_EQ(ping.value(), ping_count + 1);
118 ++ping_count;
119 });
120 // Confirm that the ping and pong counts both match, and the value also
121 // matches.
122 test_event_loop->MakeWatcher(
123 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
124 EXPECT_EQ(pong.value(), pong_count + 1);
125 ++pong_count;
126 EXPECT_EQ(ping_count, pong_count);
127 });
128
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800129 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
Austin Schuhe309d2a2019-11-29 13:25:21 -0800130 EXPECT_EQ(ping_count, 2010);
Austin Schuhe309d2a2019-11-29 13:25:21 -0800131}
132
Brian Silverman1f345222020-09-24 21:14:48 -0700133// Tests calling StartLogging twice.
134TEST_F(LoggerDeathTest, ExtraStart) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800135 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700136 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800137 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700138 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700139 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700140 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800141 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700142 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700143 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700144 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800145 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700146 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800147 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700148
149 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
150
151 {
152 std::unique_ptr<EventLoop> logger_event_loop =
153 event_loop_factory_.MakeEventLoop("logger");
154
155 event_loop_factory_.RunFor(chrono::milliseconds(95));
156
157 Logger logger(logger_event_loop.get());
158 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700159 logger_event_loop->OnRun([base_name1, base_name2, &logger_event_loop,
160 &logger]() {
161 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
162 base_name1, logger_event_loop->configuration(),
163 logger_event_loop.get(), logger_event_loop->node()));
164 EXPECT_DEATH(logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
165 base_name2, logger_event_loop->configuration(),
166 logger_event_loop.get(), logger_event_loop->node())),
167 "Already logging");
168 });
Brian Silverman1f345222020-09-24 21:14:48 -0700169 event_loop_factory_.RunFor(chrono::milliseconds(20000));
170 }
171}
172
James Kuszmaul94ca5132022-07-19 09:11:08 -0700173// Tests that we die if the replayer attempts to send on a logged channel.
174TEST_F(LoggerDeathTest, DieOnDuplicateReplayChannels) {
175 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
176 aos::configuration::ReadConfig(
177 ArtifactPath("aos/events/pingpong_config.json"));
178 SimulatedEventLoopFactory event_loop_factory(&config.message());
179 const ::std::string tmpdir = aos::testing::TestTmpDir();
180 const ::std::string base_name = tmpdir + "/logfile";
181 const ::std::string config_file =
182 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700183 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul94ca5132022-07-19 09:11:08 -0700184 // Remove the log file.
185 unlink(config_file.c_str());
186 unlink(logfile.c_str());
187
188 LOG(INFO) << "Logging data to " << logfile;
189
190 {
191 std::unique_ptr<EventLoop> logger_event_loop =
192 event_loop_factory.MakeEventLoop("logger");
193
194 Logger logger(logger_event_loop.get());
195 logger.set_separate_config(false);
196 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700197 logger.StartLoggingOnRun(base_name);
James Kuszmaul94ca5132022-07-19 09:11:08 -0700198
199 event_loop_factory.RunFor(chrono::seconds(2));
200 }
201
202 LogReader reader(logfile);
203
204 reader.Register();
205
206 std::unique_ptr<EventLoop> test_event_loop =
207 reader.event_loop_factory()->MakeEventLoop("log_reader");
208
209 EXPECT_DEATH(test_event_loop->MakeSender<examples::Ping>("/test"),
210 "exclusive channel.*examples.Ping");
211}
212
Brian Silverman1f345222020-09-24 21:14:48 -0700213// Tests calling StopLogging twice.
214TEST_F(LoggerDeathTest, ExtraStop) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800215 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700216 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800217 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700218 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700219 const ::std::string logfile = base_name + ".part0.bfbs";
220 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800221 unlink(config.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700222 unlink(logfile.c_str());
223
224 LOG(INFO) << "Logging data to " << logfile;
225
226 {
227 std::unique_ptr<EventLoop> logger_event_loop =
228 event_loop_factory_.MakeEventLoop("logger");
229
230 event_loop_factory_.RunFor(chrono::milliseconds(95));
231
232 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800233 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700234 logger.set_polling_period(std::chrono::milliseconds(100));
235 logger_event_loop->OnRun([base_name, &logger_event_loop, &logger]() {
Alexei Strots01395492023-03-20 13:59:56 -0700236 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700237 base_name, logger_event_loop->configuration(),
238 logger_event_loop.get(), logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700239 logger.StopLogging(aos::monotonic_clock::min_time);
240 EXPECT_DEATH(logger.StopLogging(aos::monotonic_clock::min_time),
241 "Not logging right now");
242 });
243 event_loop_factory_.RunFor(chrono::milliseconds(20000));
244 }
245}
246
247// Tests that we can startup twice.
248TEST_F(LoggerTest, StartsTwice) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800249 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700250 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800251 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700252 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700253 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700254 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800255 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700256 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700257 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700258 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800259 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700260 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800261 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700262
263 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
264
265 {
266 std::unique_ptr<EventLoop> logger_event_loop =
267 event_loop_factory_.MakeEventLoop("logger");
268
269 event_loop_factory_.RunFor(chrono::milliseconds(95));
270
271 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800272 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700273 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700274 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700275 base_name1, logger_event_loop->configuration(), logger_event_loop.get(),
276 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700277 event_loop_factory_.RunFor(chrono::milliseconds(10000));
278 logger.StopLogging(logger_event_loop->monotonic_now());
279 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Alexei Strots01395492023-03-20 13:59:56 -0700280 logger.StartLogging(std::make_unique<MultiNodeFilesLogNamer>(
Austin Schuh11717692022-10-16 17:11:28 -0700281 base_name2, logger_event_loop->configuration(), logger_event_loop.get(),
282 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700283 event_loop_factory_.RunFor(chrono::milliseconds(10000));
284 }
285
286 for (const auto &logfile :
287 {std::make_tuple(logfile1, 10), std::make_tuple(logfile2, 2010)}) {
288 SCOPED_TRACE(std::get<0>(logfile));
289 LogReader reader(std::get<0>(logfile));
290 reader.Register();
291
Austin Schuh07676622021-01-21 18:59:17 -0800292 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Brian Silverman1f345222020-09-24 21:14:48 -0700293
294 std::unique_ptr<EventLoop> test_event_loop =
295 reader.event_loop_factory()->MakeEventLoop("log_reader");
296
297 int ping_count = std::get<1>(logfile);
298 int pong_count = std::get<1>(logfile);
299
300 // Confirm that the ping and pong counts both match, and the value also
301 // matches.
302 test_event_loop->MakeWatcher("/test",
303 [&ping_count](const examples::Ping &ping) {
304 EXPECT_EQ(ping.value(), ping_count + 1);
305 ++ping_count;
306 });
307 test_event_loop->MakeWatcher(
308 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
309 EXPECT_EQ(pong.value(), pong_count + 1);
310 ++pong_count;
311 EXPECT_EQ(ping_count, pong_count);
312 });
313
314 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
315 EXPECT_EQ(ping_count, std::get<1>(logfile) + 1000);
316 }
317}
318
Austin Schuhfa895892020-01-07 20:07:41 -0800319// Tests that we can read and write rotated log files.
320TEST_F(LoggerTest, RotatedLogFile) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800321 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700322 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800323 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700324 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700325 const ::std::string logfile0 = base_name + "_data.part0.bfbs";
326 const ::std::string logfile1 = base_name + "_data.part1.bfbs";
Austin Schuhfa895892020-01-07 20:07:41 -0800327 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800328 unlink(config.c_str());
Austin Schuhfa895892020-01-07 20:07:41 -0800329 unlink(logfile0.c_str());
330 unlink(logfile1.c_str());
331
332 LOG(INFO) << "Logging data to " << logfile0 << " and " << logfile1;
333
334 {
Austin Schuhfa895892020-01-07 20:07:41 -0800335 std::unique_ptr<EventLoop> logger_event_loop =
336 event_loop_factory_.MakeEventLoop("logger");
337
338 event_loop_factory_.RunFor(chrono::milliseconds(95));
339
Brian Silverman1f345222020-09-24 21:14:48 -0700340 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800341 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700342 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700343 logger.StartLoggingOnRun(base_name);
Austin Schuhfa895892020-01-07 20:07:41 -0800344 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700345 logger.Rotate();
Austin Schuhfa895892020-01-07 20:07:41 -0800346 event_loop_factory_.RunFor(chrono::milliseconds(10000));
347 }
348
Austin Schuh64fab802020-09-09 22:47:47 -0700349 {
350 // Confirm that the UUIDs match for both the parts and the logger, and the
351 // parts_index increments.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800352 std::vector<SizePrefixedFlatbufferVector<LogFileHeader>> log_header;
Austin Schuh64fab802020-09-09 22:47:47 -0700353 for (std::string_view f : {logfile0, logfile1}) {
Austin Schuh3bd4c402020-11-06 18:19:06 -0800354 log_header.emplace_back(ReadHeader(f).value());
Austin Schuh64fab802020-09-09 22:47:47 -0700355 }
356
Brian Silvermanae7c0332020-09-30 16:58:23 -0700357 EXPECT_EQ(log_header[0].message().log_event_uuid()->string_view(),
358 log_header[1].message().log_event_uuid()->string_view());
Austin Schuh64fab802020-09-09 22:47:47 -0700359 EXPECT_EQ(log_header[0].message().parts_uuid()->string_view(),
360 log_header[1].message().parts_uuid()->string_view());
361
362 EXPECT_EQ(log_header[0].message().parts_index(), 0);
363 EXPECT_EQ(log_header[1].message().parts_index(), 1);
364 }
365
Austin Schuhfa895892020-01-07 20:07:41 -0800366 // Even though it doesn't make any difference here, exercise the logic for
367 // passing in a separate config.
Austin Schuh287d43d2020-12-04 20:19:33 -0800368 LogReader reader(SortParts({logfile0, logfile1}), &config_.message());
Austin Schuhfa895892020-01-07 20:07:41 -0800369
370 // Confirm that we can remap logged channels to point to new buses.
371 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
372
373 // This sends out the fetched messages and advances time to the start of the
374 // log file.
375 reader.Register();
376
Austin Schuh07676622021-01-21 18:59:17 -0800377 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800378
379 std::unique_ptr<EventLoop> test_event_loop =
380 reader.event_loop_factory()->MakeEventLoop("log_reader");
381
382 int ping_count = 10;
383 int pong_count = 10;
384
385 // Confirm that the ping value matches in the remapped channel location.
386 test_event_loop->MakeWatcher("/original/test",
387 [&ping_count](const examples::Ping &ping) {
388 EXPECT_EQ(ping.value(), ping_count + 1);
389 ++ping_count;
390 });
391 // Confirm that the ping and pong counts both match, and the value also
392 // matches.
393 test_event_loop->MakeWatcher(
394 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
395 EXPECT_EQ(pong.value(), pong_count + 1);
396 ++pong_count;
397 EXPECT_EQ(ping_count, pong_count);
398 });
399
400 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
401 EXPECT_EQ(ping_count, 2010);
402}
403
Austin Schuh4c4e0092019-12-22 16:18:03 -0800404// Tests that a large number of messages per second doesn't overwhelm writev.
405TEST_F(LoggerTest, ManyMessages) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800406 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700407 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800408 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700409 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700410 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800411 // Remove the log file.
Austin Schuh25b46712021-01-03 00:04:38 -0800412 unlink(config.c_str());
Austin Schuh4c4e0092019-12-22 16:18:03 -0800413 unlink(logfile.c_str());
414
415 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700416 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800417
418 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800419 std::unique_ptr<EventLoop> logger_event_loop =
420 event_loop_factory_.MakeEventLoop("logger");
421
422 std::unique_ptr<EventLoop> ping_spammer_event_loop =
423 event_loop_factory_.MakeEventLoop("ping_spammer");
424 aos::Sender<examples::Ping> ping_sender =
425 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
426
427 aos::TimerHandler *timer_handler =
428 ping_spammer_event_loop->AddTimer([&ping_sender]() {
429 aos::Sender<examples::Ping>::Builder builder =
430 ping_sender.MakeBuilder();
431 examples::Ping::Builder ping_builder =
432 builder.MakeBuilder<examples::Ping>();
Austin Schuhbfe6c572022-01-27 20:48:20 -0800433 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800434 });
435
436 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
437 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
438 timer_handler->Setup(ping_spammer_event_loop->monotonic_now(),
439 chrono::microseconds(50));
440 });
441
Brian Silverman1f345222020-09-24 21:14:48 -0700442 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800443 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700444 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700445 logger.StartLoggingOnRun(base_name);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800446
447 event_loop_factory_.RunFor(chrono::milliseconds(1000));
448 }
449}
450
James Kuszmaul890c2492022-04-06 14:59:31 -0700451// Tests that we can read a logfile that has channels which were sent too fast.
452TEST(SingleNodeLoggerNoFixtureTest, ReadTooFast) {
453 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
454 aos::configuration::ReadConfig(
455 ArtifactPath("aos/events/pingpong_config.json"));
456 SimulatedEventLoopFactory event_loop_factory(&config.message());
457 const ::std::string tmpdir = aos::testing::TestTmpDir();
458 const ::std::string base_name = tmpdir + "/logfile";
459 const ::std::string config_file =
460 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700461 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul890c2492022-04-06 14:59:31 -0700462 // Remove the log file.
463 unlink(config_file.c_str());
464 unlink(logfile.c_str());
465
466 LOG(INFO) << "Logging data to " << logfile;
467
468 int sent_messages = 0;
469
470 {
471 std::unique_ptr<EventLoop> logger_event_loop =
472 event_loop_factory.MakeEventLoop("logger");
473
474 std::unique_ptr<EventLoop> ping_spammer_event_loop =
475 event_loop_factory.GetNodeEventLoopFactory(nullptr)->MakeEventLoop(
476 "ping_spammer", {NodeEventLoopFactory::CheckSentTooFast::kNo,
James Kuszmaul94ca5132022-07-19 09:11:08 -0700477 NodeEventLoopFactory::ExclusiveSenders::kNo,
478 {}});
James Kuszmaul890c2492022-04-06 14:59:31 -0700479 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, &sent_messages]() {
484 aos::Sender<examples::Ping>::Builder builder =
485 ping_sender.MakeBuilder();
486 examples::Ping::Builder ping_builder =
487 builder.MakeBuilder<examples::Ping>();
488 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
489 ++sent_messages;
490 });
491
492 constexpr std::chrono::microseconds kSendPeriod{10};
493 const int max_legal_messages =
494 ping_sender.channel()->frequency() *
495 event_loop_factory.configuration()->channel_storage_duration() /
496 1000000000;
497
498 ping_spammer_event_loop->OnRun(
499 [&ping_spammer_event_loop, kSendPeriod, timer_handler]() {
500 timer_handler->Setup(
501 ping_spammer_event_loop->monotonic_now() + kSendPeriod / 2,
502 kSendPeriod);
503 });
504
505 Logger logger(logger_event_loop.get());
506 logger.set_separate_config(false);
507 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700508 logger.StartLoggingOnRun(base_name);
James Kuszmaul890c2492022-04-06 14:59:31 -0700509
510 event_loop_factory.RunFor(kSendPeriod * max_legal_messages * 2);
511 }
512
513 LogReader reader(logfile);
514
515 reader.Register();
516
517 std::unique_ptr<EventLoop> test_event_loop =
518 reader.event_loop_factory()->MakeEventLoop("log_reader");
519
520 int replay_count = 0;
521
522 test_event_loop->MakeWatcher(
523 "/test", [&replay_count](const examples::Ping &) { ++replay_count; });
524
525 reader.event_loop_factory()->Run();
526 EXPECT_EQ(replay_count, sent_messages);
527}
528
Austin Schuhe309d2a2019-11-29 13:25:21 -0800529} // namespace testing
530} // namespace logger
531} // namespace aos