blob: 3c583032d3e01c3283b899b710a351d056d96b68 [file] [log] [blame]
// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_log_sink/log_sink.h"
#include <string>
#include "gtest/gtest.h"
#include "pw_log/levels.h"
#include "pw_log_proto/log.pwpb.h"
#include "pw_protobuf/decoder.h"
namespace pw::log_sink {
namespace {
constexpr size_t kMaxTokenizedMessageSize = 512;
constexpr char kTokenizedMessage[] = "Test Message";
class TestSink : public Sink {
public:
void HandleEntry(ConstByteSpan message) {
pw::protobuf::Decoder log_decoder(message);
std::string_view log_entry_message;
EXPECT_TRUE(log_decoder.Next().ok()); // line_level - 2
EXPECT_TRUE(log_decoder.Next().ok()); // flags - 3
EXPECT_TRUE(log_decoder.Next().ok()); // timestamp - 5
EXPECT_TRUE(log_decoder.Next().ok()); // message_string - 16
EXPECT_EQ(16U, log_decoder.FieldNumber());
EXPECT_TRUE(log_decoder.ReadString(&log_entry_message).ok());
last_message_string_ = log_entry_message;
message_count_++;
}
void HandleDropped(size_t count) { drop_count_ += count; }
void VerifyMessage(std::string tokenized_message) {
EXPECT_EQ(tokenized_message, last_message_string_);
}
size_t GetMessageCount() { return message_count_; }
size_t GetDropCount() { return drop_count_; }
private:
std::string last_message_string_;
size_t message_count_ = 0;
size_t drop_count_ = 0;
};
void LogMessageForTest(const char* message) {
pw_LogSink_Log(0, 0, nullptr, nullptr, 0, nullptr, "%s", message);
}
void LogInvalidMessageForTest() {
char long_message[kMaxTokenizedMessageSize + 1];
memset(long_message, 'A', sizeof(long_message));
long_message[kMaxTokenizedMessageSize] = '\0';
pw_LogSink_Log(0, 0, nullptr, nullptr, 0, nullptr, "%s", long_message);
}
} // namespace
TEST(LogSink, NoSink) {
// Confirm that the log function does not crash when no sink is present.
LogMessageForTest(kTokenizedMessage);
}
TEST(LogSink, SingleSink) {
TestSink test_sink;
AddSink(test_sink);
LogMessageForTest(kTokenizedMessage);
test_sink.VerifyMessage(kTokenizedMessage);
RemoveSink(test_sink);
}
TEST(LogSink, MultipleSink) {
TestSink test_sink_io;
TestSink test_sink_bt;
AddSink(test_sink_io);
AddSink(test_sink_bt);
LogMessageForTest(kTokenizedMessage);
test_sink_io.VerifyMessage(kTokenizedMessage);
test_sink_bt.VerifyMessage(kTokenizedMessage);
RemoveSink(test_sink_io);
LogMessageForTest(kTokenizedMessage);
test_sink_io.VerifyMessage(kTokenizedMessage);
EXPECT_EQ(test_sink_io.GetMessageCount(), 1U);
EXPECT_EQ(test_sink_bt.GetMessageCount(), 2U);
RemoveSink(test_sink_bt);
}
TEST(LogSink, DroppedEntries) {
TestSink test_sink;
LogMessageForTest(kTokenizedMessage);
AddSink(test_sink);
LogMessageForTest(kTokenizedMessage);
EXPECT_EQ(test_sink.GetMessageCount(), 1U);
EXPECT_EQ(test_sink.GetDropCount(), 1U);
LogInvalidMessageForTest();
EXPECT_EQ(test_sink.GetMessageCount(), 1U);
EXPECT_EQ(test_sink.GetDropCount(), 2U);
LogMessageForTest(kTokenizedMessage);
EXPECT_EQ(test_sink.GetMessageCount(), 2U);
EXPECT_EQ(test_sink.GetDropCount(), 2U);
RemoveSink(test_sink);
}
} // namespace pw::log_sink