00b86fbd00
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: OFF) (push) Failing after 5m37s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: ON) (push) Has been cancelled
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Has been cancelled
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Has been cancelled
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: OFF) (push) Has been cancelled
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: ON) (push) Has been cancelled
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Has been cancelled
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Has been cancelled
Bigfoot / Clang Format Checks (push) Has been cancelled
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Has been cancelled
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Has been cancelled
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: OFF) (push) Has been cancelled
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: ON) (push) Has been cancelled
538 lines
17 KiB
C++
538 lines
17 KiB
C++
/*********************************************************************
|
|
* \file SlotMap.cpp
|
|
*
|
|
* \author Romain BOULLARD
|
|
* \date May 2026
|
|
*********************************************************************/
|
|
#include <Utils/Containers/SlotMap.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
namespace Bigfoot
|
|
{
|
|
template<class VERSION_TYPE, class INDEX_TYPE>
|
|
struct SlotMapConfig
|
|
{
|
|
using Version = VERSION_TYPE;
|
|
using Index = INDEX_TYPE;
|
|
};
|
|
|
|
using SlotMapConfigs = ::testing::Types<SlotMapConfig<std::uint8_t, std::uint8_t>,
|
|
SlotMapConfig<std::uint8_t, std::uint16_t>,
|
|
SlotMapConfig<std::uint8_t, std::uint32_t>,
|
|
SlotMapConfig<std::uint16_t, std::uint8_t>,
|
|
SlotMapConfig<std::uint16_t, std::uint16_t>,
|
|
SlotMapConfig<std::uint16_t, std::uint32_t>,
|
|
SlotMapConfig<std::uint32_t, std::uint8_t>,
|
|
SlotMapConfig<std::uint32_t, std::uint16_t>,
|
|
SlotMapConfig<std::uint32_t, std::uint32_t>>;
|
|
|
|
struct SlotMapConfigNames
|
|
{
|
|
template<class T>
|
|
static std::string GetName(int)
|
|
{
|
|
return "VERSION" + std::to_string(sizeof(typename T::Version) * 8) + "_INDEX" +
|
|
std::to_string(sizeof(typename T::Index) * 8);
|
|
}
|
|
};
|
|
|
|
/****************************************************************************************/
|
|
|
|
template<class CONFIG>
|
|
class SlotKeyFixture: public ::testing::Test
|
|
{
|
|
protected:
|
|
using SlotMapVersion = typename CONFIG::Version;
|
|
using SlotMapIndex = typename CONFIG::Index;
|
|
using SlotMapType = SlotMap<std::uint32_t, SlotMapVersion, SlotMapIndex>;
|
|
using SlotKey = typename SlotMapType::SlotKey;
|
|
};
|
|
|
|
TYPED_TEST_SUITE(SlotKeyFixture, SlotMapConfigs, SlotMapConfigNames);
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotKeyFixture, DefaultSlotKeyIsInvalid)
|
|
{
|
|
constexpr typename TestFixture::SlotMapIndex index = 0;
|
|
constexpr typename TestFixture::SlotMapVersion version = 0;
|
|
|
|
constexpr typename TestFixture::SlotKey slotKey {};
|
|
EXPECT_FALSE(slotKey.Valid());
|
|
EXPECT_EQ(slotKey.GetVersion(), version);
|
|
EXPECT_EQ(slotKey.GetIndex(), index);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotKeyFixture, Valid_ShouldReturnTrueIfTheSlotKeyIsValid)
|
|
{
|
|
constexpr typename TestFixture::SlotMapIndex index = 0;
|
|
constexpr typename TestFixture::SlotMapVersion version = 1;
|
|
|
|
constexpr typename TestFixture::SlotKey slotKey {version, index};
|
|
EXPECT_TRUE(slotKey.Valid());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotKeyFixture, Valid_ShouldReturnFalseIfTheSlotKeyIsValid)
|
|
{
|
|
constexpr typename TestFixture::SlotMapIndex index = 0;
|
|
constexpr typename TestFixture::SlotMapVersion version = 0;
|
|
|
|
constexpr typename TestFixture::SlotKey slotKey {version, index};
|
|
EXPECT_FALSE(slotKey.Valid());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotKeyFixture, GetVersion_ShouldReturnTheVersion)
|
|
{
|
|
constexpr typename TestFixture::SlotMapIndex index = 0;
|
|
constexpr typename TestFixture::SlotMapVersion version = 42;
|
|
|
|
constexpr typename TestFixture::SlotKey slotKey {version, index};
|
|
EXPECT_EQ(slotKey.GetVersion(), version);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotKeyFixture, GetIndex_ShouldReturnTheIndex)
|
|
{
|
|
constexpr typename TestFixture::SlotMapIndex index = 42;
|
|
constexpr typename TestFixture::SlotMapVersion version = 0;
|
|
|
|
constexpr typename TestFixture::SlotKey slotKey {version, index};
|
|
EXPECT_EQ(slotKey.GetIndex(), index);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
template<class CONFIG>
|
|
class SlotMapFixture: public ::testing::Test
|
|
{
|
|
protected:
|
|
using SlotMapVersion = typename CONFIG::Version;
|
|
using SlotMapIndex = typename CONFIG::Index;
|
|
using SlotMapType = SlotMap<std::uint32_t, SlotMapVersion, SlotMapIndex>;
|
|
using SlotKey = typename SlotMapType::SlotKey;
|
|
|
|
SlotMapType m_slotMap;
|
|
};
|
|
|
|
TYPED_TEST_SUITE(SlotMapFixture, SlotMapConfigs, SlotMapConfigNames);
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Insert_ShouldReturnAValidSlotKey)
|
|
{
|
|
const auto slotKey = this->m_slotMap.Insert(42);
|
|
EXPECT_TRUE(slotKey.Valid());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Insert_ShouldRecycleASlotKeyAfterARemove)
|
|
{
|
|
const auto slotKey = this->m_slotMap.Insert(42);
|
|
this->m_slotMap.Remove(slotKey);
|
|
|
|
const auto secondSlotKey = this->m_slotMap.Insert(69);
|
|
EXPECT_NE(secondSlotKey.GetVersion(), slotKey.GetVersion());
|
|
EXPECT_EQ(secondSlotKey.GetIndex(), slotKey.GetIndex());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Has_ShouldReturnTrueIfTheSlotMapHasTheKey)
|
|
{
|
|
const auto slotKey = this->m_slotMap.Insert(42);
|
|
EXPECT_TRUE(this->m_slotMap.Has(slotKey));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Has_ShouldReturnFalseIfTheSlotMapDoesNotHaveTheKey)
|
|
{
|
|
const auto slotKey = this->m_slotMap.Insert(42);
|
|
this->m_slotMap.Remove(slotKey);
|
|
EXPECT_FALSE(this->m_slotMap.Has(slotKey));
|
|
EXPECT_FALSE(this->m_slotMap.Has(typename TestFixture::SlotKey {1, 22}));
|
|
EXPECT_FALSE(this->m_slotMap.Has(typename TestFixture::SlotKey {}));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Remove_ShouldRemoveTheSlotKey)
|
|
{
|
|
const auto slotKey = this->m_slotMap.Insert(42);
|
|
this->m_slotMap.Remove(slotKey);
|
|
EXPECT_FALSE(this->m_slotMap.Has(slotKey));
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Remove_ShouldNotRecycleASlotWhenVersionWasExhausted)
|
|
{
|
|
if constexpr (std::is_same_v<typename TestFixture::SlotMapVersion, std::uint32_t>)
|
|
{
|
|
GTEST_SKIP() << "Skipped for 32-bit version: exhausting all versions is too slow.";
|
|
}
|
|
else
|
|
{
|
|
auto key = this->m_slotMap.Insert(1);
|
|
|
|
for (typename TestFixture::SlotMapVersion i = 1;
|
|
i < std::numeric_limits<typename TestFixture::SlotMapVersion>::max();
|
|
++i)
|
|
{
|
|
this->m_slotMap.Remove(key);
|
|
const auto newKey = this->m_slotMap.Insert(1);
|
|
EXPECT_EQ(newKey.GetIndex(), key.GetIndex());
|
|
key = newKey;
|
|
}
|
|
|
|
// Slot is at MAX_VERSION — one more remove should overflow and permanently deactivate it
|
|
EXPECT_EQ(key.GetVersion(), std::numeric_limits<typename TestFixture::SlotMapVersion>::max());
|
|
this->m_slotMap.Remove(key);
|
|
|
|
EXPECT_FALSE(this->m_slotMap.Has(key));
|
|
|
|
// Dead slot must not be recycled; a new insert must allocate a fresh slot index
|
|
const auto newKey = this->m_slotMap.Insert(2);
|
|
EXPECT_NE(newKey.GetIndex(), key.GetIndex());
|
|
|
|
// Ensure an invalid key does not return an exhausted slot
|
|
EXPECT_EQ(this->m_slotMap.Get(typename TestFixture::SlotKey {}), nullptr);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Remove_ShouldNotDoAnythingInCaseOfDoubleRemove)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
|
|
this->m_slotMap.Remove(slotKey1);
|
|
this->m_slotMap.Remove(slotKey1);
|
|
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey2), 69);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Remove_ShouldNotDoAnythingInCaseStaleKey)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
|
|
this->m_slotMap.Remove(typename TestFixture::SlotKey {2, 0});
|
|
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 42);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Get_ShouldReturnNullptrForInvalidSlotKeys)
|
|
{
|
|
const auto slotKey = this->m_slotMap.Insert(42);
|
|
this->m_slotMap.Remove(slotKey);
|
|
|
|
const auto validate = [&](auto& p_slotMap)
|
|
{
|
|
EXPECT_EQ(p_slotMap.Get(slotKey), nullptr);
|
|
EXPECT_EQ(p_slotMap.Get(typename TestFixture::SlotKey {1, 3}), nullptr);
|
|
EXPECT_EQ(p_slotMap.Get(typename TestFixture::SlotKey {}), nullptr);
|
|
};
|
|
|
|
validate(this->m_slotMap);
|
|
const auto& constSlotMap = this->m_slotMap;
|
|
validate(constSlotMap);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Get_ShouldReturnTheValueForValidSlotKeys)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
const auto slotKey3 = this->m_slotMap.Insert(28);
|
|
const auto slotKey4 = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Remove(slotKey2);
|
|
|
|
const auto validate = [&](auto& p_slotMap)
|
|
{
|
|
EXPECT_EQ(*p_slotMap.Get(slotKey1), 42);
|
|
EXPECT_EQ(*p_slotMap.Get(slotKey3), 28);
|
|
EXPECT_EQ(*p_slotMap.Get(slotKey4), 0);
|
|
};
|
|
|
|
validate(this->m_slotMap);
|
|
const auto& constSlotMap = this->m_slotMap;
|
|
validate(constSlotMap);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Reset_ResetsTheSlotMapAndMakesCollisionWithOldSlotKeys)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Reset();
|
|
|
|
const auto slotKey5 = this->m_slotMap.Insert(128);
|
|
|
|
EXPECT_EQ(slotKey1, slotKey5);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey5), 128);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 128);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Clear_ResetsTheSlotMapAndButGuaranteesNotCollisionWithOldSlotKeys)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Clear();
|
|
|
|
const auto slotKey5 = this->m_slotMap.Insert(128);
|
|
|
|
EXPECT_NE(slotKey1, slotKey5);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey5), 128);
|
|
EXPECT_EQ(this->m_slotMap.Get(slotKey1), nullptr);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, GetSize_ReturnTheSizeOfTheSlotMap)
|
|
{
|
|
EXPECT_EQ(this->m_slotMap.GetSize(), 0);
|
|
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
EXPECT_EQ(this->m_slotMap.GetSize(), 4);
|
|
|
|
this->m_slotMap.Remove(slotKey2);
|
|
|
|
EXPECT_EQ(this->m_slotMap.GetSize(), 3);
|
|
|
|
this->m_slotMap.Clear();
|
|
|
|
EXPECT_EQ(this->m_slotMap.GetSize(), 0);
|
|
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
EXPECT_EQ(this->m_slotMap.GetSize(), 4);
|
|
|
|
this->m_slotMap.Reset();
|
|
|
|
EXPECT_EQ(this->m_slotMap.GetSize(), 0);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Empty_ShouldReturnTrueIfTheSlotMapIsEmpty)
|
|
{
|
|
EXPECT_TRUE(this->m_slotMap.Empty());
|
|
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Clear();
|
|
|
|
EXPECT_TRUE(this->m_slotMap.Empty());
|
|
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Reset();
|
|
|
|
EXPECT_TRUE(this->m_slotMap.Empty());
|
|
|
|
const auto slotKey9 = this->m_slotMap.Insert(42);
|
|
this->m_slotMap.Remove(slotKey9);
|
|
|
|
EXPECT_TRUE(this->m_slotMap.Empty());
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Empty_ShouldReturnFalseIfTheSlotMapIsNotEmpty)
|
|
{
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
EXPECT_FALSE(this->m_slotMap.Empty());
|
|
|
|
this->m_slotMap.Clear();
|
|
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
std::ignore = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
EXPECT_FALSE(this->m_slotMap.Empty());
|
|
|
|
this->m_slotMap.Reset();
|
|
|
|
const auto slotKey9 = this->m_slotMap.Insert(42);
|
|
EXPECT_FALSE(this->m_slotMap.Empty());
|
|
this->m_slotMap.Remove(slotKey9);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, Iterator)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
const auto slotKey3 = this->m_slotMap.Insert(28);
|
|
const auto slotKey4 = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Remove(slotKey2);
|
|
|
|
eastl::vector<std::uint32_t> values;
|
|
for (auto it = this->m_slotMap.begin(); it != this->m_slotMap.end(); ++it)
|
|
{
|
|
values.push_back(*it);
|
|
}
|
|
|
|
ASSERT_EQ(values.size(), 3);
|
|
EXPECT_EQ(values[0], 42);
|
|
EXPECT_EQ(values[1], 0);
|
|
EXPECT_EQ(values[2], 28);
|
|
|
|
// The non-const iterator is mutable.
|
|
for (std::uint32_t& value: this->m_slotMap)
|
|
{
|
|
value += 100;
|
|
}
|
|
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 142);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey3), 128);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey4), 100);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, ConstIterator)
|
|
{
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Remove(slotKey2);
|
|
|
|
const auto& constSlotMap = this->m_slotMap;
|
|
|
|
eastl::vector<std::uint32_t> values;
|
|
for (auto it = constSlotMap.begin(); it != constSlotMap.end(); ++it)
|
|
{
|
|
values.push_back(*it);
|
|
}
|
|
|
|
ASSERT_EQ(values.size(), 3);
|
|
EXPECT_EQ(values[0], 42);
|
|
EXPECT_EQ(values[1], 0);
|
|
EXPECT_EQ(values[2], 28);
|
|
|
|
// cbegin/cend yield the same const traversal.
|
|
eastl::vector<std::uint32_t> cValues;
|
|
for (auto it = this->m_slotMap.cbegin(); it != this->m_slotMap.cend(); ++it)
|
|
{
|
|
cValues.push_back(*it);
|
|
}
|
|
|
|
EXPECT_EQ(values, cValues);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, ReverseIterator)
|
|
{
|
|
const auto slotKey1 = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
const auto slotKey3 = this->m_slotMap.Insert(28);
|
|
const auto slotKey4 = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Remove(slotKey2);
|
|
|
|
eastl::vector<std::uint32_t> values;
|
|
for (auto it = this->m_slotMap.rbegin(); it != this->m_slotMap.rend(); ++it)
|
|
{
|
|
values.push_back(*it);
|
|
}
|
|
|
|
ASSERT_EQ(values.size(), 3);
|
|
EXPECT_EQ(values[0], 28);
|
|
EXPECT_EQ(values[1], 0);
|
|
EXPECT_EQ(values[2], 42);
|
|
|
|
// The non-const reverse iterator is mutable.
|
|
for (auto it = this->m_slotMap.rbegin(); it != this->m_slotMap.rend(); ++it)
|
|
{
|
|
*it += 100;
|
|
}
|
|
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 142);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey3), 128);
|
|
EXPECT_EQ(*this->m_slotMap.Get(slotKey4), 100);
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
TYPED_TEST(SlotMapFixture, ConstReverseIterator)
|
|
{
|
|
std::ignore = this->m_slotMap.Insert(42);
|
|
const auto slotKey2 = this->m_slotMap.Insert(69);
|
|
std::ignore = this->m_slotMap.Insert(28);
|
|
std::ignore = this->m_slotMap.Insert(0);
|
|
|
|
this->m_slotMap.Remove(slotKey2);
|
|
|
|
const auto& constSlotMap = this->m_slotMap;
|
|
|
|
eastl::vector<std::uint32_t> values;
|
|
for (auto it = constSlotMap.rbegin(); it != constSlotMap.rend(); ++it)
|
|
{
|
|
values.push_back(*it);
|
|
}
|
|
|
|
ASSERT_EQ(values.size(), 3);
|
|
EXPECT_EQ(values[0], 28);
|
|
EXPECT_EQ(values[1], 0);
|
|
EXPECT_EQ(values[2], 42);
|
|
|
|
// crbegin/crend yield the same const reverse traversal.
|
|
eastl::vector<std::uint32_t> crValues;
|
|
for (auto it = this->m_slotMap.crbegin(); it != this->m_slotMap.crend(); ++it)
|
|
{
|
|
crValues.push_back(*it);
|
|
}
|
|
|
|
EXPECT_EQ(values, crValues);
|
|
}
|
|
} // namespace Bigfoot
|