blob: 4f25730152f11cc91d02fb45ab9a4a5ffa8de201 [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;
David Srbecky078d7ba2018-06-21 15:36:48 +010034 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer, start_bit_offset);
35 EncodeVarintBits(writer, value);
David Srbecky052f8ca2018-04-26 15:42:54 +010036
David Srbeckya38e6cf2018-06-26 18:13:49 +010037 BitMemoryReader reader(buffer.data(), start_bit_offset);
David Srbecky078d7ba2018-06-21 15:36:48 +010038 uint32_t result = DecodeVarintBits(reader);
David Srbeckyd1606412018-07-31 15:05:14 +010039 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +010040 EXPECT_EQ(value, result);
41 }
42 }
43}
44
45TEST(BitTableTest, TestEmptyTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010046 MallocArenaPool pool;
47 ArenaStack arena_stack(&pool);
48 ScopedArenaAllocator allocator(&arena_stack);
49
David Srbecky052f8ca2018-04-26 15:42:54 +010050 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010051 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbeckycf7833e2018-06-14 16:45:22 +010052 BitTableBuilderBase<1> builder(&allocator);
David Srbecky078d7ba2018-06-21 15:36:48 +010053 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +010054
David Srbeckya38e6cf2018-06-26 18:13:49 +010055 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +010056 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +010057 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +010058 EXPECT_EQ(0u, table.NumRows());
59}
60
61TEST(BitTableTest, TestSingleColumnTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010062 MallocArenaPool pool;
63 ArenaStack arena_stack(&pool);
64 ScopedArenaAllocator allocator(&arena_stack);
65
David Srbecky052f8ca2018-04-26 15:42:54 +010066 constexpr uint32_t kNoValue = -1;
67 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010068 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbeckycf7833e2018-06-14 16:45:22 +010069 BitTableBuilderBase<1> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +010070 builder.Add({42u});
71 builder.Add({kNoValue});
72 builder.Add({1000u});
73 builder.Add({kNoValue});
David Srbecky078d7ba2018-06-21 15:36:48 +010074 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +010075
David Srbeckya38e6cf2018-06-26 18:13:49 +010076 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +010077 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +010078 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +010079 EXPECT_EQ(4u, table.NumRows());
80 EXPECT_EQ(42u, table.Get(0));
81 EXPECT_EQ(kNoValue, table.Get(1));
82 EXPECT_EQ(1000u, table.Get(2));
83 EXPECT_EQ(kNoValue, table.Get(3));
84 EXPECT_EQ(10u, table.NumColumnBits(0));
85}
86
87TEST(BitTableTest, TestUnalignedTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010088 MallocArenaPool pool;
89 ArenaStack arena_stack(&pool);
90 ScopedArenaAllocator allocator(&arena_stack);
91
David Srbecky052f8ca2018-04-26 15:42:54 +010092 for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
93 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010094 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer, start_bit_offset);
David Srbeckycf7833e2018-06-14 16:45:22 +010095 BitTableBuilderBase<1> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +010096 builder.Add({42u});
David Srbecky078d7ba2018-06-21 15:36:48 +010097 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +010098
David Srbeckya38e6cf2018-06-26 18:13:49 +010099 BitMemoryReader reader(buffer.data(), start_bit_offset);
David Srbecky078d7ba2018-06-21 15:36:48 +0100100 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +0100101 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +0100102 EXPECT_EQ(1u, table.NumRows());
103 EXPECT_EQ(42u, table.Get(0));
104 }
105}
106
107TEST(BitTableTest, TestBigTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +0100108 MallocArenaPool pool;
109 ArenaStack arena_stack(&pool);
110 ScopedArenaAllocator allocator(&arena_stack);
111
David Srbecky052f8ca2018-04-26 15:42:54 +0100112 constexpr uint32_t kNoValue = -1;
113 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +0100114 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbeckycf7833e2018-06-14 16:45:22 +0100115 BitTableBuilderBase<4> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100116 builder.Add({42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
117 builder.Add({62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
David Srbecky078d7ba2018-06-21 15:36:48 +0100118 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +0100119
David Srbeckya38e6cf2018-06-26 18:13:49 +0100120 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +0100121 BitTableBase<4> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +0100122 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +0100123 EXPECT_EQ(2u, table.NumRows());
124 EXPECT_EQ(42u, table.Get(0, 0));
125 EXPECT_EQ(kNoValue, table.Get(0, 1));
126 EXPECT_EQ(0u, table.Get(0, 2));
127 EXPECT_EQ(static_cast<uint32_t>(-2), table.Get(0, 3));
128 EXPECT_EQ(62u, table.Get(1, 0));
129 EXPECT_EQ(kNoValue, table.Get(1, 1));
130 EXPECT_EQ(63u, table.Get(1, 2));
131 EXPECT_EQ(static_cast<uint32_t>(-3), table.Get(1, 3));
132 EXPECT_EQ(6u, table.NumColumnBits(0));
133 EXPECT_EQ(0u, table.NumColumnBits(1));
134 EXPECT_EQ(7u, table.NumColumnBits(2));
135 EXPECT_EQ(32u, table.NumColumnBits(3));
136}
137
David Srbecky159c9dd2018-05-24 14:56:51 +0100138TEST(BitTableTest, TestDedup) {
139 MallocArenaPool pool;
140 ArenaStack arena_stack(&pool);
141 ScopedArenaAllocator allocator(&arena_stack);
142
David Srbeckycf7833e2018-06-14 16:45:22 +0100143 BitTableBuilderBase<2> builder(&allocator);
144 BitTableBuilderBase<2>::Entry value0{1, 2};
145 BitTableBuilderBase<2>::Entry value1{3, 4};
David Srbecky5513c2b2018-05-24 15:03:20 +0100146 EXPECT_EQ(0u, builder.Dedup(&value0));
147 EXPECT_EQ(1u, builder.Dedup(&value1));
148 EXPECT_EQ(0u, builder.Dedup(&value0));
149 EXPECT_EQ(1u, builder.Dedup(&value1));
150 EXPECT_EQ(2u, builder.size());
151}
152
153TEST(BitTableTest, TestBitmapTable) {
154 MallocArenaPool pool;
155 ArenaStack arena_stack(&pool);
156 ScopedArenaAllocator allocator(&arena_stack);
157
158 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +0100159 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbecky5513c2b2018-05-24 15:03:20 +0100160 const uint64_t value = 0xDEADBEEF0BADF00Dull;
161 BitmapTableBuilder builder(&allocator);
162 std::multimap<uint64_t, size_t> indicies; // bitmap -> row.
163 for (size_t bit_length = 0; bit_length <= BitSizeOf<uint64_t>(); ++bit_length) {
164 uint64_t bitmap = value & MaxInt<uint64_t>(bit_length);
165 indicies.emplace(bitmap, builder.Dedup(&bitmap, MinimumBitsToStore(bitmap)));
166 }
David Srbecky078d7ba2018-06-21 15:36:48 +0100167 builder.Encode(writer);
David Srbecky5513c2b2018-05-24 15:03:20 +0100168 EXPECT_EQ(1 + static_cast<uint32_t>(POPCOUNT(value)), builder.size());
169
David Srbeckya38e6cf2018-06-26 18:13:49 +0100170 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +0100171 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +0100172 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky5513c2b2018-05-24 15:03:20 +0100173 for (auto it : indicies) {
174 uint64_t expected = it.first;
175 BitMemoryRegion actual = table.GetBitMemoryRegion(it.second);
176 EXPECT_GE(actual.size_in_bits(), MinimumBitsToStore(expected));
177 for (size_t b = 0; b < actual.size_in_bits(); b++, expected >>= 1) {
178 EXPECT_EQ(expected & 1, actual.LoadBit(b)) << "b=" << b;
179 }
180 }
181}
182
183TEST(BitTableTest, TestCollisions) {
184 MallocArenaPool pool;
185 ArenaStack arena_stack(&pool);
186 ScopedArenaAllocator allocator(&arena_stack);
David Srbecky159c9dd2018-05-24 14:56:51 +0100187 FNVHash<MemoryRegion> hasher;
David Srbecky5513c2b2018-05-24 15:03:20 +0100188
David Srbeckycf7833e2018-06-14 16:45:22 +0100189 BitTableBuilderBase<2>::Entry value0{56948505, 0};
190 BitTableBuilderBase<2>::Entry value1{67108869, 0};
David Srbecky5513c2b2018-05-24 15:03:20 +0100191
David Srbeckycf7833e2018-06-14 16:45:22 +0100192 BitTableBuilderBase<2> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100193 EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(value0))),
194 hasher(MemoryRegion(&value1, sizeof(value1))));
David Srbecky159c9dd2018-05-24 14:56:51 +0100195 EXPECT_EQ(0u, builder.Dedup(&value0));
196 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky159c9dd2018-05-24 14:56:51 +0100197 EXPECT_EQ(0u, builder.Dedup(&value0));
198 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky5513c2b2018-05-24 15:03:20 +0100199 EXPECT_EQ(2u, builder.size());
200
201 BitmapTableBuilder builder2(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100202 EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0[0])))),
203 hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1[0])))));
204 EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
205 EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
206 EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
207 EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
David Srbecky5513c2b2018-05-24 15:03:20 +0100208 EXPECT_EQ(2u, builder2.size());
David Srbecky159c9dd2018-05-24 14:56:51 +0100209}
210
David Srbecky052f8ca2018-04-26 15:42:54 +0100211} // namespace art