blob: 2d60e3cd926914758b1ab0c3195ccf5b2bdb54c5 [file] [log] [blame] [edit]
// Copyright 2025 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 "src/graphics/display/lib/api-protocols/cpp/inplace-vector.h"
#include <zircon/assert.h>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace display::internal {
namespace {
TEST(InplaceVectorTest, InitializerListConstructor) {
const InplaceVector<int, 10> vector = {40, 41, 42, 43};
EXPECT_THAT(vector, ::testing::ElementsAre(40, 41, 42, 43));
}
TEST(InplaceVectorTest, EmplaceBack) {
InplaceVector<int, 10> vector;
int& emplace_back0_result = vector.emplace_back(40);
int& emplace_back1_result = vector.emplace_back(41);
int& emplace_back2_result = vector.emplace_back(42);
int& emplace_back3_result = vector.emplace_back(43);
EXPECT_EQ(&emplace_back0_result, vector.data());
EXPECT_EQ(&emplace_back1_result, vector.data() + 1);
EXPECT_EQ(&emplace_back2_result, vector.data() + 2);
EXPECT_EQ(&emplace_back3_result, vector.data() + 3);
EXPECT_THAT(vector, ::testing::ElementsAre(40, 41, 42, 43));
}
TEST(InplaceVectorTest, EmptyConst) {
const InplaceVector<int, 10> empty_vector;
EXPECT_EQ(empty_vector.empty(), true);
EXPECT_EQ(empty_vector.size(), 0u);
}
TEST(InplaceVectorTest, Empty) {
InplaceVector<int, 10> empty_vector;
EXPECT_EQ(empty_vector.empty(), true);
EXPECT_EQ(empty_vector.size(), 0u);
}
TEST(InplaceVectorTest, CapacityMethodsConst) {
const InplaceVector<int, 10> vector = {40, 41, 42, 43, 44, 45};
EXPECT_EQ(vector.empty(), false);
EXPECT_EQ(vector.size(), 6u);
EXPECT_EQ(vector.max_size(), 10u);
EXPECT_EQ(vector.capacity(), 10u);
}
TEST(InplaceVectorTest, CapacityMethods) {
InplaceVector<int, 10> vector = {40, 41, 42, 43, 44, 45};
EXPECT_EQ(vector.empty(), false);
EXPECT_EQ(vector.size(), 6u);
EXPECT_EQ(vector.max_size(), 10u);
EXPECT_EQ(vector.capacity(), 10u);
}
TEST(InplaceVectorTest, ElementAccessMethodsConst) {
const InplaceVector<int, 10> vector = {40, 41, 42, 43, 44, 45};
EXPECT_EQ(*vector.data(), 40);
// NOLINTNEXTLINE(readability-container-data-pointer): Need to test [0].
EXPECT_EQ(&vector[0], vector.data());
EXPECT_EQ(&vector[1], vector.data() + 1);
EXPECT_EQ(&vector[2], vector.data() + 2);
EXPECT_EQ(&vector.front(), vector.data());
EXPECT_EQ(&vector.back(), vector.data() + 5);
}
TEST(InplaceVectorTest, Data) {
InplaceVector<int, 10> vector = {40, 41, 42, 43, 44, 45};
*vector.data() = 80;
EXPECT_THAT(vector, ::testing::ElementsAre(80, 41, 42, 43, 44, 45));
}
TEST(InplaceVectorTest, ArrayOperator) {
InplaceVector<int, 10> vector = {40, 41, 42, 43, 44};
++vector[0];
EXPECT_THAT(vector, ::testing::ElementsAre(41, 41, 42, 43, 44));
vector[1] += 1000;
EXPECT_THAT(vector, ::testing::ElementsAre(41, 1041, 42, 43, 44));
vector[2] += 2000;
EXPECT_THAT(vector, ::testing::ElementsAre(41, 1041, 2042, 43, 44));
}
TEST(InplaceVectorTest, Front) {
InplaceVector<int, 10> vector = {40, 41, 42, 43, 44};
EXPECT_EQ(&vector.front(), vector.data());
vector.front() += 1000;
EXPECT_THAT(vector, ::testing::ElementsAre(1040, 41, 42, 43, 44));
}
TEST(InplaceVectorTest, Back) {
InplaceVector<int, 10> vector = {40, 41, 42, 43, 44};
EXPECT_EQ(&vector.back(), vector.data() + 4);
vector.back() += 1000;
EXPECT_THAT(vector, ::testing::ElementsAre(40, 41, 42, 43, 1044));
}
TEST(InplaceVectorTest, RangeForLoopConst) {
const InplaceVector<int, 10> vector = {40, 41, 42, 43};
std::vector<int> iterated_values;
for (const int& value : vector) {
iterated_values.push_back(value);
}
EXPECT_THAT(iterated_values, ::testing::ElementsAre(40, 41, 42, 43));
}
TEST(InplaceVectorTest, IteratorMethodsConst) {
const InplaceVector<int, 10> vector = {40, 41, 42, 43, 44};
EXPECT_EQ(&(*vector.begin()), vector.data());
EXPECT_EQ(&(*(++vector.begin())), vector.data() + 1);
EXPECT_EQ(&(*(++(++vector.begin()))), vector.data() + 2);
EXPECT_EQ(vector.end(), vector.begin() + 5);
EXPECT_EQ(vector.cbegin(), vector.begin());
EXPECT_EQ(vector.cend(), vector.end());
EXPECT_EQ(&(*vector.rbegin()), vector.data() + 4);
EXPECT_EQ(&(*(++vector.rbegin())), vector.data() + 3);
EXPECT_EQ(&(*(++(++vector.rbegin()))), vector.data() + 2);
EXPECT_EQ(vector.rend(), vector.rbegin() + 5);
EXPECT_EQ(vector.crbegin(), vector.rbegin());
EXPECT_EQ(vector.crend(), vector.rend());
}
TEST(InplaceVectorTest, RangeForLoop) {
InplaceVector<int, 10> vector = {40, 41, 42, 43};
for (int& value : vector) {
value += 1000;
}
EXPECT_THAT(vector, ::testing::ElementsAre(1040, 1041, 1042, 1043));
}
TEST(InplaceVectorTest, IteratorMethods) {
InplaceVector<int, 10> vector = {40, 41, 42, 43, 44};
EXPECT_EQ(&(*vector.begin()), vector.data());
EXPECT_EQ(&(*(++vector.begin())), vector.data() + 1);
EXPECT_EQ(&(*(++(++vector.begin()))), vector.data() + 2);
EXPECT_EQ(vector.end(), vector.begin() + 5);
EXPECT_EQ(&(*vector.rbegin()), vector.data() + 4);
EXPECT_EQ(&(*(++vector.rbegin())), vector.data() + 3);
EXPECT_EQ(&(*(++(++vector.rbegin()))), vector.data() + 2);
EXPECT_EQ(vector.rend(), vector.rbegin() + 5);
}
class DestructionLogger {
public:
explicit DestructionLogger(int id, std::vector<int>* destruction_log)
: id_(id), destruction_log_(*destruction_log) {
ZX_DEBUG_ASSERT(destruction_log != nullptr);
}
DestructionLogger(const DestructionLogger&) = delete;
DestructionLogger& operator=(const DestructionLogger&) = delete;
~DestructionLogger() { destruction_log_.push_back(id_); }
private:
const int id_;
std::vector<int>& destruction_log_;
};
TEST(InplaceVectorTest, DestructorOnlyCalledOnUsedElements) {
std::vector<int> destruction_log;
{
InplaceVector<DestructionLogger, 10> vector;
vector.emplace_back(1, &destruction_log);
vector.emplace_back(2, &destruction_log);
vector.emplace_back(3, &destruction_log);
}
EXPECT_THAT(destruction_log, ::testing::ElementsAre(1, 2, 3));
}
struct NoMove {
explicit constexpr NoMove(int id) : id(id) {}
NoMove(const NoMove&) = default;
NoMove& operator=(const NoMove&) = default;
NoMove(NoMove&&) = delete;
NoMove& operator=(NoMove&&) = delete;
int id;
};
constexpr bool operator==(const NoMove& lhs, const NoMove& rhs) { return lhs.id == rhs.id; }
TEST(InplaceVectorTest, PushBackCopy) {
InplaceVector<NoMove, 10> vector;
constexpr NoMove element1(1), element2(2), element3(3);
vector.push_back(element1);
vector.push_back(element2);
vector.push_back(element3);
EXPECT_THAT(vector, ::testing::ElementsAre(element1, element2, element3));
}
struct MoveOnly {
explicit constexpr MoveOnly(int id) : id(id) {}
MoveOnly(const MoveOnly&) = delete;
MoveOnly& operator=(const MoveOnly&) = delete;
MoveOnly(MoveOnly&& rhs) : id(rhs.id) { rhs.id = 0; }
MoveOnly& operator=(MoveOnly&& rhs) {
id = rhs.id;
rhs.id = 0;
return *this;
}
int id;
};
TEST(InplaceVectorTest, PushBackMove) {
InplaceVector<MoveOnly, 10> vector;
MoveOnly element1(1), element2(2), element3(3);
vector.push_back(std::move(element1));
vector.push_back(std::move(element2));
vector.push_back(std::move(element3));
EXPECT_EQ(vector[0].id, 1);
EXPECT_EQ(vector[1].id, 2);
EXPECT_EQ(vector[2].id, 3);
EXPECT_EQ(element1.id, 0);
EXPECT_EQ(element2.id, 0);
EXPECT_EQ(element3.id, 0);
}
TEST(InplaceVectorTest, Clear) {
std::vector<int> destruction_log;
{
InplaceVector<DestructionLogger, 10> vector;
vector.emplace_back(1, &destruction_log);
vector.emplace_back(2, &destruction_log);
vector.emplace_back(3, &destruction_log);
vector.clear();
EXPECT_THAT(vector, ::testing::IsEmpty());
EXPECT_THAT(destruction_log, ::testing::ElementsAre(1, 2, 3));
destruction_log.clear();
}
EXPECT_THAT(destruction_log, ::testing::IsEmpty());
}
} // namespace
} // namespace display::internal