You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
6.7 KiB
242 lines
6.7 KiB
// 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
|