// Copyright 2021 The Tint Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "src/tint/utils/enum_set.h" #include #include #include "gmock/gmock.h" namespace tint::utils { namespace { using ::testing::ElementsAre; enum class E { A = 0, B = 3, C = 7 }; std::ostream& operator<<(std::ostream& out, E e) { switch (e) { case E::A: return out << "A"; case E::B: return out << "B"; case E::C: return out << "C"; } return out << "E(" << static_cast(e) << ")"; } TEST(EnumSetTest, ConstructEmpty) { EnumSet set; EXPECT_FALSE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); EXPECT_TRUE(set.Empty()); } TEST(EnumSetTest, ConstructWithSingle) { EnumSet set(E::B); EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); EXPECT_FALSE(set.Empty()); } TEST(EnumSetTest, ConstructWithMultiple) { EnumSet set(E::A, E::C); EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); EXPECT_FALSE(set.Empty()); } TEST(EnumSetTest, AssignSet) { EnumSet set; set = EnumSet(E::A, E::C); EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); } TEST(EnumSetTest, AssignEnum) { EnumSet set(E::A); set = E::B; EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, AddEnum) { EnumSet set; set.Add(E::B); EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, RemoveEnum) { EnumSet set(E::A, E::B); set.Remove(E::B); EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, AddEnums) { EnumSet set; set.Add(E::B, E::C); EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); } TEST(EnumSetTest, RemoveEnums) { EnumSet set(E::A, E::B); set.Remove(E::C, E::B); EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, AddEnumSet) { EnumSet set; set.Add(EnumSet{E::B, E::C}); EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); } TEST(EnumSetTest, RemoveEnumSet) { EnumSet set(E::A, E::B); set.Remove(EnumSet{E::B, E::C}); EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, OperatorPlusEnum) { EnumSet set = EnumSet{E::B} + E::C; EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); } TEST(EnumSetTest, OperatorMinusEnum) { EnumSet set = EnumSet{E::A, E::B} - E::B; EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, OperatorPlusSet) { EnumSet set = EnumSet{E::B} + EnumSet{E::B, E::C}; EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_TRUE(set.Contains(E::C)); } TEST(EnumSetTest, OperatorMinusSet) { EnumSet set = EnumSet{E::A, E::B} - EnumSet{E::B, E::C}; EXPECT_TRUE(set.Contains(E::A)); EXPECT_FALSE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, OperatorAnd) { EnumSet set = EnumSet{E::A, E::B} & EnumSet{E::B, E::C}; EXPECT_FALSE(set.Contains(E::A)); EXPECT_TRUE(set.Contains(E::B)); EXPECT_FALSE(set.Contains(E::C)); } TEST(EnumSetTest, EqualitySet) { EXPECT_TRUE(EnumSet(E::A, E::B) == EnumSet(E::A, E::B)); EXPECT_FALSE(EnumSet(E::A, E::B) == EnumSet(E::A, E::C)); } TEST(EnumSetTest, InequalitySet) { EXPECT_FALSE(EnumSet(E::A, E::B) != EnumSet(E::A, E::B)); EXPECT_TRUE(EnumSet(E::A, E::B) != EnumSet(E::A, E::C)); } TEST(EnumSetTest, EqualityEnum) { EXPECT_TRUE(EnumSet(E::A) == E::A); EXPECT_FALSE(EnumSet(E::B) == E::A); EXPECT_FALSE(EnumSet(E::B) == E::C); EXPECT_FALSE(EnumSet(E::A, E::B) == E::A); EXPECT_FALSE(EnumSet(E::A, E::B) == E::B); EXPECT_FALSE(EnumSet(E::A, E::B) == E::C); } TEST(EnumSetTest, InequalityEnum) { EXPECT_FALSE(EnumSet(E::A) != E::A); EXPECT_TRUE(EnumSet(E::B) != E::A); EXPECT_TRUE(EnumSet(E::B) != E::C); EXPECT_TRUE(EnumSet(E::A, E::B) != E::A); EXPECT_TRUE(EnumSet(E::A, E::B) != E::B); EXPECT_TRUE(EnumSet(E::A, E::B) != E::C); } TEST(EnumSetTest, Hash) { auto hash = [&](EnumSet s) { return std::hash>()(s); }; EXPECT_EQ(hash(EnumSet(E::A, E::B)), hash(EnumSet(E::A, E::B))); EXPECT_NE(hash(EnumSet(E::A, E::B)), hash(EnumSet(E::A, E::C))); } TEST(EnumSetTest, Value) { EXPECT_EQ(EnumSet().Value(), 0u); EXPECT_EQ(EnumSet(E::A).Value(), 1u); EXPECT_EQ(EnumSet(E::B).Value(), 8u); EXPECT_EQ(EnumSet(E::C).Value(), 128u); EXPECT_EQ(EnumSet(E::A, E::C).Value(), 129u); } TEST(EnumSetTest, Iterator) { auto set = EnumSet(E::C, E::A); auto it = set.begin(); EXPECT_EQ(*it, E::A); EXPECT_NE(it, set.end()); ++it; EXPECT_EQ(*it, E::C); EXPECT_NE(it, set.end()); ++it; EXPECT_EQ(it, set.end()); } TEST(EnumSetTest, IteratorEmpty) { auto set = EnumSet(); EXPECT_EQ(set.begin(), set.end()); } TEST(EnumSetTest, Loop) { auto set = EnumSet(E::C, E::A); std::vector seen; for (auto e : set) { seen.emplace_back(e); } EXPECT_THAT(seen, ElementsAre(E::A, E::C)); } TEST(EnumSetTest, Ostream) { std::stringstream ss; ss << EnumSet(E::A, E::C); EXPECT_EQ(ss.str(), "{A, C}"); } } // namespace } // namespace tint::utils