EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MultiIndexTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MultiIndexTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
12 
13 #include <cstdint>
14 #include <type_traits>
15 #include <unordered_set>
16 
17 #include <boost/mpl/list.hpp>
18 
19 // 32bit split into a three level hierachy.
21 // 64bit split into a four level hierachy
23 using Indices = boost::mpl::list<Index32, Index64>;
24 
26  // verify that the MultiIndex is a trivial type
27  // this seems to be compiler-dependent; disable for now
28  BOOST_CHECK(std::is_standard_layout_v<T>);
29  BOOST_CHECK(std::is_trivially_default_constructible_v<T>);
30  BOOST_CHECK(std::is_trivially_copy_constructible_v<T>);
31  BOOST_CHECK(std::is_trivially_move_constructible_v<T>);
32  BOOST_CHECK((std::is_trivially_assignable_v<T, T>));
33  BOOST_CHECK((std::is_trivially_copy_assignable_v<T>));
34  BOOST_CHECK((std::is_trivially_move_assignable_v<T>));
35 }
36 
37 BOOST_AUTO_TEST_CASE(index32_construct) {
38  // construct from encoded value
39  {
40  Index32 idx(0xabcd2400u);
41  BOOST_CHECK_EQUAL(idx.value(), 0xabcd2400u);
42  BOOST_CHECK_EQUAL(idx.level(0), 0xabcdu);
43  BOOST_CHECK_EQUAL(idx.level(1), 0x24u);
44  BOOST_CHECK_EQUAL(idx.level(2), 0x00u);
45  }
46  // assign from encoded value
47  {
48  Index32 idx = 0xabcd2400u;
49  BOOST_CHECK_EQUAL(idx.value(), 0xabcd2400u);
50  BOOST_CHECK_EQUAL(idx.level(0), 0xabcdu);
51  BOOST_CHECK_EQUAL(idx.level(1), 0x24u);
52  BOOST_CHECK_EQUAL(idx.level(2), 0x00u);
53  }
54 }
55 
56 BOOST_AUTO_TEST_CASE(index32_set) {
57  Index32 idx = Index32::Zeros();
58  // set a specific level within limits
59  idx.set(0, 24u);
60  BOOST_CHECK_EQUAL(idx.value(), 0x00180000u);
61  BOOST_CHECK_EQUAL(idx.level(0), 24u);
62  BOOST_CHECK_EQUAL(idx.level(1), 0u);
63  BOOST_CHECK_EQUAL(idx.level(2), 0u);
64  // set a specific level outside the valid range, should be truncated
65  idx.set(2, 0xfff);
66  BOOST_CHECK_EQUAL(idx.value(), 0x001800ffu);
67  BOOST_CHECK_EQUAL(idx.level(0), 24u);
68  BOOST_CHECK_EQUAL(idx.level(1), 0u);
69  BOOST_CHECK_EQUAL(idx.level(2), 255u);
70 }
71 
72 BOOST_AUTO_TEST_CASE(index32_set_overflow) {
73  // maximum values for each level
74  Index32::Value maxValues[] = {
75  (1u << 16u) - 1u,
76  (1u << 8u) - 1u,
77  (1u << 8u) - 1u,
78  };
79  // check that values above max are truncated
80  std::size_t lvl = 0;
81  for (auto maxValue : maxValues) {
82  BOOST_CHECK_EQUAL(Index32::Zeros().set(lvl, maxValue + 1),
83  Index32::Zeros().set(lvl, 0u));
84  lvl += 1;
85  }
86 }
87 
88 BOOST_AUTO_TEST_CASE(index64_set_overflow) {
89  // maximum values for each level
90  Index32::Value maxValues[] = {
91  (1u << 13u) - 1u,
92  (1u << 17u) - 1u,
93  (1u << 21u) - 1u,
94  (1u << 13u) - 1u,
95  };
96  // check that values above max are truncated
97  std::size_t lvl = 0;
98  for (auto maxValue : maxValues) {
99  BOOST_CHECK_EQUAL(Index64::Zeros().set(lvl, maxValue + 1),
100  Index64::Zeros().set(lvl, 0u));
101  lvl += 1;
102  }
103 }
104 
105 BOOST_AUTO_TEST_CASE(index32_encode) {
106  // all three levels set
107  auto idx3 = Index32::Encode(13u, 14u, 15u);
108  BOOST_CHECK_EQUAL(idx3.level(0), 13u);
109  BOOST_CHECK_EQUAL(idx3.level(1), 14u);
110  BOOST_CHECK_EQUAL(idx3.level(2), 15u);
111  // first two levels set
112  auto idx2 = Index32::Encode(13u, 14u);
113  BOOST_CHECK_EQUAL(idx2.level(0), 13u);
114  BOOST_CHECK_EQUAL(idx2.level(1), 14u);
115  BOOST_CHECK_EQUAL(idx2.level(2), 0u);
116  // only the first level set
117  auto idx1 = Index32::Encode(13u);
118  BOOST_CHECK_EQUAL(idx1.level(0), 13u);
119  BOOST_CHECK_EQUAL(idx1.level(1), 0u);
120  BOOST_CHECK_EQUAL(idx1.level(2), 0u);
121  // nothing set
122  auto idx0 = Index32::Encode();
123  BOOST_CHECK_EQUAL(idx0, Index32::Zeros());
124  BOOST_CHECK_EQUAL(idx0.value(), 0u);
125  BOOST_CHECK_EQUAL(idx0.level(0), 0u);
126  BOOST_CHECK_EQUAL(idx0.level(1), 0u);
127  BOOST_CHECK_EQUAL(idx0.level(2), 0u);
128 }
129 
130 BOOST_AUTO_TEST_CASE(index64_encode) {
131  // all four levels set
132  auto idx4 = Index64::Encode(23u, 14u, 15u, 17u);
133  BOOST_CHECK_EQUAL(idx4.level(0), 23u);
134  BOOST_CHECK_EQUAL(idx4.level(1), 14u);
135  BOOST_CHECK_EQUAL(idx4.level(2), 15u);
136  BOOST_CHECK_EQUAL(idx4.level(3), 17u);
137  // first three levels set
138  auto idx3 = Index64::Encode(23u, 14u, 15u);
139  BOOST_CHECK_EQUAL(idx3.level(0), 23u);
140  BOOST_CHECK_EQUAL(idx3.level(1), 14u);
141  BOOST_CHECK_EQUAL(idx3.level(2), 15u);
142  BOOST_CHECK_EQUAL(idx3.level(3), 0u);
143  // first two levels set
144  auto idx2 = Index64::Encode(23u, 14u);
145  BOOST_CHECK_EQUAL(idx2.level(0), 23u);
146  BOOST_CHECK_EQUAL(idx2.level(1), 14u);
147  BOOST_CHECK_EQUAL(idx2.level(2), 0u);
148  BOOST_CHECK_EQUAL(idx2.level(3), 0u);
149  // only the first level set
150  auto idx1 = Index64::Encode(23u);
151  BOOST_CHECK_EQUAL(idx1.level(0), 23u);
152  BOOST_CHECK_EQUAL(idx1.level(1), 0u);
153  BOOST_CHECK_EQUAL(idx1.level(2), 0u);
154  BOOST_CHECK_EQUAL(idx1.level(3), 0u);
155  // nothing set
156  auto idx0 = Index64::Encode();
157  BOOST_CHECK_EQUAL(idx0, Index64::Zeros());
158  BOOST_CHECK_EQUAL(idx0.value(), 0u);
159  BOOST_CHECK_EQUAL(idx0.level(0), 0u);
160  BOOST_CHECK_EQUAL(idx0.level(1), 0u);
161  BOOST_CHECK_EQUAL(idx0.level(2), 0u);
162  BOOST_CHECK_EQUAL(idx0.level(3), 0u);
163 }
164 
165 BOOST_AUTO_TEST_CASE(uint32_sibling) {
166  auto idx = Index32::Encode(1u, 12u, 123u);
167  BOOST_CHECK_EQUAL(idx.makeNextSibling(0), Index32::Encode(2u));
168  BOOST_CHECK_EQUAL(idx.makeNextSibling(1), Index32::Encode(1u, 13u));
169  BOOST_CHECK_EQUAL(idx.makeNextSibling(2), Index32::Encode(1u, 12u, 124u));
170 }
171 
172 BOOST_AUTO_TEST_CASE(uint64_sibling) {
173  auto idx = Index64::Encode(1u, 12u, 123u, 1234u);
174  BOOST_CHECK_EQUAL(idx.makeNextSibling(0), Index64::Encode(2u));
175  BOOST_CHECK_EQUAL(idx.makeNextSibling(1), Index64::Encode(1u, 13u));
176  BOOST_CHECK_EQUAL(idx.makeNextSibling(2), Index64::Encode(1u, 12u, 124u));
177  BOOST_CHECK_EQUAL(idx.makeNextSibling(3),
178  Index64::Encode(1u, 12u, 123u, 1235u));
179 }
180 
181 BOOST_AUTO_TEST_CASE(uint32_descendant) {
182  auto idx = Index32::Encode(1u, 12u, 123u);
183  BOOST_CHECK_EQUAL(idx.makeLastDescendant(0), Index32::Encode(1u, 255u, 255u));
184  BOOST_CHECK_EQUAL(idx.makeLastDescendant(1), Index32::Encode(1u, 12u, 255u));
185  // last index has no descendant and stays the same
186  BOOST_CHECK_EQUAL(idx.makeLastDescendant(2), Index32::Encode(1u, 12u, 123u));
187 }
188 
189 BOOST_AUTO_TEST_CASE(uint64_descendant) {
190  auto idx = Index64::Encode(1u, 12u, 123u, 1234u);
191  // from Index64 definition above
192  auto max1 = (1u << 17) - 1u;
193  auto max2 = (1u << 21) - 1u;
194  auto max3 = (1u << 13) - 1u;
195  BOOST_CHECK_EQUAL(idx.makeLastDescendant(0),
196  Index64::Encode(1u, max1, max2, max3));
197  BOOST_CHECK_EQUAL(idx.makeLastDescendant(1),
198  Index64::Encode(1u, 12u, max2, max3));
199  BOOST_CHECK_EQUAL(idx.makeLastDescendant(2),
200  Index64::Encode(1u, 12u, 123u, max3));
201  // last index has no descendant and stays the same
202  BOOST_CHECK_EQUAL(idx.makeLastDescendant(3),
203  Index64::Encode(1u, 12u, 123u, 1234u));
204 }
205 
206 BOOST_AUTO_TEST_CASE(index32_as_key) {
207  std::unordered_set<Index32> set;
208 
209  set.emplace(Index32::Encode(1u, 2u, 4u));
210  set.emplace(Index32::Encode(1u, 3u, 4u));
211  set.emplace(Index32::Encode(2u));
212 
213  BOOST_CHECK(not set.count(Index32(0u)));
214  BOOST_CHECK(not set.count(Index32(UINT32_MAX)));
215  BOOST_CHECK_EQUAL(set.size(), 3);
216  // automatically converts encoded value to MultiIndex
217  BOOST_CHECK(set.count(0x00010204u));
218  BOOST_CHECK(set.count(0x00010304u));
219  BOOST_CHECK(set.count(Index32::Encode(2u)));
220 }
221 
222 BOOST_AUTO_TEST_CASE(index64_as_key) {
223  std::unordered_set<Index64> set;
224 
225  set.emplace(Index64::Encode(1u, 1u, 1u));
226  set.emplace(Index64::Encode(2u));
227  // same as above
228  set.emplace(Index64::Encode(2u, 0u, 0u, 0u));
229  set.emplace(Index64::Encode(2u, 1u));
230 
231  BOOST_CHECK(not set.count(Index64(0u)));
232  BOOST_CHECK(not set.count(Index64(UINT64_MAX)));
233  BOOST_CHECK_EQUAL(set.size(), 3);
234 }