2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef FOLLY_EXPERIMENTAL_CODING_TEST_UTILS_H
18 #define FOLLY_EXPERIMENTAL_CODING_TEST_UTILS_H
26 #include <unordered_set>
27 #include <glog/logging.h>
28 #include <gtest/gtest.h>
30 namespace folly { namespace compression {
32 std::vector<uint32_t> generateRandomList(size_t n, uint32_t maxId) {
33 CHECK_LT(n, 2 * maxId);
35 std::uniform_int_distribution<> uid(1, maxId);
36 std::unordered_set<uint32_t> dataset;
37 while (dataset.size() < n) {
38 uint32_t value = uid(gen);
39 if (dataset.count(value) == 0) {
40 dataset.insert(value);
44 std::vector<uint32_t> ids(dataset.begin(), dataset.end());
45 std::sort(ids.begin(), ids.end());
49 std::vector<uint32_t> generateSeqList(uint32_t minId, uint32_t maxId,
51 CHECK_LE(minId, maxId);
53 std::vector<uint32_t> ids;
54 ids.reserve((maxId - minId) / step + 1);
55 for (uint32_t i = minId; i <= maxId; i += step) {
61 std::vector<uint32_t> loadList(const std::string& filename) {
62 std::ifstream fin(filename);
63 std::vector<uint32_t> result;
71 template <class Reader, class List>
72 void testNext(const std::vector<uint32_t>& data, const List& list) {
74 EXPECT_EQ(reader.value(), 0);
75 for (size_t i = 0; i < data.size(); ++i) {
76 EXPECT_TRUE(reader.next());
77 EXPECT_EQ(reader.value(), data[i]);
79 EXPECT_FALSE(reader.next());
80 EXPECT_EQ(reader.value(), std::numeric_limits<uint32_t>::max());
83 template <class Reader, class List>
84 void testSkip(const std::vector<uint32_t>& data, const List& list,
86 CHECK_GT(skipStep, 0);
88 EXPECT_EQ(reader.value(), 0);
89 for (size_t i = skipStep - 1; i < data.size(); i += skipStep) {
90 EXPECT_TRUE(reader.skip(skipStep));
91 EXPECT_EQ(reader.value(), data[i]);
93 EXPECT_FALSE(reader.skip(skipStep));
94 EXPECT_EQ(reader.value(), std::numeric_limits<uint32_t>::max());
95 EXPECT_FALSE(reader.next());
98 template <class Reader, class List>
99 void testSkip(const std::vector<uint32_t>& data, const List& list) {
100 for (size_t skipStep = 1; skipStep < 25; ++skipStep) {
101 testSkip<Reader, List>(data, list, skipStep);
103 for (size_t skipStep = 25; skipStep <= 500; skipStep += 25) {
104 testSkip<Reader, List>(data, list, skipStep);
108 template <class Reader, class List>
109 void testSkipTo(const std::vector<uint32_t>& data, const List& list,
111 CHECK_GT(skipToStep, 0);
114 EXPECT_EQ(reader.value(), 0);
116 const uint32_t delta = std::max<uint32_t>(1, data.back() / skipToStep);
117 uint32_t value = delta;
118 auto it = data.begin();
120 it = std::lower_bound(it, data.end(), value);
121 if (it == data.end()) {
122 EXPECT_FALSE(reader.skipTo(value));
125 EXPECT_TRUE(reader.skipTo(value));
126 EXPECT_EQ(reader.value(), *it);
127 value = reader.value() + delta;
130 EXPECT_EQ(reader.value(), std::numeric_limits<uint32_t>::max());
131 EXPECT_FALSE(reader.next());
134 template <class Reader, class List>
135 void testSkipTo(const std::vector<uint32_t>& data, const List& list) {
136 for (size_t steps = 10; steps < 100; steps += 10) {
137 testSkipTo<Reader, List>(data, list, steps);
139 for (size_t steps = 100; steps <= 1000; steps += 100) {
140 testSkipTo<Reader, List>(data, list, steps);
142 testSkipTo<Reader, List>(data, list, std::numeric_limits<size_t>::max());
145 EXPECT_FALSE(reader.skipTo(data.back() + 1));
146 EXPECT_EQ(reader.value(), std::numeric_limits<uint32_t>::max());
147 EXPECT_FALSE(reader.next());
151 template <class Reader, class Encoder>
153 typename Encoder::CompressedList list;
154 const typename Encoder::ValueType* const data = nullptr;
155 Encoder::encode(data, 0, list);
158 EXPECT_FALSE(reader.next());
159 EXPECT_EQ(reader.size(), 0);
163 EXPECT_FALSE(reader.skip(1));
164 EXPECT_FALSE(reader.skip(10));
168 EXPECT_FALSE(reader.skipTo(1));
172 template <class Reader, class Encoder>
173 void testAll(const std::vector<uint32_t>& data) {
174 typename Encoder::CompressedList list;
175 Encoder::encode(data.begin(), data.end(), list);
176 testNext<Reader>(data, list);
177 testSkip<Reader>(data, list);
178 testSkipTo<Reader>(data, list);
182 template <class Reader, class List>
183 void bmNext(const List& list, const std::vector<uint32_t>& data,
188 for (size_t i = 0, j; i < iters; ) {
190 for (j = 0; reader.next(); ++j, ++i) {
191 const uint32_t value = reader.value();
192 CHECK_EQ(value, data[j]) << j;
197 template <class Reader, class List>
198 void bmSkip(const List& list, const std::vector<uint32_t>& data,
199 size_t skip, size_t iters) {
200 if (skip >= data.size()) {
203 for (size_t i = 0, j; i < iters; ) {
205 for (j = skip - 1; j < data.size(); j += skip, ++i) {
207 const uint32_t value = reader.value();
208 CHECK_EQ(value, data[j]);
213 template <class Reader, class List>
214 void bmSkipTo(const List& list, const std::vector<uint32_t>& data,
215 size_t skip, size_t iters) {
216 if (skip >= data.size()) {
219 for (size_t i = 0, j; i < iters; ) {
221 for (j = 0; j < data.size(); j += skip, ++i) {
222 reader.skipTo(data[j]);
223 const uint32_t value = reader.value();
224 CHECK_EQ(value, data[j]);
231 #endif // FOLLY_EXPERIMENTAL_CODING_TEST_UTILS_H