Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "base/bit_string.h"
     18 
     19 #include "gtest/gtest.h"
     20 #include "android-base/logging.h"
     21 
     22 namespace art {
     23 
     24 constexpr size_t BitString::kBitSizeAtPosition[BitString::kCapacity];
     25 constexpr size_t BitString::kCapacity;
     26 
     27 };  // namespace art
     28 
     29 using namespace art;  // NOLINT [build/namespaces] [5]
     30 
     31 // These helper functions are only used by the test,
     32 // so they are not in the main BitString class.
     33 std::string Stringify(BitString bit_string) {
     34   std::stringstream ss;
     35   ss << bit_string;
     36   return ss.str();
     37 }
     38 
     39 BitStringChar MakeBitStringChar(size_t idx, size_t val) {
     40   return BitStringChar(val, BitString::MaybeGetBitLengthAtPosition(idx));
     41 }
     42 
     43 BitStringChar MakeBitStringChar(size_t val) {
     44   return BitStringChar(val, MinimumBitsToStore(val));
     45 }
     46 
     47 BitString MakeBitString(std::initializer_list<size_t> values = {}) {
     48   CHECK_GE(BitString::kCapacity, values.size());
     49 
     50   BitString bs{};
     51 
     52   size_t i = 0;
     53   for (size_t val : values) {
     54     bs.SetAt(i, MakeBitStringChar(i, val));
     55     ++i;
     56   }
     57 
     58   return bs;
     59 }
     60 
     61 template <typename T>
     62 size_t AsUint(const T& value) {
     63   size_t uint_value = 0;
     64   memcpy(&uint_value, &value, sizeof(value));
     65   return uint_value;
     66 }
     67 
     68 // Make max bitstring, e.g. BitString[4095,15,2047] for {12,4,11}
     69 template <size_t kCount = BitString::kCapacity>
     70 BitString MakeBitStringMax() {
     71   BitString bs{};
     72 
     73   for (size_t i = 0; i < kCount; ++i) {
     74     bs.SetAt(i,
     75              MakeBitStringChar(i, MaxInt<BitStringChar::StorageType>(BitString::kBitSizeAtPosition[i])));
     76   }
     77 
     78   return bs;
     79 }
     80 
     81 BitString SetBitStringCharAt(BitString bit_string, size_t i, size_t val) {
     82   BitString bs = bit_string;
     83   bs.SetAt(i, MakeBitStringChar(i, val));
     84   return bs;
     85 }
     86 
     87 #define EXPECT_BITSTRING_STR(expected_str, actual_value)                       \
     88   EXPECT_STREQ((expected_str), Stringify((actual_value)).c_str())
     89 
     90 // TODO: Consider removing this test, it's kind of replicating the logic in GetLsbForPosition().
     91 TEST(InstanceOfBitString, GetLsbForPosition) {
     92   ASSERT_LE(3u, BitString::kCapacity);
     93   // Test will fail if kCapacity is not at least 3. Update it.
     94   EXPECT_EQ(0u, BitString::GetLsbForPosition(0u));
     95   EXPECT_EQ(BitString::kBitSizeAtPosition[0u], BitString::GetLsbForPosition(1u));
     96   EXPECT_EQ(BitString::kBitSizeAtPosition[0u] + BitString::kBitSizeAtPosition[1u],
     97             BitString::GetLsbForPosition(2u));
     98 }
     99 
    100 TEST(InstanceOfBitString, ToString) {
    101   EXPECT_BITSTRING_STR("BitString[]", MakeBitString({0}));
    102   EXPECT_BITSTRING_STR("BitString[1]", MakeBitString({1}));
    103   EXPECT_BITSTRING_STR("BitString[1,2,3]", MakeBitString({1, 2, 3}));
    104 }
    105 
    106 TEST(InstanceOfBitString, ReadWrite) {
    107   BitString bs = MakeBitString();
    108 
    109   // Update tests if changing the capacity.
    110   ASSERT_EQ(BitString::kCapacity, 3u);
    111 
    112   EXPECT_BITSTRING_STR("BitString[]", bs);
    113   bs = SetBitStringCharAt(bs, /*i*/0, /*val*/1u);
    114   EXPECT_BITSTRING_STR("BitString[1]", bs);
    115   bs = SetBitStringCharAt(bs, /*i*/1, /*val*/2u);
    116   EXPECT_BITSTRING_STR("BitString[1,2]", bs);
    117   bs = SetBitStringCharAt(bs, /*i*/2, /*val*/3u);
    118   EXPECT_BITSTRING_STR("BitString[1,2,3]", bs);
    119 
    120   // There should be at least "kCapacity" # of checks here, 1 for each unique position.
    121   EXPECT_EQ(MakeBitStringChar(/*idx*/0, /*val*/1u), bs[0]);
    122   EXPECT_EQ(MakeBitStringChar(/*idx*/1, /*val*/2u), bs[1]);
    123   EXPECT_EQ(MakeBitStringChar(/*idx*/2, /*val*/3u), bs[2]);
    124 
    125   // Each maximal value should be tested here for each position.
    126   uint32_t max_bitstring_ints[] = {
    127       MaxInt<uint32_t>(12),
    128       MaxInt<uint32_t>(4),
    129       MaxInt<uint32_t>(11),
    130   };
    131 
    132   // Update tests if changing the tuning values above.
    133   for (size_t i = 0; i < arraysize(max_bitstring_ints); ++i) {
    134     ASSERT_EQ(MinimumBitsToStore(max_bitstring_ints[i]), BitString::kBitSizeAtPosition[i]) << i;
    135   }
    136 
    137   BitString bs_max = MakeBitStringMax();
    138 
    139   for (size_t i = 0; i < arraysize(max_bitstring_ints); ++i) {
    140     ASSERT_EQ(max_bitstring_ints[i], static_cast<uint32_t>(bs_max[i])) << i;
    141   }
    142 
    143   EXPECT_EQ(MaskLeastSignificant(BitString::GetBitLengthTotalAtPosition(BitString::kCapacity)),
    144             AsUint(MakeBitStringMax()));
    145 }
    146 
    147 template <size_t kPos>
    148 constexpr auto MaxForPos() {
    149     return MaxInt<BitString::StorageType>(BitString::kBitSizeAtPosition[kPos]);
    150 }
    151 
    152 TEST(InstanceOfBitString, MemoryRepresentation) {
    153   // Verify that the lower positions are stored in less significant bits.
    154   BitString bs = MakeBitString({MaxForPos<0>(), MaxForPos<1>()});
    155   BitString::StorageType as_int = static_cast<BitString::StorageType>(bs);
    156 
    157   // Below tests assumes the capacity is at least 3.
    158   ASSERT_LE(3u, BitString::kCapacity);
    159   EXPECT_EQ((MaxForPos<0>() << 0) | (MaxForPos<1>() << BitString::kBitSizeAtPosition[0]),
    160             as_int);
    161 }
    162 
    163 TEST(InstanceOfBitString, Truncate) {
    164   EXPECT_BITSTRING_STR("BitString[]", MakeBitString({1, 2, 3}).Truncate(0));
    165   EXPECT_BITSTRING_STR("BitString[1]", MakeBitString({1, 2, 3}).Truncate(1));
    166   EXPECT_BITSTRING_STR("BitString[1,2]", MakeBitString({1, 2, 3}).Truncate(2));
    167   EXPECT_BITSTRING_STR("BitString[1,2,3]", MakeBitString({1, 2, 3}).Truncate(3));
    168 }
    169