1 | /// Bug in GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 |
2 | #if !__clang__ |
3 | #pragma GCC diagnostic push |
4 | #pragma GCC diagnostic ignored "-Warray-bounds" |
5 | #endif |
6 | |
7 | #include <Common/CompactArray.h> |
8 | #include <IO/WriteBufferFromFile.h> |
9 | #include <IO/ReadBufferFromFile.h> |
10 | #include <filesystem> |
11 | #include <string> |
12 | #include <iostream> |
13 | #include <fstream> |
14 | #include <stdexcept> |
15 | #include <cstdlib> |
16 | #include <port/unistd.h> |
17 | |
18 | namespace fs = std::filesystem; |
19 | |
20 | static std::string createTmpPath(const std::string & filename) |
21 | { |
22 | char pattern[] = "/tmp/fileXXXXXX" ; |
23 | char * dir = mkdtemp(pattern); |
24 | if (dir == nullptr) |
25 | throw std::runtime_error("Could not create directory" ); |
26 | |
27 | return std::string(dir) + "/" + filename; |
28 | } |
29 | |
30 | template <size_t width, size_t bucket_count, typename Generator> |
31 | struct Test |
32 | { |
33 | static void perform() |
34 | { |
35 | bool ok = true; |
36 | |
37 | std::string filename; |
38 | |
39 | try |
40 | { |
41 | using Store = DB::CompactArray<UInt64, width, bucket_count>; |
42 | |
43 | Store store; |
44 | |
45 | for (size_t i = 0; i < bucket_count; ++i) |
46 | store[i] = Generator::execute(i, width); |
47 | |
48 | filename = createTmpPath("compact_array.bin" ); |
49 | |
50 | { |
51 | DB::WriteBufferFromFile wb(filename); |
52 | wb.write(reinterpret_cast<const char *>(&store), sizeof(store)); |
53 | } |
54 | |
55 | { |
56 | DB::ReadBufferFromFile rb(filename); |
57 | typename Store::Reader reader(rb); |
58 | while (reader.next()) |
59 | { |
60 | const auto & data = reader.get(); |
61 | if (data.second != store[data.first]) |
62 | throw std::runtime_error("Found discrepancy" ); |
63 | } |
64 | } |
65 | } |
66 | catch (const Poco::Exception & ex) |
67 | { |
68 | std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " failed " |
69 | << "(Error: " << ex.what() << ": " << ex.displayText() << ")\n" ; |
70 | ok = false; |
71 | } |
72 | catch (const std::runtime_error & ex) |
73 | { |
74 | std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " failed " |
75 | << "(Error: " << ex.what() << ")\n" ; |
76 | ok = false; |
77 | } |
78 | catch (...) |
79 | { |
80 | std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " failed\n" ; |
81 | ok = false; |
82 | } |
83 | |
84 | fs::remove_all(fs::path(filename).parent_path().string()); |
85 | |
86 | if (ok) |
87 | std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " passed\n" ; |
88 | } |
89 | }; |
90 | |
91 | |
92 | template <typename Generator> |
93 | struct TestSet |
94 | { |
95 | static void execute() |
96 | { |
97 | Test<1, 1, Generator>::perform(); |
98 | Test<1, 2, Generator>::perform(); |
99 | Test<1, 3, Generator>::perform(); |
100 | Test<1, 4, Generator>::perform(); |
101 | Test<1, 5, Generator>::perform(); |
102 | Test<1, 6, Generator>::perform(); |
103 | Test<1, 7, Generator>::perform(); |
104 | Test<1, 8, Generator>::perform(); |
105 | Test<1, 9, Generator>::perform(); |
106 | Test<1, 10, Generator>::perform(); |
107 | Test<1, 16, Generator>::perform(); |
108 | Test<1, 32, Generator>::perform(); |
109 | Test<1, 64, Generator>::perform(); |
110 | Test<1, 128, Generator>::perform(); |
111 | Test<1, 256, Generator>::perform(); |
112 | Test<1, 512, Generator>::perform(); |
113 | Test<1, 1024, Generator>::perform(); |
114 | |
115 | Test<2, 1, Generator>::perform(); |
116 | Test<2, 2, Generator>::perform(); |
117 | Test<2, 3, Generator>::perform(); |
118 | Test<2, 4, Generator>::perform(); |
119 | Test<2, 5, Generator>::perform(); |
120 | Test<2, 6, Generator>::perform(); |
121 | Test<2, 7, Generator>::perform(); |
122 | Test<2, 8, Generator>::perform(); |
123 | Test<2, 9, Generator>::perform(); |
124 | Test<2, 10, Generator>::perform(); |
125 | Test<2, 16, Generator>::perform(); |
126 | Test<2, 32, Generator>::perform(); |
127 | Test<2, 64, Generator>::perform(); |
128 | Test<2, 128, Generator>::perform(); |
129 | Test<2, 256, Generator>::perform(); |
130 | Test<2, 512, Generator>::perform(); |
131 | Test<2, 1024, Generator>::perform(); |
132 | |
133 | Test<3, 1, Generator>::perform(); |
134 | Test<3, 2, Generator>::perform(); |
135 | Test<3, 3, Generator>::perform(); |
136 | Test<3, 4, Generator>::perform(); |
137 | Test<3, 5, Generator>::perform(); |
138 | Test<3, 6, Generator>::perform(); |
139 | Test<3, 7, Generator>::perform(); |
140 | Test<3, 8, Generator>::perform(); |
141 | Test<3, 9, Generator>::perform(); |
142 | Test<3, 10, Generator>::perform(); |
143 | Test<3, 16, Generator>::perform(); |
144 | Test<3, 32, Generator>::perform(); |
145 | Test<3, 64, Generator>::perform(); |
146 | Test<3, 128, Generator>::perform(); |
147 | Test<3, 256, Generator>::perform(); |
148 | Test<3, 512, Generator>::perform(); |
149 | Test<3, 1024, Generator>::perform(); |
150 | |
151 | Test<4, 1, Generator>::perform(); |
152 | Test<4, 2, Generator>::perform(); |
153 | Test<4, 3, Generator>::perform(); |
154 | Test<4, 4, Generator>::perform(); |
155 | Test<4, 5, Generator>::perform(); |
156 | Test<4, 6, Generator>::perform(); |
157 | Test<4, 7, Generator>::perform(); |
158 | Test<4, 8, Generator>::perform(); |
159 | Test<4, 9, Generator>::perform(); |
160 | Test<4, 10, Generator>::perform(); |
161 | Test<4, 16, Generator>::perform(); |
162 | Test<4, 32, Generator>::perform(); |
163 | Test<4, 64, Generator>::perform(); |
164 | Test<4, 128, Generator>::perform(); |
165 | Test<4, 256, Generator>::perform(); |
166 | Test<4, 512, Generator>::perform(); |
167 | Test<4, 1024, Generator>::perform(); |
168 | |
169 | Test<5, 1, Generator>::perform(); |
170 | Test<5, 2, Generator>::perform(); |
171 | Test<5, 3, Generator>::perform(); |
172 | Test<5, 4, Generator>::perform(); |
173 | Test<5, 5, Generator>::perform(); |
174 | Test<5, 6, Generator>::perform(); |
175 | Test<5, 7, Generator>::perform(); |
176 | Test<5, 8, Generator>::perform(); |
177 | Test<5, 9, Generator>::perform(); |
178 | Test<5, 10, Generator>::perform(); |
179 | Test<5, 16, Generator>::perform(); |
180 | Test<5, 32, Generator>::perform(); |
181 | Test<5, 64, Generator>::perform(); |
182 | Test<5, 128, Generator>::perform(); |
183 | Test<5, 256, Generator>::perform(); |
184 | Test<5, 512, Generator>::perform(); |
185 | Test<5, 1024, Generator>::perform(); |
186 | |
187 | Test<6, 1, Generator>::perform(); |
188 | Test<6, 2, Generator>::perform(); |
189 | Test<6, 3, Generator>::perform(); |
190 | Test<6, 4, Generator>::perform(); |
191 | Test<6, 5, Generator>::perform(); |
192 | Test<6, 6, Generator>::perform(); |
193 | Test<6, 7, Generator>::perform(); |
194 | Test<6, 8, Generator>::perform(); |
195 | Test<6, 9, Generator>::perform(); |
196 | Test<6, 10, Generator>::perform(); |
197 | Test<6, 16, Generator>::perform(); |
198 | Test<6, 32, Generator>::perform(); |
199 | Test<6, 64, Generator>::perform(); |
200 | Test<6, 128, Generator>::perform(); |
201 | Test<6, 256, Generator>::perform(); |
202 | Test<6, 512, Generator>::perform(); |
203 | Test<6, 1024, Generator>::perform(); |
204 | |
205 | Test<7, 1, Generator>::perform(); |
206 | Test<7, 2, Generator>::perform(); |
207 | Test<7, 3, Generator>::perform(); |
208 | Test<7, 4, Generator>::perform(); |
209 | Test<7, 5, Generator>::perform(); |
210 | Test<7, 6, Generator>::perform(); |
211 | Test<7, 7, Generator>::perform(); |
212 | Test<7, 8, Generator>::perform(); |
213 | Test<7, 9, Generator>::perform(); |
214 | Test<7, 10, Generator>::perform(); |
215 | Test<7, 16, Generator>::perform(); |
216 | Test<7, 32, Generator>::perform(); |
217 | Test<7, 64, Generator>::perform(); |
218 | Test<7, 128, Generator>::perform(); |
219 | Test<7, 256, Generator>::perform(); |
220 | Test<7, 512, Generator>::perform(); |
221 | Test<7, 1024, Generator>::perform(); |
222 | } |
223 | }; |
224 | |
225 | struct Generator1 |
226 | { |
227 | static UInt8 execute(size_t, size_t width) |
228 | { |
229 | return (1 << width) - 1; |
230 | } |
231 | }; |
232 | |
233 | struct Generator2 |
234 | { |
235 | static UInt8 execute(size_t i, size_t width) |
236 | { |
237 | return (i >> 1) & ((1 << width) - 1); |
238 | } |
239 | }; |
240 | |
241 | struct Generator3 |
242 | { |
243 | static UInt8 execute(size_t i, size_t width) |
244 | { |
245 | return (i * 17 + 31) % (1ULL << width); |
246 | } |
247 | }; |
248 | |
249 | static void runTests() |
250 | { |
251 | std::cout << "Test set 1\n" ; |
252 | TestSet<Generator1>::execute(); |
253 | std::cout << "Test set 2\n" ; |
254 | TestSet<Generator2>::execute(); |
255 | std::cout << "Test set 3\n" ; |
256 | TestSet<Generator3>::execute(); |
257 | } |
258 | |
259 | int main() |
260 | { |
261 | runTests(); |
262 | return 0; |
263 | } |
264 | |
265 | #if !__clang__ |
266 | #pragma GCC diagnostic pop |
267 | #endif |
268 | |