blob: dd4aaf00563d40ffd6d2aadccb2ee4cd321ac886 [file] [log] [blame]
Philipp Schrader790cb542023-07-05 21:06:52 -07001#include "gtest/gtest.h"
2
James Kuszmaul09632422022-05-25 15:56:19 -07003#include "aos/events/logging/log_reader.h"
4#include "aos/events/logging/log_writer.h"
5#include "aos/events/ping_lib.h"
Eric Schmiedebergb38477e2022-12-02 16:08:04 -07006#include "aos/events/pong_lib.h"
James Kuszmaul09632422022-05-25 15:56:19 -07007#include "aos/events/shm_event_loop.h"
8#include "aos/json_to_flatbuffer.h"
9#include "aos/testing/path.h"
10#include "aos/testing/tmpdir.h"
James Kuszmaul09632422022-05-25 15:56:19 -070011
Eric Schmiedebergb38477e2022-12-02 16:08:04 -070012DECLARE_string(override_hostname);
13
James Kuszmaul09632422022-05-25 15:56:19 -070014namespace aos::logger::testing {
15
16class RealtimeLoggerTest : public ::testing::Test {
17 protected:
18 RealtimeLoggerTest()
19 : shm_dir_(aos::testing::TestTmpDir() + "/aos"),
20 config_file_(
21 aos::testing::ArtifactPath("aos/events/pingpong_config.json")),
22 config_(aos::configuration::ReadConfig(config_file_)),
23 event_loop_factory_(&config_.message()),
24 ping_event_loop_(event_loop_factory_.MakeEventLoop("ping")),
Eric Schmiedebergb38477e2022-12-02 16:08:04 -070025 pong_event_loop_(event_loop_factory_.MakeEventLoop("pong")),
26 ping_(ping_event_loop_.get()),
27 pong_(pong_event_loop_.get()),
28 tmpdir_(aos::testing::TestTmpDir()),
29 base_name_(tmpdir_ + "/logfile/") {
James Kuszmaul09632422022-05-25 15:56:19 -070030 FLAGS_shm_base = shm_dir_;
31
Eric Schmiedebergb38477e2022-12-02 16:08:04 -070032 // Nuke the shm and log dirs, to ensure we aren't being affected by any
33 // preexisting tests.
James Kuszmaul09632422022-05-25 15:56:19 -070034 aos::util::UnlinkRecursive(shm_dir_);
Eric Schmiedebergb38477e2022-12-02 16:08:04 -070035 aos::util::UnlinkRecursive(base_name_);
36 }
37
38 gflags::FlagSaver flag_saver_;
39 std::string shm_dir_;
40
41 const std::string config_file_;
42 const aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
43
44 // Factory and Ping class to generate a test logfile.
45 SimulatedEventLoopFactory event_loop_factory_;
46 std::unique_ptr<EventLoop> ping_event_loop_;
47 std::unique_ptr<EventLoop> pong_event_loop_;
48 Ping ping_;
49 Pong pong_;
50 const std::string tmpdir_;
51 const std::string base_name_;
52};
53
54class RealtimeMultiNodeLoggerTest : public ::testing::Test {
55 protected:
56 RealtimeMultiNodeLoggerTest()
57 : shm_dir_(aos::testing::TestTmpDir() + "/aos"),
58 config_file_(aos::testing::ArtifactPath(
59 "aos/events/logging/multinode_pingpong_combined_config.json")),
60 config_(aos::configuration::ReadConfig(config_file_)),
61 event_loop_factory_(&config_.message()),
62 ping_event_loop_(event_loop_factory_.MakeEventLoop(
63 "pi1", configuration::GetNode(&config_.message(), "pi1"))),
64 ping_(ping_event_loop_.get()),
65 tmpdir_(aos::testing::TestTmpDir()),
66 base_name_(tmpdir_ + "/logfile/") {
67 FLAGS_shm_base = shm_dir_;
68
69 // Nuke the shm and log dirs, to ensure we aren't being affected by any
70 // preexisting tests.
71 aos::util::UnlinkRecursive(shm_dir_);
72 aos::util::UnlinkRecursive(base_name_);
James Kuszmaul09632422022-05-25 15:56:19 -070073 }
74
75 gflags::FlagSaver flag_saver_;
76 std::string shm_dir_;
77
78 const std::string config_file_;
79 const aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
80
81 // Factory and Ping class to generate a test logfile.
82 SimulatedEventLoopFactory event_loop_factory_;
83 std::unique_ptr<EventLoop> ping_event_loop_;
84 Ping ping_;
Eric Schmiedebergb38477e2022-12-02 16:08:04 -070085 const std::string tmpdir_;
86 const std::string base_name_;
James Kuszmaul09632422022-05-25 15:56:19 -070087};
88
89TEST_F(RealtimeLoggerTest, RealtimeReplay) {
James Kuszmaul09632422022-05-25 15:56:19 -070090 {
James Kuszmaul09632422022-05-25 15:56:19 -070091 event_loop_factory_.RunFor(std::chrono::milliseconds(95));
92
Austin Schuheeb86fc2024-04-04 20:12:39 -070093 std::unique_ptr<EventLoop> logger_event_loop =
94 event_loop_factory_.MakeEventLoop("logger");
James Kuszmaul09632422022-05-25 15:56:19 -070095 Logger logger(logger_event_loop.get());
96 logger.set_separate_config(false);
97 logger.set_polling_period(std::chrono::milliseconds(100));
Eric Schmiedebergb38477e2022-12-02 16:08:04 -070098 logger.StartLoggingOnRun(base_name_);
James Kuszmaul09632422022-05-25 15:56:19 -070099 event_loop_factory_.RunFor(std::chrono::milliseconds(2000));
100 }
101
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700102 LogReader reader(logger::SortParts(logger::FindLogs(base_name_)));
James Kuszmaul09632422022-05-25 15:56:19 -0700103 ShmEventLoop shm_event_loop(reader.configuration());
104 reader.Register(&shm_event_loop);
105 reader.OnEnd(shm_event_loop.node(),
106 [&shm_event_loop]() { shm_event_loop.Exit(); });
107
108 Fetcher<examples::Ping> ping_fetcher =
109 shm_event_loop.MakeFetcher<examples::Ping>("/test");
110
111 shm_event_loop.AddTimer([]() { LOG(INFO) << "Hello, World!"; })
Philipp Schradera6712522023-07-05 20:25:11 -0700112 ->Schedule(shm_event_loop.monotonic_now(), std::chrono::seconds(1));
James Kuszmaul09632422022-05-25 15:56:19 -0700113
114 shm_event_loop.Run();
115 reader.Deregister();
116
117 ASSERT_TRUE(ping_fetcher.Fetch());
118 ASSERT_EQ(ping_fetcher->value(), 210);
119}
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700120
121// Tests that ReplayChannels causes no messages to be replayed other than what
122// is included on a single node config
123TEST_F(RealtimeLoggerTest, SingleNodeReplayChannels) {
124 {
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700125 event_loop_factory_.RunFor(std::chrono::milliseconds(95));
126
Austin Schuheeb86fc2024-04-04 20:12:39 -0700127 std::unique_ptr<EventLoop> logger_event_loop =
128 event_loop_factory_.MakeEventLoop("logger");
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700129 Logger logger(logger_event_loop.get());
130 logger.set_separate_config(false);
131 logger.set_polling_period(std::chrono::milliseconds(100));
132 logger.StartLoggingOnRun(base_name_);
133 event_loop_factory_.RunFor(std::chrono::milliseconds(2000));
134 }
135
136 ReplayChannels replay_channels{{"/test", "aos.examples.Ping"}};
137 LogReader reader(logger::SortParts(logger::FindLogs(base_name_)),
138 &config_.message(), &replay_channels);
139 ShmEventLoop shm_event_loop(reader.configuration());
140 reader.Register(&shm_event_loop);
141 reader.OnEnd(shm_event_loop.node(),
142 [&shm_event_loop]() { shm_event_loop.Exit(); });
143
144 Fetcher<examples::Ping> ping_fetcher =
145 shm_event_loop.MakeFetcher<examples::Ping>("/test");
146 Fetcher<examples::Pong> pong_fetcher =
147 shm_event_loop.MakeFetcher<examples::Pong>("/test");
148
149 shm_event_loop.AddTimer([]() { LOG(INFO) << "Hello, World!"; })
Philipp Schradera6712522023-07-05 20:25:11 -0700150 ->Schedule(shm_event_loop.monotonic_now(), std::chrono::seconds(1));
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700151
Naman Guptac87b3102023-02-28 14:42:02 -0800152 // End timer should not be called in this case, it should automatically quit
153 // the event loop and check for number of fetches messages
154 // This is added to make sure OnEnd is called consistently
155 // When OnEnd is not called after finishing of the log, this will eventually
156 // quit due to the end timer but will report a failure
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700157 size_t run_seconds = 3;
Naman Guptac87b3102023-02-28 14:42:02 -0800158 auto *const end_timer =
159 shm_event_loop.AddTimer([&shm_event_loop, run_seconds]() {
160 shm_event_loop.Exit();
161 FAIL() << "OnEnd wasn't called on log end so quitting after "
162 << run_seconds << " seconds.";
163 });
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700164 shm_event_loop.OnRun([&shm_event_loop, end_timer, run_seconds]() {
165 LOG(INFO) << "Quitting in: " << run_seconds;
Philipp Schradera6712522023-07-05 20:25:11 -0700166 end_timer->Schedule(shm_event_loop.monotonic_now() +
167 std::chrono::seconds(run_seconds));
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700168 });
Naman Guptac87b3102023-02-28 14:42:02 -0800169
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700170 shm_event_loop.Run();
171 reader.Deregister();
172
173 ASSERT_TRUE(ping_fetcher.Fetch());
174 ASSERT_EQ(ping_fetcher->value(), 210);
175 ASSERT_FALSE(pong_fetcher.Fetch());
176}
177
178// Tests that ReplayChannels causes no messages to be replayed other than what
179// is included on a multi node config
180TEST_F(RealtimeMultiNodeLoggerTest, ReplayChannelsPingTest) {
181 FLAGS_override_hostname = "raspberrypi";
182 {
183 std::unique_ptr<EventLoop> logger_event_loop =
184 event_loop_factory_.MakeEventLoop(
185 "logger", configuration::GetNode(&config_.message(), "pi1"));
186
187 event_loop_factory_.RunFor(std::chrono::milliseconds(95));
188
189 Logger logger(logger_event_loop.get());
190 logger.set_separate_config(false);
191 logger.set_polling_period(std::chrono::milliseconds(100));
192
Alexei Strots01395492023-03-20 13:59:56 -0700193 std::unique_ptr<MultiNodeFilesLogNamer> namer =
194 std::make_unique<MultiNodeFilesLogNamer>(
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700195 base_name_, &config_.message(), logger_event_loop.get(),
196 configuration::GetNode(&config_.message(), "pi1"));
197
198 logger.StartLogging(std::move(namer));
199 event_loop_factory_.RunFor(std::chrono::milliseconds(2000));
200 }
201
202 ReplayChannels replay_channels{{"/test", "aos.examples.Ping"}};
203 LogReader reader(logger::SortParts(logger::FindLogs(base_name_)),
204 &config_.message(), &replay_channels);
205 ShmEventLoop shm_event_loop(reader.configuration());
206 reader.Register(&shm_event_loop);
207 reader.OnEnd(shm_event_loop.node(),
208 [&shm_event_loop]() { shm_event_loop.Exit(); });
209
210 Fetcher<examples::Ping> ping_fetcher =
211 shm_event_loop.MakeFetcher<examples::Ping>("/test");
212
213 shm_event_loop.AddTimer([]() { LOG(INFO) << "Hello, World!"; })
Philipp Schradera6712522023-07-05 20:25:11 -0700214 ->Schedule(shm_event_loop.monotonic_now(), std::chrono::seconds(1));
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700215
216 shm_event_loop.Run();
217 reader.Deregister();
218
219 ASSERT_TRUE(ping_fetcher.Fetch());
220 ASSERT_EQ(ping_fetcher->value(), 210);
221}
222
223// Tests that when remapping a channel included in ReplayChannels messages are
224// sent on the remapped channel
225TEST_F(RealtimeMultiNodeLoggerTest, RemappedReplayChannelsTest) {
226 FLAGS_override_hostname = "raspberrypi";
227 {
228 std::unique_ptr<EventLoop> logger_event_loop =
229 event_loop_factory_.MakeEventLoop(
230 "logger", configuration::GetNode(&config_.message(), "pi1"));
231
232 event_loop_factory_.RunFor(std::chrono::milliseconds(95));
233
234 Logger logger(logger_event_loop.get());
235 logger.set_separate_config(false);
236 logger.set_polling_period(std::chrono::milliseconds(100));
237
Alexei Strots01395492023-03-20 13:59:56 -0700238 std::unique_ptr<MultiNodeFilesLogNamer> namer =
239 std::make_unique<MultiNodeFilesLogNamer>(
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700240 base_name_, &config_.message(), logger_event_loop.get(),
241 configuration::GetNode(&config_.message(), "pi1"));
242
243 logger.StartLogging(std::move(namer));
244 event_loop_factory_.RunFor(std::chrono::milliseconds(2000));
245 }
246
247 ReplayChannels replay_channels{{"/test", "aos.examples.Ping"}};
248 LogReader reader(logger::SortParts(logger::FindLogs(base_name_)),
249 &config_.message(), &replay_channels);
250 reader.RemapLoggedChannel<aos::examples::Ping>("/test", "/original");
251 ShmEventLoop shm_event_loop(reader.configuration());
252 reader.Register(&shm_event_loop);
253 reader.OnEnd(shm_event_loop.node(),
254 [&shm_event_loop]() { shm_event_loop.Exit(); });
255
256 Fetcher<examples::Ping> original_ping_fetcher =
257 shm_event_loop.MakeFetcher<examples::Ping>("/original/test");
258
259 Fetcher<examples::Ping> ping_fetcher =
260 shm_event_loop.MakeFetcher<examples::Ping>("/test");
261
262 shm_event_loop.AddTimer([]() { LOG(INFO) << "Hello, World!"; })
Philipp Schradera6712522023-07-05 20:25:11 -0700263 ->Schedule(shm_event_loop.monotonic_now(), std::chrono::seconds(1));
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700264
265 shm_event_loop.Run();
266 reader.Deregister();
267
268 ASSERT_TRUE(original_ping_fetcher.Fetch());
269 ASSERT_EQ(original_ping_fetcher->value(), 210);
270 ASSERT_FALSE(ping_fetcher.Fetch());
271}
272
273// Tests that messages are not replayed when they do not exist in the
274// ReplayChannels provided to LogReader. The channels used here do not
275// exist in the log being replayed, and there's no messages on those
276// channels as well.
277TEST_F(RealtimeMultiNodeLoggerTest, DoesNotExistInReplayChannelsTest) {
278 FLAGS_override_hostname = "raspberrypi";
279 {
280 std::unique_ptr<EventLoop> logger_event_loop =
281 event_loop_factory_.MakeEventLoop(
282 "logger", configuration::GetNode(&config_.message(), "pi1"));
283
284 event_loop_factory_.RunFor(std::chrono::milliseconds(95));
285
286 Logger logger(logger_event_loop.get());
287 logger.set_separate_config(false);
288 logger.set_polling_period(std::chrono::milliseconds(100));
Alexei Strots01395492023-03-20 13:59:56 -0700289 std::unique_ptr<MultiNodeFilesLogNamer> namer =
290 std::make_unique<MultiNodeFilesLogNamer>(
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700291 base_name_, &config_.message(), logger_event_loop.get(),
292 configuration::GetNode(&config_.message(), "pi1"));
293
294 logger.StartLogging(std::move(namer));
295 event_loop_factory_.RunFor(std::chrono::milliseconds(2000));
296 }
297
298 ReplayChannels replay_channels{{"/test", "aos.examples.Pong"},
299 {"/test", "fake"},
300 {"fake", "aos.examples.Ping"}};
301 LogReader reader(logger::SortParts(logger::FindLogs(base_name_)),
302 &config_.message(), &replay_channels);
303 ShmEventLoop shm_event_loop(reader.configuration());
304 reader.Register(&shm_event_loop);
305 reader.OnEnd(shm_event_loop.node(),
306 [&shm_event_loop]() { shm_event_loop.Exit(); });
307
308 Fetcher<examples::Ping> ping_fetcher =
309 shm_event_loop.MakeFetcher<examples::Ping>("/test");
310
311 auto *const end_timer = shm_event_loop.AddTimer([&shm_event_loop]() {
312 LOG(INFO) << "All done, quitting now";
313 shm_event_loop.Exit();
314 });
315
316 // TODO(#21) reader.OnEnd() is not working as expected when
317 // using replay_channels
318 // keep looking for 3 seconds if some message comes, just in case
319 size_t run_seconds = 3;
320 shm_event_loop.OnRun([&shm_event_loop, end_timer, run_seconds]() {
321 LOG(INFO) << "Quitting in: " << run_seconds;
Philipp Schradera6712522023-07-05 20:25:11 -0700322 end_timer->Schedule(shm_event_loop.monotonic_now() +
323 std::chrono::seconds(run_seconds));
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700324 });
325
326 shm_event_loop.Run();
327 reader.Deregister();
328 ASSERT_FALSE(ping_fetcher.Fetch());
329}
330
331using RealtimeMultiNodeLoggerDeathTest = RealtimeMultiNodeLoggerTest;
332
333// Tests that remapping a channel not included in the replay channels passed to
334// LogReader throws an error since this would indicate the user is trying to use
335// the channel being remapped.
336TEST_F(RealtimeMultiNodeLoggerDeathTest,
337 RemapLoggedChannelNotIncludedInReplayChannels) {
338 FLAGS_override_hostname = "raspberrypi";
339 {
340 std::unique_ptr<EventLoop> logger_event_loop =
341 event_loop_factory_.MakeEventLoop(
342 "logger", configuration::GetNode(&config_.message(), "pi1"));
343
344 event_loop_factory_.RunFor(std::chrono::milliseconds(95));
345
346 Logger logger(logger_event_loop.get());
347 logger.set_separate_config(false);
348 logger.set_polling_period(std::chrono::milliseconds(100));
349
Alexei Strots01395492023-03-20 13:59:56 -0700350 std::unique_ptr<MultiNodeFilesLogNamer> namer =
351 std::make_unique<MultiNodeFilesLogNamer>(
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700352 base_name_, &config_.message(), logger_event_loop.get(),
353 configuration::GetNode(&config_.message(), "pi1"));
354
355 logger.StartLogging(std::move(namer));
356 event_loop_factory_.RunFor(std::chrono::milliseconds(2000));
357 }
358
359 ReplayChannels replay_channels{{"/test", "aos.examples.Ping"}};
360 LogReader reader(logger::SortParts(logger::FindLogs(base_name_)),
361 &config_.message(), &replay_channels);
362 EXPECT_DEATH(
363 reader.RemapLoggedChannel<aos::examples::Ping>("/fake", "/original"),
Eric Schmiedeberge279b532023-04-19 16:36:02 -0600364 "which is not included in the replay channels passed to");
Eric Schmiedebergb38477e2022-12-02 16:08:04 -0700365}
366
James Kuszmaul09632422022-05-25 15:56:19 -0700367} // namespace aos::logger::testing