blob: 59be0b50918d3b0cb5edbd5d6039b1c8a2e0fb61 [file] [log] [blame]
// Copyright 2018 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 "garnet/bin/guest/vmm/device/test_with_device.h"
#include "garnet/bin/guest/vmm/device/virtio_queue_fake.h"
static constexpr char kVirtioConsoleUrl[] =
"fuchsia-pkg://fuchsia.com/virtio_console#meta/virtio_console.cmx";
static constexpr uint16_t kNumQueues = 2;
static constexpr uint16_t kQueueSize = 16;
class VirtioConsoleTest : public TestWithDevice {
protected:
VirtioConsoleTest()
: rx_queue_(phys_mem_, PAGE_SIZE * kNumQueues, kQueueSize),
tx_queue_(phys_mem_, rx_queue_.end(), kQueueSize) {}
void SetUp() override {
// Launch device process.
fuchsia::guest::device::StartInfo start_info;
zx_status_t status =
LaunchDevice(kVirtioConsoleUrl, tx_queue_.end(), &start_info);
ASSERT_EQ(ZX_OK, status);
// Setup console socket.
status = zx::socket::create(ZX_SOCKET_STREAM, &socket_, &remote_socket_);
ASSERT_EQ(ZX_OK, status);
// Start device execution.
services.ConnectToService(console_.NewRequest());
status = console_->Start(std::move(start_info), std::move(remote_socket_));
ASSERT_EQ(ZX_OK, status);
// Configure device queues.
VirtioQueueFake* queues[kNumQueues] = {&rx_queue_, &tx_queue_};
for (size_t i = 0; i < kNumQueues; i++) {
auto q = queues[i];
q->Configure(PAGE_SIZE * i, PAGE_SIZE);
status = console_->ConfigureQueue(i, q->size(), q->desc(), q->avail(),
q->used());
ASSERT_EQ(ZX_OK, status);
}
}
fuchsia::guest::device::VirtioConsoleSyncPtr console_;
VirtioQueueFake rx_queue_;
VirtioQueueFake tx_queue_;
zx::socket socket_;
zx::socket remote_socket_;
};
TEST_F(VirtioConsoleTest, Receive) {
void* data_1;
void* data_2;
zx_status_t status = DescriptorChainBuilder(rx_queue_)
.AppendWritableDescriptor(&data_1, 6)
.AppendWritableDescriptor(&data_2, 6)
.Build();
ASSERT_EQ(ZX_OK, status);
char input[] = "hello\0world";
size_t actual;
status = socket_.write(0, input, sizeof(input), &actual);
ASSERT_EQ(ZX_OK, status);
EXPECT_EQ(sizeof(input), actual);
status = console_->NotifyQueue(0);
ASSERT_EQ(ZX_OK, status);
status = WaitOnInterrupt();
ASSERT_EQ(ZX_OK, status);
EXPECT_STREQ("hello", static_cast<char*>(data_1));
EXPECT_STREQ("world", static_cast<char*>(data_2));
}
TEST_F(VirtioConsoleTest, Transmit) {
zx_status_t status =
DescriptorChainBuilder(tx_queue_)
.AppendReadableDescriptor("hello ", sizeof("hello ") - 1)
.AppendReadableDescriptor("world", sizeof("world"))
.Build();
ASSERT_EQ(ZX_OK, status);
status = console_->NotifyQueue(1);
ASSERT_EQ(ZX_OK, status);
status = WaitOnInterrupt();
ASSERT_EQ(ZX_OK, status);
char buf[16] = {};
size_t actual;
status = socket_.read(0, buf, sizeof(buf), &actual);
ASSERT_EQ(ZX_OK, status);
char output[] = "hello world";
EXPECT_EQ(sizeof(output), actual);
EXPECT_STREQ(output, buf);
}