#include #include #include #include #include #include SCENARIO("Flat Map initialization and construction", "[flat_map]") { GIVEN("An empty context") { WHEN("constructing by default") { auto map = kstd::flat_map{}; THEN("the Flat Map does not contain elements") { REQUIRE_FALSE(map.contains(1)); } } } } SCENARIO("Flat Map modifiers", "[flat_map]") { GIVEN("An empty Flat Map") { auto map = kstd::flat_map{}; WHEN("emplacing a new element") { auto [it, inserted] = map.emplace(1, 100); THEN("the map contains the new element") { REQUIRE(inserted); REQUIRE(map.contains(1)); } } WHEN("emplacing an existing element") { map.emplace(1, 100); auto [it, inserted] = map.emplace(1, 200); THEN("the map does not insert the duplicate") { REQUIRE_FALSE(inserted); REQUIRE(map.contains(1)); } } } } SCENARIO("Flat Map element access", "[flat_map]") { GIVEN("A populated Flat Map") { auto map = kstd::flat_map{}; map.emplace(1, 10); map.emplace(2, 20); map.emplace(3, 30); WHEN("accessing an existing element with at()") { auto & val = map.at(2); THEN("it returns a reference to the mapped value") { REQUIRE(val == 20); } THEN("the mapped value can be modified") { val = 200; REQUIRE(map.at(2) == 200); } } WHEN("accessing a non-existent element with at()") { THEN("it panics") { REQUIRE_THROWS_AS(map.at(4), kstd::tests::os_panic); } } } GIVEN("A const populated Flat Map") { auto map_builder = kstd::flat_map{}; map_builder.emplace(1, 10); map_builder.emplace(2, 20); auto const map = map_builder; WHEN("accessing an existing element with const at()") { auto const & val = map.at(2); THEN("it returns a const reference to the mapped value") { REQUIRE(val == 20); } } WHEN("accessing a non-existent element with const at()") { THEN("it panics") { REQUIRE_THROWS_AS(map.at(4), kstd::tests::os_panic); } } } } SCENARIO("Flat Map iterators", "[flat_map]") { GIVEN("A populated Flat Map") { auto map = kstd::flat_map{}; map.emplace(1, 10); map.emplace(2, 20); map.emplace(3, 30); WHEN("using forward iterators") { THEN("they navigate the elements in the correct forward order") { auto it = map.begin(); REQUIRE(it != map.end()); REQUIRE((*it).first == 1); ++it; REQUIRE(it != map.end()); REQUIRE((*it).first == 2); ++it; REQUIRE(it != map.end()); REQUIRE((*it).first == 3); ++it; REQUIRE(it == map.end()); } THEN("const forward iterators provide correct access") { auto it = map.cbegin(); REQUIRE(it != map.cend()); REQUIRE((*it).first == 1); ++it; REQUIRE(it != map.cend()); REQUIRE((*it).first == 2); ++it; REQUIRE(it != map.cend()); REQUIRE((*it).first == 3); ++it; REQUIRE(it == map.cend()); } THEN("assignment through the proxy modifies the mapped value") { auto it = map.begin(); *it = std::pair{1, 100}; REQUIRE(it->second == 100); REQUIRE(map.at(1) == 100); } THEN("structured bindings evaluate correctly") { auto it = map.cbegin(); auto [key, value] = *it; REQUIRE(key == 1); REQUIRE(value == 10); STATIC_REQUIRE(std::is_same_v); STATIC_REQUIRE(std::is_same_v); } } WHEN("using reverse iterators") { THEN("they navigate the elements in the correct reverse order") { auto it = map.rbegin(); REQUIRE(it != map.rend()); REQUIRE((*it).first == 3); ++it; REQUIRE(it != map.rend()); REQUIRE((*it).first == 2); ++it; REQUIRE(it != map.rend()); REQUIRE((*it).first == 1); ++it; REQUIRE(it == map.rend()); } THEN("const reverse iterators provide correct access") { auto it = map.crbegin(); REQUIRE(it != map.crend()); REQUIRE((*it).first == 3); ++it; REQUIRE(it != map.crend()); REQUIRE((*it).first == 2); ++it; REQUIRE(it != map.crend()); REQUIRE((*it).first == 1); ++it; REQUIRE(it == map.crend()); } } } GIVEN("an empty Flat Map") { auto map = kstd::flat_map{}; WHEN("getting iterators") { THEN("begin() equals end() and cbegin() equals cend()") { REQUIRE(map.begin() == map.end()); REQUIRE(map.cbegin() == map.cend()); } THEN("rbegin() equals rend() and crbegin() equals crend()") { REQUIRE(map.rbegin() == map.rend()); REQUIRE(map.crbegin() == map.crend()); } } } } SCENARIO("Flat Map heterogeneous element access", "[flat_map]") { GIVEN("A populated Flat Map with a transparent comparator") { auto map = kstd::flat_map>{}; map.emplace(1, 10); map.emplace(2, 20); map.emplace(3, 30); WHEN("accessing an existing element with a different key type via at()") { long const key = 2L; auto & val = map.at(key); THEN("it returns a reference to the mapped value") { REQUIRE(val == 20); } THEN("the mapped value can be modified") { val = 200; REQUIRE(map.at(2L) == 200); } } WHEN("accessing a non-existent element with a different key type via at()") { long const key = 4L; THEN("it panics") { REQUIRE_THROWS_AS(map.at(key), kstd::tests::os_panic); } } } GIVEN("A const populated Flat Map with a transparent comparator") { auto map_builder = kstd::flat_map>{}; map_builder.emplace(1, 10); map_builder.emplace(2, 20); auto const map = map_builder; WHEN("accessing an existing element with a different key type via const at()") { long const key = 2L; auto const & val = map.at(key); THEN("it returns a const reference to the mapped value") { REQUIRE(val == 20); } } WHEN("accessing a non-existent element with a different key type via const at()") { long const key = 4L; THEN("it panics") { REQUIRE_THROWS_AS(map.at(key), kstd::tests::os_panic); } } } }