• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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