blob: 80b3a4a8205b1fdda4c599f8b6c831f55ec0c577 [file] [log] [blame]
Austin Schuh6bb8a822021-03-31 23:04:39 -07001#include <sys/stat.h>
2
Austin Schuh315b96b2020-12-11 21:21:12 -08003#include "absl/strings/str_format.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -08004#include "aos/events/event_loop.h"
Tyler Chatowb7c6eba2021-07-28 14:43:23 -07005#include "aos/events/logging/log_reader.h"
Austin Schuhb06f03b2021-02-17 22:00:37 -08006#include "aos/events/logging/log_writer.h"
milind1f1dca32021-07-03 13:50:07 -07007#include "aos/events/logging/snappy_encoder.h"
Austin Schuh01b4c352020-09-21 23:09:39 -07008#include "aos/events/message_counter.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -08009#include "aos/events/ping_lib.h"
10#include "aos/events/pong_lib.h"
11#include "aos/events/simulated_event_loop.h"
Austin Schuh0de30f32020-12-06 12:44:28 -080012#include "aos/network/remote_message_generated.h"
Austin Schuh87dd3832021-01-01 23:07:31 -080013#include "aos/network/testing_time_converter.h"
Austin Schuh8d7e0bb2020-10-02 17:57:00 -070014#include "aos/network/timestamp_generated.h"
Austin Schuh373f1762021-06-02 21:07:09 -070015#include "aos/testing/path.h"
Austin Schuhc243b422020-10-11 15:35:08 -070016#include "aos/testing/tmpdir.h"
Austin Schuh2f8fd752020-09-01 22:38:28 -070017#include "aos/util/file.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080018#include "glog/logging.h"
Austin Schuh6f3babe2020-01-26 20:34:50 -080019#include "gmock/gmock.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080020#include "gtest/gtest.h"
21
Austin Schuh3bd4c402020-11-06 18:19:06 -080022#ifdef LZMA
23#include "aos/events/logging/lzma_encoder.h"
24#endif
25
Austin Schuhe309d2a2019-11-29 13:25:21 -080026namespace aos {
27namespace logger {
28namespace testing {
29
30namespace chrono = std::chrono;
Austin Schuh0de30f32020-12-06 12:44:28 -080031using aos::message_bridge::RemoteMessage;
Naman Guptaa63aa132023-03-22 20:06:34 -070032using aos::testing::ArtifactPath;
Austin Schuh01b4c352020-09-21 23:09:39 -070033using aos::testing::MessageCounter;
Austin Schuhe309d2a2019-11-29 13:25:21 -080034
Austin Schuhee4713b2021-03-21 19:25:17 -070035constexpr std::string_view kSingleConfigSha256(
Austin Schuhb8bca732021-07-30 22:32:00 -070036 "bbe1b563139273b23a5405eebc2f2740cefcda5f96681acd0a84b8ff9ab93ea4");
Austin Schuh8c399962020-12-25 21:51:45 -080037
Austin Schuhe309d2a2019-11-29 13:25:21 -080038class LoggerTest : public ::testing::Test {
39 public:
40 LoggerTest()
Austin Schuh373f1762021-06-02 21:07:09 -070041 : config_(aos::configuration::ReadConfig(
42 ArtifactPath("aos/events/pingpong_config.json"))),
Austin Schuhe309d2a2019-11-29 13:25:21 -080043 event_loop_factory_(&config_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080044 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080045 ping_(ping_event_loop_.get()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080046 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
Austin Schuhe309d2a2019-11-29 13:25:21 -080047 pong_(pong_event_loop_.get()) {}
48
49 // Config and factory.
50 aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
51 SimulatedEventLoopFactory event_loop_factory_;
52
53 // Event loop and app for Ping
54 std::unique_ptr<EventLoop> ping_event_loop_;
55 Ping ping_;
56
57 // Event loop and app for Pong
58 std::unique_ptr<EventLoop> pong_event_loop_;
59 Pong pong_;
60};
61
Brian Silverman1f345222020-09-24 21:14:48 -070062using LoggerDeathTest = LoggerTest;
63
Austin Schuhe309d2a2019-11-29 13:25:21 -080064// Tests that we can startup at all. This confirms that the channels are all in
65// the config.
66TEST_F(LoggerTest, Starts) {
Austin Schuhc243b422020-10-11 15:35:08 -070067 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -070068 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -080069 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -070070 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -070071 const ::std::string logfile = base_name + "_data.part0.bfbs";
Austin Schuhe309d2a2019-11-29 13:25:21 -080072 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -080073 unlink(config.c_str());
Austin Schuhe309d2a2019-11-29 13:25:21 -080074 unlink(logfile.c_str());
75
76 LOG(INFO) << "Logging data to " << logfile;
77
78 {
Austin Schuhe309d2a2019-11-29 13:25:21 -080079 std::unique_ptr<EventLoop> logger_event_loop =
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080080 event_loop_factory_.MakeEventLoop("logger");
Austin Schuhe309d2a2019-11-29 13:25:21 -080081
82 event_loop_factory_.RunFor(chrono::milliseconds(95));
83
Brian Silverman1f345222020-09-24 21:14:48 -070084 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -080085 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -070086 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -070087 logger.StartLoggingOnRun(base_name);
Austin Schuhe309d2a2019-11-29 13:25:21 -080088 event_loop_factory_.RunFor(chrono::milliseconds(20000));
89 }
90
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080091 // Even though it doesn't make any difference here, exercise the logic for
92 // passing in a separate config.
93 LogReader reader(logfile, &config_.message());
Austin Schuhe309d2a2019-11-29 13:25:21 -080094
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080095 // Confirm that we can remap logged channels to point to new buses.
96 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
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
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -0800110 // Confirm that the ping value matches in the remapped channel location.
111 test_event_loop->MakeWatcher("/original/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);
Austin Schuhe309d2a2019-11-29 13:25:21 -0800127}
128
Brian Silverman1f345222020-09-24 21:14:48 -0700129// Tests calling StartLogging twice.
130TEST_F(LoggerDeathTest, ExtraStart) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800131 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700132 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800133 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700134 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700135 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700136 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800137 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700138 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700139 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700140 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800141 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700142 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800143 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700144
145 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
146
147 {
148 std::unique_ptr<EventLoop> logger_event_loop =
149 event_loop_factory_.MakeEventLoop("logger");
150
151 event_loop_factory_.RunFor(chrono::milliseconds(95));
152
153 Logger logger(logger_event_loop.get());
154 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700155 logger_event_loop->OnRun(
156 [base_name1, base_name2, &logger_event_loop, &logger]() {
157 logger.StartLogging(std::make_unique<MultiNodeLogNamer>(
158 base_name1, logger_event_loop->configuration(),
159 logger_event_loop.get(), logger_event_loop->node()));
160 EXPECT_DEATH(logger.StartLogging(std::make_unique<MultiNodeLogNamer>(
161 base_name2, logger_event_loop->configuration(),
162 logger_event_loop.get(), logger_event_loop->node())),
163 "Already logging");
164 });
Brian Silverman1f345222020-09-24 21:14:48 -0700165 event_loop_factory_.RunFor(chrono::milliseconds(20000));
166 }
167}
168
James Kuszmaul94ca5132022-07-19 09:11:08 -0700169// Tests that we die if the replayer attempts to send on a logged channel.
170TEST_F(LoggerDeathTest, DieOnDuplicateReplayChannels) {
171 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
172 aos::configuration::ReadConfig(
173 ArtifactPath("aos/events/pingpong_config.json"));
174 SimulatedEventLoopFactory event_loop_factory(&config.message());
175 const ::std::string tmpdir = aos::testing::TestTmpDir();
176 const ::std::string base_name = tmpdir + "/logfile";
177 const ::std::string config_file =
178 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700179 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul94ca5132022-07-19 09:11:08 -0700180 // Remove the log file.
181 unlink(config_file.c_str());
182 unlink(logfile.c_str());
183
184 LOG(INFO) << "Logging data to " << logfile;
185
186 {
187 std::unique_ptr<EventLoop> logger_event_loop =
188 event_loop_factory.MakeEventLoop("logger");
189
190 Logger logger(logger_event_loop.get());
191 logger.set_separate_config(false);
192 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700193 logger.StartLoggingOnRun(base_name);
James Kuszmaul94ca5132022-07-19 09:11:08 -0700194
195 event_loop_factory.RunFor(chrono::seconds(2));
196 }
197
198 LogReader reader(logfile);
199
200 reader.Register();
201
202 std::unique_ptr<EventLoop> test_event_loop =
203 reader.event_loop_factory()->MakeEventLoop("log_reader");
204
205 EXPECT_DEATH(test_event_loop->MakeSender<examples::Ping>("/test"),
206 "exclusive channel.*examples.Ping");
207}
208
Brian Silverman1f345222020-09-24 21:14:48 -0700209// Tests calling StopLogging twice.
210TEST_F(LoggerDeathTest, ExtraStop) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800211 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700212 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800213 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700214 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Brian Silverman1f345222020-09-24 21:14:48 -0700215 const ::std::string logfile = base_name + ".part0.bfbs";
216 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800217 unlink(config.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700218 unlink(logfile.c_str());
219
220 LOG(INFO) << "Logging data to " << logfile;
221
222 {
223 std::unique_ptr<EventLoop> logger_event_loop =
224 event_loop_factory_.MakeEventLoop("logger");
225
226 event_loop_factory_.RunFor(chrono::milliseconds(95));
227
228 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800229 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700230 logger.set_polling_period(std::chrono::milliseconds(100));
231 logger_event_loop->OnRun([base_name, &logger_event_loop, &logger]() {
Austin Schuh11717692022-10-16 17:11:28 -0700232 logger.StartLogging(std::make_unique<MultiNodeLogNamer>(
233 base_name, logger_event_loop->configuration(),
234 logger_event_loop.get(), logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700235 logger.StopLogging(aos::monotonic_clock::min_time);
236 EXPECT_DEATH(logger.StopLogging(aos::monotonic_clock::min_time),
237 "Not logging right now");
238 });
239 event_loop_factory_.RunFor(chrono::milliseconds(20000));
240 }
241}
242
243// Tests that we can startup twice.
244TEST_F(LoggerTest, StartsTwice) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800245 const ::std::string tmpdir = aos::testing::TestTmpDir();
Brian Silverman1f345222020-09-24 21:14:48 -0700246 const ::std::string base_name1 = tmpdir + "/logfile1";
Austin Schuh25b46712021-01-03 00:04:38 -0800247 const ::std::string config1 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700248 absl::StrCat(base_name1, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700249 const ::std::string logfile1 = base_name1 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700250 const ::std::string base_name2 = tmpdir + "/logfile2";
Austin Schuh25b46712021-01-03 00:04:38 -0800251 const ::std::string config2 =
Austin Schuhee4713b2021-03-21 19:25:17 -0700252 absl::StrCat(base_name2, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700253 const ::std::string logfile2 = base_name2 + "_data.part0.bfbs";
Brian Silverman1f345222020-09-24 21:14:48 -0700254 unlink(logfile1.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800255 unlink(config1.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700256 unlink(logfile2.c_str());
Austin Schuh25b46712021-01-03 00:04:38 -0800257 unlink(config2.c_str());
Brian Silverman1f345222020-09-24 21:14:48 -0700258
259 LOG(INFO) << "Logging data to " << logfile1 << " then " << logfile2;
260
261 {
262 std::unique_ptr<EventLoop> logger_event_loop =
263 event_loop_factory_.MakeEventLoop("logger");
264
265 event_loop_factory_.RunFor(chrono::milliseconds(95));
266
267 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800268 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700269 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700270 logger.StartLogging(std::make_unique<MultiNodeLogNamer>(
271 base_name1, logger_event_loop->configuration(), logger_event_loop.get(),
272 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700273 event_loop_factory_.RunFor(chrono::milliseconds(10000));
274 logger.StopLogging(logger_event_loop->monotonic_now());
275 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh11717692022-10-16 17:11:28 -0700276 logger.StartLogging(std::make_unique<MultiNodeLogNamer>(
277 base_name2, logger_event_loop->configuration(), logger_event_loop.get(),
278 logger_event_loop->node()));
Brian Silverman1f345222020-09-24 21:14:48 -0700279 event_loop_factory_.RunFor(chrono::milliseconds(10000));
280 }
281
282 for (const auto &logfile :
283 {std::make_tuple(logfile1, 10), std::make_tuple(logfile2, 2010)}) {
284 SCOPED_TRACE(std::get<0>(logfile));
285 LogReader reader(std::get<0>(logfile));
286 reader.Register();
287
Austin Schuh07676622021-01-21 18:59:17 -0800288 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Brian Silverman1f345222020-09-24 21:14:48 -0700289
290 std::unique_ptr<EventLoop> test_event_loop =
291 reader.event_loop_factory()->MakeEventLoop("log_reader");
292
293 int ping_count = std::get<1>(logfile);
294 int pong_count = std::get<1>(logfile);
295
296 // Confirm that the ping and pong counts both match, and the value also
297 // matches.
298 test_event_loop->MakeWatcher("/test",
299 [&ping_count](const examples::Ping &ping) {
300 EXPECT_EQ(ping.value(), ping_count + 1);
301 ++ping_count;
302 });
303 test_event_loop->MakeWatcher(
304 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
305 EXPECT_EQ(pong.value(), pong_count + 1);
306 ++pong_count;
307 EXPECT_EQ(ping_count, pong_count);
308 });
309
310 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
311 EXPECT_EQ(ping_count, std::get<1>(logfile) + 1000);
312 }
313}
314
Austin Schuhfa895892020-01-07 20:07:41 -0800315// Tests that we can read and write rotated log files.
316TEST_F(LoggerTest, RotatedLogFile) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800317 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700318 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800319 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700320 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700321 const ::std::string logfile0 = base_name + "_data.part0.bfbs";
322 const ::std::string logfile1 = base_name + "_data.part1.bfbs";
Austin Schuhfa895892020-01-07 20:07:41 -0800323 // Remove it.
Austin Schuh25b46712021-01-03 00:04:38 -0800324 unlink(config.c_str());
Austin Schuhfa895892020-01-07 20:07:41 -0800325 unlink(logfile0.c_str());
326 unlink(logfile1.c_str());
327
328 LOG(INFO) << "Logging data to " << logfile0 << " and " << logfile1;
329
330 {
Austin Schuhfa895892020-01-07 20:07:41 -0800331 std::unique_ptr<EventLoop> logger_event_loop =
332 event_loop_factory_.MakeEventLoop("logger");
333
334 event_loop_factory_.RunFor(chrono::milliseconds(95));
335
Brian Silverman1f345222020-09-24 21:14:48 -0700336 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800337 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700338 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700339 logger.StartLoggingOnRun(base_name);
Austin Schuhfa895892020-01-07 20:07:41 -0800340 event_loop_factory_.RunFor(chrono::milliseconds(10000));
Austin Schuh2f8fd752020-09-01 22:38:28 -0700341 logger.Rotate();
Austin Schuhfa895892020-01-07 20:07:41 -0800342 event_loop_factory_.RunFor(chrono::milliseconds(10000));
343 }
344
Austin Schuh64fab802020-09-09 22:47:47 -0700345 {
346 // Confirm that the UUIDs match for both the parts and the logger, and the
347 // parts_index increments.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800348 std::vector<SizePrefixedFlatbufferVector<LogFileHeader>> log_header;
Austin Schuh64fab802020-09-09 22:47:47 -0700349 for (std::string_view f : {logfile0, logfile1}) {
Austin Schuh3bd4c402020-11-06 18:19:06 -0800350 log_header.emplace_back(ReadHeader(f).value());
Austin Schuh64fab802020-09-09 22:47:47 -0700351 }
352
Brian Silvermanae7c0332020-09-30 16:58:23 -0700353 EXPECT_EQ(log_header[0].message().log_event_uuid()->string_view(),
354 log_header[1].message().log_event_uuid()->string_view());
Austin Schuh64fab802020-09-09 22:47:47 -0700355 EXPECT_EQ(log_header[0].message().parts_uuid()->string_view(),
356 log_header[1].message().parts_uuid()->string_view());
357
358 EXPECT_EQ(log_header[0].message().parts_index(), 0);
359 EXPECT_EQ(log_header[1].message().parts_index(), 1);
360 }
361
Austin Schuhfa895892020-01-07 20:07:41 -0800362 // Even though it doesn't make any difference here, exercise the logic for
363 // passing in a separate config.
Austin Schuh287d43d2020-12-04 20:19:33 -0800364 LogReader reader(SortParts({logfile0, logfile1}), &config_.message());
Austin Schuhfa895892020-01-07 20:07:41 -0800365
366 // Confirm that we can remap logged channels to point to new buses.
367 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
368
369 // This sends out the fetched messages and advances time to the start of the
370 // log file.
371 reader.Register();
372
Austin Schuh07676622021-01-21 18:59:17 -0800373 EXPECT_THAT(reader.LoggedNodes(), ::testing::ElementsAre(nullptr));
Austin Schuhfa895892020-01-07 20:07:41 -0800374
375 std::unique_ptr<EventLoop> test_event_loop =
376 reader.event_loop_factory()->MakeEventLoop("log_reader");
377
378 int ping_count = 10;
379 int pong_count = 10;
380
381 // Confirm that the ping value matches in the remapped channel location.
382 test_event_loop->MakeWatcher("/original/test",
383 [&ping_count](const examples::Ping &ping) {
384 EXPECT_EQ(ping.value(), ping_count + 1);
385 ++ping_count;
386 });
387 // Confirm that the ping and pong counts both match, and the value also
388 // matches.
389 test_event_loop->MakeWatcher(
390 "/test", [&pong_count, &ping_count](const examples::Pong &pong) {
391 EXPECT_EQ(pong.value(), pong_count + 1);
392 ++pong_count;
393 EXPECT_EQ(ping_count, pong_count);
394 });
395
396 reader.event_loop_factory()->RunFor(std::chrono::seconds(100));
397 EXPECT_EQ(ping_count, 2010);
398}
399
Austin Schuh4c4e0092019-12-22 16:18:03 -0800400// Tests that a large number of messages per second doesn't overwhelm writev.
401TEST_F(LoggerTest, ManyMessages) {
Austin Schuhc6f8f1b2020-12-02 23:23:39 -0800402 const ::std::string tmpdir = aos::testing::TestTmpDir();
Austin Schuh2f8fd752020-09-01 22:38:28 -0700403 const ::std::string base_name = tmpdir + "/logfile";
Austin Schuh25b46712021-01-03 00:04:38 -0800404 const ::std::string config =
Austin Schuhee4713b2021-03-21 19:25:17 -0700405 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh2f8fd752020-09-01 22:38:28 -0700406 const ::std::string logfile = base_name + ".part0.bfbs";
Austin Schuh4c4e0092019-12-22 16:18:03 -0800407 // Remove the log file.
Austin Schuh25b46712021-01-03 00:04:38 -0800408 unlink(config.c_str());
Austin Schuh4c4e0092019-12-22 16:18:03 -0800409 unlink(logfile.c_str());
410
411 LOG(INFO) << "Logging data to " << logfile;
Austin Schuh4c3b9702020-08-30 11:34:55 -0700412 ping_.set_quiet(true);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800413
414 {
Austin Schuh4c4e0092019-12-22 16:18:03 -0800415 std::unique_ptr<EventLoop> logger_event_loop =
416 event_loop_factory_.MakeEventLoop("logger");
417
418 std::unique_ptr<EventLoop> ping_spammer_event_loop =
419 event_loop_factory_.MakeEventLoop("ping_spammer");
420 aos::Sender<examples::Ping> ping_sender =
421 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
422
423 aos::TimerHandler *timer_handler =
424 ping_spammer_event_loop->AddTimer([&ping_sender]() {
425 aos::Sender<examples::Ping>::Builder builder =
426 ping_sender.MakeBuilder();
427 examples::Ping::Builder ping_builder =
428 builder.MakeBuilder<examples::Ping>();
Austin Schuhbfe6c572022-01-27 20:48:20 -0800429 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800430 });
431
432 // 100 ms / 0.05 ms -> 2000 messages. Should be enough to crash it.
433 ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
434 timer_handler->Setup(ping_spammer_event_loop->monotonic_now(),
435 chrono::microseconds(50));
436 });
437
Brian Silverman1f345222020-09-24 21:14:48 -0700438 Logger logger(logger_event_loop.get());
Austin Schuh8c399962020-12-25 21:51:45 -0800439 logger.set_separate_config(false);
Brian Silverman1f345222020-09-24 21:14:48 -0700440 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700441 logger.StartLoggingOnRun(base_name);
Austin Schuh4c4e0092019-12-22 16:18:03 -0800442
443 event_loop_factory_.RunFor(chrono::milliseconds(1000));
444 }
445}
446
James Kuszmaul890c2492022-04-06 14:59:31 -0700447// Tests that we can read a logfile that has channels which were sent too fast.
448TEST(SingleNodeLoggerNoFixtureTest, ReadTooFast) {
449 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
450 aos::configuration::ReadConfig(
451 ArtifactPath("aos/events/pingpong_config.json"));
452 SimulatedEventLoopFactory event_loop_factory(&config.message());
453 const ::std::string tmpdir = aos::testing::TestTmpDir();
454 const ::std::string base_name = tmpdir + "/logfile";
455 const ::std::string config_file =
456 absl::StrCat(base_name, kSingleConfigSha256, ".bfbs");
Austin Schuh11717692022-10-16 17:11:28 -0700457 const ::std::string logfile = base_name + "_data.part0.bfbs";
James Kuszmaul890c2492022-04-06 14:59:31 -0700458 // Remove the log file.
459 unlink(config_file.c_str());
460 unlink(logfile.c_str());
461
462 LOG(INFO) << "Logging data to " << logfile;
463
464 int sent_messages = 0;
465
466 {
467 std::unique_ptr<EventLoop> logger_event_loop =
468 event_loop_factory.MakeEventLoop("logger");
469
470 std::unique_ptr<EventLoop> ping_spammer_event_loop =
471 event_loop_factory.GetNodeEventLoopFactory(nullptr)->MakeEventLoop(
472 "ping_spammer", {NodeEventLoopFactory::CheckSentTooFast::kNo,
James Kuszmaul94ca5132022-07-19 09:11:08 -0700473 NodeEventLoopFactory::ExclusiveSenders::kNo,
474 {}});
James Kuszmaul890c2492022-04-06 14:59:31 -0700475 aos::Sender<examples::Ping> ping_sender =
476 ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
477
478 aos::TimerHandler *timer_handler =
479 ping_spammer_event_loop->AddTimer([&ping_sender, &sent_messages]() {
480 aos::Sender<examples::Ping>::Builder builder =
481 ping_sender.MakeBuilder();
482 examples::Ping::Builder ping_builder =
483 builder.MakeBuilder<examples::Ping>();
484 CHECK_EQ(builder.Send(ping_builder.Finish()), RawSender::Error::kOk);
485 ++sent_messages;
486 });
487
488 constexpr std::chrono::microseconds kSendPeriod{10};
489 const int max_legal_messages =
490 ping_sender.channel()->frequency() *
491 event_loop_factory.configuration()->channel_storage_duration() /
492 1000000000;
493
494 ping_spammer_event_loop->OnRun(
495 [&ping_spammer_event_loop, kSendPeriod, timer_handler]() {
496 timer_handler->Setup(
497 ping_spammer_event_loop->monotonic_now() + kSendPeriod / 2,
498 kSendPeriod);
499 });
500
501 Logger logger(logger_event_loop.get());
502 logger.set_separate_config(false);
503 logger.set_polling_period(std::chrono::milliseconds(100));
Austin Schuh11717692022-10-16 17:11:28 -0700504 logger.StartLoggingOnRun(base_name);
James Kuszmaul890c2492022-04-06 14:59:31 -0700505
506 event_loop_factory.RunFor(kSendPeriod * max_legal_messages * 2);
507 }
508
509 LogReader reader(logfile);
510
511 reader.Register();
512
513 std::unique_ptr<EventLoop> test_event_loop =
514 reader.event_loop_factory()->MakeEventLoop("log_reader");
515
516 int replay_count = 0;
517
518 test_event_loop->MakeWatcher(
519 "/test", [&replay_count](const examples::Ping &) { ++replay_count; });
520
521 reader.event_loop_factory()->Run();
522 EXPECT_EQ(replay_count, sent_messages);
523}
524
Austin Schuhe309d2a2019-11-29 13:25:21 -0800525} // namespace testing
526} // namespace logger
527} // namespace aos