Line data Source code
1 : // Copyright (c) 2011-2026 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/edhttp
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : /** \file
20 : * \brief Verify the snap_uri class.
21 : *
22 : * This file implements tests to verify that the snap_uri
23 : * class functions as expected.
24 : */
25 :
26 : // edhttp
27 : //
28 : #include <edhttp/compression/compressor.h>
29 :
30 : #include <edhttp/exception.h>
31 : #include <edhttp/token.h>
32 :
33 :
34 : // self
35 : //
36 : #include "catch_main.h"
37 :
38 :
39 : // snapdev
40 : //
41 : #include <snapdev/file_contents.h>
42 : #include <snapdev/not_used.h>
43 :
44 :
45 : // snaplogger
46 : //
47 : #include <snaplogger/message.h>
48 :
49 :
50 : // C++
51 : //
52 : #include <random>
53 :
54 :
55 : // last include
56 : //
57 : #include <snapdev/poison.h>
58 :
59 :
60 :
61 : namespace
62 : {
63 :
64 :
65 :
66 : class compressor_named
67 : : public edhttp::compressor
68 : {
69 : public:
70 181 : compressor_named(char const * name) : compressor(name) {}
71 :
72 0 : virtual char const * get_name() const override { return nullptr; }
73 0 : virtual edhttp::buffer_t compress(edhttp::buffer_t const & input, edhttp::level_t level, bool text) override { snapdev::NOT_USED(input, level, text); return edhttp::buffer_t(); }
74 0 : virtual bool compatible(edhttp::buffer_t const & input) const override { snapdev::NOT_USED(input); return false; }
75 0 : virtual edhttp::buffer_t decompress(edhttp::buffer_t const & input) override { snapdev::NOT_USED(input); return edhttp::buffer_t(); }
76 0 : virtual edhttp::buffer_t decompress(edhttp::buffer_t const & input, std::size_t uncompressed_size) override { snapdev::NOT_USED(input, uncompressed_size); return edhttp::buffer_t(); }
77 : };
78 :
79 :
80 :
81 : } // no name namespace
82 :
83 :
84 :
85 4 : CATCH_TEST_CASE("compressor_bz2", "[compression]")
86 : {
87 4 : CATCH_START_SECTION("compressor_bz2: verify bz2 compressor")
88 : {
89 3 : edhttp::compressor * bz2(edhttp::get_compressor("bz2"));
90 1 : CATCH_REQUIRE(bz2 != nullptr);
91 1 : CATCH_REQUIRE(strcmp(bz2->get_name(), "bz2") == 0);
92 :
93 : // generate a random buffer to compress of 1kb to 16kb in size
94 : //
95 1 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
96 12 : for(edhttp::level_t level(0); level <= 100; level += 10)
97 : {
98 11 : edhttp::buffer_t const compressed(bz2->compress(input, level, rand() & 1 == 0));
99 :
100 11 : bool equal(true);
101 11 : if(compressed.size() == input.size())
102 : {
103 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
104 : {
105 0 : if(compressed[pos] != input[pos])
106 : {
107 0 : equal = false;
108 0 : break;
109 : }
110 : }
111 : }
112 : else
113 : {
114 11 : equal = false;
115 : }
116 11 : CATCH_REQUIRE_FALSE(equal);
117 :
118 11 : edhttp::buffer_t const decompressed(bz2->decompress(compressed));
119 11 : CATCH_REQUIRE(decompressed.size() == input.size());
120 :
121 11 : equal = true;
122 46112 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
123 : {
124 46101 : if(decompressed[pos] != input[pos])
125 : {
126 0 : equal = false;
127 0 : break;
128 : }
129 : }
130 11 : CATCH_REQUIRE(equal);
131 :
132 88 : for(std::size_t s(2); s < 9; ++s)
133 : {
134 231 : edhttp::buffer_t const broken_compressed_small(compressed.data(), compressed.data() + s);
135 77 : edhttp::buffer_t const compressed_repeat(bz2->decompress(broken_compressed_small));
136 77 : CATCH_REQUIRE(compressed_repeat == broken_compressed_small);
137 :
138 231 : edhttp::buffer_t broken_compressed_small2(compressed.data(), compressed.data() + s);
139 77 : broken_compressed_small2.back() ^= 0xff;
140 77 : edhttp::buffer_t const compressed_repeat2(bz2->decompress(broken_compressed_small2));
141 77 : CATCH_REQUIRE(compressed_repeat2 == broken_compressed_small2);
142 :
143 77 : edhttp::buffer_t const compressed_repeat3(bz2->decompress(broken_compressed_small2, input.size()));
144 77 : CATCH_REQUIRE(compressed_repeat3 == broken_compressed_small2);
145 77 : }
146 :
147 : // we do recognize a bz2 buffer
148 : //
149 11 : CATCH_REQUIRE_FALSE(bz2->compatible(input));
150 11 : CATCH_REQUIRE(bz2->compatible(compressed));
151 11 : CATCH_REQUIRE_FALSE(bz2->compatible(decompressed));
152 11 : }
153 1 : }
154 5 : CATCH_END_SECTION()
155 :
156 4 : CATCH_START_SECTION("compressor_bz2: verify small buffers with bz2 compressor")
157 : {
158 3 : edhttp::compressor * bz2(edhttp::get_compressor("bz2"));
159 1 : CATCH_REQUIRE(bz2 != nullptr);
160 :
161 : // generate a random buffer to compress of 1kb to 16kb in size
162 : //
163 20 : for(int size(1); size < 20; ++size)
164 : {
165 19 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
166 19 : edhttp::buffer_t const compressed(bz2->compress(input, rand() % 95 + 5, rand() & 1 == 0));
167 :
168 19 : bool equal(true);
169 19 : if(compressed.size() == input.size())
170 : {
171 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
172 : {
173 0 : if(compressed[pos] != input[pos])
174 : {
175 0 : equal = false;
176 0 : break;
177 : }
178 : }
179 : }
180 : else
181 : {
182 19 : equal = false;
183 : }
184 19 : CATCH_REQUIRE_FALSE(equal);
185 :
186 19 : edhttp::buffer_t const decompressed(bz2->decompress(compressed));
187 19 : CATCH_REQUIRE(decompressed.size() == input.size());
188 :
189 19 : equal = true;
190 209 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
191 : {
192 190 : if(decompressed[pos] != input[pos])
193 : {
194 0 : equal = false;
195 0 : break;
196 : }
197 : }
198 19 : CATCH_REQUIRE(equal);
199 :
200 : // we do recognize a bz2 buffer
201 : //
202 19 : CATCH_REQUIRE(bz2->compatible(compressed));
203 19 : }
204 : }
205 5 : CATCH_END_SECTION()
206 :
207 4 : CATCH_START_SECTION("compressor_bz2: verify invalid bz2 magic length")
208 : {
209 3 : edhttp::compressor * bz2(edhttp::get_compressor("bz2"));
210 1 : CATCH_REQUIRE(bz2 != nullptr);
211 1 : CATCH_REQUIRE(strcmp(bz2->get_name(), "bz2") == 0);
212 :
213 10 : for(std::size_t size(0); size < 9; ++size)
214 : {
215 : // generate a random buffer to compress of 1kb to 16kb in size
216 : //
217 9 : auto input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
218 9 : if(size >= 1)
219 : {
220 8 : input[0] = 'B';
221 : }
222 9 : if(size >= 2)
223 : {
224 7 : input[1] = 'Z';
225 : }
226 9 : if(size >= 3)
227 : {
228 6 : input[2] = 'h';
229 : }
230 9 : if(size >= 4)
231 : {
232 5 : input[3] = rand() % 10 + '0';
233 : }
234 9 : CATCH_REQUIRE_FALSE(bz2->compatible(input));
235 9 : }
236 : }
237 5 : CATCH_END_SECTION()
238 :
239 4 : CATCH_START_SECTION("compressor_bz2: attempt bz2 compressing an empty buffer")
240 : {
241 3 : edhttp::compressor * bz2(edhttp::get_compressor("bz2"));
242 1 : CATCH_REQUIRE(bz2 != nullptr);
243 1 : CATCH_REQUIRE(strcmp(bz2->get_name(), "bz2") == 0);
244 :
245 1 : edhttp::buffer_t const empty;
246 1 : CATCH_REQUIRE_FALSE(bz2->compatible(empty));
247 :
248 22 : for(edhttp::level_t level(0); level <= 120; level += rand() % 10 + 1)
249 : {
250 21 : edhttp::buffer_t const compressed(bz2->compress(empty, level, false));
251 :
252 : // an empty buffer can be "compressed" (the output is bigger, but it
253 : // does not fail)
254 : //
255 : //CATCH_REQUIRE(empty == compressed);
256 :
257 21 : edhttp::buffer_t const decompressed(bz2->decompress(compressed));
258 21 : CATCH_REQUIRE(empty == decompressed);
259 21 : }
260 1 : }
261 5 : CATCH_END_SECTION()
262 4 : }
263 :
264 :
265 3 : CATCH_TEST_CASE("compressor_deflate", "[compression]")
266 : {
267 3 : CATCH_START_SECTION("compressor_deflate: verify deflate compressor")
268 : {
269 3 : edhttp::compressor * deflate(edhttp::get_compressor("deflate"));
270 1 : CATCH_REQUIRE(deflate != nullptr);
271 1 : CATCH_REQUIRE(strcmp(deflate->get_name(), "deflate") == 0);
272 :
273 : // generate a random buffer to compress of 1kb to 16kb in size
274 : //
275 1 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
276 12 : for(edhttp::level_t level(0); level <= 100; level += 10)
277 : {
278 11 : edhttp::buffer_t const compressed(deflate->compress(input, level, rand() & 1 == 0));
279 :
280 11 : bool equal(true);
281 11 : if(compressed.size() == input.size())
282 : {
283 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
284 : {
285 0 : if(compressed[pos] != input[pos])
286 : {
287 0 : equal = false;
288 0 : break;
289 : }
290 : }
291 : }
292 : else
293 : {
294 11 : equal = false;
295 : }
296 11 : CATCH_REQUIRE_FALSE(equal);
297 :
298 11 : edhttp::buffer_t const decompressed(deflate->decompress(compressed, input.size()));
299 11 : CATCH_REQUIRE(decompressed.size() == input.size());
300 :
301 11 : equal = true;
302 108174 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
303 : {
304 108163 : if(decompressed[pos] != input[pos])
305 : {
306 0 : equal = false;
307 0 : break;
308 : }
309 : }
310 11 : CATCH_REQUIRE(equal);
311 :
312 : // decompress with the wrong size has to fail
313 : // failure in this case means the input buffer is returned as is
314 : //
315 11 : edhttp::buffer_t compressed_repeat(deflate->decompress(compressed, input.size() / 2));
316 11 : CATCH_REQUIRE(compressed_repeat.size() == compressed.size());
317 11 : CATCH_REQUIRE(compressed_repeat == compressed);
318 :
319 11 : compressed_repeat = deflate->decompress(compressed, 3);
320 11 : CATCH_REQUIRE(compressed_repeat.size() == compressed.size());
321 11 : CATCH_REQUIRE(compressed_repeat == compressed);
322 :
323 : // we cannot recognize a deflated buffer because it has no magic
324 : //
325 11 : CATCH_REQUIRE_FALSE(deflate->compatible(input));
326 11 : CATCH_REQUIRE_FALSE(deflate->compatible(compressed));
327 11 : CATCH_REQUIRE_FALSE(deflate->compatible(decompressed));
328 11 : }
329 1 : }
330 4 : CATCH_END_SECTION()
331 :
332 3 : CATCH_START_SECTION("compressor_deflate: attempt deflate compressing an empty buffer")
333 : {
334 3 : edhttp::compressor * deflate(edhttp::get_compressor("deflate"));
335 1 : CATCH_REQUIRE(deflate != nullptr);
336 1 : CATCH_REQUIRE(strcmp(deflate->get_name(), "deflate") == 0);
337 :
338 1 : edhttp::buffer_t const empty;
339 1 : CATCH_REQUIRE_FALSE(deflate->compatible(empty));
340 :
341 21 : for(edhttp::level_t level(rand() % 6); level <= 120; level += rand() % 10 + 1)
342 : {
343 20 : edhttp::buffer_t const compressed(deflate->compress(empty, level, false));
344 :
345 : // an empty buffer can be "compressed" (the output is bigger, but it
346 : // does not fail)
347 : //
348 : //CATCH_REQUIRE(empty == compressed);
349 :
350 20 : edhttp::buffer_t const decompressed(deflate->decompress(compressed, 0));
351 20 : CATCH_REQUIRE(empty == decompressed);
352 20 : }
353 1 : }
354 4 : CATCH_END_SECTION()
355 :
356 3 : CATCH_START_SECTION("compressor_deflate: compress small buffers with deflate")
357 : {
358 3 : edhttp::compressor * deflate(edhttp::get_compressor("deflate"));
359 1 : CATCH_REQUIRE(deflate != nullptr);
360 1 : CATCH_REQUIRE(strcmp(deflate->get_name(), "deflate") == 0);
361 :
362 1024 : for(std::size_t size(1); size < 1024; ++size)
363 : {
364 1023 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
365 1023 : edhttp::buffer_t const compressed(deflate->compress(input, rand() % 95 + 5, (rand() & 1) == 0));
366 :
367 1023 : edhttp::buffer_t const decompressed(deflate->decompress(compressed, size));
368 1023 : CATCH_REQUIRE(input == decompressed);
369 1023 : }
370 : }
371 4 : CATCH_END_SECTION()
372 3 : }
373 :
374 :
375 4 : CATCH_TEST_CASE("compressor_gzip", "[compression]")
376 : {
377 4 : CATCH_START_SECTION("compressor_gzip: verify gzip compressor")
378 : {
379 3 : edhttp::compressor * gzip(edhttp::get_compressor("gzip"));
380 1 : CATCH_REQUIRE(gzip != nullptr);
381 1 : CATCH_REQUIRE(strcmp(gzip->get_name(), "gzip") == 0);
382 :
383 : // generate a random buffer to compress of 1kb to 16kb in size
384 : //
385 1 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
386 12 : for(edhttp::level_t level(0); level <= 100; level += 10)
387 : {
388 11 : edhttp::buffer_t const compressed(gzip->compress(input, level, rand() & 1 == 0));
389 :
390 11 : bool equal(true);
391 11 : if(compressed.size() == input.size())
392 : {
393 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
394 : {
395 0 : if(compressed[pos] != input[pos])
396 : {
397 0 : equal = false;
398 0 : break;
399 : }
400 : }
401 : }
402 : else
403 : {
404 11 : equal = false;
405 : }
406 11 : CATCH_REQUIRE_FALSE(equal);
407 :
408 11 : edhttp::buffer_t const decompressed(gzip->decompress(compressed));
409 11 : CATCH_REQUIRE(decompressed.size() == input.size());
410 :
411 11 : equal = true;
412 152559 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
413 : {
414 152548 : if(decompressed[pos] != input[pos])
415 : {
416 0 : equal = false;
417 0 : break;
418 : }
419 : }
420 11 : CATCH_REQUIRE(equal);
421 :
422 88 : for(std::size_t s(2); s < 9; ++s)
423 : {
424 231 : edhttp::buffer_t const broken_compressed_small(compressed.data(), compressed.data() + s);
425 77 : edhttp::buffer_t const compressed_repeat(gzip->decompress(broken_compressed_small));
426 77 : CATCH_REQUIRE(compressed_repeat == broken_compressed_small);
427 77 : }
428 :
429 : // we do recognize a gzip buffer
430 : //
431 11 : CATCH_REQUIRE_FALSE(gzip->compatible(input));
432 11 : CATCH_REQUIRE(gzip->compatible(compressed));
433 11 : CATCH_REQUIRE_FALSE(gzip->compatible(decompressed));
434 11 : }
435 1 : }
436 5 : CATCH_END_SECTION()
437 :
438 4 : CATCH_START_SECTION("compressor_gzip: verify small buffers with gzip compressor")
439 : {
440 3 : edhttp::compressor * gzip(edhttp::get_compressor("gzip"));
441 1 : CATCH_REQUIRE(gzip != nullptr);
442 :
443 : // generate a random buffer to compress of 1kb to 16kb in size
444 : //
445 20 : for(int size(1); size < 20; ++size)
446 : {
447 19 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
448 19 : edhttp::buffer_t const compressed(gzip->compress(input, rand() % 95 + 5, rand() & 1 == 0));
449 :
450 19 : bool equal(true);
451 19 : if(compressed.size() == input.size())
452 : {
453 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
454 : {
455 0 : if(compressed[pos] != input[pos])
456 : {
457 0 : equal = false;
458 0 : break;
459 : }
460 : }
461 : }
462 : else
463 : {
464 19 : equal = false;
465 : }
466 19 : CATCH_REQUIRE_FALSE(equal);
467 :
468 19 : edhttp::buffer_t const decompressed(gzip->decompress(compressed));
469 19 : CATCH_REQUIRE(decompressed.size() == input.size());
470 :
471 19 : equal = true;
472 209 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
473 : {
474 190 : if(decompressed[pos] != input[pos])
475 : {
476 0 : equal = false;
477 0 : break;
478 : }
479 : }
480 19 : CATCH_REQUIRE(equal);
481 :
482 : // we do recognize a gzip buffer
483 : //
484 19 : CATCH_REQUIRE(gzip->compatible(compressed));
485 19 : }
486 : }
487 5 : CATCH_END_SECTION()
488 :
489 4 : CATCH_START_SECTION("compressor_gzip: verify invalid gzip magic length")
490 : {
491 3 : edhttp::compressor * gzip(edhttp::get_compressor("gzip"));
492 1 : CATCH_REQUIRE(gzip != nullptr);
493 1 : CATCH_REQUIRE(strcmp(gzip->get_name(), "gzip") == 0);
494 :
495 11 : for(std::size_t size(0); size < 10; ++size)
496 : {
497 : // generate a random buffer to compress of 1kb to 16kb in size
498 : //
499 10 : auto input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
500 10 : if(size >= 1)
501 : {
502 9 : input[0] = 0x1F;
503 : }
504 10 : if(size >= 2)
505 : {
506 8 : input[1] = 0x8B;
507 : }
508 10 : CATCH_REQUIRE_FALSE(gzip->compatible(input));
509 10 : }
510 : }
511 5 : CATCH_END_SECTION()
512 :
513 4 : CATCH_START_SECTION("compressor_gzip: attempt gzip compressing an empty buffer")
514 : {
515 3 : edhttp::compressor * gzip(edhttp::get_compressor("gzip"));
516 1 : CATCH_REQUIRE(gzip != nullptr);
517 1 : CATCH_REQUIRE(strcmp(gzip->get_name(), "gzip") == 0);
518 :
519 1 : edhttp::buffer_t const empty;
520 1 : CATCH_REQUIRE_FALSE(gzip->compatible(empty));
521 :
522 23 : for(edhttp::level_t level(0); level <= 120; level += rand() % 10 + 1)
523 : {
524 22 : edhttp::buffer_t const compressed(gzip->compress(empty, level, false));
525 :
526 : // an empty buffer can be "compressed" (but the output is bigger,
527 : // yet it does not fail with gzip)
528 : //
529 : //CATCH_REQUIRE(empty == compressed);
530 :
531 22 : edhttp::buffer_t const decompressed(gzip->decompress(compressed));
532 22 : CATCH_REQUIRE(empty == decompressed);
533 22 : }
534 1 : }
535 5 : CATCH_END_SECTION()
536 4 : }
537 :
538 :
539 4 : CATCH_TEST_CASE("compressor_xz", "[compression]")
540 : {
541 4 : CATCH_START_SECTION("compressor_xz: verify xz compressor")
542 : {
543 : // use a text file (this very file) because that compresses well
544 : //
545 1 : snapdev::file_contents source(SNAP_CATCH2_NAMESPACE::g_source_dir() + "/tests/catch_compressor.cpp");
546 1 : CATCH_REQUIRE(source.read_all());
547 1 : std::string const data(source.contents());
548 3 : edhttp::buffer_t const input(data.begin(), data.end());
549 :
550 3 : edhttp::compressor * xz(edhttp::get_compressor("xz"));
551 1 : CATCH_REQUIRE(xz != nullptr);
552 1 : CATCH_REQUIRE(strcmp(xz->get_name(), "xz") == 0);
553 :
554 12 : for(edhttp::level_t level(0); level <= 100; level += 10)
555 : {
556 11 : edhttp::buffer_t const compressed(xz->compress(input, level, rand() & 1 == 0));
557 :
558 11 : bool equal(true);
559 11 : if(compressed.size() == input.size())
560 : {
561 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
562 : {
563 0 : if(compressed[pos] != input[pos])
564 : {
565 0 : equal = false;
566 0 : break;
567 : }
568 : }
569 : }
570 : else
571 : {
572 11 : equal = false;
573 : }
574 11 : CATCH_REQUIRE_FALSE(equal);
575 :
576 11 : edhttp::buffer_t const decompressed(xz->decompress(compressed));
577 11 : CATCH_REQUIRE(decompressed.size() == input.size());
578 :
579 11 : equal = true;
580 464596 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
581 : {
582 464585 : if(decompressed[pos] != input[pos])
583 : {
584 0 : equal = false;
585 0 : break;
586 : }
587 : }
588 11 : CATCH_REQUIRE(equal);
589 :
590 88 : for(std::size_t s(2); s < 9; ++s)
591 : {
592 231 : edhttp::buffer_t const broken_compressed_small(compressed.data(), compressed.data() + s);
593 77 : edhttp::buffer_t const compressed_repeat(xz->decompress(broken_compressed_small));
594 77 : CATCH_REQUIRE(compressed_repeat == broken_compressed_small);
595 77 : }
596 :
597 : // we do recognize a xz buffer
598 : //
599 11 : CATCH_REQUIRE_FALSE(xz->compatible(input));
600 11 : CATCH_REQUIRE(xz->compatible(compressed));
601 11 : CATCH_REQUIRE_FALSE(xz->compatible(decompressed));
602 11 : }
603 1 : }
604 5 : CATCH_END_SECTION()
605 :
606 4 : CATCH_START_SECTION("compressor_xz: verify small buffers with xz compressor")
607 : {
608 3 : edhttp::compressor * xz(edhttp::get_compressor("xz"));
609 1 : CATCH_REQUIRE(xz != nullptr);
610 :
611 : // generate a random buffer to compress of 1kb to 16kb in size
612 : //
613 20 : for(int size(1); size < 20; ++size)
614 : {
615 19 : auto const input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
616 19 : edhttp::buffer_t const compressed(xz->compress(input, rand() % 95 + 5, rand() & 1 == 0));
617 :
618 19 : bool equal(true);
619 19 : if(compressed.size() == input.size())
620 : {
621 0 : for(std::size_t pos(0); pos < compressed.size(); ++pos)
622 : {
623 0 : if(compressed[pos] != input[pos])
624 : {
625 0 : equal = false;
626 0 : break;
627 : }
628 : }
629 : }
630 : else
631 : {
632 19 : equal = false;
633 : }
634 19 : CATCH_REQUIRE_FALSE(equal);
635 :
636 19 : edhttp::buffer_t const decompressed(xz->decompress(compressed));
637 19 : CATCH_REQUIRE(decompressed.size() == input.size());
638 :
639 19 : equal = true;
640 209 : for(std::size_t pos(0); pos < decompressed.size(); ++pos)
641 : {
642 190 : if(decompressed[pos] != input[pos])
643 : {
644 0 : equal = false;
645 0 : break;
646 : }
647 : }
648 19 : CATCH_REQUIRE(equal);
649 :
650 : // we do recognize a xz buffer
651 : //
652 19 : CATCH_REQUIRE(xz->compatible(compressed));
653 19 : }
654 : }
655 5 : CATCH_END_SECTION()
656 :
657 4 : CATCH_START_SECTION("compressor_xz: verify invalid xz magic length")
658 : {
659 3 : edhttp::compressor * xz(edhttp::get_compressor("xz"));
660 1 : CATCH_REQUIRE(xz != nullptr);
661 1 : CATCH_REQUIRE(strcmp(xz->get_name(), "xz") == 0);
662 :
663 11 : for(std::size_t size(0); size < 10; ++size)
664 : {
665 : // generate a random buffer to compress of 1kb to 16kb in size
666 : //
667 10 : auto input(SNAP_CATCH2_NAMESPACE::random_buffer(size, size));
668 10 : if(size >= 1)
669 : {
670 9 : input[0] = 0xFD;
671 : }
672 10 : if(size >= 2)
673 : {
674 8 : input[1] = '7';
675 : }
676 10 : if(size >= 3)
677 : {
678 7 : input[2] = 'z';
679 : }
680 10 : if(size >= 4)
681 : {
682 6 : input[3] = 'X';
683 : }
684 10 : if(size >= 5)
685 : {
686 5 : input[4] = 'Z';
687 : }
688 10 : CATCH_REQUIRE_FALSE(xz->compatible(input));
689 10 : }
690 : }
691 5 : CATCH_END_SECTION()
692 :
693 4 : CATCH_START_SECTION("compressor_xz: attempt xz compressing an empty buffer")
694 : {
695 3 : edhttp::compressor * xz(edhttp::get_compressor("xz"));
696 1 : CATCH_REQUIRE(xz != nullptr);
697 1 : CATCH_REQUIRE(strcmp(xz->get_name(), "xz") == 0);
698 :
699 1 : edhttp::buffer_t const empty;
700 1 : CATCH_REQUIRE_FALSE(xz->compatible(empty));
701 :
702 24 : for(edhttp::level_t level(0); level <= 120; level += rand() % 10 + 1)
703 : {
704 23 : edhttp::buffer_t const compressed(xz->compress(empty, level, false));
705 :
706 : // an empty buffer cannot be "compressed" (the output is bigger,
707 : // but it does not fail)
708 : //
709 : //CATCH_REQUIRE(empty == compressed);
710 :
711 23 : edhttp::buffer_t const decompressed(xz->decompress(compressed));
712 23 : CATCH_REQUIRE(empty == decompressed);
713 23 : }
714 1 : }
715 5 : CATCH_END_SECTION()
716 4 : }
717 :
718 :
719 14 : CATCH_TEST_CASE("compressor", "[compression]")
720 : {
721 14 : CATCH_START_SECTION("compressor: verify list of compressors in our library")
722 : {
723 1 : advgetopt::string_list_t const list(edhttp::compressor_list());
724 :
725 1 : CATCH_REQUIRE(list.size() == 4);
726 :
727 : // internally it's in a map so it remains sorted
728 : //
729 1 : CATCH_REQUIRE(list[0] == "bz2");
730 1 : CATCH_REQUIRE(list[1] == "deflate");
731 1 : CATCH_REQUIRE(list[2] == "gzip");
732 1 : CATCH_REQUIRE(list[3] == "xz");
733 :
734 5 : for(auto const & name : list)
735 : {
736 4 : edhttp::compressor * c(edhttp::get_compressor(name));
737 4 : CATCH_REQUIRE(c != nullptr);
738 : }
739 1 : }
740 15 : CATCH_END_SECTION()
741 :
742 14 : CATCH_START_SECTION("compressor: verify the \"unknown\" compressor does not exist")
743 : {
744 3 : edhttp::compressor * unknown(edhttp::get_compressor("unknown"));
745 1 : CATCH_REQUIRE(unknown == nullptr);
746 : }
747 15 : CATCH_END_SECTION()
748 :
749 14 : CATCH_START_SECTION("compressor: compress() with an empty input buffer")
750 : {
751 : // compress() with an empty buffer ignores the other parameters
752 : //
753 1 : advgetopt::string_list_t const list(edhttp::compressor_list());
754 11 : for(int i(0); i < 10; ++i)
755 : {
756 10 : edhttp::buffer_t const buffer;
757 10 : std::string compressor_name(list[rand() % list.size()]);
758 40 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, rand() % 96 + 5, rand() % 1 == 0));
759 10 : CATCH_REQUIRE(compressed.first == buffer);
760 10 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
761 10 : }
762 1 : }
763 15 : CATCH_END_SECTION()
764 :
765 14 : CATCH_START_SECTION("compressor: compress() with too small a level")
766 : {
767 : // compress() with an empty buffer ignores the other parameters
768 : //
769 1 : advgetopt::string_list_t const list(edhttp::compressor_list());
770 11 : for(int i(0); i < 10; ++i)
771 : {
772 10 : edhttp::buffer_t const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1, 1024));
773 10 : std::string compressor_name(list[rand() % list.size()]);
774 40 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, rand() % 5, rand() % 1 == 0));
775 10 : CATCH_REQUIRE(compressed.first == buffer);
776 10 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
777 10 : }
778 1 : }
779 15 : CATCH_END_SECTION()
780 :
781 14 : CATCH_START_SECTION("compressor: compress() with unknown compressor")
782 : {
783 : // compress() with an empty buffer ignores the other parameters
784 : //
785 11 : for(int i(0); i < 10; ++i)
786 : {
787 10 : edhttp::buffer_t const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
788 30 : std::string compressor_name("unknown");
789 40 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, rand() % 96 + 5, rand() % 1 == 0));
790 10 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
791 10 : CATCH_REQUIRE(compressed.first == buffer);
792 10 : }
793 : }
794 15 : CATCH_END_SECTION()
795 :
796 14 : CATCH_START_SECTION("compressor: compress() small buffers with bz2 return input")
797 : {
798 : // compress() with an empty buffer ignores the other parameters
799 : //
800 10 : for(int i(1); i < 10; ++i)
801 : {
802 9 : edhttp::buffer_t const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1, i));
803 27 : std::string compressor_name("bz2");
804 36 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, 100, rand() % 1 == 0));
805 9 : CATCH_REQUIRE(compressed.first == buffer);
806 9 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
807 9 : }
808 : }
809 15 : CATCH_END_SECTION()
810 :
811 14 : CATCH_START_SECTION("compressor: compress() small buffers with gzip return input")
812 : {
813 : // compress() with an empty buffer ignores the other parameters
814 : //
815 10 : for(int i(1); i < 10; ++i)
816 : {
817 9 : edhttp::buffer_t const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1, i));
818 27 : edhttp::result_t const compressed(edhttp::compress({"gzip"}, buffer, rand() % 96 + 5, rand() % 1 == 0));
819 9 : CATCH_REQUIRE(compressed.first == buffer);
820 9 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
821 9 : }
822 : }
823 15 : CATCH_END_SECTION()
824 :
825 14 : CATCH_START_SECTION("compressor: compress() small buffers with xz return input")
826 : {
827 : // compress() with a small buffer ignores the other parameters
828 : //
829 10 : for(int i(1); i < 10; ++i)
830 : {
831 9 : edhttp::buffer_t const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1, i));
832 27 : edhttp::result_t const compressed(edhttp::compress({"xz"}, buffer, rand() % 96 + 5, rand() % 1 == 0));
833 9 : CATCH_REQUIRE(compressed.first == buffer);
834 9 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
835 9 : }
836 : }
837 15 : CATCH_END_SECTION()
838 :
839 14 : CATCH_START_SECTION("compressor: compress() with deflate; decompress explicitly")
840 : {
841 : // get text because it compresses well and the test will work
842 : //
843 1 : snapdev::file_contents source(SNAP_CATCH2_NAMESPACE::g_source_dir() + "/tests/catch_compressor.cpp");
844 1 : CATCH_REQUIRE(source.read_all());
845 1 : std::string const data(source.contents());
846 3 : edhttp::buffer_t const buffer(data.begin(), data.end());
847 3 : edhttp::compressor * deflate(edhttp::get_compressor("deflate"));
848 1 : CATCH_REQUIRE(deflate != nullptr);
849 1 : CATCH_REQUIRE(strcmp(deflate->get_name(), "deflate") == 0);
850 10 : for(int i(1); i < 10; ++i)
851 : {
852 27 : std::string compressor_name("deflate");
853 36 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, rand() % 96 + 5, true));
854 9 : CATCH_REQUIRE(compressed.second == "deflate");
855 :
856 : // deflate data as no magic, so calling decompress() "fails"
857 : //
858 9 : edhttp::result_t const decompressed(edhttp::decompress(compressed.first));
859 9 : CATCH_REQUIRE(decompressed.second == edhttp::compressor::NO_COMPRESSION);
860 9 : CATCH_REQUIRE(decompressed.first == compressed.first); // still compressed
861 :
862 : // instead we have to explicitly decompress
863 : //
864 9 : edhttp::buffer_t const original(deflate->decompress(compressed.first, buffer.size()));
865 9 : CATCH_REQUIRE(original == buffer);
866 9 : }
867 1 : }
868 15 : CATCH_END_SECTION()
869 :
870 14 : CATCH_START_SECTION("compressor: compress()/decompress() with bz2")
871 : {
872 : // get text because it compresses well and the test will work
873 : //
874 1 : snapdev::file_contents source(SNAP_CATCH2_NAMESPACE::g_source_dir() + "/tests/catch_compressor.cpp");
875 1 : CATCH_REQUIRE(source.read_all());
876 1 : std::string const data(source.contents());
877 3 : edhttp::buffer_t const buffer(data.begin(), data.end());
878 3 : edhttp::compressor * bz2(edhttp::get_compressor("bz2"));
879 1 : CATCH_REQUIRE(bz2 != nullptr);
880 1 : CATCH_REQUIRE(strcmp(bz2->get_name(), "bz2") == 0);
881 10 : for(int i(1); i < 10; ++i)
882 : {
883 27 : std::string compressor_name("bz2");
884 36 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, rand() % 96 + 5, true));
885 9 : CATCH_REQUIRE(compressed.second == "bz2");
886 9 : CATCH_REQUIRE(bz2->compatible(compressed.first));
887 9 : CATCH_REQUIRE(compressed.first != buffer);
888 9 : edhttp::result_t const decompressed(edhttp::decompress(compressed.first));
889 9 : CATCH_REQUIRE(decompressed.second == "bz2");
890 9 : CATCH_REQUIRE(decompressed.first == buffer);
891 9 : }
892 1 : }
893 15 : CATCH_END_SECTION()
894 :
895 14 : CATCH_START_SECTION("compressor: compress()/decompress() a large buffer with bz2")
896 : {
897 : // get text because it compresses well and the test will work
898 : //
899 1 : snapdev::file_contents source(SNAP_CATCH2_NAMESPACE::g_source_dir() + "/tests/catch_compressor.cpp");
900 1 : CATCH_REQUIRE(source.read_all());
901 1 : std::string data(source.contents());
902 3 : while(data.length() < 1024 * 100 + 1)
903 : {
904 2 : data += data;
905 : }
906 3 : edhttp::buffer_t const buffer(data.begin(), data.end());
907 3 : edhttp::compressor * bz2(edhttp::get_compressor("bz2"));
908 1 : CATCH_REQUIRE(bz2 != nullptr);
909 1 : CATCH_REQUIRE(strcmp(bz2->get_name(), "bz2") == 0);
910 10 : for(int i(1); i < 10; ++i)
911 : {
912 27 : edhttp::result_t const compressed(edhttp::compress({"bz2"}, buffer, rand() % 96 + 5, true));
913 9 : CATCH_REQUIRE(compressed.second == "bz2");
914 9 : CATCH_REQUIRE(bz2->compatible(compressed.first));
915 9 : CATCH_REQUIRE(compressed.first != buffer);
916 9 : edhttp::result_t const decompressed(edhttp::decompress(compressed.first));
917 9 : CATCH_REQUIRE(decompressed.second == "bz2");
918 9 : CATCH_REQUIRE(decompressed.first == buffer);
919 :
920 : // also test with the size
921 : //
922 9 : edhttp::buffer_t const decompressed2(bz2->decompress(compressed.first, buffer.size()));
923 9 : CATCH_REQUIRE(decompressed2 == buffer);
924 9 : }
925 1 : }
926 15 : CATCH_END_SECTION()
927 :
928 14 : CATCH_START_SECTION("compressor: compress()/decompress() with gzip")
929 : {
930 : // get text because it compresses well and the test will work
931 : //
932 1 : snapdev::file_contents source(SNAP_CATCH2_NAMESPACE::g_source_dir() + "/tests/catch_compressor.cpp");
933 1 : CATCH_REQUIRE(source.read_all());
934 1 : std::string const data(source.contents());
935 3 : edhttp::buffer_t const buffer(data.begin(), data.end());
936 3 : edhttp::compressor * gzip(edhttp::get_compressor("gzip"));
937 1 : CATCH_REQUIRE(gzip != nullptr);
938 1 : CATCH_REQUIRE(strcmp(gzip->get_name(), "gzip") == 0);
939 10 : for(int i(1); i < 10; ++i)
940 : {
941 27 : std::string compressor_name("gzip");
942 36 : edhttp::result_t const compressed(edhttp::compress({compressor_name}, buffer, rand() % 96 + 5, true));
943 9 : CATCH_REQUIRE(compressed.second == "gzip");
944 9 : CATCH_REQUIRE(gzip->compatible(compressed.first));
945 9 : CATCH_REQUIRE(compressed.first != buffer);
946 9 : edhttp::result_t const decompressed(edhttp::decompress(compressed.first));
947 9 : CATCH_REQUIRE(decompressed.second == "gzip");
948 9 : CATCH_REQUIRE(decompressed.first == buffer);
949 9 : }
950 1 : }
951 15 : CATCH_END_SECTION()
952 :
953 14 : CATCH_START_SECTION("compressor: compress()/decompress() with best compressor")
954 : {
955 : // get text because it compresses well and the test works every time
956 : //
957 1 : snapdev::file_contents source(SNAP_CATCH2_NAMESPACE::g_source_dir() + "/tests/catch_compressor.cpp");
958 1 : CATCH_REQUIRE(source.read_all());
959 1 : std::string const data(source.contents());
960 3 : edhttp::buffer_t const buffer(data.begin(), data.end());
961 11 : for(int i(0); i < 10; ++i)
962 : {
963 10 : advgetopt::string_list_t names;
964 10 : if((i & 1) == 1)
965 : {
966 15 : names.push_back("bz2");
967 15 : names.push_back("gzip");
968 5 : std::random_device rd;
969 5 : std::mt19937 g(rd());
970 5 : std::shuffle(names.begin(), names.end(), g);
971 5 : }
972 10 : edhttp::result_t const compressed(edhttp::compress({}, buffer, rand() % 96 + 5, true));
973 10 : if(compressed.second == edhttp::compressor::NO_COMPRESSION)
974 : {
975 : // no compression possible
976 : //
977 0 : CATCH_REQUIRE(compressed.first == buffer);
978 : }
979 : else
980 : {
981 10 : edhttp::compressor * c(edhttp::get_compressor(compressed.second));
982 10 : CATCH_REQUIRE(c != nullptr);
983 10 : CATCH_REQUIRE(c->get_name() == compressed.second);
984 : //SNAP_LOG_WARNING << "--- c = " << c->get_name() << SNAP_LOG_SEND;
985 10 : if(compressed.second != "deflate")
986 : {
987 10 : CATCH_REQUIRE(c->compatible(compressed.first));
988 10 : edhttp::result_t const decompressed(edhttp::decompress(compressed.first));
989 10 : CATCH_REQUIRE(decompressed.second == compressed.second);
990 10 : CATCH_REQUIRE(decompressed.first == buffer);
991 10 : }
992 : else
993 : {
994 : // deflate cannot be accessed from edhttp::decompress() because
995 : // there is no magic and thus it cannot be a sure thing
996 : //
997 0 : edhttp::buffer_t const decompressed(c->decompress(compressed.first, buffer.size()));
998 0 : CATCH_REQUIRE(decompressed == buffer);
999 0 : }
1000 : }
1001 10 : }
1002 1 : }
1003 15 : CATCH_END_SECTION()
1004 :
1005 14 : CATCH_START_SECTION("compressor: compress() too small a buffer with any compressor")
1006 : {
1007 11 : for(int i(0); i < 10; ++i)
1008 : {
1009 : // generate a very small random buffer to compress so that the
1010 : // result is larger than the input and thus "fails" in a slightly
1011 : // different path
1012 : //
1013 10 : edhttp::buffer_t const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1, 5));
1014 10 : edhttp::result_t const compressed(edhttp::compress({}, buffer, rand() % 96 + 5, true));
1015 10 : CATCH_REQUIRE(compressed.second == edhttp::compressor::NO_COMPRESSION);
1016 10 : CATCH_REQUIRE(compressed.first == buffer);
1017 10 : }
1018 : }
1019 15 : CATCH_END_SECTION()
1020 80 : }
1021 :
1022 :
1023 6 : CATCH_TEST_CASE("compressor_error", "[compression][error]")
1024 : {
1025 6 : CATCH_START_SECTION("compressor_error: deflate decompress() requires a size")
1026 : {
1027 3 : edhttp::compressor * deflate(edhttp::get_compressor("deflate"));
1028 1 : CATCH_REQUIRE(deflate != nullptr);
1029 1 : CATCH_REQUIRE(strcmp(deflate->get_name(), "deflate") == 0);
1030 :
1031 : // generate a random buffer to compress of 1kb to 16kb in size
1032 : //
1033 1 : auto const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
1034 4 : CATCH_REQUIRE_THROWS_MATCHES(
1035 : deflate->decompress(buffer)
1036 : , edhttp::not_implemented
1037 : , Catch::Matchers::ExceptionMessage(
1038 : "not_implemented: deflate::decompress() without the uncompressed_size parameter is not implemented."));
1039 1 : }
1040 7 : CATCH_END_SECTION()
1041 :
1042 6 : CATCH_START_SECTION("compressor_error: gzip decompress() does not support a size")
1043 : {
1044 3 : edhttp::compressor * gzip(edhttp::get_compressor("gzip"));
1045 1 : CATCH_REQUIRE(gzip != nullptr);
1046 1 : CATCH_REQUIRE(strcmp(gzip->get_name(), "gzip") == 0);
1047 :
1048 : // generate a random buffer to compress of 1kb to 16kb in size
1049 : //
1050 1 : auto const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
1051 4 : CATCH_REQUIRE_THROWS_MATCHES(
1052 : gzip->decompress(buffer, buffer.size())
1053 : , edhttp::not_implemented
1054 : , Catch::Matchers::ExceptionMessage(
1055 : "not_implemented: gzip::decompress() with a size is not implemented."));
1056 1 : }
1057 7 : CATCH_END_SECTION()
1058 :
1059 6 : CATCH_START_SECTION("compressor_error: xz decompress() does not support a size")
1060 : {
1061 3 : edhttp::compressor * gzip(edhttp::get_compressor("xz"));
1062 1 : CATCH_REQUIRE(gzip != nullptr);
1063 1 : CATCH_REQUIRE(strcmp(gzip->get_name(), "xz") == 0);
1064 :
1065 : // generate a random buffer to compress of 1kb to 16kb in size
1066 : //
1067 1 : auto const buffer(SNAP_CATCH2_NAMESPACE::random_buffer(1024, 1024 * 16));
1068 4 : CATCH_REQUIRE_THROWS_MATCHES(
1069 : gzip->decompress(buffer, buffer.size())
1070 : , edhttp::not_implemented
1071 : , Catch::Matchers::ExceptionMessage(
1072 : "not_implemented: xz::decompress() with a size is not implemented."));
1073 1 : }
1074 7 : CATCH_END_SECTION()
1075 :
1076 6 : CATCH_START_SECTION("compressor_error: compressor name cannot be nullptr or empty")
1077 : {
1078 4 : CATCH_REQUIRE_THROWS_MATCHES(
1079 : new compressor_named(nullptr)
1080 : , edhttp::invalid_token
1081 : , Catch::Matchers::ExceptionMessage(
1082 : "edhttp_exception: the name of a compressor cannot be empty."));
1083 :
1084 4 : CATCH_REQUIRE_THROWS_MATCHES(
1085 : new compressor_named("")
1086 : , edhttp::invalid_token
1087 : , Catch::Matchers::ExceptionMessage(
1088 : "edhttp_exception: the name of a compressor cannot be empty."));
1089 : }
1090 7 : CATCH_END_SECTION()
1091 :
1092 6 : CATCH_START_SECTION("compressor_error: compressor name cannot be a special name")
1093 : {
1094 4 : CATCH_REQUIRE_THROWS_MATCHES(
1095 : new compressor_named(edhttp::compressor::NO_COMPRESSION)
1096 : , edhttp::incompatible
1097 : , Catch::Matchers::ExceptionMessage(
1098 : "edhttp_exception: name \"none\" is not available as a compressor name."));
1099 : }
1100 7 : CATCH_END_SECTION()
1101 :
1102 6 : CATCH_START_SECTION("compressor_error: compressor name cannot include a special character")
1103 : {
1104 : // Note: we cannot test character '\0' since we use a C-string to
1105 : // name the compressor (so '\0' is end of string in this case)
1106 : //
1107 256 : for(int c(1); c < 256; ++c)
1108 : {
1109 765 : std::string name("name");
1110 255 : name += c;
1111 255 : if(!edhttp::is_token(name))
1112 : {
1113 : // if the following doesn't throw, then we have an issue
1114 : // because the compressor will have a temporary string
1115 : // as its name
1116 : //
1117 356 : CATCH_REQUIRE_THROWS_MATCHES(
1118 : new compressor_named(name.c_str())
1119 : , edhttp::invalid_token
1120 : , Catch::Matchers::ExceptionMessage(
1121 : "edhttp_exception: a compressor name (\"" + name + "\") must be a valid HTTP token."));
1122 : }
1123 255 : }
1124 :
1125 : // also a token cannot start with the '$' character
1126 : //
1127 : // TODO: determine why I had that one; this is not true at all and
1128 : // never was although maybe it was for use to support some
1129 : // kind of variables
1130 : //
1131 : //CATCH_REQUIRE_THROWS_MATCHES(
1132 : // new compressor_named("$name")
1133 : // , edhttp::invalid_token
1134 : // , Catch::Matchers::ExceptionMessage(
1135 : // "edhttp_exception: a compressor name (\"$name\") must be a valid HTTP token."));
1136 : }
1137 7 : CATCH_END_SECTION()
1138 6 : }
1139 :
1140 :
1141 : // vim: ts=4 sw=4 et
|