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.
169 lines
5.5 KiB
169 lines
5.5 KiB
/*
|
|
* 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));
|
|
}
|