blob: 692861a4a952f49452950b63949fc0edd562d0ff [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
David Srbecky052f8ca2018-04-26 15:42:54 +010029TEST(BitTableTest, TestEmptyTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010030 MallocArenaPool pool;
31 ArenaStack arena_stack(&pool);
32 ScopedArenaAllocator allocator(&arena_stack);
33
David Srbecky052f8ca2018-04-26 15:42:54 +010034 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010035 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbeckycf7833e2018-06-14 16:45:22 +010036 BitTableBuilderBase<1> builder(&allocator);
David Srbecky078d7ba2018-06-21 15:36:48 +010037 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +010038
David Srbeckya38e6cf2018-06-26 18:13:49 +010039 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +010040 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +010041 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +010042 EXPECT_EQ(0u, table.NumRows());
43}
44
45TEST(BitTableTest, TestSingleColumnTable) {
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 constexpr uint32_t kNoValue = -1;
51 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010052 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbeckycf7833e2018-06-14 16:45:22 +010053 BitTableBuilderBase<1> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +010054 builder.Add({42u});
55 builder.Add({kNoValue});
56 builder.Add({1000u});
57 builder.Add({kNoValue});
David Srbecky078d7ba2018-06-21 15:36:48 +010058 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +010059
David Srbeckya38e6cf2018-06-26 18:13:49 +010060 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +010061 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +010062 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +010063 EXPECT_EQ(4u, table.NumRows());
64 EXPECT_EQ(42u, table.Get(0));
65 EXPECT_EQ(kNoValue, table.Get(1));
66 EXPECT_EQ(1000u, table.Get(2));
67 EXPECT_EQ(kNoValue, table.Get(3));
68 EXPECT_EQ(10u, table.NumColumnBits(0));
69}
70
71TEST(BitTableTest, TestUnalignedTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010072 MallocArenaPool pool;
73 ArenaStack arena_stack(&pool);
74 ScopedArenaAllocator allocator(&arena_stack);
75
David Srbecky052f8ca2018-04-26 15:42:54 +010076 for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
77 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010078 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer, start_bit_offset);
David Srbeckycf7833e2018-06-14 16:45:22 +010079 BitTableBuilderBase<1> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +010080 builder.Add({42u});
David Srbecky078d7ba2018-06-21 15:36:48 +010081 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +010082
David Srbeckya38e6cf2018-06-26 18:13:49 +010083 BitMemoryReader reader(buffer.data(), start_bit_offset);
David Srbecky078d7ba2018-06-21 15:36:48 +010084 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +010085 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +010086 EXPECT_EQ(1u, table.NumRows());
87 EXPECT_EQ(42u, table.Get(0));
88 }
89}
90
91TEST(BitTableTest, TestBigTable) {
David Srbeckydd966bc2018-05-24 13:55:52 +010092 MallocArenaPool pool;
93 ArenaStack arena_stack(&pool);
94 ScopedArenaAllocator allocator(&arena_stack);
95
David Srbecky052f8ca2018-04-26 15:42:54 +010096 constexpr uint32_t kNoValue = -1;
97 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +010098 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbeckycf7833e2018-06-14 16:45:22 +010099 BitTableBuilderBase<4> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100100 builder.Add({42u, kNoValue, 0u, static_cast<uint32_t>(-2)});
101 builder.Add({62u, kNoValue, 63u, static_cast<uint32_t>(-3)});
David Srbecky078d7ba2018-06-21 15:36:48 +0100102 builder.Encode(writer);
David Srbecky052f8ca2018-04-26 15:42:54 +0100103
David Srbeckya38e6cf2018-06-26 18:13:49 +0100104 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +0100105 BitTableBase<4> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +0100106 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
David Srbecky052f8ca2018-04-26 15:42:54 +0100107 EXPECT_EQ(2u, table.NumRows());
108 EXPECT_EQ(42u, table.Get(0, 0));
109 EXPECT_EQ(kNoValue, table.Get(0, 1));
110 EXPECT_EQ(0u, table.Get(0, 2));
111 EXPECT_EQ(static_cast<uint32_t>(-2), table.Get(0, 3));
112 EXPECT_EQ(62u, table.Get(1, 0));
113 EXPECT_EQ(kNoValue, table.Get(1, 1));
114 EXPECT_EQ(63u, table.Get(1, 2));
115 EXPECT_EQ(static_cast<uint32_t>(-3), table.Get(1, 3));
116 EXPECT_EQ(6u, table.NumColumnBits(0));
117 EXPECT_EQ(0u, table.NumColumnBits(1));
118 EXPECT_EQ(7u, table.NumColumnBits(2));
119 EXPECT_EQ(32u, table.NumColumnBits(3));
120}
121
David Srbecky159c9dd2018-05-24 14:56:51 +0100122TEST(BitTableTest, TestDedup) {
123 MallocArenaPool pool;
124 ArenaStack arena_stack(&pool);
125 ScopedArenaAllocator allocator(&arena_stack);
126
David Srbeckycf7833e2018-06-14 16:45:22 +0100127 BitTableBuilderBase<2> builder(&allocator);
128 BitTableBuilderBase<2>::Entry value0{1, 2};
129 BitTableBuilderBase<2>::Entry value1{3, 4};
David Srbecky5513c2b2018-05-24 15:03:20 +0100130 EXPECT_EQ(0u, builder.Dedup(&value0));
131 EXPECT_EQ(1u, builder.Dedup(&value1));
132 EXPECT_EQ(0u, builder.Dedup(&value0));
133 EXPECT_EQ(1u, builder.Dedup(&value1));
134 EXPECT_EQ(2u, builder.size());
135}
136
137TEST(BitTableTest, TestBitmapTable) {
138 MallocArenaPool pool;
139 ArenaStack arena_stack(&pool);
140 ScopedArenaAllocator allocator(&arena_stack);
141
142 std::vector<uint8_t> buffer;
David Srbecky078d7ba2018-06-21 15:36:48 +0100143 BitMemoryWriter<std::vector<uint8_t>> writer(&buffer);
David Srbecky5513c2b2018-05-24 15:03:20 +0100144 const uint64_t value = 0xDEADBEEF0BADF00Dull;
145 BitmapTableBuilder builder(&allocator);
Alex Light1e52a072019-06-25 09:12:04 -0700146 std::multimap<uint64_t, size_t> indices; // bitmap -> row.
David Srbecky5513c2b2018-05-24 15:03:20 +0100147 for (size_t bit_length = 0; bit_length <= BitSizeOf<uint64_t>(); ++bit_length) {
148 uint64_t bitmap = value & MaxInt<uint64_t>(bit_length);
Alex Light1e52a072019-06-25 09:12:04 -0700149 indices.emplace(bitmap, builder.Dedup(&bitmap, MinimumBitsToStore(bitmap)));
David Srbecky5513c2b2018-05-24 15:03:20 +0100150 }
David Srbecky078d7ba2018-06-21 15:36:48 +0100151 builder.Encode(writer);
David Srbecky5513c2b2018-05-24 15:03:20 +0100152 EXPECT_EQ(1 + static_cast<uint32_t>(POPCOUNT(value)), builder.size());
153
David Srbeckya38e6cf2018-06-26 18:13:49 +0100154 BitMemoryReader reader(buffer.data());
David Srbecky078d7ba2018-06-21 15:36:48 +0100155 BitTableBase<1> table(reader);
David Srbeckyd1606412018-07-31 15:05:14 +0100156 EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
Alex Light1e52a072019-06-25 09:12:04 -0700157 for (auto it : indices) {
David Srbecky5513c2b2018-05-24 15:03:20 +0100158 uint64_t expected = it.first;
159 BitMemoryRegion actual = table.GetBitMemoryRegion(it.second);
160 EXPECT_GE(actual.size_in_bits(), MinimumBitsToStore(expected));
161 for (size_t b = 0; b < actual.size_in_bits(); b++, expected >>= 1) {
162 EXPECT_EQ(expected & 1, actual.LoadBit(b)) << "b=" << b;
163 }
164 }
165}
166
167TEST(BitTableTest, TestCollisions) {
168 MallocArenaPool pool;
169 ArenaStack arena_stack(&pool);
170 ScopedArenaAllocator allocator(&arena_stack);
David Srbecky159c9dd2018-05-24 14:56:51 +0100171 FNVHash<MemoryRegion> hasher;
David Srbecky5513c2b2018-05-24 15:03:20 +0100172
David Srbeckycf7833e2018-06-14 16:45:22 +0100173 BitTableBuilderBase<2>::Entry value0{56948505, 0};
174 BitTableBuilderBase<2>::Entry value1{67108869, 0};
David Srbecky5513c2b2018-05-24 15:03:20 +0100175
David Srbeckycf7833e2018-06-14 16:45:22 +0100176 BitTableBuilderBase<2> builder(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100177 EXPECT_EQ(hasher(MemoryRegion(&value0, sizeof(value0))),
178 hasher(MemoryRegion(&value1, sizeof(value1))));
David Srbecky159c9dd2018-05-24 14:56:51 +0100179 EXPECT_EQ(0u, builder.Dedup(&value0));
180 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky159c9dd2018-05-24 14:56:51 +0100181 EXPECT_EQ(0u, builder.Dedup(&value0));
182 EXPECT_EQ(1u, builder.Dedup(&value1));
David Srbecky5513c2b2018-05-24 15:03:20 +0100183 EXPECT_EQ(2u, builder.size());
184
185 BitmapTableBuilder builder2(&allocator);
David Srbeckyf325e282018-06-13 15:02:32 +0100186 EXPECT_EQ(hasher(MemoryRegion(&value0, BitsToBytesRoundUp(MinimumBitsToStore(value0[0])))),
187 hasher(MemoryRegion(&value1, BitsToBytesRoundUp(MinimumBitsToStore(value1[0])))));
188 EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
189 EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
190 EXPECT_EQ(0u, builder2.Dedup(&value0[0], MinimumBitsToStore(value0[0])));
191 EXPECT_EQ(1u, builder2.Dedup(&value1[0], MinimumBitsToStore(value1[0])));
David Srbecky5513c2b2018-05-24 15:03:20 +0100192 EXPECT_EQ(2u, builder2.size());
David Srbecky159c9dd2018-05-24 14:56:51 +0100193}
194
David Srbecky052f8ca2018-04-26 15:42:54 +0100195} // namespace art