blob: 1c3b5f0f07b866cc60c14401cc715e668f81b50d [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 "usb/request-fidl.h"
#include <lib/fake-bti/bti.h>
#include <zxtest/zxtest.h>
namespace {
TEST(RequestFidlTest, EmptyRequestTest) {
fuchsia_hardware_usb_request::Request request;
usb::FidlRequest fidl_request(std::move(request));
}
TEST(RequestFidlTest, LengthTest) {
usb::FidlRequest fidl_request;
fidl_request.add_vmo_id(0, 16, 0).add_data({}, 16, 0);
EXPECT_EQ(fidl_request.length(), 32);
}
TEST(RequestFidlTest, UnpinTest) {
zx::vmo vmo;
ASSERT_OK(zx::vmo::create(16, 0, &vmo));
fuchsia_hardware_usb_request::Request request;
request.data()
.emplace()
.emplace_back()
.buffer(fuchsia_hardware_usb_request::Buffer::WithVmoId(1))
.offset(0)
.size(32);
request.data()
->emplace_back()
.buffer(
fuchsia_hardware_usb_request::Buffer::WithData(std::vector<uint8_t>{0x0, 0x0, 0x0, 0x0}))
.offset(0)
.size(4);
usb::FidlRequest fidl_request(std::move(request));
zx::bti fake_bti;
ASSERT_OK(fake_bti_create(fake_bti.reset_and_get_address()));
EXPECT_OK(fidl_request.PhysMap(fake_bti));
size_t actual;
fake_bti_pinned_vmo_info_t info[1];
EXPECT_OK(fake_bti_get_pinned_vmos(fake_bti.get(), info, 1, &actual));
EXPECT_EQ(actual, 1);
void* mapped;
EXPECT_OK(zx::vmar::root_self()->map(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, zx::vmo(info[0].vmo),
0, info[0].size, reinterpret_cast<uintptr_t*>(&mapped)));
auto iter3 = fidl_request.phys_iter(1, zx_system_get_page_size());
EXPECT_EQ((*iter3.begin()).second, 4);
uint8_t expected_vals[] = {0xA, 0xB, 0xC, 0xC};
memcpy(mapped, expected_vals, sizeof(expected_vals));
EXPECT_OK(zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(mapped), info[0].size));
EXPECT_OK(fidl_request.Unpin());
EXPECT_OK(fake_bti_get_pinned_vmos(fake_bti.get(), nullptr, 0, &actual));
EXPECT_EQ(actual, 0);
EXPECT_BYTES_EQ((*fidl_request->data())[1].buffer()->data()->data(), expected_vals,
sizeof(expected_vals));
}
TEST(RequestFidlTest, VmoIdTest) {
fuchsia_hardware_usb_request::Request request;
request.data()
.emplace()
.emplace_back()
.buffer(fuchsia_hardware_usb_request::Buffer::WithVmoId(0))
.offset(0)
.size(16);
request.data()
->emplace_back()
.buffer(fuchsia_hardware_usb_request::Buffer::WithVmoId(1))
.offset(0)
.size(16);
request.data()
.emplace()
.emplace_back()
.buffer(fuchsia_hardware_usb_request::Buffer::WithVmoId(2))
.offset(0)
.size(16);
usb::FidlRequest fidl_request(std::move(request));
zx::bti fake_bti;
ASSERT_OK(fake_bti_create(fake_bti.reset_and_get_address()));
EXPECT_OK(fidl_request.PhysMap(fake_bti));
size_t actual;
EXPECT_OK(fake_bti_get_pinned_vmos(fake_bti.get(), nullptr, 0, &actual));
EXPECT_EQ(actual, 0);
}
TEST(RequestFidlTest, DataTest) {
fuchsia_hardware_usb_request::Request request;
uint8_t expected1[] = {0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8,
0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0};
request.data()
.emplace()
.emplace_back()
.buffer(fuchsia_hardware_usb_request::Buffer::WithData(
std::vector<uint8_t>(std::begin(expected1), std::end(expected1))))
.offset(0)
.size(16);
uint8_t expected2[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5,
0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
request.data()
->emplace_back()
.buffer(fuchsia_hardware_usb_request::Buffer::WithData(
std::vector<uint8_t>(std::begin(expected2), std::end(expected2))))
.offset(0)
.size(32);
usb::FidlRequest fidl_request(std::move(request));
zx::bti fake_bti;
ASSERT_OK(fake_bti_create(fake_bti.reset_and_get_address()));
EXPECT_OK(fidl_request.PhysMap(fake_bti));
size_t actual;
fake_bti_pinned_vmo_info_t info[2];
EXPECT_OK(fake_bti_get_pinned_vmos(fake_bti.get(), info, 2, &actual));
EXPECT_EQ(actual, 2);
void* mapped;
EXPECT_OK(zx::vmar::root_self()->map(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, zx::vmo(info[0].vmo),
0, info[0].size, reinterpret_cast<uintptr_t*>(&mapped)));
auto iter1 = fidl_request.phys_iter(0, zx_system_get_page_size());
EXPECT_BYTES_EQ(mapped, expected1, sizeof(expected1));
EXPECT_EQ((*iter1.begin()).second, 16);
EXPECT_OK(zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(mapped), info[0].size));
EXPECT_OK(zx::vmar::root_self()->map(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, zx::vmo(info[1].vmo),
0, info[1].size, reinterpret_cast<uintptr_t*>(&mapped)));
auto iter2 = fidl_request.phys_iter(1, zx_system_get_page_size());
EXPECT_BYTES_EQ(mapped, expected2, sizeof(expected2));
EXPECT_EQ((*iter2.begin()).second, 32);
EXPECT_OK(zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(mapped), info[1].size));
}
TEST(RequestFidlTest, MixedTest) {
std::vector<uint8_t> tmp(32);
usb::FidlRequest fidl_request;
fidl_request.add_vmo_id(3, 16, 0).add_vmo_id(7, 16, 0).add_data(std::move(tmp), 32, 0);
zx::bti fake_bti;
ASSERT_OK(fake_bti_create(fake_bti.reset_and_get_address()));
EXPECT_OK(fidl_request.PhysMap(fake_bti));
size_t actual;
EXPECT_OK(fake_bti_get_pinned_vmos(fake_bti.get(), nullptr, 0, &actual));
EXPECT_EQ(actual, 1);
auto iter = fidl_request.phys_iter(2, zx_system_get_page_size());
EXPECT_EQ((*iter.begin()).second, 32);
}
TEST(RequestFidlTest, PoolTest) {
usb::FidlRequestPool pool;
EXPECT_TRUE(pool.Empty());
pool.Add(usb::FidlRequest(usb::EndpointType::BULK));
EXPECT_TRUE(pool.Full());
usb::FidlRequest control(usb::EndpointType::CONTROL);
control.add_vmo_id(9, 2, 0).add_vmo_id(1, 4, 0);
pool.Add(std::move(control));
EXPECT_TRUE(pool.Full());
{
auto req = pool.Get();
EXPECT_TRUE(req.has_value());
EXPECT_FALSE(pool.Empty());
EXPECT_FALSE(pool.Full());
EXPECT_EQ(req->request().information()->Which(),
fuchsia_hardware_usb_request::RequestInfo::Tag::kBulk);
pool.Put(std::move(*req));
EXPECT_TRUE(pool.Full());
}
{
auto req = pool.Get();
EXPECT_TRUE(req.has_value());
EXPECT_FALSE(pool.Empty());
EXPECT_FALSE(pool.Full());
EXPECT_EQ(req->request().information()->Which(),
fuchsia_hardware_usb_request::RequestInfo::Tag::kControl);
EXPECT_EQ(req->request().data()->size(), 2);
EXPECT_EQ(req->request().data()->at(0).buffer()->vmo_id().value(), 9);
EXPECT_EQ(req->request().data()->at(0).size(), 2);
EXPECT_EQ(req->request().data()->at(0).offset(), 0);
EXPECT_EQ(req->request().data()->at(1).buffer()->vmo_id().value(), 1);
EXPECT_EQ(req->request().data()->at(1).size(), 4);
EXPECT_EQ(req->request().data()->at(1).offset(), 0);
}
{
auto req = pool.Remove();
EXPECT_TRUE(req.has_value());
EXPECT_TRUE(pool.Empty());
pool.Put(std::move(*req));
EXPECT_TRUE(pool.Full());
}
{
auto req = pool.Remove();
EXPECT_TRUE(req.has_value());
EXPECT_TRUE(pool.Empty());
}
{
auto req = pool.Remove();
EXPECT_FALSE(req.has_value());
}
// Make sure that we are able to destruct even with requests sitting in the pool.
pool.Add(usb::FidlRequest(usb::EndpointType::BULK));
EXPECT_TRUE(pool.Full());
}
} // namespace