LCOV - code coverage report
Current view: top level - tests - catch_compressor.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 533 584 91.3 %
Date: 2024-10-28 20:58:35 Functions: 7 12 58.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14

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