blob: 8abf0da9d9067dbd6b521852e3874daf4b6f7352 [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 Srbeckydd966bc2018-05-24 13:55:52 +010053 BitTableBuilder<uint32_t> 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 Srbeckydd966bc2018-05-24 13:55:52 +010070 BitTableBuilder<uint32_t> 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 Srbeckydd966bc2018-05-24 13:55:52 +010096 BitTableBuilder<uint32_t> 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 Srbeckydd966bc2018-05-24 13:55:52 +0100116 struct RowData {
117 uint32_t a;
118 uint32_t b;
119 uint32_t c;
120 uint32_t d;
121 };
122 BitTableBuilder<RowData> builder(&allocator);
123 builder.Add(RowData{42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
124 builder.Add(RowData{62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
David Srbecky052f8ca2018-04-26 15:42:54 +0100125 builder.Encode(&buffer, &encode_bit_offset);
126
127 size_t decode_bit_offset = 0;
128 BitTable<4> table(buffer.data(), buffer.size(), &decode_bit_offset);
129 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
130 EXPECT_EQ(2u, table.NumRows());
131 EXPECT_EQ(42u, table.Get(0, 0));
132 EXPECT_EQ(kNoValue, table.Get(0, 1));
133 EXPECT_EQ(0u, table.Get(0, 2));
134 EXPECT_EQ(static_cast<uint32_t>(-2), table.Get(0, 3));
135 EXPECT_EQ(62u, table.Get(1, 0));
136 EXPECT_EQ(kNoValue, table.Get(1, 1));
137 EXPECT_EQ(63u, table.Get(1, 2));
138 EXPECT_EQ(static_cast<uint32_t>(-3), table.Get(1, 3));
139 EXPECT_EQ(6u, table.NumColumnBits(0));
140 EXPECT_EQ(0u, table.NumColumnBits(1));
141 EXPECT_EQ(7u, table.NumColumnBits(2));
142 EXPECT_EQ(32u, table.NumColumnBits(3));
143}
144
David Srbecky159c9dd2018-05-24 14:56:51 +0100145TEST(BitTableTest, TestDedup) {
146 MallocArenaPool pool;
147 ArenaStack arena_stack(&pool);
148 ScopedArenaAllocator allocator(&arena_stack);
149
150 struct RowData {
151 uint32_t a;
152 uint32_t b;
153 };
154 BitTableBuilder<RowData> builder(&allocator);
155 RowData value0{1, 2};
156 RowData value1{3, 4};
David Srbecky5513c2b2018-05-24 15:03:20 +0100157 EXPECT_EQ(0u, builder.Dedup(&value0));
158 EXPECT_EQ(1u, builder.Dedup(&value1));
159 EXPECT_EQ(0u, builder.Dedup(&value0));
160 EXPECT_EQ(1u, builder.Dedup(&value1));
161 EXPECT_EQ(2u, builder.size());
162}
163
164TEST(BitTableTest, TestBitmapTable) {
165 MallocArenaPool pool;
166 ArenaStack arena_stack(&pool);
167 ScopedArenaAllocator allocator(&arena_stack);
168
169 std::vector<uint8_t> buffer;
170 size_t encode_bit_offset = 0;
171 const uint64_t value = 0xDEADBEEF0BADF00Dull;
172 BitmapTableBuilder builder(&allocator);
173 std::multimap<uint64_t, size_t> indicies; // bitmap -> row.
174 for (size_t bit_length = 0; bit_length <= BitSizeOf<uint64_t>(); ++bit_length) {
175 uint64_t bitmap = value & MaxInt<uint64_t>(bit_length);
176 indicies.emplace(bitmap, builder.Dedup(&bitmap, MinimumBitsToStore(bitmap)));
177 }
178 builder.Encode(&buffer, &encode_bit_offset);
179 EXPECT_EQ(1 + static_cast<uint32_t>(POPCOUNT(value)), builder.size());
180
181 size_t decode_bit_offset = 0;
182 BitTable<1> table(buffer.data(), buffer.size(), &decode_bit_offset);
183 EXPECT_EQ(encode_bit_offset, decode_bit_offset);
184 for (auto it : indicies) {
185 uint64_t expected = it.first;
186 BitMemoryRegion actual = table.GetBitMemoryRegion(it.second);
187 EXPECT_GE(actual.size_in_bits(), MinimumBitsToStore(expected));
188 for (size_t b = 0; b < actual.size_in_bits(); b++, expected >>= 1) {
189 EXPECT_EQ(expected & 1, actual.LoadBit(b)) << "b=" << b;
190 }
191 }
192}
193
194TEST(BitTableTest, TestCollisions) {
195 MallocArenaPool pool;
196 ArenaStack arena_stack(&pool);
197 ScopedArenaAllocator allocator(&arena_stack);
David Srbecky159c9dd2018-05-24 14:56:51 +0100198 FNVHash<MemoryRegion> hasher;
David Srbecky5513c2b2018-05-24 15:03:20 +0100199
200 struct RowData {
201 uint32_t a;
202 uint32_t b;
203 };
204 RowData value0{56948505, 0};
205 RowData value1{67108869, 0};
206
207 BitTableBuilder<RowData> builder(&allocator);
208 EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(RowData))),
209 hasher(MemoryRegion(&value1, sizeof(RowData))));
David Srbecky159c9dd2018-05-24 14:56:51 +0100210 EXPECT_EQ(0u, builder.Dedup(&value0));
211 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky159c9dd2018-05-24 14:56:51 +0100212 EXPECT_EQ(0u, builder.Dedup(&value0));
213 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky5513c2b2018-05-24 15:03:20 +0100214 EXPECT_EQ(2u, builder.size());
215
216 BitmapTableBuilder builder2(&allocator);
217 EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0.a)))),
218 hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1.a)))));
219 EXPECT_EQ(0u, builder2.Dedup(&value0.a, MinimumBitsToStore(value0.a)));
220 EXPECT_EQ(1u, builder2.Dedup(&value1.a, MinimumBitsToStore(value1.a)));
221 EXPECT_EQ(0u, builder2.Dedup(&value0.a, MinimumBitsToStore(value0.a)));
222 EXPECT_EQ(1u, builder2.Dedup(&value1.a, MinimumBitsToStore(value1.a)));
223 EXPECT_EQ(2u, builder2.size());
David Srbecky159c9dd2018-05-24 14:56:51 +0100224}
225
David Srbecky052f8ca2018-04-26 15:42:54 +0100226} // namespace art