blob: 969940fe3906025e9b93e4a74741b557abc13aa3 [file] [log] [blame]
David Srbecky052f8ca2018-04-26 15:42:54 +01001/*
2 * Copyright (C) 2018 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 "bit_table.h"
18
David Srbeckydd966bc2018-05-24 13:55:52 +010019#include <map>
20
David Srbecky052f8ca2018-04-26 15:42:54 +010021#include "gtest/gtest.h"
22
David Srbeckydd966bc2018-05-24 13:55:52 +010023#include "base/arena_allocator.h"
24#include "base/bit_utils.h"
25#include "base/malloc_arena_pool.h"
26
David Srbecky052f8ca2018-04-26 15:42:54 +010027namespace art {
28
29TEST(BitTableTest, TestVarint) {
30 for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
31 uint32_t values[] = { 0, 1, 11, 12, 15, 16, 255, 256, ~1u, ~0u };
32 for (uint32_t value : values) {
33 std::vector<uint8_t> buffer;
34 size_t encode_bit_offset = start_bit_offset;
35 EncodeVarintBits(&buffer, &encode_bit_offset, value);
36
37 size_t decode_bit_offset = start_bit_offset;
38 BitMemoryRegion region(MemoryRegion(buffer.data(), buffer.size()));
39 uint32_t result = DecodeVarintBits(region, &decode_bit_offset);
40 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
41 EXPECT_EQ(value, result);
42 }
43 }
44}
45
46TEST(BitTableTest, TestEmptyTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010047 MallocArenaPool pool;
48 ArenaStack arena_stack(&pool);
49 ScopedArenaAllocator allocator(&arena_stack);
50
David Srbecky052f8ca2018-04-26 15:42:54 +010051 std::vector<uint8_t> buffer;
52 size_t encode_bit_offset = 0;
David Srbeckyf325e282018-06-13 15:02:32 +010053 BitTableBuilder<1> builder(&allocator);
David Srbecky052f8ca2018-04-26 15:42:54 +010054 builder.Encode(&buffer, &encode_bit_offset);
55
56 size_t decode_bit_offset = 0;
57 BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
58 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
59 EXPECT_EQ(0u, table.NumRows());
60}
61
62TEST(BitTableTest, TestSingleColumnTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010063 MallocArenaPool pool;
64 ArenaStack arena_stack(&pool);
65 ScopedArenaAllocator allocator(&arena_stack);
66
David Srbecky052f8ca2018-04-26 15:42:54 +010067 constexpr uint32_t kNoValue = -1;
68 std::vector<uint8_t> buffer;
69 size_t encode_bit_offset = 0;
David Srbeckyf325e282018-06-13 15:02:32 +010070 BitTableBuilder<1> builder(&allocator);
71 builder.Add({42u});
72 builder.Add({kNoValue});
73 builder.Add({1000u});
74 builder.Add({kNoValue});
David Srbecky052f8ca2018-04-26 15:42:54 +010075 builder.Encode(&buffer, &encode_bit_offset);
76
77 size_t decode_bit_offset = 0;
78 BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
79 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
80 EXPECT_EQ(4u, table.NumRows());
81 EXPECT_EQ(42u, table.Get(0));
82 EXPECT_EQ(kNoValue, table.Get(1));
83 EXPECT_EQ(1000u, table.Get(2));
84 EXPECT_EQ(kNoValue, table.Get(3));
85 EXPECT_EQ(10u, table.NumColumnBits(0));
86}
87
88TEST(BitTableTest, TestUnalignedTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010089 MallocArenaPool pool;
90 ArenaStack arena_stack(&pool);
91 ScopedArenaAllocator allocator(&arena_stack);
92
David Srbecky052f8ca2018-04-26 15:42:54 +010093 for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
94 std::vector<uint8_t> buffer;
95 size_t encode_bit_offset = start_bit_offset;
David Srbeckyf325e282018-06-13 15:02:32 +010096 BitTableBuilder<1> builder(&allocator);
97 builder.Add({42u});
David Srbecky052f8ca2018-04-26 15:42:54 +010098 builder.Encode(&buffer, &encode_bit_offset);
99
100 size_t decode_bit_offset = start_bit_offset;
101 BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
102 EXPECT_EQ(encode_bit_offset, decode_bit_offset) << " start_bit_offset=" << start_bit_offset;
103 EXPECT_EQ(1u, table.NumRows());
104 EXPECT_EQ(42u, table.Get(0));
105 }
106}
107
108TEST(BitTableTest, TestBigTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +0100109 MallocArenaPool pool;
110 ArenaStack arena_stack(&pool);
111 ScopedArenaAllocator allocator(&arena_stack);
112
David Srbecky052f8ca2018-04-26 15:42:54 +0100113 constexpr uint32_t kNoValue = -1;
114 std::vector<uint8_t> buffer;
115 size_t encode_bit_offset = 0;
David Srbeckyf325e282018-06-13 15:02:32 +0100116 BitTableBuilder<4> builder(&allocator);
117 builder.Add({42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
118 builder.Add({62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
David Srbecky052f8ca2018-04-26 15:42:54 +0100119 builder.Encode(&buffer, &encode_bit_offset);
120
121 size_t decode_bit_offset = 0;
122 BitTable<4> table(buffer.data(), buffer.size(), &decode_bit_offset);
123 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
124 EXPECT_EQ(2u, table.NumRows());
125 EXPECT_EQ(42u, table.Get(0, 0));
126 EXPECT_EQ(kNoValue, table.Get(0, 1));
127 EXPECT_EQ(0u, table.Get(0, 2));
128 EXPECT_EQ(static_cast<uint32_t>(-2), table.Get(0, 3));
129 EXPECT_EQ(62u, table.Get(1, 0));
130 EXPECT_EQ(kNoValue, table.Get(1, 1));
131 EXPECT_EQ(63u, table.Get(1, 2));
132 EXPECT_EQ(static_cast<uint32_t>(-3), table.Get(1, 3));
133 EXPECT_EQ(6u, table.NumColumnBits(0));
134 EXPECT_EQ(0u, table.NumColumnBits(1));
135 EXPECT_EQ(7u, table.NumColumnBits(2));
136 EXPECT_EQ(32u, table.NumColumnBits(3));
137}
138
David Srbecky159c9dd2018-05-24 14:56:51 +0100139TEST(BitTableTest, TestDedup) {
140 MallocArenaPool pool;
141 ArenaStack arena_stack(&pool);
142 ScopedArenaAllocator allocator(&arena_stack);
143
David Srbeckyf325e282018-06-13 15:02:32 +0100144 BitTableBuilder<2> builder(&allocator);
145 BitTableBuilder<2>::Entry value0{1, 2};
146 BitTableBuilder<2>::Entry value1{3, 4};
David Srbecky5513c2b2018-05-24 15:03:20 +0100147 EXPECT_EQ(0u, builder.Dedup(&value0));
148 EXPECT_EQ(1u, builder.Dedup(&value1));
149 EXPECT_EQ(0u, builder.Dedup(&value0));
150 EXPECT_EQ(1u, builder.Dedup(&value1));
151 EXPECT_EQ(2u, builder.size());
152}
153
154TEST(BitTableTest, TestBitmapTable) {
155 MallocArenaPool pool;
156 ArenaStack arena_stack(&pool);
157 ScopedArenaAllocator allocator(&arena_stack);
158
159 std::vector<uint8_t> buffer;
160 size_t encode_bit_offset = 0;
161 const uint64_t value = 0xDEADBEEF0BADF00Dull;
162 BitmapTableBuilder builder(&allocator);
163 std::multimap<uint64_t, size_t> indicies; // bitmap -> row.
164 for (size_t bit_length = 0; bit_length <= BitSizeOf<uint64_t>(); ++bit_length) {
165 uint64_t bitmap = value & MaxInt<uint64_t>(bit_length);
166 indicies.emplace(bitmap, builder.Dedup(&bitmap, MinimumBitsToStore(bitmap)));
167 }
168 builder.Encode(&buffer, &encode_bit_offset);
169 EXPECT_EQ(1 + static_cast<uint32_t>(POPCOUNT(value)), builder.size());
170
171 size_t decode_bit_offset = 0;
172 BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
173 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
174 for (auto it : indicies) {
175 uint64_t expected = it.first;
176 BitMemoryRegion actual = table.GetBitMemoryRegion(it.second);
177 EXPECT_GE(actual.size_in_bits(), MinimumBitsToStore(expected));
178 for (size_t b = 0; b < actual.size_in_bits(); b++, expected >>= 1) {
179 EXPECT_EQ(expected & 1, actual.LoadBit(b)) << "b=" << b;
180 }
181 }
182}
183
184TEST(BitTableTest, TestCollisions) {
185 MallocArenaPool pool;
186 ArenaStack arena_stack(&pool);
187 ScopedArenaAllocator allocator(&arena_stack);
David Srbecky159c9dd2018-05-24 14:56:51 +0100188 FNVHash<MemoryRegion> hasher;
David Srbecky5513c2b2018-05-24 15:03:20 +0100189
David Srbeckyf325e282018-06-13 15:02:32 +0100190 BitTableBuilder<2>::Entry value0{56948505, 0};
191 BitTableBuilder<2>::Entry value1{67108869, 0};
David Srbecky5513c2b2018-05-24 15:03:20 +0100192
David Srbeckyf325e282018-06-13 15:02:32 +0100193 BitTableBuilder<2> builder(&allocator);
194 EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(value0))),
195 hasher(MemoryRegion(&value1, sizeof(value1))));
David Srbecky159c9dd2018-05-24 14:56:51 +0100196 EXPECT_EQ(0u, builder.Dedup(&value0));
197 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky159c9dd2018-05-24 14:56:51 +0100198 EXPECT_EQ(0u, builder.Dedup(&value0));
199 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky5513c2b2018-05-24 15:03:20 +0100200 EXPECT_EQ(2u, builder.size());
201
202 BitmapTableBuilder builder2(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100203 EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0[0])))),
204 hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1[0])))));
205 EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
206 EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
207 EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
208 EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
David Srbecky5513c2b2018-05-24 15:03:20 +0100209 EXPECT_EQ(2u, builder2.size());
David Srbecky159c9dd2018-05-24 14:56:51 +0100210}
211
David Srbecky052f8ca2018-04-26 15:42:54 +0100212} // namespace art