| /* | |
| * Copyright (C) 2017 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "bit_string.h" | |
| #include "gtest/gtest.h" | |
| #include "android-base/logging.h" | |
| namespace art { | |
| constexpr size_t BitString::kBitSizeAtPosition[BitString::kCapacity]; | |
| constexpr size_t BitString::kCapacity; | |
| }; // namespace art | |
| using namespace art; // NOLINT [build/namespaces] [5] | |
| // These helper functions are only used by the test, | |
| // so they are not in the main BitString class. | |
| std::string Stringify(BitString bit_string) { | |
| std::stringstream ss; | |
| ss << bit_string; | |
| return ss.str(); | |
| } | |
| BitStringChar MakeBitStringChar(size_t idx, size_t val) { | |
| return BitStringChar(val, BitString::MaybeGetBitLengthAtPosition(idx)); | |
| } | |
| BitStringChar MakeBitStringChar(size_t val) { | |
| return BitStringChar(val, MinimumBitsToStore(val)); | |
| } | |
| BitString MakeBitString(std::initializer_list<size_t> values = {}) { | |
| CHECK_GE(BitString::kCapacity, values.size()); | |
| BitString bs{}; | |
| size_t i = 0; | |
| for (size_t val : values) { | |
| bs.SetAt(i, MakeBitStringChar(i, val)); | |
| ++i; | |
| } | |
| return bs; | |
| } | |
| template <typename T> | |
| size_t AsUint(const T& value) { | |
| size_t uint_value = 0; | |
| memcpy(&uint_value, &value, sizeof(value)); | |
| return uint_value; | |
| } | |
| // Make max bitstring, e.g. BitString[4095,15,2047] for {12,4,11} | |
| template <size_t kCount = BitString::kCapacity> | |
| BitString MakeBitStringMax() { | |
| BitString bs{}; | |
| for (size_t i = 0; i < kCount; ++i) { | |
| bs.SetAt(i, | |
| MakeBitStringChar(i, MaxInt<BitStringChar::StorageType>(BitString::kBitSizeAtPosition[i]))); | |
| } | |
| return bs; | |
| } | |
| BitString SetBitStringCharAt(BitString bit_string, size_t i, size_t val) { | |
| BitString bs = bit_string; | |
| bs.SetAt(i, MakeBitStringChar(i, val)); | |
| return bs; | |
| } | |
| #define EXPECT_BITSTRING_STR(expected_str, actual_value) \ | |
| EXPECT_STREQ((expected_str), Stringify((actual_value)).c_str()) | |
| // TODO: Consider removing this test, it's kind of replicating the logic in GetLsbForPosition(). | |
| TEST(InstanceOfBitString, GetLsbForPosition) { | |
| ASSERT_LE(3u, BitString::kCapacity); | |
| // Test will fail if kCapacity is not at least 3. Update it. | |
| EXPECT_EQ(0u, BitString::GetLsbForPosition(0u)); | |
| EXPECT_EQ(BitString::kBitSizeAtPosition[0u], BitString::GetLsbForPosition(1u)); | |
| EXPECT_EQ(BitString::kBitSizeAtPosition[0u] + BitString::kBitSizeAtPosition[1u], | |
| BitString::GetLsbForPosition(2u)); | |
| } | |
| TEST(InstanceOfBitString, ToString) { | |
| EXPECT_BITSTRING_STR("BitString[]", MakeBitString({0})); | |
| EXPECT_BITSTRING_STR("BitString[1]", MakeBitString({1})); | |
| EXPECT_BITSTRING_STR("BitString[1,2,3]", MakeBitString({1, 2, 3})); | |
| } | |
| TEST(InstanceOfBitString, ReadWrite) { | |
| BitString bs = MakeBitString(); | |
| // Update tests if changing the capacity. | |
| ASSERT_EQ(BitString::kCapacity, 3u); | |
| EXPECT_BITSTRING_STR("BitString[]", bs); | |
| bs = SetBitStringCharAt(bs, /*i=*/0, /*val=*/1u); | |
| EXPECT_BITSTRING_STR("BitString[1]", bs); | |
| bs = SetBitStringCharAt(bs, /*i=*/1, /*val=*/2u); | |
| EXPECT_BITSTRING_STR("BitString[1,2]", bs); | |
| bs = SetBitStringCharAt(bs, /*i=*/2, /*val=*/3u); | |
| EXPECT_BITSTRING_STR("BitString[1,2,3]", bs); | |
| // There should be at least "kCapacity" # of checks here, 1 for each unique position. | |
| EXPECT_EQ(MakeBitStringChar(/*idx=*/0, /*val=*/1u), bs[0]); | |
| EXPECT_EQ(MakeBitStringChar(/*idx=*/1, /*val=*/2u), bs[1]); | |
| EXPECT_EQ(MakeBitStringChar(/*idx=*/2, /*val=*/3u), bs[2]); | |
| // Each maximal value should be tested here for each position. | |
| uint32_t max_bitstring_ints[] = { | |
| MaxInt<uint32_t>(12), | |
| MaxInt<uint32_t>(4), | |
| MaxInt<uint32_t>(11), | |
| }; | |
| // Update tests if changing the tuning values above. | |
| for (size_t i = 0; i < arraysize(max_bitstring_ints); ++i) { | |
| ASSERT_EQ(MinimumBitsToStore(max_bitstring_ints[i]), BitString::kBitSizeAtPosition[i]) << i; | |
| } | |
| BitString bs_max = MakeBitStringMax(); | |
| for (size_t i = 0; i < arraysize(max_bitstring_ints); ++i) { | |
| ASSERT_EQ(max_bitstring_ints[i], static_cast<uint32_t>(bs_max[i])) << i; | |
| } | |
| EXPECT_EQ(MaskLeastSignificant(BitString::GetBitLengthTotalAtPosition(BitString::kCapacity)), | |
| AsUint(MakeBitStringMax())); | |
| } | |
| template <size_t kPos> | |
| constexpr auto MaxForPos() { | |
| return MaxInt<BitString::StorageType>(BitString::kBitSizeAtPosition[kPos]); | |
| } | |
| TEST(InstanceOfBitString, MemoryRepresentation) { | |
| // Verify that the lower positions are stored in less significant bits. | |
| BitString bs = MakeBitString({MaxForPos<0>(), MaxForPos<1>()}); | |
| BitString::StorageType as_int = static_cast<BitString::StorageType>(bs); | |
| // Below tests assumes the capacity is at least 3. | |
| ASSERT_LE(3u, BitString::kCapacity); | |
| EXPECT_EQ((MaxForPos<0>() << 0) | (MaxForPos<1>() << BitString::kBitSizeAtPosition[0]), | |
| as_int); | |
| } | |
| TEST(InstanceOfBitString, Truncate) { | |
| EXPECT_BITSTRING_STR("BitString[]", MakeBitString({1, 2, 3}).Truncate(0)); | |
| EXPECT_BITSTRING_STR("BitString[1]", MakeBitString({1, 2, 3}).Truncate(1)); | |
| EXPECT_BITSTRING_STR("BitString[1,2]", MakeBitString({1, 2, 3}).Truncate(2)); | |
| EXPECT_BITSTRING_STR("BitString[1,2,3]", MakeBitString({1, 2, 3}).Truncate(3)); | |
| } |