ContainerTests.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <TestTypes.h>
  9. #include <AzCore/Math/Random.h>
  10. #include <AzCore/std/time.h>
  11. #include <AzRHI/Containers/Handle.h>
  12. #include <AzRHI/Containers/HandleMap.h>
  13. #include <AzRHI/Containers/ChunkedVector.h>
  14. namespace UnitTest
  15. {
  16. struct IntContainer
  17. {
  18. const AZ::u32 DefaultValue = 1234;
  19. IntContainer(AZ::u32& totalCount, AZ::u32 value)
  20. : m_value{ value }
  21. , m_totalCount{ &totalCount }
  22. {
  23. totalCount++;
  24. }
  25. IntContainer(const IntContainer& rhs)
  26. : m_value{ rhs.m_value }
  27. , m_totalCount{ rhs.m_totalCount }
  28. {
  29. (*m_totalCount)++;
  30. }
  31. IntContainer(IntContainer&& rhs)
  32. : m_value{ rhs.m_value }
  33. , m_totalCount{ rhs.m_totalCount }
  34. {
  35. rhs.m_totalCount = nullptr;
  36. }
  37. ~IntContainer()
  38. {
  39. if (m_totalCount)
  40. {
  41. --(*m_totalCount);
  42. }
  43. }
  44. AZ::u32* m_totalCount = nullptr;
  45. AZ::u32 m_value = DefaultValue;
  46. };
  47. class ChunkedVectorTest
  48. : public UnitTest::LeakDetectionFixture
  49. {
  50. public:
  51. void run()
  52. {
  53. static const size_t CapacityLogSize = 16; // 65535 elements.
  54. static const size_t Capacity = (1 << CapacityLogSize);
  55. AZ::u32 totalCount = 0;
  56. AzRHI::ChunkedVector<IntContainer, AZStd::allocator, CapacityLogSize> v;
  57. //////////////////////////////////////////////////////////////////////////
  58. // Test push back (copy construction)
  59. for (AZ::u32 i = 0; i < Capacity; ++i)
  60. {
  61. IntContainer value(totalCount, i);
  62. v.push_back(value);
  63. }
  64. ASSERT_TRUE(v.size() == Capacity);
  65. ASSERT_TRUE(v.capacity() == Capacity);
  66. for (size_t i = 0; i < Capacity; ++i)
  67. {
  68. ASSERT_TRUE(v[i].m_value == i);
  69. }
  70. for (size_t i = 0; i < Capacity; ++i)
  71. {
  72. v.pop_back();
  73. }
  74. ASSERT_TRUE(v.size() == 0);
  75. ASSERT_TRUE(v.capacity() == Capacity);
  76. ASSERT_TRUE(totalCount == 0);
  77. //////////////////////////////////////////////////////////////////////////
  78. // Test push back (move construction)
  79. for (AZ::u32 i = 0; i < Capacity; ++i)
  80. {
  81. v.push_back(IntContainer(totalCount, i));
  82. }
  83. ASSERT_TRUE(v.size() == Capacity);
  84. for (size_t i = 0; i < Capacity; ++i)
  85. {
  86. ASSERT_TRUE(v[i].m_value == i);
  87. }
  88. for (size_t i = 0; i < Capacity; ++i)
  89. {
  90. v.pop_back();
  91. }
  92. ASSERT_TRUE(v.size() == 0);
  93. ASSERT_TRUE(v.capacity() == Capacity);
  94. ASSERT_TRUE(totalCount == 0);
  95. ///////////////////////////////////////////////////////////////////////////
  96. // Test emplacement
  97. for (AZ::u32 i = 0; i < Capacity; ++i)
  98. {
  99. v.emplace_back(totalCount, i * 2);
  100. }
  101. for (size_t i = 0; i < Capacity; ++i)
  102. {
  103. ASSERT_TRUE(v[i].m_value == (i * 2));
  104. }
  105. v.clear();
  106. ASSERT_TRUE(v.size() == 0);
  107. ASSERT_TRUE(v.capacity() == Capacity);
  108. ASSERT_TRUE(totalCount == 0);
  109. }
  110. };
  111. TEST_F(ChunkedVectorTest, Test)
  112. {
  113. run();
  114. }
  115. class HandleMapTest
  116. : public UnitTest::LeakDetectionFixture
  117. {
  118. public:
  119. HandleMapTest()
  120. : LeakDetectionFixture()
  121. {}
  122. void run()
  123. {
  124. AZ::u32 totalCount = 0;
  125. using TestHandle = AzRHI::Handle<AzRHI::HandleFormats::Index16Generation16>;
  126. AzRHI::HandleMap<IntContainer, TestHandle> m;
  127. AZStd::unordered_map<TestHandle, AZ::u32> m_allocations;
  128. AZ::SimpleLcgRandom random(AZStd::GetTimeNowMicroSecond());
  129. const AZ::u32 IterationCount = 100000;
  130. for (AZ::u32 i = 0; i < IterationCount; ++i)
  131. {
  132. // Add
  133. if (random.GetRandom() % 2 == 0)
  134. {
  135. AZ::u32 randomValue = random.GetRandom();
  136. TestHandle handle = m.emplace(totalCount, randomValue);
  137. if (handle.IsValid())
  138. {
  139. auto result = m_allocations.emplace(handle, randomValue);
  140. ASSERT_TRUE(result.second); // we should not have a duplicate.
  141. }
  142. else
  143. {
  144. // We should be full.
  145. ASSERT_TRUE(m.size() == TestHandle::Traits::HandleCountMax);
  146. }
  147. }
  148. // Remove
  149. else
  150. {
  151. if (m_allocations.size())
  152. {
  153. auto it = m_allocations.begin();
  154. AZ::u32 index = (random.GetRandom() % m_allocations.size());
  155. while (index)
  156. {
  157. ++it;
  158. --index;
  159. }
  160. m.remove(it->first);
  161. m_allocations.erase(it);
  162. }
  163. }
  164. ASSERT_TRUE(m.size() == m_allocations.size());
  165. ASSERT_TRUE(totalCount == m_allocations.size());
  166. // Test an access
  167. if (m_allocations.size())
  168. {
  169. auto it = m_allocations.begin();
  170. AZ::u32 index = (random.GetRandom() % m_allocations.size());
  171. while (index)
  172. {
  173. ++it;
  174. --index;
  175. }
  176. TestHandle handle = it->first;
  177. AZ::u32 value = it->second;
  178. const IntContainer* container = m[handle];
  179. ASSERT_TRUE(container);
  180. ASSERT_TRUE(container->m_value == value);
  181. }
  182. }
  183. }
  184. };
  185. TEST_F(HandleMapTest, Test)
  186. {
  187. run();
  188. }
  189. }