Home | History | Annotate | Download | only in brillo
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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