| /* | |
| * Copyright (c) 2020 Daniel R. Carvalho | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| #include <gtest/gtest.h> | |
| #include <cstdint> | |
| #include <limits> | |
| #include "base/flags.hh" | |
| using namespace gem5; | |
| /** Test default zero-initialized constructor. */ | |
| TEST(FlagsTest, ConstructorZero) | |
| { | |
| const Flags<uint32_t> flags; | |
| ASSERT_EQ(uint32_t(0), uint32_t(flags)); | |
| } | |
| /** Test constructor with a single-bit initial value. */ | |
| TEST(FlagsTest, ConstructorSingle) | |
| { | |
| const uint32_t value = (1 << 3); | |
| const Flags<uint32_t> flags(value); | |
| ASSERT_EQ(value, uint32_t(flags)); | |
| } | |
| /** Test constructor with an initial multi-bit value. */ | |
| TEST(FlagsTest, ConstructorMulti) | |
| { | |
| const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9); | |
| const Flags<uint32_t> flags(value); | |
| ASSERT_EQ(value, uint32_t(flags)); | |
| } | |
| /** Test assignment of variable of underlying type. */ | |
| TEST(FlagsTest, TypeAssignment) | |
| { | |
| const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags; | |
| flags = value; | |
| ASSERT_EQ(value, uint32_t(flags)); | |
| } | |
| /** | |
| * Test assignment of variable of underlying type, overwriting an initial | |
| * value. | |
| */ | |
| TEST(FlagsTest, TypeAssignmentOverwrite) | |
| { | |
| const uint32_t init_value = (1 << 5) | (1 << 6) ; | |
| const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags(init_value); | |
| flags = value; | |
| ASSERT_EQ(value, uint32_t(flags)); | |
| } | |
| /** Test assignment of other Flags. */ | |
| TEST(FlagsTest, FlagsAssignment) | |
| { | |
| const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags_a; | |
| Flags<uint32_t> flags_b(value); | |
| flags_a = flags_b; | |
| ASSERT_EQ(uint32_t(flags_a), uint32_t(flags_b)); | |
| } | |
| /** Test assignment of other Flags, overwriting an initial value. */ | |
| TEST(FlagsTest, FlagsAssignmentOverwrite) | |
| { | |
| const uint32_t init_value = (1 << 5) | (1 << 6); | |
| const uint32_t value = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags_a(init_value); | |
| Flags<uint32_t> flags_b(value); | |
| flags_a = flags_b; | |
| ASSERT_EQ(uint32_t(flags_a), uint32_t(flags_b)); | |
| } | |
| /** Test isSet for multiple bits set. */ | |
| TEST(FlagsTest, IsSetValue) | |
| { | |
| const uint32_t value_a = (1 << 3); | |
| const uint32_t value_b = (1 << 5); | |
| const Flags<uint32_t> flags(value_a | value_b); | |
| ASSERT_TRUE(flags.isSet(value_a)); | |
| ASSERT_FALSE(flags.isSet(value_a << 1)); | |
| ASSERT_TRUE(flags.isSet(value_b)); | |
| } | |
| /** Test isSet comparing against another flag. */ | |
| TEST(FlagsTest, IsSetType) | |
| { | |
| const uint32_t value_a = (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9); | |
| const uint32_t value_c = (1 << 4) | (1 << 8); | |
| const Flags<uint32_t> flags(value_a); | |
| ASSERT_TRUE(flags.isSet(value_b)); | |
| ASSERT_FALSE(flags.isSet(value_c)); | |
| } | |
| /** Test allSet comparing against another flag. */ | |
| TEST(FlagsTest, AllSetMatch) | |
| { | |
| const uint32_t value_a = (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9); | |
| const Flags<uint32_t> flags(value_a); | |
| ASSERT_TRUE(flags.allSet(value_a)); | |
| ASSERT_FALSE(flags.allSet(value_b)); | |
| } | |
| /** Test noneSet comparing against another flag. */ | |
| TEST(FlagsTest, NoneSetMatch) | |
| { | |
| const uint32_t value_a = (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 6); | |
| const uint32_t value_c = (1 << 3) | (1 << 4) | (1 << 9); | |
| const Flags<uint32_t> flags(value_a); | |
| ASSERT_FALSE(flags.noneSet(value_a)); | |
| ASSERT_FALSE(flags.noneSet(value_b)); | |
| ASSERT_TRUE(flags.noneSet(value_c)); | |
| } | |
| /** Test if no bits are set after a full clear. */ | |
| TEST(FlagsTest, Clear) | |
| { | |
| const uint32_t value = (1 << 5) | (1 << 6); | |
| Flags<uint32_t> flags(value); | |
| flags.clear(); | |
| ASSERT_EQ(0, uint32_t(flags)); | |
| } | |
| /** Test clearing specific bits. */ | |
| TEST(FlagsTest, ClearMatch) | |
| { | |
| const uint32_t value_a = (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags(value_a); | |
| flags.clear(value_b); | |
| ASSERT_FALSE(flags.isSet(value_a & value_b)); | |
| ASSERT_TRUE(flags.isSet(value_a ^ (value_a & value_b))); | |
| } | |
| /** Test setting with a few overlapping bits. */ | |
| TEST(FlagsTest, SetOverlapping) | |
| { | |
| const uint32_t value_a = (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags(value_a); | |
| flags.set(value_b); | |
| ASSERT_EQ(value_a | value_b, uint32_t(flags)); | |
| } | |
| /** | |
| * Test conditional set. If true the selected bits are set; otherwise, they | |
| * are cleared. | |
| */ | |
| TEST(FlagsTest, ConditionalSet) | |
| { | |
| const uint32_t value_a = (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9); | |
| Flags<uint32_t> flags_true(value_a); | |
| flags_true.set(value_b, true); | |
| ASSERT_EQ(value_a | value_b, uint32_t(flags_true)); | |
| Flags<uint32_t> flags_false(value_a); | |
| flags_false.set(value_b, false); | |
| ASSERT_EQ(value_a & ~value_b, uint32_t(flags_false)); | |
| } | |
| /** | |
| * Test replacing a masked selection of bits. This means that bits of the | |
| * original value that match the mask will be replaced by the bits of | |
| * the new value that match the mask. | |
| */ | |
| TEST(FlagsTest, ReplaceOverlapping) | |
| { | |
| const uint32_t value_a = (1 << 4) | (1 << 5) | (1 << 6); | |
| const uint32_t value_b = (1 << 3) | (1 << 5) | (1 << 9); | |
| const uint32_t mask = (1 << 4) | (1 << 5) | (1 << 9) | (1 << 10); | |
| // (1 << 4) is set in value_a, but is not set in value_b, so it is cleared | |
| // (1 << 5) is set in both values, so it remains set | |
| // (1 << 9) is not set in value_a, but it is in value_b, so it is set | |
| // (1 << 10) is not set in both values, so it remains not set | |
| const uint32_t result = (1 << 5) | (1 << 6) | (1 << 9); | |
| Flags<uint32_t> flags(value_a); | |
| flags.replace(value_b, mask); | |
| ASSERT_EQ(result, uint32_t(flags)); | |
| } |