blob: 00ca647536e47ca780e92d198d8bd156f28844e6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/syslog/cpp/log_level.h>
#include <memory>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "lib/inspect/cpp/vmo/types.h"
#include "src/developer/forensics/feedback_data/constants.h"
#include "src/developer/forensics/feedback_data/system_log_recorder/encoding/identity_encoder.h"
#include "src/developer/forensics/feedback_data/system_log_recorder/system_log_recorder.h"
#include "src/developer/forensics/testing/log_message.h"
#include "src/developer/forensics/utils/log_format.h"
#include "src/developer/forensics/utils/redact/redactor.h"
#include "src/lib/fxl/strings/string_printf.h"
namespace forensics {
namespace feedback_data {
namespace system_log_recorder {
namespace {
::fpromise::result<fuchsia::logger::LogMessage, std::string> BuildLogMessage(
const int32_t severity, const std::string& text,
const zx::duration timestamp_offset = zx::duration(0),
const std::vector<std::string>& tags = {}) {
return ::fpromise::ok(testing::BuildLogMessage(severity, text, timestamp_offset, tags));
}
// Only change "X" for one character. i.e. X -> 12 is not allowed.
const auto kMaxLogLineSize =
StorageSize::Bytes(Format(BuildLogMessage(fuchsia_logging::LOG_INFO, "line X").value()).size());
const auto kRepeatedFormatStrSize =
StorageSize::Bytes(std::string("!!! MESSAGE REPEATED X MORE TIMES !!!\n").size());
// We set the block size to an arbitrary large numbers for test cases where the block logic does
// not matter.
const auto kVeryLargeBlockSize = kMaxLogLineSize * 100;
std::unique_ptr<Encoder> MakeIdentityEncoder() {
return std::unique_ptr<Encoder>(new IdentityEncoder());
}
std::unique_ptr<RedactorBase> MakeIdentityRedactor() {
return std::unique_ptr<RedactorBase>(new IdentityRedactor(inspect::BoolProperty()));
}
class SimpleRedactor : public RedactorBase {
public:
SimpleRedactor(const bool count_calls)
: RedactorBase(inspect::BoolProperty()), count_calls_(count_calls) {}
std::string& Redact(std::string& text) override {
text = (count_calls_) ? fxl::StringPrintf("R: %d", ++num_calls_) : "R";
return text;
}
std::string& RedactJson(std::string& text) override { return Redact(text); }
std::string UnredactedCanary() const override { return ""; }
std::string RedactedCanary() const override { return ""; }
private:
bool count_calls_;
int num_calls_{0};
};
std::unique_ptr<RedactorBase> MakeSimpleRedactor(const bool count_calls) {
return std::unique_ptr<RedactorBase>(new SimpleRedactor(count_calls));
}
TEST(LogMessageStoreTest, NotSafeAfterInterruption) {
LogMessageStore store(kMaxLogLineSize * 10, kMaxLogLineSize, MakeIdentityRedactor(),
MakeIdentityEncoder());
EXPECT_FALSE(store.SafeAfterInterruption());
}
TEST(LogMessageStoreTest, UnlimitedMessages) {
// Set the block to hold 10 log messages while the buffer holds 1 log message (but the buffer
// limits should be ignored because the component has just started up).
LogMessageStore store(kMaxLogLineSize * 10, kMaxLogLineSize, MakeIdentityRedactor(),
MakeIdentityEncoder());
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
bool end_of_block;
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 2 MORE TIMES !!!
[15604.000][07559][07687][] INFO: line 1
!!! MESSAGE REPEATED 2 MORE TIMES !!!
[15604.000][07559][07687][] INFO: line 2
!!! MESSAGE REPEATED 2 MORE TIMES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, AppliesRedaction) {
// Set the block to hold 10 log messages while the buffer holds 1 log message (but the buffer
// limits should be ignored because the component has just started up).
LogMessageStore store(kMaxLogLineSize * 10, kMaxLogLineSize,
MakeSimpleRedactor(/*count_calls=*/true), MakeIdentityEncoder());
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
bool end_of_block;
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: R: 1
[15604.000][07559][07687][] INFO: R: 2
[15604.000][07559][07687][] INFO: R: 3
[15604.000][07559][07687][] INFO: R: 4
[15604.000][07559][07687][] INFO: R: 5
[15604.000][07559][07687][] INFO: R: 6
[15604.000][07559][07687][] INFO: R: 7
[15604.000][07559][07687][] INFO: R: 8
[15604.000][07559][07687][] INFO: R: 9
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, RedactionCompressed) {
// Set the block to hold 10 log messages while the buffer holds 1 log message (but the buffer
// limits should be ignored because the component has just started up).
LogMessageStore store(kMaxLogLineSize * 10, kMaxLogLineSize,
MakeSimpleRedactor(/*count_calls=*/false), MakeIdentityEncoder());
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
bool end_of_block;
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: R
!!! MESSAGE REPEATED 8 MORE TIMES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyBlock) {
// Set the block to hold 2 log messages while the buffer holds 1 log message.
LogMessageStore store(kMaxLogLineSize * 2, kMaxLogLineSize, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
bool end_of_block;
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 1
)");
EXPECT_TRUE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 2
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 3")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 3
)");
EXPECT_TRUE(end_of_block);
}
TEST(LogMessageStoreTest, AddAndConsume) {
// Set up the store to hold 2 log lines.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
bool end_of_block;
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
[15604.000][07559][07687][] INFO: line 1
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 3")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 2
[15604.000][07559][07687][] INFO: line 3
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, DropsCorrectly) {
bool end_of_block;
// Set up the store to hold 2 log lines to test that the subsequent 3 are dropped.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 3")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 4")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
[15604.000][07559][07687][] INFO: line 1
!!! DROPPED 3 MESSAGES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, DropsSubsequentShorterMessages) {
bool end_of_block;
// Even though the store could hold 2 log lines, all the lines after the first one will be
// dropped because the second log message is very long.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(
fuchsia_logging::LOG_INFO,
"This is a very big message that will not fit so it should not be displayed!")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 2")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 3")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 4")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! DROPPED 4 MESSAGES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetitionMessage_AtConsume) {
bool end_of_block;
// Set up the store to hold 2 log line. With three repeated messages, the last two messages
// should get reduced to a single repeated message.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 2 MORE TIMES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetition_DoNotResetRepeatedWarningOnConsume) {
bool end_of_block;
// Test that we only write repeated warning messages when repeated messages span over 2 buffers.
// Block capacity: very large (unlimited for this example)
// Buffer capacity: 1 log message
//
// __________________
// |input |output |
// |________|_______| _
// |line 0 |line 0 | |
// |line 0 |x2 | |---- Consume 1
// |line 0 | | |
// |________|_______| _|
// |line 0 |x2 | |
// |line 0 | | |---- Consume 2
// |________|_______| _|
//
// Note: xN = last message repeated N times
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 2 MORE TIMES !!!
)");
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"(!!! MESSAGE REPEATED 2 MORE TIMES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetition_ResetRepeatedWarningOnConsume) {
bool end_of_block;
// Test that the first log of a block should not be a repeated warning message.
// Block capacity: 1 log message
// Buffer capacity: 1 log message
//
// __________________
// |input |output |
// |________|_______| _
// |line 0 |line 0 | |
// |line 0 |x2 | |---- Consume 1
// |line 0 | | |
// |________|_______| _|
// | End of Block |
// |----------------| _
// |line 0 |line 0 | |
// |line 0 |x1 | |---- Consume 2
// |________|_______| _|
// | End of Block |
// -----------------
// Note: xN = last message repeated N times
LogMessageStore store(kMaxLogLineSize, kMaxLogLineSize, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 2 MORE TIMES !!!
)");
EXPECT_TRUE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
)");
EXPECT_TRUE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetition_LimitRepetitionBuffers) {
bool end_of_block;
// Test that repeated messages do not extend over more than kMaxRepeatedBuffers.
// Block capacity: 2 * kMaxRepeatedBuffer log message (test only uses one block)
// Buffer capacity: 2 log messages
// __________________
// |input |output |
// |________|_______| _
// |line 0 |line 0 | |
// |line 0 |x1 | |---- Consume 1 time
// |________|_______| _|
// |line 0 |x1 | |
// | | | |---- Consume (kMaxRepeatedBuffers - 1) times
// |________|_______| _|
// |line 0 | | |
// | | | |---- Consume kMaxRepeatedBuffers times
// |________|_______| _|
// |line 1 |xRep | |
// | |line 1 | |---- Consume 1 time
// |________|_______| _|
//
// Note: xN = last message repeated N times, Rep = kMaxRepeatedBuffers.
LogMessageStore store(2 * kMaxRepeatedBuffers * kMaxLogLineSize, 2 * kMaxLogLineSize,
MakeIdentityRedactor(), MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
)");
for (size_t i = 1; i < kMaxRepeatedBuffers; i++) {
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"(!!! MESSAGE REPEATED 1 MORE TIME !!!
)");
}
for (size_t i = 0; i < kMaxRepeatedBuffers; i++) {
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), "");
}
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block),
"!!! MESSAGE REPEATED " + std::to_string(kMaxRepeatedBuffers) + " MORE TIMES !!!\n" +
"[15604.000][07559][07687][] INFO: line 1\n");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetitionMessage_WhenMessageChanges) {
bool end_of_block;
// Set up the store to hold 3 log line. Verify that a repetition message appears after input
// repetition and before the input change.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2 + kRepeatedFormatStrSize,
MakeIdentityRedactor(), MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
[15604.000][07559][07687][] INFO: line 1
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetitionMessage_WhenSeverityChanges) {
bool end_of_block;
// Set up the store to hold 3 log line. Verify that a repetition message appears after input
// repetition and before the input severity change.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2 + kRepeatedFormatStrSize,
MakeIdentityRedactor(), MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_WARNING, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
[15604.000][07559][07687][] WARN: line 0
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepetitionMessage_WhenTagsChange) {
bool end_of_block;
// Set up the store to hold 4 log lines. Verify that a repetition message appears after
// input repetition and before the input change.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 3 + kRepeatedFormatStrSize,
MakeIdentityRedactor(), MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(
store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0", zx::duration(0), {"tag1"})));
EXPECT_TRUE(
store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0", zx::duration(0), {"tag1"})));
EXPECT_TRUE(store.Add(
BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0", zx::duration(0), {"tag1", "tag2"})));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][tag1] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
[15604.000][07559][07687][tag1, tag2] INFO: line 0
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyDroppedRepeatedMessage_OnBufferFull) {
bool end_of_block;
// Set up the store to hold 1 log line. Verify that repeated messages that occur after the
// buffer is full get dropped.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 1, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! DROPPED 2 MESSAGES !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyNoRepeatMessage_AfterFirstConsume) {
bool end_of_block;
// Set up the store to hold 1 log line. Verify that there is no repeat message right after
// dropping messages.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 1, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! DROPPED 1 MESSAGES !!!
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 1
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepeatMessage_AfterFirstConsume) {
bool end_of_block;
// Set up the store to hold 3 log lines. Verify that there can be a repeat message after
// consume, when no messages were dropped.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 3, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
[15604.000][07559][07687][] INFO: line 1
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"(!!! MESSAGE REPEATED 1 MORE TIME !!!
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyRepeatedAndDropped) {
bool end_of_block;
// Set up the store to hold 2 log lines. Verify that we can have the repeated message, and then
// the dropped message.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
!!! DROPPED 1 MESSAGES !!!
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 1
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyNoRepeatMessage_TimeOrdering) {
bool end_of_block;
// Set up the store to hold 2 log line. Verify time ordering: a message cannot be counted as
// repeated if it's in between messages, even if those messages get dropped.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1 overflow msg")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1 overflow msg")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! DROPPED 5 MESSAGES !!!
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyAppendToEnd) {
bool end_of_block;
// Set up the store to hold 2 log line. Verify time ordering: a message cannot be counted as
// repeated if it's in between messages, even if those messages get dropped.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1 overflow msg")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 1 overflow msg")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_FALSE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
store.AppendToEnd("DONE\n");
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
!!! DROPPED 4 MESSAGES !!!
DONE
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
)");
EXPECT_FALSE(end_of_block);
}
TEST(LogMessageStoreTest, VerifyNoRepeatWarningAfter_AppendToEnd) {
bool end_of_block;
// Set up the store to hold 2 log line. Verify time ordering: a message cannot be counted as
// repeated if it's in between messages, even if those messages get dropped.
LogMessageStore store(kVeryLargeBlockSize, kMaxLogLineSize * 2, MakeIdentityRedactor(),
MakeIdentityEncoder());
store.TurnOnRateLimiting();
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
store.AppendToEnd("DONE\n");
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
!!! MESSAGE REPEATED 1 MORE TIME !!!
DONE
)");
EXPECT_FALSE(end_of_block);
EXPECT_TRUE(store.Add(BuildLogMessage(fuchsia_logging::LOG_INFO, "line 0")));
EXPECT_EQ(store.Consume(&end_of_block), R"([15604.000][07559][07687][] INFO: line 0
)");
EXPECT_FALSE(end_of_block);
}
} // namespace
} // namespace system_log_recorder
} // namespace feedback_data
} // namespace forensics