1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "brillo/enum_flags.h"
6
7 #include <gtest/gtest.h>
8
9 namespace brillo {
10
11 class EnumFlagsTest : public testing::Test {};
12
13 enum SomeFlagsEnum /* : int */ {
14 FLAG_NONE = 0,
15 FLAG_ONE = 1,
16 FLAG_TWO = 2,
17 FLAG_THREE = 4,
18 };
19
20 enum class SomeFlagsEnumClass /* : int */ {
21 NONE = 0,
22 ONE = 1,
23 TWO = 2,
24 THREE = 4,
25 };
26
27 enum SomeBigFlagsEnum : int64_t {
28 BIG_FLAG_NONE = 0,
29 BIG_FLAG_ONE = 1,
30 BIG_FLAG_TWO = 2,
31 BIG_FLAG_THREE = 4,
32 BIG_FLAG_FOUR = 8,
33 };
34
35 DECLARE_FLAGS_ENUM(SomeFlagsEnum);
36 DECLARE_FLAGS_ENUM(SomeFlagsEnumClass);
37 DECLARE_FLAGS_ENUM(SomeBigFlagsEnum);
38
39 // These first tests show how these operators are meant to be used.
40
TEST_F(EnumFlagsTest,SampleUsage)41 TEST_F(EnumFlagsTest, SampleUsage) {
42 SomeFlagsEnum value = FLAG_NONE;
43
44 // Set a flag.
45 value |= FLAG_ONE;
46 EXPECT_EQ(FLAG_ONE, value);
47
48 // Set another
49 value |= FLAG_THREE;
50 EXPECT_EQ(FLAG_ONE | FLAG_THREE, value);
51
52 // Clear a flag
53 value &= ~FLAG_ONE;
54 EXPECT_EQ(FLAG_THREE, value);
55
56 // Toggle a flag
57 value ^= FLAG_TWO;
58 EXPECT_EQ(FLAG_THREE | FLAG_TWO, value);
59 }
60
TEST_F(EnumFlagsTest,SampleUsageOfMasks)61 TEST_F(EnumFlagsTest, SampleUsageOfMasks) {
62 SomeFlagsEnum flags = FLAG_ONE | FLAG_THREE;
63
64 EXPECT_TRUE(flags & FLAG_ONE);
65 EXPECT_TRUE(flags & FLAG_THREE);
66 EXPECT_FALSE(flags & FLAG_TWO);
67 EXPECT_TRUE(flags & ~FLAG_TWO);
68 }
69
TEST_F(EnumFlagsTest,SampleUsageWithEnumClass)70 TEST_F(EnumFlagsTest, SampleUsageWithEnumClass) {
71 SomeFlagsEnumClass value = SomeFlagsEnumClass::NONE;
72
73 // Set a flag.
74 value |= SomeFlagsEnumClass::ONE;
75 EXPECT_EQ(SomeFlagsEnumClass::ONE, value);
76
77 // Set another
78 value |= SomeFlagsEnumClass::THREE;
79 EXPECT_EQ(SomeFlagsEnumClass::ONE | SomeFlagsEnumClass::THREE, value);
80
81 // Clear a flag
82 value &= ~SomeFlagsEnumClass::ONE;
83 EXPECT_EQ(SomeFlagsEnumClass::THREE, value);
84
85 // Toggle a flag
86 value ^= SomeFlagsEnumClass::TWO;
87 EXPECT_EQ(SomeFlagsEnumClass::THREE | SomeFlagsEnumClass::TWO, value);
88 }
89
TEST_F(EnumFlagsTest,SampleUsageWithBigEnumType)90 TEST_F(EnumFlagsTest, SampleUsageWithBigEnumType) {
91 SomeBigFlagsEnum value = BIG_FLAG_NONE;
92
93 // Set a flag.
94 value |= BIG_FLAG_ONE;
95 EXPECT_EQ(BIG_FLAG_ONE, value);
96
97 // Set another
98 value |= BIG_FLAG_THREE;
99 EXPECT_EQ(FLAG_ONE | BIG_FLAG_THREE, value);
100
101 // Clear a flag
102 value &= ~BIG_FLAG_ONE;
103 EXPECT_EQ(BIG_FLAG_THREE, value);
104
105 // Toggle a flag
106 value ^= BIG_FLAG_TWO;
107 EXPECT_EQ(BIG_FLAG_THREE | BIG_FLAG_TWO, value);
108 }
109
110 // These following tests verify the binary behavior of the operators. They do
111 // not demonstrate standard usage.
112
TEST_F(EnumFlagsTest,BinaryBehaviorOfAssignmentOperators)113 TEST_F(EnumFlagsTest, BinaryBehaviorOfAssignmentOperators) {
114 SomeFlagsEnum value = FLAG_NONE;
115
116 // Set a flag.
117 value |= FLAG_ONE;
118 EXPECT_EQ(1, value);
119
120 // Set another
121 value |= FLAG_THREE;
122 EXPECT_EQ(5, value);
123
124 // Clear a flag
125 value &= ~FLAG_ONE;
126 EXPECT_EQ(4, value);
127
128 // Toggle a flag
129 value ^= FLAG_TWO;
130 EXPECT_EQ(6, value);
131 }
132
TEST_F(EnumFlagsTest,BinaryBehaviorOfAssignmentOperatorsWithEnumClass)133 TEST_F(EnumFlagsTest, BinaryBehaviorOfAssignmentOperatorsWithEnumClass) {
134 SomeFlagsEnumClass value = SomeFlagsEnumClass::NONE;
135
136 // Set a flag.
137 value |= SomeFlagsEnumClass::ONE;
138 EXPECT_EQ(1, static_cast<int>(value)); //
139
140 // Set another
141 value |= SomeFlagsEnumClass::THREE;
142 EXPECT_EQ(5, static_cast<int>(value));
143
144 // Clear a flag
145 value &= ~SomeFlagsEnumClass::ONE;
146 EXPECT_EQ(4, static_cast<int>(value));
147
148 // Toggle a flag
149 value ^= SomeFlagsEnumClass::TWO;
150 EXPECT_EQ(6, static_cast<int>(value));
151 }
152
TEST_F(EnumFlagsTest,BinaryBehaviorOfSimpleOperations)153 TEST_F(EnumFlagsTest, BinaryBehaviorOfSimpleOperations) {
154 // These values are set directly with a cast for clarity.
155 const int all_bits_int = -1;
156 const SomeFlagsEnum all_bits = static_cast<SomeFlagsEnum>(all_bits_int);
157 const SomeFlagsEnum just_2_bits = static_cast<SomeFlagsEnum>(3);
158
159 // Inverting a flag should result in all bits set in the base type but that
160 // one.
161 EXPECT_EQ(-2, ~FLAG_ONE);
162 EXPECT_EQ(-3, ~FLAG_TWO);
163
164 // OR'ing two flags should result in both being set.
165 EXPECT_EQ(3, FLAG_ONE | FLAG_TWO);
166
167 // AND'ing two flags should result in 0.
168 EXPECT_EQ(FLAG_NONE, FLAG_ONE & FLAG_TWO);
169
170 // AND'ing a mask with a flag should result in that flag.
171 EXPECT_EQ(FLAG_ONE, all_bits & FLAG_ONE);
172
173 // XOR'ing two flags should result in both being set.
174 EXPECT_EQ(3, FLAG_ONE ^ FLAG_TWO);
175
176 // XOR'ing a mask with a flag should toggle that flag in the mask.
177 EXPECT_EQ(FLAG_ONE, FLAG_NONE ^ FLAG_ONE);
178 EXPECT_EQ(FLAG_TWO, just_2_bits ^ FLAG_ONE);
179 }
180
TEST_F(EnumFlagsTest,BinaryBehaviorOfSimpleOperationsOnEnumClass)181 TEST_F(EnumFlagsTest, BinaryBehaviorOfSimpleOperationsOnEnumClass) {
182 // These values are set directly with a cast for clarity.
183 const int all_bits_int = -1;
184 const SomeFlagsEnumClass all_bits =
185 static_cast<SomeFlagsEnumClass>(all_bits_int);
186 const SomeFlagsEnumClass just_2_bits = static_cast<SomeFlagsEnumClass>(3);
187
188 // Inverting a flag should result in all bits set in the base type but that
189 // one.
190 EXPECT_EQ(-2, static_cast<int>(~SomeFlagsEnumClass::ONE));
191 EXPECT_EQ(-3, static_cast<int>(~SomeFlagsEnumClass::TWO));
192
193 // OR'ing two flags should result in both being set.
194 EXPECT_EQ(
195 3, static_cast<int>(SomeFlagsEnumClass::ONE | SomeFlagsEnumClass::TWO));
196
197 // AND'ing two flags should result in 0.
198 EXPECT_EQ(SomeFlagsEnumClass::NONE,
199 SomeFlagsEnumClass::ONE & SomeFlagsEnumClass::TWO);
200
201 // AND'ing a mask with a flag should result in that flag.
202 EXPECT_EQ(SomeFlagsEnumClass::ONE, all_bits & SomeFlagsEnumClass::ONE);
203
204 // XOR'ing two flags should result in both being set.
205 EXPECT_EQ(
206 3, static_cast<int>(SomeFlagsEnumClass::ONE ^ SomeFlagsEnumClass::TWO));
207
208 // XOR'ing a mask with a flag should toggle that flag in the mask.
209 EXPECT_EQ(SomeFlagsEnumClass::ONE,
210 SomeFlagsEnumClass::NONE ^ SomeFlagsEnumClass::ONE);
211 EXPECT_EQ(SomeFlagsEnumClass::TWO, just_2_bits ^ SomeFlagsEnumClass::ONE);
212 }
213
TEST_F(EnumFlagsTest,BinaryBehaviorOfSimpleOperationsWithBaseType)214 TEST_F(EnumFlagsTest, BinaryBehaviorOfSimpleOperationsWithBaseType) {
215 // These values are set directly with a cast for clarity.
216 const int64_t all_bits_int = -1;
217 const SomeBigFlagsEnum all_bits = static_cast<SomeBigFlagsEnum>(all_bits_int);
218 const SomeBigFlagsEnum just_2_bits = static_cast<SomeBigFlagsEnum>(3);
219
220 // Inverting a flag should result in all bits set in the base type but that
221 // one.
222 EXPECT_EQ(all_bits ^ BIG_FLAG_ONE, ~BIG_FLAG_ONE);
223
224 // OR'ing two flags should result in both being set.
225 EXPECT_EQ(3, BIG_FLAG_ONE | BIG_FLAG_TWO);
226
227 // AND'ing two flags should result in 0.
228 EXPECT_EQ(BIG_FLAG_NONE, BIG_FLAG_ONE & BIG_FLAG_TWO);
229
230 // AND'ing a mask with a flag should result in that flag.
231 EXPECT_EQ(BIG_FLAG_ONE, all_bits & BIG_FLAG_ONE);
232
233 // XOR'ing two flags should result in both being set.
234 EXPECT_EQ(3, BIG_FLAG_ONE ^ BIG_FLAG_TWO);
235
236 // XOR'ing a mask with a flag should toggle that flag in the mask.
237 EXPECT_EQ(BIG_FLAG_ONE, BIG_FLAG_NONE ^ BIG_FLAG_ONE);
238 EXPECT_EQ(BIG_FLAG_TWO, just_2_bits ^ BIG_FLAG_ONE);
239 }
240
241 } // namespace brillo
242