Project
Loading...
Searching...
No Matches
testEnumFlags.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#define BOOST_TEST_MODULE Test Flags
13#define BOOST_TEST_MAIN
14#define BOOST_TEST_DYN_LINK
15
16#include <boost/test/unit_test.hpp>
17#include <stdexcept>
18#include <string>
19
21
22// Example enum to use with EnumFlags
23enum class TestEnum : uint8_t {
24 Bit1,
25 Bit2,
26 Bit3,
27 Bit4,
29};
30
31// Very long enum
32// to test that it works beyond 32 bits
33enum class TestEnumLong : uint64_t {
34 Bit1,
35 Bit2,
36 Bit3,
37 Bit4,
38 Bit5,
39 Bit6,
40 Bit7,
41 Bit8,
42 Bit9,
43 Bit10,
44 Bit11,
45 Bit12,
46 Bit13,
47 Bit14,
48 Bit15,
49 Bit16,
50 Bit17,
51 Bit18,
52 Bit19,
53 Bit20,
54 Bit21,
55 Bit22,
56 Bit23,
57 Bit24,
58 Bit25,
59 Bit26,
60 Bit27,
61 Bit28,
62 Bit29,
63 Bit30,
64 Bit31,
65 Bit32,
66 Bit33,
67 Bit34,
68 // ...
69};
70
72{
73 using EFlags = o2::utils::EnumFlags<TestEnum>;
74
75 // Test default initialization
76 EFlags flags;
77 BOOST_TEST(flags.None == 0);
78 BOOST_TEST(flags.All == 31);
79 BOOST_TEST(flags.value() == 0);
80 BOOST_TEST(!flags.any());
81
82 // Test initialization with a single flag
83 EFlags flag1(TestEnum::Bit1);
84 BOOST_TEST(flag1.test(TestEnum::Bit1));
85 BOOST_TEST(!flag1.test(TestEnum::Bit2));
86 BOOST_TEST(flag1.value() == (1 << static_cast<unsigned int>(TestEnum::Bit1)));
87
88 // Test initialization with initializer list
89 EFlags multipleFlags({TestEnum::Bit1, TestEnum::Bit3});
90 BOOST_TEST(multipleFlags.test(TestEnum::Bit1));
91 BOOST_TEST(multipleFlags.test(TestEnum::Bit3));
92 BOOST_TEST(!multipleFlags.test(TestEnum::Bit2));
93 BOOST_TEST(multipleFlags.any());
94
95 // Test reset
96 multipleFlags.reset(TestEnum::Bit1);
97 BOOST_TEST(!multipleFlags.test(TestEnum::Bit1));
98 BOOST_TEST(multipleFlags.test(TestEnum::Bit3));
99 multipleFlags.reset();
100 BOOST_TEST(!multipleFlags.any());
101
102 // Test operator|
103 EFlags combinedFlags = flag1 | EFlags(TestEnum::Bit2);
104 BOOST_TEST(combinedFlags.test(TestEnum::Bit1));
105 BOOST_TEST(combinedFlags.test(TestEnum::Bit2));
106 BOOST_TEST(!combinedFlags.test(TestEnum::Bit3));
107
108 // Test operator[]
109 BOOST_TEST(combinedFlags[TestEnum::Bit1]);
110 BOOST_TEST(combinedFlags[TestEnum::Bit2]);
111 BOOST_TEST(!combinedFlags[TestEnum::Bit3]);
112
113 // Test operator|=
114 combinedFlags |= TestEnum::Bit3;
115 BOOST_TEST(combinedFlags.test(TestEnum::Bit3));
116
117 // Test operator&
118 EFlags intersection = combinedFlags & TestEnum::Bit1;
119 BOOST_TEST(intersection.test(TestEnum::Bit1));
120 BOOST_TEST(!intersection.test(TestEnum::Bit2));
121 BOOST_TEST(intersection.value() == (1 << static_cast<unsigned int>(TestEnum::Bit1)));
122
123 // Test operator&=
124 combinedFlags &= TestEnum::Bit1;
125 BOOST_TEST(combinedFlags.test(TestEnum::Bit1));
126 BOOST_TEST(!combinedFlags.test(TestEnum::Bit2));
127 BOOST_TEST(!combinedFlags.test(TestEnum::Bit3));
128
129 // Test operator~ (complement)
130 EFlags complement = ~EFlags(TestEnum::Bit1);
131 BOOST_TEST(!complement.test(TestEnum::Bit1));
132 BOOST_TEST(complement.test(TestEnum::Bit2));
133 BOOST_TEST(complement.test(TestEnum::Bit3));
134
135 // Test string() method
136 {
137 std::string flagString = flag1.string();
138 BOOST_TEST(flagString.back() == '1'); // Ensure the least significant bit is set for flag1
139 }
140
141 // Test set with binary string
142 {
143 std::string binaryStr = "101";
144 flags.set(binaryStr, 2);
148 }
149
150 // Test invalid binary string in set
151 BOOST_CHECK_THROW(flags.set(std::string("invalid"), 2), std::invalid_argument);
152
153 // Test range validation in set
154 BOOST_CHECK_THROW(flags.set(std::string("100000000"), 2), std::out_of_range);
155
156 { // Test that return lists are sensible
157 const auto n = flags.getNames();
158 const auto v = flags.getValues();
159 BOOST_CHECK(n.size() == v.size());
160 }
161
162 { // print test
163 std::cout << flags;
164 }
165
166 // Test flag tokenization and parsing
167 {
168 { // only one scoped flag
169 std::string str = "TestEnum::Bit2";
170 flags.set(str);
173 }
174
175 { // test with ws-triming and scope mixing
176 std::string str = "Bit4|TestEnum::Bit2 | Bit1 ";
177 flags.set(str);
182 }
183
184 { // test with different delimiter
185 std::string str = "Bit4,TestEnum::Bit2 , Bit1 ";
186 flags.set(str);
191 }
192
193 { // throw test with mixed delimiter
194 std::string str = "Bit4|TestEnum::Bit2 , Bit1 ";
195 BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
196 }
197
198 { // test throw
199 std::string str = "Invalid";
200 BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
201 }
202 }
203
204 // Test all_of and none_of
205 {
206 EFlags allFlags({TestEnum::Bit1, TestEnum::Bit2, TestEnum::Bit3});
207 BOOST_TEST(allFlags.all_of(TestEnum::Bit1, TestEnum::Bit2));
208 BOOST_TEST(!allFlags.all_of(TestEnum::Bit4));
209 BOOST_TEST(allFlags.none_of(TestEnum::Bit4));
210 }
211
212 // Test toggle
213 {
214 EFlags toggleFlags;
215 toggleFlags.toggle(TestEnum::Bit4);
216 BOOST_TEST(toggleFlags.test(TestEnum::Bit4));
217 toggleFlags.toggle(TestEnum::Bit4);
218 BOOST_TEST(!toggleFlags.test(TestEnum::Bit4));
219 }
220
221 // Create a flag set and serialize it
222 {
223 EFlags serializedFlags{TestEnum::Bit1, TestEnum::Bit3};
224 std::string serialized = serializedFlags.serialize();
225 BOOST_CHECK_EQUAL(serialized, "5"); // 5 in binary is 0101, meaning Bit1 and Bit3 are set.
226
227 // Deserialize back into a flag set
228 EFlags deserializedFlags;
229 deserializedFlags.deserialize(serialized);
230 BOOST_CHECK(deserializedFlags == serializedFlags); // Ensure the deserialized flags match the original
231 }
232
233 // Test with an empty flag set
234 {
235 EFlags emptyFlags;
236 std::string serialized = emptyFlags.serialize();
237 BOOST_CHECK_EQUAL(serialized, "0");
238
239 EFlags deserialized;
240 deserialized.deserialize(serialized);
241 BOOST_CHECK(deserialized == emptyFlags);
242
243 // Test with all flags set
244 EFlags allFlags(EFlags::All);
245 serialized = allFlags.serialize();
246 BOOST_CHECK_EQUAL(serialized, std::to_string(EFlags::All));
247
248 deserialized.deserialize(serialized);
249 BOOST_CHECK(deserialized == allFlags);
250 }
251
252 // check throw deserializng out of range
253 {
254 EFlags flag;
255 std::string str = "999999";
256 BOOST_CHECK_THROW(flag.deserialize(str), std::out_of_range);
257 }
258
259 // Create two flag sets
260 {
261 EFlags flags1{TestEnum::Bit1, TestEnum::Bit2};
262 EFlags flags2{TestEnum::Bit3, TestEnum::Bit4};
263
264 // Perform a union operation
265 EFlags unionFlags = flags1.union_with(flags2);
266 BOOST_CHECK(unionFlags.test(TestEnum::Bit1));
267 BOOST_CHECK(unionFlags.test(TestEnum::Bit2));
268 BOOST_CHECK(unionFlags.test(TestEnum::Bit3));
269 BOOST_CHECK(unionFlags.test(TestEnum::Bit4));
270 BOOST_CHECK_EQUAL(unionFlags.value(), 15); // 1111 in binary
271 }
272
273 // Create two overlapping flag sets
274 {
277
278 // Perform an intersection operation
279 EFlags intersectionFlags = flags3.intersection_with(flags4);
280 BOOST_CHECK(intersectionFlags.test(TestEnum::Bit2));
281 BOOST_CHECK(intersectionFlags.test(TestEnum::Bit3));
282 BOOST_CHECK(!intersectionFlags.test(TestEnum::Bit1));
283 BOOST_CHECK(!intersectionFlags.test(TestEnum::Bit4));
284 BOOST_CHECK_EQUAL(intersectionFlags.value(), 6); // 0110 in binary
285 }
286
287 {
288 // Create two flag sets
290 EFlags flags2{TestEnum::Bit2, TestEnum::Bit3};
291
292 // Check containment
293 BOOST_CHECK(flags1.contains(flags2)); // flags1 contains all flags in flags2
294 BOOST_CHECK(!flags2.contains(flags1)); // flags2 does not contain all flags in flags1
295
296 // Test with disjoint sets
297 EFlags flags3{TestEnum::Bit4};
298 BOOST_CHECK(!flags1.contains(flags3)); // flags1 does not contain flags3
299 }
300
301 {
302 // Test compilation using an enum with more than 32 bits
304 test.set("Bit32");
306 }
307}
Classs to aggregate and manage enum-based on-off flags.
Definition EnumFlags.h:348
GLdouble n
Definition glcorearb.h:1982
const GLdouble * v
Definition glcorearb.h:832
GLbitfield flags
Definition glcorearb.h:1570
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
FIXME: do not use data model tables.
TestEnum
@ Bit5VeryLongName
TestEnumLong
BOOST_AUTO_TEST_CASE(Flags_test)
BOOST_CHECK(tree)
BOOST_TEST(digits==digitsD, boost::test_tools::per_element())
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())
const std::string str