blob: f53d5a7d6de7584663b102947429b54014e0f208 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/debuglog.h>
#include <lib/unittest/unittest.h>
#include <ktl/unique_ptr.h>
#include "debuglog_internal.h"
namespace {
bool log_format() {
BEGIN_TEST;
fbl::AllocChecker ac;
ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
ASSERT_TRUE(ac.check(), "");
char msg[] = "Hello World";
log->write(DEBUGLOG_WARNING, 0, msg, sizeof(msg));
dlog_header* header = reinterpret_cast<dlog_header*>(log->data);
EXPECT_EQ(DEBUGLOG_WARNING, header->severity);
EXPECT_EQ(0, header->flags);
EXPECT_EQ(0u, header->pid);
EXPECT_EQ(0u, header->tid);
ASSERT_EQ(12, header->datalen);
uint8_t* msg_bytes = log->data + sizeof(dlog_header);
EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[0]), msg_bytes, sizeof(msg));
END_TEST;
}
bool log_wrap() {
BEGIN_TEST;
fbl::AllocChecker ac;
ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
ASSERT_TRUE(ac.check(), "");
char msg[] = "Hello World";
const size_t kTruncateTarget = 5; // An unaligned length somewhere in the middle of msg.
const size_t pad = ALIGN4_TRUNC(DLOG_SIZE - sizeof(dlog_header) - kTruncateTarget);
// We need to trigger some writes, but we don't care what we write, so we just need a buffer large
// enough to be copied from. Doesn't much matter what's in it.
char dummy[DLOG_MAX_DATA]{0};
for (size_t to_write = pad; to_write;) {
size_t write = to_write - sizeof(dlog_header);
write = write > DLOG_MAX_DATA ? DLOG_MAX_DATA : write;
log->write(DEBUGLOG_WARNING, 0, dummy, write);
to_write -= write + sizeof(dlog_header);
}
EXPECT_EQ(pad, log->head);
log->write(DEBUGLOG_WARNING, 0, msg, sizeof(msg));
dlog_header* header = reinterpret_cast<dlog_header*>(log->data + pad);
EXPECT_EQ(DEBUGLOG_WARNING, header->severity);
EXPECT_EQ(0, header->flags);
EXPECT_EQ(0u, header->pid);
EXPECT_EQ(0u, header->tid);
ASSERT_EQ(sizeof(msg), header->datalen);
uint8_t* msg_bytes = log->data + pad + sizeof(dlog_header);
const size_t kTruncatedSize = DLOG_SIZE - pad - sizeof(dlog_header);
EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[0]), msg_bytes, kTruncatedSize);
EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[8]), log->data, sizeof(msg) - kTruncatedSize);
END_TEST;
}
bool log_reader_rollout() {
BEGIN_TEST;
fbl::AllocChecker ac;
ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
ASSERT_TRUE(ac.check(), "");
DlogReader reader;
reader.InitializeForTest(log.get());
char msg[] = "Hello World";
log->write(DEBUGLOG_WARNING, 0, msg, sizeof(msg));
uint8_t read_buf[DLOG_MAX_RECORD];
size_t got;
ASSERT_EQ(ZX_OK, reader.Read(0, read_buf, sizeof(read_buf), &got));
ASSERT_EQ(sizeof(dlog_header) + sizeof(msg), got);
dlog_header* header = reinterpret_cast<dlog_header*>(read_buf);
EXPECT_EQ(DEBUGLOG_WARNING, header->severity);
// Header should be zeroed out.
EXPECT_EQ(0u, header->header);
EXPECT_EQ(0, header->flags);
EXPECT_EQ(0u, header->pid);
EXPECT_EQ(0u, header->tid);
ASSERT_EQ(sizeof(msg), header->datalen);
uint8_t* msg_bytes = &read_buf[sizeof(dlog_header)];
EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[0]), msg_bytes, sizeof(msg));
for (size_t i = 0; i < DLOG_SIZE; i += sizeof(dlog_header) + sizeof(msg)) {
log->write(DEBUGLOG_WARNING, 0, msg, sizeof(msg));
}
ASSERT_EQ(ZX_OK, reader.Read(0, read_buf, sizeof(read_buf), &got));
ASSERT_EQ(sizeof(dlog_header) + sizeof(msg), got);
header = reinterpret_cast<dlog_header*>(read_buf);
EXPECT_EQ(DEBUGLOG_WARNING, header->severity);
// The amount of data rolled out should be snuck in here.
EXPECT_EQ(sizeof(dlog_header) + sizeof(msg), header->header);
EXPECT_EQ(0, header->flags);
EXPECT_EQ(0u, header->pid);
EXPECT_EQ(0u, header->tid);
ASSERT_EQ(sizeof(msg), header->datalen);
msg_bytes = &read_buf[sizeof(dlog_header)];
EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[0]), msg_bytes, sizeof(msg));
reader.Disconnect();
END_TEST;
}
} // namespace
#define DEBUGLOG_UNITTEST(fname) UNITTEST(#fname, fname)
UNITTEST_START_TESTCASE(debuglog_tests)
DEBUGLOG_UNITTEST(log_format)
DEBUGLOG_UNITTEST(log_wrap)
DEBUGLOG_UNITTEST(log_reader_rollout)
UNITTEST_END_TESTCASE(debuglog_tests, "debuglog_tests", "Debuglog test")