Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.5.28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
indexmap.cpp
1#include <Core/Utils/IndexMap.hpp>
2#include <catch2/catch_test_macros.hpp>
3#include <unittestUtils.hpp>
4
5using Ra::Core::Utils::Index;
7
8// Just a standard test structure
9struct Foo {
10 explicit Foo( int x ) : value( x ) {}
11 int value;
12};
13
14TEST_CASE( "Core/Utils/IndexMap", "[unittests][Core][Core/Utils][IndexMap]" ) {
15
16 SECTION( "Sanity checks" ) {
17 IndexMap<Foo> map1;
18 // New map should be empty
19 REQUIRE( map1.empty() );
20 // New map should be empty (size)
21 REQUIRE( map1.size() == 0 );
22 // New map should not be full
23 REQUIRE( !map1.full() );
24 }
25
26 SECTION( "Test Copyable" ) {
27 IndexMap<Foo> map1;
28 Index i1, i2;
29 i1 = map1.insert( Foo( 12 ) );
30 REQUIRE( i1.isValid() );
31
32 // We expect to have one element now.
33 REQUIRE( !map1.empty() );
34 REQUIRE( map1.size() == 1 );
35
36 // Test value read and write
37 REQUIRE( map1.at( i1 ).value == 12 );
38 REQUIRE( map1[i1].value == 12 );
39
40 map1.access( i1 ).value = 24;
41 REQUIRE( map1.at( i1 ).value == 24 );
42
43 map1[i1].value = 32;
44 REQUIRE( map1.at( i1 ).value == 32 );
45
46 i2 = map1.insert( Foo( 42 ) );
47 REQUIRE( map1.at( i2 ).value == 42 );
48 REQUIRE( map1.size() == 2 );
49
51 // Test range-based for loop (relies on iterators)
52 uint counter = 0;
53 for ( const Foo& f : map1 ) {
54 REQUIRE( ( f.value == 32 || f.value == 42 ) );
55 ++counter;
56 }
57 REQUIRE( counter == 2 );
58
59 // Test non-const loop
60 counter = 0;
61 for ( Foo& f : map1 ) {
62 f.value = 2 * f.value;
63 REQUIRE( ( f.value == 2 * 32 || f.value == 2 * 42 ) );
64 ++counter;
65 }
66 REQUIRE( counter == 2 );
67
68 // Test index iterators
69 counter = 0;
70 for ( auto it = map1.cbegin_index(); it != map1.cend_index(); ++it ) {
71 REQUIRE( ( *it == i1 || *it == i2 ) );
72 ++counter;
73 }
74
76 // Test methods contains and remove
77
78 REQUIRE( map1.contains( i1 ) );
79 REQUIRE( map1.contains( i2 ) );
80 REQUIRE( !map1.contains( Index( 12000 ) ) );
81
82 // Remove an item once.
83 bool result = map1.remove( i1 );
84 REQUIRE( result );
85 REQUIRE( map1.size() == 1 );
86
87 // Removing it twice should not work.
88 result = map1.remove( i1 );
89 REQUIRE( !result );
90
91 // Remove the other item
92 result = map1.remove( Index( 1000 ) );
93 REQUIRE( !result );
94
95 result = map1.remove( i2 );
96 REQUIRE( result );
97
98 REQUIRE( map1.size() == 0 );
99 REQUIRE( map1.empty() );
100 }
101
102 SECTION( "Test Non-Copyable" ) {
103 using Ra::Core::Utils::Index;
105 // Now try to insert non-copyable elements
106
108 Index i1 = map2.emplace( std::move( 12 ) );
109 // map insert (inplace)
110 REQUIRE( i1.isValid() );
111
112 Index i2 = map2.emplace( std::move( 42 ) );
113 // map insert (inplace)
114 REQUIRE( i2.isValid() );
115
116 // map access (inplace)
117 REQUIRE( map2[i1].value == 12 );
118 REQUIRE( map2[i2].value == 42 );
119
120 // Test the clear function
121 map2.clear();
122 REQUIRE( map2.size() == 0 );
123 REQUIRE( map2.empty() );
124 }
125}
126
127template <typename T>
128void testType() {
129 T step = std::numeric_limits<T>::max() / T { 1000 };
130 for ( T i = static_cast<T>( std::numeric_limits<Index::IntegerType>::max() ) + 1;
131 i < static_cast<T>( std::numeric_limits<T>::max() - 2 * step );
132 i += step ) {
133 // Index is more than max, so it is invalid
134 Index idx { i };
135 REQUIRE( idx.isInvalid() );
136 }
137}
138
139TEST_CASE( "Core/Utils/Index/Ctor", "[unittests][Core][Core/Utils][Index]" ) {
140
141 Index idxInvalid;
142 REQUIRE( idxInvalid.isInvalid() );
143 // testing everything is too long
144 const int step = std::numeric_limits<Index::IntegerType>::max() / 1000;
145 for ( Index::IntegerType i = 0; i < std::numeric_limits<Index::IntegerType>::max() - 2 * step;
146 i += step ) {
147 Index idx { i };
148 REQUIRE( idx.isValid() );
149 auto idxUl = Index { static_cast<unsigned long int>( i ) };
150 auto idxL = Index { static_cast<long int>( i ) };
151 auto idxU = Index { static_cast<unsigned int>( i ) };
152 REQUIRE( idxUl.isValid() );
153 REQUIRE( idxU.isValid() );
154 REQUIRE( idxL.isValid() );
155 REQUIRE( idx == idxUl );
156 REQUIRE( idx == idxU );
157 REQUIRE( idx == idxL );
158 }
159
160 testType<unsigned long int>();
161 // testType<long int>(); /* this does not pass on Windows (visual 2019 and visual 2022)*/
162 testType<unsigned int>();
163 testType<size_t>();
164}
const T & at(const Index &idx) const
Return a read-only ref to object with the given index. Crashes if index does not exist.
Definition IndexMap.hpp:213
void clear()
Return the size of the IndexMap ( number of object contained ).
Definition IndexMap.hpp:236
Index emplace(const Args &&... args)
Definition IndexMap.hpp:184
T & access(const Index &idx)
Return a reference to the object with the given index. Crash if index does not exist.
Definition IndexMap.hpp:221
Index insert(const T &obj)
Destructor.
Definition IndexMap.hpp:170
bool empty() const
Clear the IndexMap.
Definition IndexMap.hpp:247
bool full() const
Return true if the IndexMap is empty.
Definition IndexMap.hpp:252
T max(T... args)
T move(T... args)