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