blob: b8ad6cb9a91c6866418bb3e48d3b19f8bb12399c [file] [log] [blame]
// Copyright 2023 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/elfldltl/abi-span.h>
#include <lib/elfldltl/testing/typed-test.h>
#include <gtest/gtest.h>
namespace {
// First two default template arguments.
static_assert(std::is_same_v<elfldltl::AbiSpan<int>,
elfldltl::AbiSpan<int, cpp20::dynamic_extent, elfldltl::Elf<>>>);
FORMAT_TYPED_TEST_SUITE(ElfldltlAbiSpanTests);
template <class Span>
constexpr void BasicCtorAndAssignTests() {
static_assert(std::is_same_v<typename Span::element_type, typename Span::Ptr::value_type>);
static_assert(std::is_same_v<typename Span::size_type, typename Span::Ptr::size_type>);
static_assert(std::is_same_v<typename Span::Addr, typename Span::Ptr::Addr>);
[[maybe_unused]] constexpr Span default_ctor;
[[maybe_unused]] constexpr Span copy_ctor(default_ctor);
[[maybe_unused]] Span assign = default_ctor;
assign = default_ctor;
}
TYPED_TEST(ElfldltlAbiSpanTests, Basic) {
using Elf = typename TestFixture::Elf;
using LocalSpan =
elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf, elfldltl::LocalAbiTraits>;
using RemoteSpan =
elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf, elfldltl::RemoteAbiTraits>;
static_assert(
std::is_same_v<LocalSpan, elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf>>);
BasicCtorAndAssignTests<LocalSpan>();
LocalSpan local;
EXPECT_TRUE(local.empty());
EXPECT_EQ(local.size(), 0u);
EXPECT_EQ(local.size_bytes(), 0u);
EXPECT_TRUE(local.get().empty());
int var;
local = LocalSpan{cpp20::span{&var, 1}};
EXPECT_FALSE(local.empty());
EXPECT_EQ(local.size(), 1u);
EXPECT_EQ(local.size_bytes(), sizeof(int));
EXPECT_EQ(local.data(), &var);
auto direct = local.get();
static_assert(std::is_same_v<decltype(direct), cpp20::span<const int>>);
EXPECT_EQ(direct.data(), &var);
EXPECT_EQ(direct.size(), 1u);
local = LocalSpan{typename LocalSpan::Ptr{&var}, 1};
EXPECT_FALSE(local.empty());
EXPECT_EQ(local.size(), 1u);
EXPECT_EQ(local.size_bytes(), sizeof(int));
EXPECT_EQ(local.data(), &var);
local = LocalSpan{local};
EXPECT_FALSE(local.empty());
EXPECT_EQ(local.size(), 1u);
EXPECT_EQ(local.size_bytes(), sizeof(int));
EXPECT_EQ(local.data(), &var);
BasicCtorAndAssignTests<RemoteSpan>();
RemoteSpan remote;
EXPECT_TRUE(remote.empty());
EXPECT_FALSE(remote.ptr());
EXPECT_EQ(remote.size(), 0u);
EXPECT_EQ(remote.size_bytes(), 0u);
remote = RemoteSpan{RemoteSpan::Ptr::FromAddress(420), 1};
EXPECT_FALSE(remote.empty());
EXPECT_EQ(remote.size(), 1u);
EXPECT_EQ(remote.size_bytes(), sizeof(int));
remote = RemoteSpan{remote};
EXPECT_FALSE(remote.empty());
EXPECT_EQ(remote.size(), 1u);
EXPECT_EQ(remote.size_bytes(), sizeof(int));
}
template <class Span>
void TestSubspan() {
using value_type = typename Span::value_type;
const auto ptr = Span::Ptr::FromAddress(sizeof(value_type) * 1);
const Span five{ptr, 5};
const Span last_2 = five.subspan(3);
EXPECT_EQ(last_2.size(), 2u);
EXPECT_EQ(last_2.ptr(), ptr + 3);
const Span middle_3 = five.subspan(1, 3);
EXPECT_EQ(middle_3.size(), 3u);
EXPECT_EQ(middle_3.ptr(), ptr + 1);
const auto fixed_last_2 = five.template subspan<3>();
EXPECT_EQ(fixed_last_2.size(), 2u);
EXPECT_EQ(fixed_last_2.ptr(), ptr + 3);
const auto fixed_middle_3 = five.template subspan<1, 3>();
EXPECT_EQ(fixed_middle_3.size(), 3u);
EXPECT_EQ(fixed_middle_3.ptr(), ptr + 1);
const Span first_2 = five.first(2);
EXPECT_EQ(first_2.ptr(), five.ptr());
EXPECT_EQ(first_2.size(), 2u);
const Span last_1 = five.last(1);
EXPECT_EQ(last_1.ptr(), five.ptr() + 4);
EXPECT_EQ(last_1.size(), 1u);
const auto fixed_first_2 = five.template first<2>();
EXPECT_EQ(fixed_first_2.ptr(), five.ptr());
EXPECT_EQ(fixed_first_2.size(), 2u);
const auto fixed_last_1 = five.template last<1>();
EXPECT_EQ(fixed_last_1.ptr(), five.ptr() + 4);
EXPECT_EQ(fixed_last_1.size(), 1u);
}
TYPED_TEST(ElfldltlAbiSpanTests, SubSpan) {
using Elf = typename TestFixture::Elf;
using LocalSpan =
elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf, elfldltl::LocalAbiTraits>;
using RemoteSpan =
elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf, elfldltl::RemoteAbiTraits>;
TestSubspan<LocalSpan>();
TestSubspan<RemoteSpan>();
}
TYPED_TEST(ElfldltlAbiSpanTests, Iterators) {
using Elf = typename TestFixture::Elf;
using Span = elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf>;
constexpr int kInts[] = {1, 2, 3, 4, 5};
const cpp20::span direct{kInts};
const Span five{direct};
EXPECT_EQ(five.begin(), direct.begin());
EXPECT_EQ(five.end(), direct.end());
EXPECT_EQ(five.rbegin(), direct.rbegin());
EXPECT_EQ(five.rend(), direct.rend());
}
TYPED_TEST(ElfldltlAbiSpanTests, Access) {
using Elf = typename TestFixture::Elf;
using Span = elfldltl::AbiSpan<const int, cpp20::dynamic_extent, Elf>;
constexpr int kInts[] = {1, 2, 3, 4, 5};
const cpp20::span direct{kInts};
const Span five{direct};
EXPECT_EQ(&five.front(), &kInts[0]);
EXPECT_EQ(&five.back(), &kInts[4]);
EXPECT_EQ(&five[2], &kInts[2]);
EXPECT_EQ(five.data(), kInts);
}
TYPED_TEST(ElfldltlAbiSpanTests, StringView) {
using Elf = typename TestFixture::Elf;
using LocalStringView = elfldltl::AbiStringView<Elf, elfldltl::LocalAbiTraits>;
using RemoteStringView = elfldltl::AbiStringView<Elf, elfldltl::RemoteAbiTraits>;
LocalStringView local;
EXPECT_TRUE(local.empty());
EXPECT_EQ(local.size(), 0u);
EXPECT_EQ(local.length(), 0u);
std::string_view str = local;
str = local.get();
EXPECT_TRUE(str.empty());
EXPECT_EQ(str.data(), nullptr);
RemoteStringView remote;
EXPECT_TRUE(remote.empty());
EXPECT_EQ(remote.size(), 0u);
EXPECT_EQ(remote.length(), 0u);
constexpr std::string_view kFoobar = "foobar";
local = LocalStringView(kFoobar);
EXPECT_FALSE(local.empty());
EXPECT_EQ(local.size(), 6u);
EXPECT_EQ(local.length(), 6u);
EXPECT_EQ(local.data(), kFoobar.data());
EXPECT_EQ(local.get(), kFoobar);
}
} // namespace