Improve messaging when ReadMessages detects a corrupted message.
Added tests for various control flag behaviors.
Change-Id: I1ea3ebae7c1e15e0bc5ce5586ac7752bde20cb80
Signed-off-by: Brian Smartt <brian.smartt@bluerivertech.com>
diff --git a/aos/events/logging/logfile_utils_test.cc b/aos/events/logging/logfile_utils_test.cc
index c9ec37e..d024ae0 100644
--- a/aos/events/logging/logfile_utils_test.cc
+++ b/aos/events/logging/logfile_utils_test.cc
@@ -9,6 +9,7 @@
#include "aos/flatbuffers.h"
#include "aos/json_to_flatbuffer.h"
#include "aos/testing/tmpdir.h"
+#include "gflags/gflags.h"
#include "gtest/gtest.h"
namespace aos {
@@ -2720,6 +2721,105 @@
"Found overlapping boots on");
}
+// Tests that we MessageReader blows up on a bad message.
+TEST(MessageReaderConfirmCrash, ReadWrite) {
+ const std::string logfile = aos::testing::TestTmpDir() + "/log.bfbs";
+ unlink(logfile.c_str());
+
+ const aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> config =
+ JsonToSizedFlatbuffer<LogFileHeader>(
+ R"({ "max_out_of_order_duration": 100000000 })");
+ const aos::SizePrefixedFlatbufferDetachedBuffer<MessageHeader> m1 =
+ JsonToSizedFlatbuffer<MessageHeader>(
+ R"({ "channel_index": 0, "monotonic_sent_time": 1 })");
+ const aos::SizePrefixedFlatbufferDetachedBuffer<MessageHeader> m2 =
+ JsonToSizedFlatbuffer<MessageHeader>(
+ R"({ "channel_index": 0, "monotonic_sent_time": 2 })");
+ const aos::SizePrefixedFlatbufferDetachedBuffer<MessageHeader> m4 =
+ JsonToSizedFlatbuffer<MessageHeader>(
+ R"({ "channel_index": 0, "monotonic_sent_time": 4 })");
+
+ // Starts out like a proper flat buffer header, but it breaks down ...
+ std::vector<uint8_t> garbage{8, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0};
+ absl::Span<uint8_t> m3_span(garbage);
+
+ {
+ DetachedBufferWriter writer(logfile, std::make_unique<DummyEncoder>());
+ writer.QueueSpan(config.span());
+ writer.QueueSpan(m1.span());
+ writer.QueueSpan(m2.span());
+ writer.QueueSpan(m3_span);
+ writer.QueueSpan(m4.span()); // This message is "hidden"
+ }
+
+ {
+ MessageReader reader(logfile);
+
+ EXPECT_EQ(reader.filename(), logfile);
+
+ EXPECT_EQ(
+ reader.max_out_of_order_duration(),
+ std::chrono::nanoseconds(config.message().max_out_of_order_duration()));
+ EXPECT_EQ(reader.newest_timestamp(), monotonic_clock::min_time);
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(1)));
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(2)));
+ // Confirm default crashing behavior
+ EXPECT_DEATH(reader.ReadMessage(), "Corrupted message at offset");
+ }
+
+ {
+ gflags::FlagSaver fs;
+
+ MessageReader reader(logfile);
+ reader.set_crash_on_corrupt_message_flag(false);
+
+ EXPECT_EQ(reader.filename(), logfile);
+
+ EXPECT_EQ(
+ reader.max_out_of_order_duration(),
+ std::chrono::nanoseconds(config.message().max_out_of_order_duration()));
+ EXPECT_EQ(reader.newest_timestamp(), monotonic_clock::min_time);
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(1)));
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(2)));
+ // Confirm avoiding the corrupted message crash, stopping instead.
+ EXPECT_FALSE(reader.ReadMessage());
+ }
+
+ {
+ gflags::FlagSaver fs;
+
+ MessageReader reader(logfile);
+ reader.set_crash_on_corrupt_message_flag(false);
+ reader.set_ignore_corrupt_messages_flag(true);
+
+ EXPECT_EQ(reader.filename(), logfile);
+
+ EXPECT_EQ(
+ reader.max_out_of_order_duration(),
+ std::chrono::nanoseconds(config.message().max_out_of_order_duration()));
+ EXPECT_EQ(reader.newest_timestamp(), monotonic_clock::min_time);
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(1)));
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(2)));
+ // Confirm skipping of the corrupted message to read the hidden one.
+ EXPECT_TRUE(reader.ReadMessage());
+ EXPECT_EQ(reader.newest_timestamp(),
+ monotonic_clock::time_point(chrono::nanoseconds(4)));
+ EXPECT_FALSE(reader.ReadMessage());
+ }
+}
+
} // namespace testing
} // namespace logger
} // namespace aos