blob: 12bdc599ada71c1dae8bc7cb83e0f0c70721bbdd [file] [log] [blame]
// Copyright 2020 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.
#ifndef SRC_LIB_ZBITL_TESTS_VMO_TESTS_H_
#define SRC_LIB_ZBITL_TESTS_VMO_TESTS_H_
#include <lib/zbitl/vmo.h>
#include <memory>
#include <string>
#include <fbl/unique_fd.h>
#include <gtest/gtest.h>
// All VMO-related test traits create extensible VMOs by default,
// parameterizing all of the creation APIs with a boolean `Resizable` template
// parameter that defaults to true. Each set of traits gives
// `kExpectExtensibility = true` to account for this default behaviour in the
// general, traits-abstracted testing; more dedicated testing with
// `Resizable = false` is given in vmo-tests.cc.
struct VmoTestTraits {
using storage_type = zx::vmo;
using payload_type = uint64_t;
using creation_traits = VmoTestTraits;
static constexpr bool kDefaultConstructedViewHasStorageError = true;
static constexpr bool kExpectExtensibility = true; // See note at the top.
static constexpr bool kExpectOneShotReads = false;
static constexpr bool kExpectUnbufferedReads = true;
static constexpr bool kExpectUnbufferedWrites = false;
struct Context {
storage_type TakeStorage() { return std::move(storage_); }
storage_type storage_;
};
template <bool Resizable = true>
static void Create(size_t size, Context* context) {
zx::vmo vmo;
ASSERT_EQ(zx::vmo::create(size, Resizable ? ZX_VMO_RESIZABLE : 0u, &vmo), ZX_OK);
*context = {std::move(vmo)};
}
template <bool Resizable = true>
static void Create(fbl::unique_fd fd, size_t size, Context* context) {
ASSERT_TRUE(fd);
std::unique_ptr<std::byte[]> buff{new std::byte[size]};
EXPECT_EQ(static_cast<ssize_t>(size), read(fd.get(), buff.get(), size));
ASSERT_NO_FATAL_FAILURE(Create<Resizable>(size, context));
ASSERT_EQ(context->storage_.write(buff.get(), 0u, size), ZX_OK);
}
static void Read(const storage_type& storage, payload_type payload, size_t size,
std::string* contents) {
contents->resize(size);
ASSERT_EQ(ZX_OK, storage.read(contents->data(), payload, size));
}
static void Write(const storage_type& storage, uint32_t offset, const std::string& data) {
ASSERT_EQ(ZX_OK, storage.write(data.data(), offset, data.size()));
}
static void ToPayload(const storage_type& storage, uint32_t offset, payload_type& payload) {
payload = static_cast<payload_type>(offset);
}
static const zx::vmo& GetVmo(const storage_type& storage) { return storage; }
};
struct UnownedVmoTestTraits {
using storage_type = zx::unowned_vmo;
using payload_type = uint64_t;
using creation_traits = VmoTestTraits;
static constexpr bool kDefaultConstructedViewHasStorageError = true;
static constexpr bool kExpectExtensibility = true; // See note at the top.
static constexpr bool kExpectOneShotReads = false;
static constexpr bool kExpectUnbufferedReads = true;
static constexpr bool kExpectUnbufferedWrites = false;
struct Context {
storage_type TakeStorage() { return std::move(storage_); }
storage_type storage_;
zx::vmo keepalive_;
};
template <bool Resizable = true>
static void Create(size_t size, Context* context) {
typename VmoTestTraits::Context vmo_context;
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Create<Resizable>(size, &vmo_context));
context->storage_ = zx::unowned_vmo{vmo_context.storage_};
context->keepalive_ = std::move(vmo_context.storage_);
}
template <bool Resizable = true>
static void Create(fbl::unique_fd fd, size_t size, Context* context) {
typename VmoTestTraits::Context vmo_context;
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Create<Resizable>(std::move(fd), size, &vmo_context));
context->storage_ = zx::unowned_vmo{vmo_context.storage_};
context->keepalive_ = std::move(vmo_context.storage_);
}
static void Read(const storage_type& storage, payload_type payload, size_t size,
std::string* contents) {
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Read(*storage, payload, size, contents));
}
static void Write(const storage_type& storage, uint32_t offset, const std::string& data) {
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Write(*storage, offset, data));
}
static void ToPayload(const storage_type& storage, uint32_t offset, payload_type& payload) {
payload = static_cast<payload_type>(offset);
}
static const zx::vmo& GetVmo(const storage_type& storage) { return *storage; }
};
struct MapOwnedVmoTestTraits {
using storage_type = zbitl::MapOwnedVmo;
using payload_type = uint64_t;
using creation_traits = MapOwnedVmoTestTraits;
static constexpr bool kDefaultConstructedViewHasStorageError = true;
static constexpr bool kExpectExtensibility = true; // See note at the top.
static constexpr bool kExpectOneShotReads = true;
static constexpr bool kExpectUnbufferedReads = true;
static constexpr bool kExpectUnbufferedWrites = true;
struct Context {
storage_type TakeStorage() { return std::move(storage_); }
storage_type storage_;
};
template <bool Resizable = true>
static void Create(size_t size, Context* context) {
typename VmoTestTraits::Context vmo_context;
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Create<Resizable>(size, &vmo_context));
*context = {zbitl::MapOwnedVmo{std::move(vmo_context.storage_), /*writable=*/true}};
}
template <bool Resizable = true>
static void Create(fbl::unique_fd fd, size_t size, Context* context) {
typename VmoTestTraits::Context vmo_context;
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Create<Resizable>(std::move(fd), size, &vmo_context));
*context = {zbitl::MapOwnedVmo{vmo_context.TakeStorage(), /*writable=*/true}};
}
static void Read(const storage_type& storage, payload_type payload, size_t size,
std::string* contents) {
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Read(storage.vmo(), payload, size, contents));
}
static void Write(const storage_type& storage, uint32_t offset, const std::string& data) {
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Write(storage.vmo(), offset, data));
}
static void ToPayload(const storage_type& storage, uint32_t offset, payload_type& payload) {
payload = static_cast<payload_type>(offset);
}
static const zx::vmo& GetVmo(const storage_type& storage) { return storage.vmo(); }
};
struct MapUnownedVmoTestTraits {
using storage_type = zbitl::MapUnownedVmo;
using payload_type = uint64_t;
using creation_traits = MapOwnedVmoTestTraits;
static constexpr bool kDefaultConstructedViewHasStorageError = true;
static constexpr bool kExpectExtensibility = true; // See note at the top.
static constexpr bool kExpectOneShotReads = true;
static constexpr bool kExpectUnbufferedReads = true;
static constexpr bool kExpectUnbufferedWrites = true;
struct Context {
storage_type TakeStorage() { return std::move(storage_); }
storage_type storage_;
zx::vmo keepalive_;
};
template <bool Resizable = true>
static void Create(fbl::unique_fd fd, size_t size, Context* context) {
typename UnownedVmoTestTraits::Context unowned_vmo_context;
ASSERT_NO_FATAL_FAILURE(
UnownedVmoTestTraits::Create<Resizable>(std::move(fd), size, &unowned_vmo_context));
context->storage_ = zbitl::MapUnownedVmo{std::move(unowned_vmo_context.storage_),
/*writable=*/true};
context->keepalive_ = std::move(unowned_vmo_context.keepalive_);
}
template <bool Resizable = true>
static void Create(size_t size, Context* context) {
typename UnownedVmoTestTraits::Context unowned_vmo_context;
ASSERT_NO_FATAL_FAILURE(UnownedVmoTestTraits::Create<Resizable>(size, &unowned_vmo_context));
*context = {zbitl::MapUnownedVmo{std::move(unowned_vmo_context.storage_),
/*writable=*/true},
std::move(unowned_vmo_context.keepalive_)};
}
static void Read(const storage_type& storage, payload_type payload, size_t size,
std::string* contents) {
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Read(storage.vmo(), payload, size, contents));
}
static void Write(const storage_type& storage, uint32_t offset, const std::string& data) {
ASSERT_NO_FATAL_FAILURE(VmoTestTraits::Write(storage.vmo(), offset, data));
}
static void ToPayload(const storage_type& storage, uint32_t offset, payload_type& payload) {
payload = static_cast<payload_type>(offset);
}
static const zx::vmo& GetVmo(const storage_type& storage) { return storage.vmo(); }
};
#endif // SRC_LIB_ZBITL_TESTS_VMO_TESTS_H_