| // Copyright 2017 The Chromium OS Authors. All rights reserved. |
| // 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 |