#include "kstd/tests/os_panic.hpp"
#include <kstd/ranges>
#include <kstd/vector>
#include <catch2/catch_test_macros.hpp>
#include <array>
#include <cstddef>
#include <ranges>
#include <utility>
SCENARIO("Vector initialization and construction", "[vector]")
{
GIVEN("An empty context")
{
WHEN("constructing by default")
{
kstd::vector<int> v;
THEN("the vector is empty")
{
REQUIRE(v.empty());
}
THEN("the size and capacity are zero")
{
REQUIRE(v.size() == 0);
REQUIRE(v.capacity() == 0);
}
}
WHEN("constructing with a specific size")
{
kstd::vector<int> v(10);
THEN("the vector is not empty")
{
REQUIRE_FALSE(v.empty());
}
THEN("the size is and capacity match the specified value")
{
REQUIRE(v.size() == 10);
REQUIRE(v.capacity() == 10);
}
}
WHEN("constructing from an initializer list")
{
kstd::vector<int> v = {1, 2, 3, 4, 5};
THEN("the vector is not empty")
{
REQUIRE_FALSE(v.empty());
}
THEN("the size is and capacity match the specified value")
{
REQUIRE(v.size() == 5);
REQUIRE(v.capacity() == 5);
}
THEN("the elements are correctly initialized")
{
REQUIRE(v[0] == 1);
REQUIRE(v[1] == 2);
REQUIRE(v[2] == 3);
REQUIRE(v[3] == 4);
REQUIRE(v[4] == 5);
}
}
}
GIVEN("A non-empty range")
{
auto range = std::array<int, 3>{1, 2, 3};
WHEN("constructing from a random-access iterator range")
{
auto v = kstd::vector<int>{std::begin(range), std::end(range)};
THEN("the vector is not empty")
{
REQUIRE_FALSE(v.empty());
}
THEN("the size and capacity match the range size")
{
REQUIRE(v.size() == std::size(range));
REQUIRE(v.capacity() == std::size(range));
}
THEN("the elements are correctly initialized")
{
REQUIRE(v[0] == 1);
REQUIRE(v[1] == 2);
REQUIRE(v[2] == 3);
}
}
WHEN("constructing from a range")
{
auto v = kstd::vector<int>{kstd::from_range, range};
THEN("the vector is not empty")
{
REQUIRE_FALSE(v.empty());
}
THEN("the size and capacity match the range size")
{
REQUIRE(v.size() == std::ranges::size(range));
REQUIRE(v.capacity() == std::ranges::size(range));
}
THEN("the elements are correctly initialized")
{
REQUIRE(v[0] == 1);
REQUIRE(v[1] == 2);
REQUIRE(v[2] == 3);
}
}
}
GIVEN("A populated vector")
{
kstd::vector<int> source = {1, 2, 3, 4, 5};
WHEN("copy constructing a new vector")
{
kstd::vector<int> copy(source);
THEN("the copy matches the original")
{
REQUIRE(copy.size() == source.size());
REQUIRE(copy.capacity() == source.capacity());
REQUIRE(copy[0] == 1);
REQUIRE(copy[1] == 2);
REQUIRE(copy[2] == 3);
REQUIRE(copy[3] == 4);
REQUIRE(copy[4] == 5);
}
THEN("the original is left unchanged")
{
REQUIRE(source.size() == 5);
REQUIRE(source.capacity() == 5);
REQUIRE(source[0] == 1);
REQUIRE(source[1] == 2);
REQUIRE(source[2] == 3);
REQUIRE(source[3] == 4);
REQUIRE(source[4] == 5);
}
}
WHEN("move constructing a new vector")
{
kstd::vector<int> moved(std::move(source));
THEN("The new vector has the original elements")
{
REQUIRE(moved.size() == 5);
REQUIRE(moved.capacity() == 5);
REQUIRE(moved[0] == 1);
REQUIRE(moved[1] == 2);
REQUIRE(moved[2] == 3);
REQUIRE(moved[3] == 4);
REQUIRE(moved[4] == 5);
}
THEN("The original vector is left in a valid but unspecified state")
{
REQUIRE(source.empty());
REQUIRE(source.size() == 0);
REQUIRE(source.capacity() == 0);
}
}
}
}
SCENARIO("Vector element access", "[vector]")
{
GIVEN("A populated vector")
{
kstd::vector<int> v = {10, 20, 30};
WHEN("accessing elements for reading")
{
THEN("operator[] and at() return the correct elements")
{
REQUIRE(v[0] == 10);
REQUIRE(v[1] == 20);
REQUIRE(v[2] == 30);
REQUIRE(v.at(0