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