blob: f1777f8be41ee66fdd8ad8ea54535931003f6236 [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_settings.h>
#include <lib/syslog/cpp/logging_backend.h>
#include <lib/syslog/cpp/logging_backend_fuchsia_private.h>
#include <lib/syslog/cpp/macros.h>
#include <cstring>
#include <vector>
#include <gtest/gtest.h>
#include "logging_backend_shared.h"
#include "src/lib/files/file.h"
#include "src/lib/files/scoped_temp_dir.h"
namespace syslog {
TEST(StructuredLogging, Log) {
FX_SLOG(WARNING, "test_log", KV("foo", "bar"));
// TODO(fxbug.dev/57482): Figure out how to verify this appropriately.
}
TEST(StructuredLogging, BackendDirect) {
syslog_backend::LogBuffer buffer;
syslog_backend::BeginRecord(&buffer, syslog::LOG_WARNING, "foo.cc", 42, "fake tag", "condition");
syslog_backend::EndRecord(&buffer);
syslog_backend::FlushRecord(&buffer);
syslog_backend::BeginRecord(&buffer, syslog::LOG_WARNING, "foo.cc", 42, "fake tag", "condition");
syslog_backend::WriteKeyValue(&buffer, "foo", static_cast<int64_t>(42));
syslog_backend::EndRecord(&buffer);
ASSERT_TRUE(syslog_backend::FlushRecord(&buffer));
// TODO(fxbug.dev/57482): Figure out how to verify this appropriately.
}
TEST(StructuredLogging, StartsAtPosition0) {
syslog_backend::LogBuffer buffer;
memset(&buffer, 0, sizeof(buffer));
syslog_backend::BeginRecord(&buffer, syslog::LOG_WARNING, "foo.cc", 42, "fake tag", "condition");
syslog_backend::EndRecord(&buffer);
ASSERT_NE(buffer.data[0], static_cast<uint64_t>(0));
}
TEST(StructuredLogging, PaddedWritePadsWithZeroes) {
uint64_t fives;
memset(&fives, 5, sizeof(fives));
uint64_t buffer[2];
memset(buffer, 5, sizeof(buffer));
// Writing "hi" results in 26984 which is
// 'h' written to byte 0 | 'i' written to byte 1
// Bytes get reversed due to endianness so they are flipped
// when combined.
WritePaddedInternal(buffer, "hi", ByteOffset::Unbounded(2));
ASSERT_EQ(buffer[0], static_cast<uint64_t>(26984));
ASSERT_EQ(buffer[1], fives);
buffer[0] = fives;
buffer[1] = fives;
WritePaddedInternal(buffer, "", ByteOffset::Unbounded(0));
ASSERT_EQ(buffer[0], fives);
ASSERT_EQ(buffer[1], fives);
}
TEST(ByteOffset, FromBuffer) {
ByteOffset offset = ByteOffset::FromBuffer(5, 10);
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(5));
ASSERT_EQ(offset.capacity(), static_cast<size_t>(10));
}
TEST(ByteOffset, Unbounded) {
ByteOffset offset = ByteOffset::Unbounded(13);
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(13));
ASSERT_EQ(offset.capacity(), static_cast<size_t>(-1));
}
TEST(ByteOffset, Addition) {
ByteOffset offset = ByteOffset::Unbounded(13);
offset = offset + 1;
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(14));
}
TEST(WordOffset, FromByteOffset) {
WordOffset<uint64_t> offset =
WordOffset<uint64_t>::FromByteOffset(ByteOffset::FromBuffer(8, 256));
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(1));
ASSERT_EQ(offset.capacity(), static_cast<size_t>(32));
}
TEST(WordOffset, ToByteOffset) {
WordOffset<uint64_t> offset =
WordOffset<uint64_t>::FromByteOffset(ByteOffset::FromBuffer(8, 256));
ASSERT_EQ(offset.ToByteOffset().unsafe_get(), static_cast<size_t>(8));
ASSERT_EQ(offset.ToByteOffset().capacity(), static_cast<size_t>(256));
}
TEST(WordOffset, Addition) {
WordOffset<uint64_t> offset =
WordOffset<uint64_t>::FromByteOffset(ByteOffset::FromBuffer(8, 256));
offset = offset + 1;
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(2));
offset = offset + WordOffset<uint64_t>::FromByteOffset(ByteOffset::Unbounded(16));
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(4));
}
TEST(WordOffset, Begin) {
WordOffset<uint64_t> offset =
WordOffset<uint64_t>::FromByteOffset(ByteOffset::FromBuffer(8, 256));
offset = offset.begin();
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(0));
ASSERT_EQ(offset.capacity(), static_cast<size_t>(32));
}
TEST(WordOffset, Reset) {
WordOffset<uint64_t> offset =
WordOffset<uint64_t>::FromByteOffset(ByteOffset::FromBuffer(8, 256));
offset.reset();
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(0));
ASSERT_EQ(offset.capacity(), static_cast<size_t>(32));
}
TEST(WordOffset, InBounds) {
WordOffset<uint64_t> offset = WordOffset<uint64_t>::FromByteOffset(ByteOffset::FromBuffer(8, 16));
ASSERT_TRUE(offset.in_bounds(WordOffset<uint64_t>::FromByteOffset(ByteOffset::Unbounded(0))));
ASSERT_FALSE(offset.in_bounds(WordOffset<uint64_t>::FromByteOffset(ByteOffset::Unbounded(8))));
}
TEST(WordOffset, Invalid) {
WordOffset<uint64_t> offset = WordOffset<uint64_t>::invalid();
ASSERT_EQ(offset.capacity(), static_cast<size_t>(0));
ASSERT_EQ(offset.unsafe_get(), static_cast<size_t>(0));
}
TEST(StructuredLogging, Overflow) {
std::vector<char> very_large_string;
very_large_string.resize(1000 * 1000);
memset(very_large_string.data(), 5, very_large_string.size());
very_large_string[very_large_string.size() - 1] = 0;
syslog_backend::LogBuffer buffer;
syslog_backend::BeginRecord(&buffer, syslog::LOG_WARNING, "foo.cc", 42, "fake tag", "condition");
syslog_backend::EndRecord(&buffer);
syslog_backend::FlushRecord(&buffer);
syslog_backend::BeginRecord(&buffer, syslog::LOG_WARNING, "foo.cc", 42, "fake tag", "condition");
syslog_backend::WriteKeyValue(&buffer, "foo", static_cast<int64_t>(42));
syslog_backend::WriteKeyValue(&buffer, "bar", very_large_string.data());
syslog_backend::EndRecord(&buffer);
ASSERT_FALSE(syslog_backend::FlushRecord(&buffer));
}
TEST(StructuredLogging, LOGS) {
std::string str;
// 5mb log shouldn't crash
str.resize(1000 * 5000);
memset(str.data(), 's', str.size() - 1);
FX_LOGS(INFO) << str;
}
TEST(StructuredLogging, Legacy) {
const char kTestMessage[] = "TEST MESSAGE";
LogSettings new_settings;
files::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.NewTempFile(&new_settings.log_file));
SetLogSettings(new_settings);
FX_LOGS(INFO) << kTestMessage;
ASSERT_EQ(0, access(new_settings.log_file.c_str(), R_OK));
std::string log;
ASSERT_TRUE(files::ReadFileToString(new_settings.log_file, &log));
EXPECT_TRUE(log.find(kTestMessage) != std::string::npos);
}
TEST(StructuredLogging, ToCStr) {
syslog_backend::LogBuffer buffer;
memset(&buffer, 0, sizeof(buffer));
syslog_backend::BeginRecord(&buffer, syslog::LOG_WARNING, "foo.cc", 42, "fake tag", "condition");
syslog_backend::EndRecord(&buffer);
auto header = syslog_backend::MsgHeader::CreatePtr(&buffer);
// Ensure that null termination only happens once
header->c_str();
header->c_str();
header->WriteString("something after the null terminator");
ASSERT_TRUE(std::string(header->c_str()).find("fake tag") != std::string::npos);
ASSERT_TRUE(std::string(header->c_str()).find("something after the null terminator") ==
std::string::npos);
}
} // namespace syslog