blob: f97531f7f760ec9cc7c21a353f5d5bc26b9fb162 [file] [log] [blame] [edit]
// 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/driver-unit-test/logger.h>
#include <lib/fidl/coding.h>
#include <lib/zx/channel.h>
#include <zircon/syscalls.h>
#include <memory>
#include <zxtest/zxtest.h>
namespace {
constexpr size_t kMaxFidlMsgSize = 8096;
constexpr char kLogMessage[] = "test log message";
const char* kFakeTestCaseName = "test_case";
const zxtest::TestCase kFakeTestCase = zxtest::TestCase{
kFakeTestCaseName, zxtest::Test::SetUpTestCase, zxtest::Test::TearDownTestCase};
const zxtest::TestInfo kFakeTestInfo = zxtest::TestInfo("test", zxtest::SourceLocation{}, nullptr);
class LoggerTest : public zxtest::Test {
protected:
void SetUp() override {
zx::channel remote;
ASSERT_OK(zx::channel::create(0, &local_, &remote));
ASSERT_EQ(ZX_OK, driver_unit_test::Logger::CreateInstance(std::move(remote)));
logger_ = driver_unit_test::Logger::GetInstance();
ASSERT_NOT_NULL(logger_);
}
void TearDown() override {
driver_unit_test::Logger::DeleteInstance();
ASSERT_NULL(driver_unit_test::Logger::GetInstance());
}
zx::channel local_;
driver_unit_test::Logger* logger_;
};
TEST_F(LoggerTest, CreateWithInvalidChannel) {
driver_unit_test::Logger::DeleteInstance();
ASSERT_NULL(driver_unit_test::Logger::GetInstance());
zx::channel invalid;
ASSERT_NE(ZX_OK, driver_unit_test::Logger::CreateInstance(std::move(invalid)));
ASSERT_NULL(driver_unit_test::Logger::GetInstance());
ASSERT_NE(ZX_OK, driver_unit_test::Logger::SendLogMessage(kLogMessage));
}
// Waits for a FIDL message on the channel and populates |out_data| with a pointer to the
// decoded data.
void DecodeMessage(const zx::channel& channel, uint64_t want_ordinal, const fidl_type_t* want_type,
std::unique_ptr<uint8_t[]>* out_data, uint32_t* out_data_size) {
// Verify we receive the expected signal on the channel.
zx_signals_t pending;
const zx_signals_t wait = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
auto deadline = zx::deadline_after(zx::sec(5));
ASSERT_OK(channel.wait_one(wait, deadline, &pending));
ASSERT_TRUE(pending & ZX_CHANNEL_READABLE);
// Create the data buffer and copy the data into it.
const uint32_t buf_size = kMaxFidlMsgSize;
std::unique_ptr<uint8_t[]> buf(new uint8_t[buf_size]);
fidl_incoming_msg_t fidl_msg = {
.bytes = buf.get(),
.handles = nullptr,
.num_bytes = buf_size,
.num_handles = 0,
};
ASSERT_OK(channel.read(0, buf.get(), nullptr /* handles */, buf_size, 0 /* num_handles */,
&fidl_msg.num_bytes, nullptr));
ASSERT_GE(fidl_msg.num_bytes, sizeof(fidl_message_header_t));
// Decode the message in-place.
auto* hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
ASSERT_EQ(want_ordinal, hdr->ordinal);
ASSERT_OK(fidl_decode_msg(want_type, &fidl_msg, nullptr));
*out_data = std::move(buf);
*out_data_size = fidl_msg.num_bytes;
}
TEST_F(LoggerTest, LogMessage) {
ASSERT_OK(driver_unit_test::Logger::SendLogMessage(kLogMessage));
std::unique_ptr<uint8_t[]> data_buf;
uint32_t data_size;
ASSERT_NO_FATAL_FAILURES(
DecodeMessage(local_, fuchsia_driver_test_LoggerLogMessageOrdinal,
&fuchsia_driver_test_LoggerLogMessageRequestTable, &data_buf, &data_size),
"could not decode message");
ASSERT_GE(data_size, sizeof(fuchsia_driver_test_LoggerLogMessageRequest));
auto request = reinterpret_cast<fuchsia_driver_test_LoggerLogMessageRequest*>(data_buf.get());
ASSERT_EQ(strlen(kLogMessage), request->msg.size);
ASSERT_EQ(0, strncmp(kLogMessage, request->msg.data, request->msg.size));
}
// Read and decode the FIDL message from the channel and check that it equals the wanted result.
void ValidateReceivedTestCase(const zx::channel& log_ch,
const fuchsia_driver_test_TestCaseResult& want) {
std::unique_ptr<uint8_t[]> data_buf;
uint32_t data_size;
ASSERT_NO_FATAL_FAILURES(
DecodeMessage(log_ch, fuchsia_driver_test_LoggerLogTestCaseOrdinal,
&fuchsia_driver_test_LoggerLogTestCaseRequestTable, &data_buf, &data_size),
"could not decode message");
ASSERT_GE(data_size, sizeof(fuchsia_driver_test_LoggerLogTestCaseRequest));
auto request = reinterpret_cast<fuchsia_driver_test_LoggerLogTestCaseRequest*>(data_buf.get());
ASSERT_EQ(strlen(kFakeTestCaseName), request->name.size);
ASSERT_EQ(0, strncmp(kFakeTestCaseName, request->name.data, request->name.size));
auto got = request->result;
ASSERT_EQ(want.passed, got.passed);
ASSERT_EQ(want.failed, got.failed);
ASSERT_EQ(want.skipped, got.skipped);
}
TEST_F(LoggerTest, LogEmptyTestCase) {
logger_->OnTestCaseStart(kFakeTestCase);
logger_->OnTestCaseEnd(kFakeTestCase);
auto want_result = fuchsia_driver_test_TestCaseResult{};
ASSERT_NO_FATAL_FAILURES(ValidateReceivedTestCase(local_, want_result));
}
TEST_F(LoggerTest, LogSingleTest) {
logger_->OnTestCaseStart(kFakeTestCase);
logger_->OnTestSuccess(kFakeTestCase, kFakeTestInfo);
logger_->OnTestCaseEnd(kFakeTestCase);
auto want_result = fuchsia_driver_test_TestCaseResult{};
want_result.passed = 1;
ASSERT_NO_FATAL_FAILURES(ValidateReceivedTestCase(local_, want_result));
}
TEST_F(LoggerTest, LogMultipleTest) {
logger_->OnTestCaseStart(kFakeTestCase);
logger_->OnTestFailure(kFakeTestCase, kFakeTestInfo);
logger_->OnTestFailure(kFakeTestCase, kFakeTestInfo);
logger_->OnTestSuccess(kFakeTestCase, kFakeTestInfo);
logger_->OnTestSkip(kFakeTestCase, kFakeTestInfo);
logger_->OnTestSuccess(kFakeTestCase, kFakeTestInfo);
logger_->OnTestSuccess(kFakeTestCase, kFakeTestInfo);
logger_->OnTestCaseEnd(kFakeTestCase);
auto want_result = fuchsia_driver_test_TestCaseResult{};
want_result.passed = 3;
want_result.failed = 2;
want_result.skipped = 1;
ASSERT_NO_FATAL_FAILURES(ValidateReceivedTestCase(local_, want_result));
}
} // anonymous namespace