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