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
32{
33 using EFlags = o2::utils::EnumFlags<TestEnum>;
34
35 // Test default initialization
36 EFlags flags;
37 BOOST_TEST(flags.None == 0);
38 BOOST_TEST(flags.All == 31);
39 BOOST_TEST(flags.value() == 0);
40 BOOST_TEST(!flags.any());
41
42 // Test initialization with a single flag
43 EFlags flag1(TestEnum::Bit1);
44 BOOST_TEST(flag1.test(TestEnum::Bit1));
45 BOOST_TEST(!flag1.test(TestEnum::Bit2));
46 BOOST_TEST(flag1.value() == (1 << static_cast<unsigned int>(TestEnum::Bit1)));
47
48 // Test initialization with initializer list
49 EFlags multipleFlags({TestEnum::Bit1, TestEnum::Bit3});
50 BOOST_TEST(multipleFlags.test(TestEnum::Bit1));
51 BOOST_TEST(multipleFlags.test(TestEnum::Bit3));
52 BOOST_TEST(!multipleFlags.test(TestEnum::Bit2));
53 BOOST_TEST(multipleFlags.any());
54
55 // Test reset
56 multipleFlags.reset(TestEnum::Bit1);
57 BOOST_TEST(!multipleFlags.test(TestEnum::Bit1));
58 BOOST_TEST(multipleFlags.test(TestEnum::Bit3));
59 multipleFlags.reset();
60 BOOST_TEST(!multipleFlags.any());
61
62 // Test operator|
63 EFlags combinedFlags = flag1 | EFlags(TestEnum::Bit2);
64 BOOST_TEST(combinedFlags.test(TestEnum::Bit1));
65 BOOST_TEST(combinedFlags.test(TestEnum::Bit2));
66 BOOST_TEST(!combinedFlags.test(TestEnum::Bit3));
67
68 // Test operator[]
69 BOOST_TEST(combinedFlags[TestEnum::Bit1]);
70 BOOST_TEST(combinedFlags[TestEnum::Bit2]);
71 BOOST_TEST(!combinedFlags[TestEnum::Bit3]);
72
73 // Test operator|=
74 combinedFlags |= TestEnum::Bit3;
75 BOOST_TEST(combinedFlags.test(TestEnum::Bit3));
76
77 // Test operator&
78 EFlags intersection = combinedFlags & TestEnum::Bit1;
79 BOOST_TEST(intersection.test(TestEnum::Bit1));
80 BOOST_TEST(!intersection.test(TestEnum::Bit2));
81 BOOST_TEST(intersection.value() == (1 << static_cast<unsigned int>(TestEnum::Bit1)));
82
83 // Test operator&=
84 combinedFlags &= TestEnum::Bit1;
85 BOOST_TEST(combinedFlags.test(TestEnum::Bit1));
86 BOOST_TEST(!combinedFlags.test(TestEnum::Bit2));
87 BOOST_TEST(!combinedFlags.test(TestEnum::Bit3));
88
89 // Test operator~ (complement)
90 EFlags complement = ~EFlags(TestEnum::Bit1);
91 BOOST_TEST(!complement.test(TestEnum::Bit1));
92 BOOST_TEST(complement.test(TestEnum::Bit2));
93 BOOST_TEST(complement.test(TestEnum::Bit3));
94
95 // Test string() method
96 {
97 std::string flagString = flag1.string();
98 BOOST_TEST(flagString.back() == '1'); // Ensure the least significant bit is set for flag1
99 }
100
101 // Test set with binary string
102 {
103 std::string binaryStr = "101";
104 flags.set(binaryStr, 2);
108 }
109
110 // Test invalid binary string in set
111 BOOST_CHECK_THROW(flags.set(std::string("invalid"), 2), std::invalid_argument);
112
113 // Test range validation in set
114 BOOST_CHECK_THROW(flags.set(std::string("100000000"), 2), std::out_of_range);
115
116 { // Test that return lists are sensible
117 const auto n = flags.getNames();
118 const auto v = flags.getValues();
119 BOOST_CHECK(n.size() == v.size());
120 }
121
122 { // print test
123 std::cout << flags;
124 }
125
126 // Test flag tokenization and parsing
127 {
128 { // only one scoped flag
129 std::string str = "TestEnum::Bit2";
130 flags.set(str);
133 }
134
135 { // test with ws-triming and scope mixing
136 std::string str = "Bit4|TestEnum::Bit2 | Bit1 ";
137 flags.set(str);
142 }
143
144 { // test with different delimiter
145 std::string str = "Bit4,TestEnum::Bit2 , Bit1 ";
146 flags.set(str);
151 }
152
153 { // throw test with mixed delimiter
154 std::string str = "Bit4|TestEnum::Bit2 , Bit1 ";
155 BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
156 }
157
158 { // test throw
159 std::string str = "Invalid";
160 BOOST_CHECK_THROW(flags.set(str), std::invalid_argument);
161 }
162 }
163
164 // Test all_of and none_of
165 {
166 EFlags allFlags({TestEnum::Bit1, TestEnum::Bit2, TestEnum::Bit3});
167 BOOST_TEST(allFlags.all_of(TestEnum::Bit1, TestEnum::Bit2));
168 BOOST_TEST(!allFlags.all_of(TestEnum::Bit4));
169 BOOST_TEST(allFlags.none_of(TestEnum::Bit4));
170 }
171
172 // Test toggle
173 {
174 EFlags toggleFlags;
175 toggleFlags.toggle(TestEnum::Bit4);
176 BOOST_TEST(toggleFlags.test(TestEnum::Bit4));
177 toggleFlags.toggle(TestEnum::Bit4);
178 BOOST_TEST(!toggleFlags.test(TestEnum::Bit4));
179 }
180
181 // Create a flag set and serialize it
182 {
183 EFlags serializedFlags{TestEnum::Bit1, TestEnum::Bit3};
184 std::string serialized = serializedFlags.serialize();
185 BOOST_CHECK_EQUAL(serialized, "5"); // 5 in binary is 0101, meaning Bit1 and Bit3 are set.
186
187 // Deserialize back into a flag set
188 EFlags deserializedFlags;
189 deserializedFlags.deserialize(serialized);
190 BOOST_CHECK(deserializedFlags == serializedFlags); // Ensure the deserialized flags match the original
191 }
192
193 // Test with an empty flag set
194 {
195 EFlags emptyFlags;
196 std::string serialized = emptyFlags.serialize();
197 BOOST_CHECK_EQUAL(serialized, "0");
198
199 EFlags deserialized;
200 deserialized.deserialize(serialized);
201 BOOST_CHECK(deserialized == emptyFlags);
202
203 // Test with all flags set
204 EFlags allFlags(EFlags::All);
205 serialized = allFlags.serialize();
206 BOOST_CHECK_EQUAL(serialized, std::to_string(EFlags::All));
207
208 deserialized.deserialize(serialized);
209 BOOST_CHECK(deserialized == allFlags);
210 }
211
212 // check throw deserializng out of range
213 {
214 EFlags flag;
215 std::string str = "999999";
216 BOOST_CHECK_THROW(flag.deserialize(str), std::out_of_range);
217 }
218
219 // Create two flag sets
220 {
221 EFlags flags1{TestEnum::Bit1, TestEnum::Bit2};
222 EFlags flags2{TestEnum::Bit3, TestEnum::Bit4};
223
224 // Perform a union operation
225 EFlags unionFlags = flags1.union_with(flags2);
226 BOOST_CHECK(unionFlags.test(TestEnum::Bit1));
227 BOOST_CHECK(unionFlags.test(TestEnum::Bit2));
228 BOOST_CHECK(unionFlags.test(TestEnum::Bit3));
229 BOOST_CHECK(unionFlags.test(TestEnum::Bit4));
230 BOOST_CHECK_EQUAL(unionFlags.value(), 15); // 1111 in binary
231 }
232
233 // Create two overlapping flag sets
234 {
237
238 // Perform an intersection operation
239 EFlags intersectionFlags = flags3.intersection_with(flags4);
240 BOOST_CHECK(intersectionFlags.test(TestEnum::Bit2));
241 BOOST_CHECK(intersectionFlags.test(TestEnum::Bit3));
242 BOOST_CHECK(!intersectionFlags.test(TestEnum::Bit1));
243 BOOST_CHECK(!intersectionFlags.test(TestEnum::Bit4));
244 BOOST_CHECK_EQUAL(intersectionFlags.value(), 6); // 0110 in binary
245 }
246
247 {
248 // Create two flag sets
250 EFlags flags2{TestEnum::Bit2, TestEnum::Bit3};
251
252 // Check containment
253 BOOST_CHECK(flags1.contains(flags2)); // flags1 contains all flags in flags2
254 BOOST_CHECK(!flags2.contains(flags1)); // flags2 does not contain all flags in flags1
255
256 // Test with disjoint sets
257 EFlags flags3{TestEnum::Bit4};
258 BOOST_CHECK(!flags1.contains(flags3)); // flags1 does not contain flags3
259 }
260}
Classs to aggregate and manage enum-based on-off flags.
Definition EnumFlags.h:347
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
TestEnum
@ Bit5VeryLongName
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