| // Copyright 2017 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "brillo/enum_flags.h" | |
| #include <gtest/gtest.h> | |
| namespace brillo { | |
| class EnumFlagsTest : public testing::Test {}; | |
| enum SomeFlagsEnum /* : int */ { | |
| FLAG_NONE = 0, | |
| FLAG_ONE = 1, | |
| FLAG_TWO = 2, | |
| FLAG_THREE = 4, | |
| }; | |
| enum class SomeFlagsEnumClass /* : int */ { | |
| NONE = 0, | |
| ONE = 1, | |
| TWO = 2, | |
| THREE = 4, | |
| }; | |
| enum SomeBigFlagsEnum : int64_t { | |
| BIG_FLAG_NONE = 0, | |
| BIG_FLAG_ONE = 1, | |
| BIG_FLAG_TWO = 2, | |
| BIG_FLAG_THREE = 4, | |
| BIG_FLAG_FOUR = 8, | |
| }; | |
| DECLARE_FLAGS_ENUM(SomeFlagsEnum); | |
| DECLARE_FLAGS_ENUM(SomeFlagsEnumClass); | |
| DECLARE_FLAGS_ENUM(SomeBigFlagsEnum); | |
| // These first tests show how these operators are meant to be used. | |
| TEST_F(EnumFlagsTest, SampleUsage) { | |
| SomeFlagsEnum value = FLAG_NONE; | |
| // Set a flag. | |
| value |= FLAG_ONE; | |
| EXPECT_EQ(FLAG_ONE, value); | |
| // Set another | |
| value |= FLAG_THREE; | |
| EXPECT_EQ(FLAG_ONE | FLAG_THREE, value); | |
| // Clear a flag | |
| value &= ~FLAG_ONE; | |
| EXPECT_EQ(FLAG_THREE, value); | |
| // Toggle a flag | |
| value ^= FLAG_TWO; | |
| EXPECT_EQ(FLAG_THREE | FLAG_TWO, value); | |
| } | |
| TEST_F(EnumFlagsTest, SampleUsageOfMasks) { | |
| SomeFlagsEnum flags = FLAG_ONE | FLAG_THREE; | |
| EXPECT_TRUE(flags & FLAG_ONE); | |
| EXPECT_TRUE(flags & FLAG_THREE); | |
| EXPECT_FALSE(flags & FLAG_TWO); | |
| EXPECT_TRUE(flags & ~FLAG_TWO); | |
| } | |
| TEST_F(EnumFlagsTest, SampleUsageWithEnumClass) { | |
| SomeFlagsEnumClass value = SomeFlagsEnumClass::NONE; | |
| // Set a flag. | |
| value |= SomeFlagsEnumClass::ONE; | |
| EXPECT_EQ(SomeFlagsEnumClass::ONE, value); | |
| // Set another | |
| value |= SomeFlagsEnumClass::THREE; | |
| EXPECT_EQ(SomeFlagsEnumClass::ONE | SomeFlagsEnumClass::THREE, value); | |
| // Clear a flag | |
| value &= ~SomeFlagsEnumClass::ONE; | |
| EXPECT_EQ(SomeFlagsEnumClass::THREE, value); | |
| // Toggle a flag | |
| value ^= SomeFlagsEnumClass::TWO; | |
| EXPECT_EQ(SomeFlagsEnumClass::THREE | SomeFlagsEnumClass::TWO, value); | |
| } | |
| TEST_F(EnumFlagsTest, SampleUsageWithBigEnumType) { | |
| SomeBigFlagsEnum value = BIG_FLAG_NONE; | |
| // Set a flag. | |
| value |= BIG_FLAG_ONE; | |
| EXPECT_EQ(BIG_FLAG_ONE, value); | |
| // Set another | |
| value |= BIG_FLAG_THREE; | |
| EXPECT_EQ(FLAG_ONE | BIG_FLAG_THREE, value); | |
| // Clear a flag | |
| value &= ~BIG_FLAG_ONE; | |
| EXPECT_EQ(BIG_FLAG_THREE, value); | |
| // Toggle a flag | |
| value ^= BIG_FLAG_TWO; | |
| EXPECT_EQ(BIG_FLAG_THREE | BIG_FLAG_TWO, value); | |
| } | |
| // These following tests verify the binary behavior of the operators. They do | |
| // not demonstrate standard usage. | |
| TEST_F(EnumFlagsTest, BinaryBehaviorOfAssignmentOperators) { | |
| SomeFlagsEnum value = FLAG_NONE; | |
| // Set a flag. | |
| value |= FLAG_ONE; | |
| EXPECT_EQ(1, value); | |
| // Set another | |
| value |= FLAG_THREE; | |
| EXPECT_EQ(5, value); | |
| // Clear a flag | |
| value &= ~FLAG_ONE; | |
| EXPECT_EQ(4, value); | |
| // Toggle a flag | |
| value ^= FLAG_TWO; | |
| EXPECT_EQ(6, value); | |
| } | |
| TEST_F(EnumFlagsTest, BinaryBehaviorOfAssignmentOperatorsWithEnumClass) { | |
| SomeFlagsEnumClass value = SomeFlagsEnumClass::NONE; | |
| // Set a flag. | |
| value |= SomeFlagsEnumClass::ONE; | |
| EXPECT_EQ(1, static_cast<int>(value)); // | |
| // Set another | |
| value |= SomeFlagsEnumClass::THREE; | |
| EXPECT_EQ(5, static_cast<int>(value)); | |
| // Clear a flag | |
| value &= ~SomeFlagsEnumClass::ONE; | |
| EXPECT_EQ(4, static_cast<int>(value)); | |
| // Toggle a flag | |
| value ^= SomeFlagsEnumClass::TWO; | |
| EXPECT_EQ(6, static_cast<int>(value)); | |
| } | |
| TEST_F(EnumFlagsTest, BinaryBehaviorOfSimpleOperations) { | |
| // These values are set directly with a cast for clarity. | |
| const int all_bits_int = -1; | |
| const SomeFlagsEnum all_bits = static_cast<SomeFlagsEnum>(all_bits_int); | |
| const SomeFlagsEnum just_2_bits = static_cast<SomeFlagsEnum>(3); | |
| // Inverting a flag should result in all bits set in the base type but that | |
| // one. | |
| EXPECT_EQ(-2, ~FLAG_ONE); | |
| EXPECT_EQ(-3, ~FLAG_TWO); | |
| // OR'ing two flags should result in both being set. | |
| EXPECT_EQ(3, FLAG_ONE | FLAG_TWO); | |
| // AND'ing two flags should result in 0. | |
| EXPECT_EQ(FLAG_NONE, FLAG_ONE & FLAG_TWO); | |
| // AND'ing a mask with a flag should result in that flag. | |
| EXPECT_EQ(FLAG_ONE, all_bits & FLAG_ONE); | |
| // XOR'ing two flags should result in both being set. | |
| EXPECT_EQ(3, FLAG_ONE ^ FLAG_TWO); | |
| // XOR'ing a mask with a flag should toggle that flag in the mask. | |
| EXPECT_EQ(FLAG_ONE, FLAG_NONE ^ FLAG_ONE); | |
| EXPECT_EQ(FLAG_TWO, just_2_bits ^ FLAG_ONE); | |
| } | |
| TEST_F(EnumFlagsTest, BinaryBehaviorOfSimpleOperationsOnEnumClass) { | |
| // These values are set directly with a cast for clarity. | |
| const int all_bits_int = -1; | |
| const SomeFlagsEnumClass all_bits = | |
| static_cast<SomeFlagsEnumClass>(all_bits_int); | |
| const SomeFlagsEnumClass just_2_bits = static_cast<SomeFlagsEnumClass>(3); | |
| // Inverting a flag should result in all bits set in the base type but that | |
| // one. | |
| EXPECT_EQ(-2, static_cast<int>(~SomeFlagsEnumClass::ONE)); | |
| EXPECT_EQ(-3, static_cast<int>(~SomeFlagsEnumClass::TWO)); | |
| // OR'ing two flags should result in both being set. | |
| EXPECT_EQ( | |
| 3, static_cast<int>(SomeFlagsEnumClass::ONE | SomeFlagsEnumClass::TWO)); | |
| // AND'ing two flags should result in 0. | |
| EXPECT_EQ(SomeFlagsEnumClass::NONE, | |
| SomeFlagsEnumClass::ONE & SomeFlagsEnumClass::TWO); | |
| // AND'ing a mask with a flag should result in that flag. | |
| EXPECT_EQ(SomeFlagsEnumClass::ONE, all_bits & SomeFlagsEnumClass::ONE); | |
| // XOR'ing two flags should result in both being set. | |
| EXPECT_EQ( | |
| 3, static_cast<int>(SomeFlagsEnumClass::ONE ^ SomeFlagsEnumClass::TWO)); | |
| // XOR'ing a mask with a flag should toggle that flag in the mask. | |
| EXPECT_EQ(SomeFlagsEnumClass::ONE, | |
| SomeFlagsEnumClass::NONE ^ SomeFlagsEnumClass::ONE); | |
| EXPECT_EQ(SomeFlagsEnumClass::TWO, just_2_bits ^ SomeFlagsEnumClass::ONE); | |
| } | |
| TEST_F(EnumFlagsTest, BinaryBehaviorOfSimpleOperationsWithBaseType) { | |
| // These values are set directly with a cast for clarity. | |
| const int64_t all_bits_int = -1; | |
| const SomeBigFlagsEnum all_bits = static_cast<SomeBigFlagsEnum>(all_bits_int); | |
| const SomeBigFlagsEnum just_2_bits = static_cast<SomeBigFlagsEnum>(3); | |
| // Inverting a flag should result in all bits set in the base type but that | |
| // one. | |
| EXPECT_EQ(all_bits ^ BIG_FLAG_ONE, ~BIG_FLAG_ONE); | |
| // OR'ing two flags should result in both being set. | |
| EXPECT_EQ(3, BIG_FLAG_ONE | BIG_FLAG_TWO); | |
| // AND'ing two flags should result in 0. | |
| EXPECT_EQ(BIG_FLAG_NONE, BIG_FLAG_ONE & BIG_FLAG_TWO); | |
| // AND'ing a mask with a flag should result in that flag. | |
| EXPECT_EQ(BIG_FLAG_ONE, all_bits & BIG_FLAG_ONE); | |
| // XOR'ing two flags should result in both being set. | |
| EXPECT_EQ(3, BIG_FLAG_ONE ^ BIG_FLAG_TWO); | |
| // XOR'ing a mask with a flag should toggle that flag in the mask. | |
| EXPECT_EQ(BIG_FLAG_ONE, BIG_FLAG_NONE ^ BIG_FLAG_ONE); | |
| EXPECT_EQ(BIG_FLAG_TWO, just_2_bits ^ BIG_FLAG_ONE); | |
| } | |
| } // namespace brillo |