1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/utils/enum_set.h"
16
17 #include <sstream>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21
22 namespace tint {
23 namespace utils {
24 namespace {
25
26 using ::testing::ElementsAre;
27
28 enum class E { A = 0, B = 3, C = 7 };
29
operator <<(std::ostream & out,E e)30 std::ostream& operator<<(std::ostream& out, E e) {
31 switch (e) {
32 case E::A:
33 return out << "A";
34 case E::B:
35 return out << "B";
36 case E::C:
37 return out << "C";
38 }
39 return out << "E(" << static_cast<uint32_t>(e) << ")";
40 }
41
TEST(EnumSetTest,ConstructEmpty)42 TEST(EnumSetTest, ConstructEmpty) {
43 EnumSet<E> set;
44 EXPECT_FALSE(set.Contains(E::A));
45 EXPECT_FALSE(set.Contains(E::B));
46 EXPECT_FALSE(set.Contains(E::C));
47 EXPECT_TRUE(set.Empty());
48 }
49
TEST(EnumSetTest,ConstructWithSingle)50 TEST(EnumSetTest, ConstructWithSingle) {
51 EnumSet<E> set(E::B);
52 EXPECT_FALSE(set.Contains(E::A));
53 EXPECT_TRUE(set.Contains(E::B));
54 EXPECT_FALSE(set.Contains(E::C));
55 EXPECT_FALSE(set.Empty());
56 }
57
TEST(EnumSetTest,ConstructWithMultiple)58 TEST(EnumSetTest, ConstructWithMultiple) {
59 EnumSet<E> set(E::A, E::C);
60 EXPECT_TRUE(set.Contains(E::A));
61 EXPECT_FALSE(set.Contains(E::B));
62 EXPECT_TRUE(set.Contains(E::C));
63 EXPECT_FALSE(set.Empty());
64 }
65
TEST(EnumSetTest,AssignSet)66 TEST(EnumSetTest, AssignSet) {
67 EnumSet<E> set;
68 set = EnumSet<E>(E::A, E::C);
69 EXPECT_TRUE(set.Contains(E::A));
70 EXPECT_FALSE(set.Contains(E::B));
71 EXPECT_TRUE(set.Contains(E::C));
72 }
73
TEST(EnumSetTest,AssignEnum)74 TEST(EnumSetTest, AssignEnum) {
75 EnumSet<E> set(E::A);
76 set = E::B;
77 EXPECT_FALSE(set.Contains(E::A));
78 EXPECT_TRUE(set.Contains(E::B));
79 EXPECT_FALSE(set.Contains(E::C));
80 }
81
TEST(EnumSetTest,AddEnum)82 TEST(EnumSetTest, AddEnum) {
83 EnumSet<E> set;
84 set.Add(E::B);
85 EXPECT_FALSE(set.Contains(E::A));
86 EXPECT_TRUE(set.Contains(E::B));
87 EXPECT_FALSE(set.Contains(E::C));
88 }
89
TEST(EnumSetTest,RemoveEnum)90 TEST(EnumSetTest, RemoveEnum) {
91 EnumSet<E> set(E::A, E::B);
92 set.Remove(E::B);
93 EXPECT_TRUE(set.Contains(E::A));
94 EXPECT_FALSE(set.Contains(E::B));
95 EXPECT_FALSE(set.Contains(E::C));
96 }
97
TEST(EnumSetTest,AddEnums)98 TEST(EnumSetTest, AddEnums) {
99 EnumSet<E> set;
100 set.Add(E::B, E::C);
101 EXPECT_FALSE(set.Contains(E::A));
102 EXPECT_TRUE(set.Contains(E::B));
103 EXPECT_TRUE(set.Contains(E::C));
104 }
105
TEST(EnumSetTest,RemoveEnums)106 TEST(EnumSetTest, RemoveEnums) {
107 EnumSet<E> set(E::A, E::B);
108 set.Remove(E::C, E::B);
109 EXPECT_TRUE(set.Contains(E::A));
110 EXPECT_FALSE(set.Contains(E::B));
111 EXPECT_FALSE(set.Contains(E::C));
112 }
113
TEST(EnumSetTest,AddEnumSet)114 TEST(EnumSetTest, AddEnumSet) {
115 EnumSet<E> set;
116 set.Add(EnumSet<E>{E::B, E::C});
117 EXPECT_FALSE(set.Contains(E::A));
118 EXPECT_TRUE(set.Contains(E::B));
119 EXPECT_TRUE(set.Contains(E::C));
120 }
121
TEST(EnumSetTest,RemoveEnumSet)122 TEST(EnumSetTest, RemoveEnumSet) {
123 EnumSet<E> set(E::A, E::B);
124 set.Remove(EnumSet<E>{E::B, E::C});
125 EXPECT_TRUE(set.Contains(E::A));
126 EXPECT_FALSE(set.Contains(E::B));
127 EXPECT_FALSE(set.Contains(E::C));
128 }
129
TEST(EnumSetTest,OperatorPlusEnum)130 TEST(EnumSetTest, OperatorPlusEnum) {
131 EnumSet<E> set = EnumSet<E>{E::B} + E::C;
132 EXPECT_FALSE(set.Contains(E::A));
133 EXPECT_TRUE(set.Contains(E::B));
134 EXPECT_TRUE(set.Contains(E::C));
135 }
136
TEST(EnumSetTest,OperatorMinusEnum)137 TEST(EnumSetTest, OperatorMinusEnum) {
138 EnumSet<E> set = EnumSet<E>{E::A, E::B} - E::B;
139 EXPECT_TRUE(set.Contains(E::A));
140 EXPECT_FALSE(set.Contains(E::B));
141 EXPECT_FALSE(set.Contains(E::C));
142 }
143
TEST(EnumSetTest,OperatorPlusSet)144 TEST(EnumSetTest, OperatorPlusSet) {
145 EnumSet<E> set = EnumSet<E>{E::B} + EnumSet<E>{E::B, E::C};
146 EXPECT_FALSE(set.Contains(E::A));
147 EXPECT_TRUE(set.Contains(E::B));
148 EXPECT_TRUE(set.Contains(E::C));
149 }
150
TEST(EnumSetTest,OperatorMinusSet)151 TEST(EnumSetTest, OperatorMinusSet) {
152 EnumSet<E> set = EnumSet<E>{E::A, E::B} - EnumSet<E>{E::B, E::C};
153 EXPECT_TRUE(set.Contains(E::A));
154 EXPECT_FALSE(set.Contains(E::B));
155 EXPECT_FALSE(set.Contains(E::C));
156 }
157
TEST(EnumSetTest,OperatorAnd)158 TEST(EnumSetTest, OperatorAnd) {
159 EnumSet<E> set = EnumSet<E>{E::A, E::B} & EnumSet<E>{E::B, E::C};
160 EXPECT_FALSE(set.Contains(E::A));
161 EXPECT_TRUE(set.Contains(E::B));
162 EXPECT_FALSE(set.Contains(E::C));
163 }
164
TEST(EnumSetTest,EqualitySet)165 TEST(EnumSetTest, EqualitySet) {
166 EXPECT_TRUE(EnumSet<E>(E::A, E::B) == EnumSet<E>(E::A, E::B));
167 EXPECT_FALSE(EnumSet<E>(E::A, E::B) == EnumSet<E>(E::A, E::C));
168 }
169
TEST(EnumSetTest,InequalitySet)170 TEST(EnumSetTest, InequalitySet) {
171 EXPECT_FALSE(EnumSet<E>(E::A, E::B) != EnumSet<E>(E::A, E::B));
172 EXPECT_TRUE(EnumSet<E>(E::A, E::B) != EnumSet<E>(E::A, E::C));
173 }
174
TEST(EnumSetTest,EqualityEnum)175 TEST(EnumSetTest, EqualityEnum) {
176 EXPECT_TRUE(EnumSet<E>(E::A) == E::A);
177 EXPECT_FALSE(EnumSet<E>(E::B) == E::A);
178 EXPECT_FALSE(EnumSet<E>(E::B) == E::C);
179 EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::A);
180 EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::B);
181 EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::C);
182 }
183
TEST(EnumSetTest,InequalityEnum)184 TEST(EnumSetTest, InequalityEnum) {
185 EXPECT_FALSE(EnumSet<E>(E::A) != E::A);
186 EXPECT_TRUE(EnumSet<E>(E::B) != E::A);
187 EXPECT_TRUE(EnumSet<E>(E::B) != E::C);
188 EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::A);
189 EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::B);
190 EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::C);
191 }
192
TEST(EnumSetTest,Hash)193 TEST(EnumSetTest, Hash) {
194 auto hash = [&](EnumSet<E> s) { return std::hash<EnumSet<E>>()(s); };
195 EXPECT_EQ(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::B)));
196 EXPECT_NE(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::C)));
197 }
198
TEST(EnumSetTest,Value)199 TEST(EnumSetTest, Value) {
200 EXPECT_EQ(EnumSet<E>().Value(), 0u);
201 EXPECT_EQ(EnumSet<E>(E::A).Value(), 1u);
202 EXPECT_EQ(EnumSet<E>(E::B).Value(), 8u);
203 EXPECT_EQ(EnumSet<E>(E::C).Value(), 128u);
204 EXPECT_EQ(EnumSet<E>(E::A, E::C).Value(), 129u);
205 }
206
TEST(EnumSetTest,Iterator)207 TEST(EnumSetTest, Iterator) {
208 auto set = EnumSet<E>(E::C, E::A);
209
210 auto it = set.begin();
211 EXPECT_EQ(*it, E::A);
212 EXPECT_NE(it, set.end());
213 ++it;
214 EXPECT_EQ(*it, E::C);
215 EXPECT_NE(it, set.end());
216 ++it;
217 EXPECT_EQ(it, set.end());
218 }
219
TEST(EnumSetTest,IteratorEmpty)220 TEST(EnumSetTest, IteratorEmpty) {
221 auto set = EnumSet<E>();
222 EXPECT_EQ(set.begin(), set.end());
223 }
224
TEST(EnumSetTest,Loop)225 TEST(EnumSetTest, Loop) {
226 auto set = EnumSet<E>(E::C, E::A);
227
228 std::vector<E> seen;
229 for (auto e : set) {
230 seen.emplace_back(e);
231 }
232
233 EXPECT_THAT(seen, ElementsAre(E::A, E::C));
234 }
235
TEST(EnumSetTest,Ostream)236 TEST(EnumSetTest, Ostream) {
237 std::stringstream ss;
238 ss << EnumSet<E>(E::A, E::C);
239 EXPECT_EQ(ss.str(), "{A, C}");
240 }
241
242 } // namespace
243 } // namespace utils
244 } // namespace tint
245