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
18namespace fs = std::filesystem;
19
20static 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
30template <size_t width, size_t bucket_count, typename Generator>
31struct 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
92template <typename Generator>
93struct 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
225struct Generator1
226{
227 static UInt8 execute(size_t, size_t width)
228 {
229 return (1 << width) - 1;
230 }
231};
232
233struct Generator2
234{
235 static UInt8 execute(size_t i, size_t width)
236 {
237 return (i >> 1) & ((1 << width) - 1);
238 }
239};
240
241struct Generator3
242{
243 static UInt8 execute(size_t i, size_t width)
244 {
245 return (i * 17 + 31) % (1ULL << width);
246 }
247};
248
249static 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
259int main()
260{
261 runTests();
262 return 0;
263}
264
265#if !__clang__
266#pragma GCC diagnostic pop
267#endif
268