blob: bf11ecee8ce9a8416f7807ff847027adecf603f8 [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 "console.h"
#include <lib/sync/completion.h>
#include <lib/syslog/logger.h>
#include <fbl/string_buffer.h>
#include <zxtest/zxtest.h>
namespace {
// Verify that calling Read() returns data from the RxSource
TEST(ConsoleTestCase, Read) {
constexpr size_t kReadSize = 10;
constexpr size_t kWriteCount = kReadSize - 1;
constexpr uint8_t kWrittenByte = 3;
sync_completion_t rx_source_done;
Console::RxSource rx_source = [write_count = kWriteCount,
&rx_source_done](uint8_t* byte) mutable {
if (write_count == 0) {
sync_completion_signal(&rx_source_done);
return ZX_ERR_SHOULD_WAIT;
}
*byte = kWrittenByte;
write_count--;
return ZX_OK;
};
Console::TxSink tx_sink = [](const uint8_t* buffer, size_t length) { return ZX_OK; };
fbl::RefPtr<Console> console;
ASSERT_OK(Console::Create(std::move(rx_source), std::move(tx_sink), {}, &console));
ASSERT_OK(sync_completion_wait_deadline(&rx_source_done, ZX_TIME_INFINITE));
uint8_t data[kReadSize] = {};
size_t actual;
ASSERT_OK(console->Read(reinterpret_cast<void*>(data), kReadSize, &actual));
ASSERT_EQ(actual, kWriteCount);
for (size_t i = 0; i < actual; ++i) {
ASSERT_EQ(data[i], kWrittenByte);
}
}
// Verify that calling Write() writes data to the TxSink
TEST(ConsoleTestCase, Write) {
uint8_t kExpectedBuffer[] = u8"Hello World";
size_t kExpectedLength = sizeof(kExpectedBuffer) - 1;
// Cause the RX thread to exit
Console::RxSource rx_source = [](uint8_t* byte) { return ZX_ERR_NOT_SUPPORTED; };
Console::TxSink tx_sink = [kExpectedLength, &kExpectedBuffer](const uint8_t* buffer,
size_t length) {
EXPECT_EQ(length, kExpectedLength);
EXPECT_BYTES_EQ(buffer, kExpectedBuffer, length);
return ZX_OK;
};
fbl::RefPtr<Console> console;
ASSERT_OK(Console::Create(std::move(rx_source), std::move(tx_sink), {}, &console));
size_t actual;
ASSERT_OK(
console->Write(reinterpret_cast<const void*>(kExpectedBuffer), kExpectedLength, &actual));
ASSERT_EQ(actual, kExpectedLength);
}
// Verify that calling Log() writes data to the TxSink
TEST(ConsoleTestCase, Log) {
const char kExpectedBuffer[] = "[00004.321] 00001:00002> [tag] INFO: Hello World\n";
size_t kExpectedLength = sizeof(kExpectedBuffer) - 1;
fbl::StringBuffer<Console::kMaxWriteSize> actual;
// Cause the RX thread to exit
Console::RxSource rx_source = [](uint8_t* byte) { return ZX_ERR_NOT_SUPPORTED; };
Console::TxSink tx_sink = [&actual](const uint8_t* buffer, size_t length) {
actual.Append(reinterpret_cast<const char*>(buffer), length);
return ZX_OK;
};
fbl::RefPtr<Console> console;
ASSERT_OK(Console::Create(std::move(rx_source), std::move(tx_sink), {}, &console));
fidl::StringView tag = "tag";
llcpp::fuchsia::logger::LogMessage log{
.pid = 1,
.tid = 2,
.time = 4321000000,
.severity = FX_LOG_INFO,
.tags = {fidl::unowned_ptr(&tag), 1},
.msg = {"Hello World"},
};
ASSERT_OK(console->Log(std::move(log)));
EXPECT_EQ(actual.size(), kExpectedLength);
EXPECT_STR_EQ(actual.c_str(), kExpectedBuffer);
}
// Verify that calling Log() does not write data to the TxSink if the tag is denied
TEST(ConsoleTestCase, LogDenyTag) {
fbl::StringBuffer<Console::kMaxWriteSize> actual;
// Cause the RX thread to exit
Console::RxSource rx_source = [](uint8_t* byte) { return ZX_ERR_NOT_SUPPORTED; };
Console::TxSink tx_sink = [](const uint8_t* buffer, size_t length) {
ADD_FAILURE("Unexpected write");
return ZX_OK;
};
fbl::RefPtr<Console> console;
ASSERT_OK(Console::Create(std::move(rx_source), std::move(tx_sink), {"deny-tag"}, &console));
fidl::StringView tag = "deny-tag";
llcpp::fuchsia::logger::LogMessage log{
.pid = 1,
.tid = 2,
.time = 4321000000,
.severity = FX_LOG_INFO,
.tags = {fidl::unowned_ptr(&tag), 1},
.msg = {"Goodbye World"},
};
ASSERT_OK(console->Log(std::move(log)));
}
} // namespace