LCOV - code coverage report
Current view: top level - tests - catch_compressor.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.3 % 585 534
Test Date: 2026-11-09 21:32:01 Functions: 58.3 % 12 7
Legend: Lines: hit not hit

            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
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions