libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

unit_h2_huffman_codec.c (52483B)


      1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
      2 /*
      3   This file is part of GNU libmicrohttpd.
      4   Copyright (C) 2025 Evgeny Grin (Karlson2k)
      5 
      6   GNU libmicrohttpd is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU Lesser General Public
      8   License as published by the Free Software Foundation; either
      9   version 2.1 of the License, or (at your option) any later version.
     10 
     11   GNU libmicrohttpd 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 GNU
     14   Lesser General Public License for more details.
     15 
     16   Alternatively, you can redistribute GNU libmicrohttpd and/or
     17   modify it under the terms of the GNU General Public License as
     18   published by the Free Software Foundation; either version 2 of
     19   the License, or (at your option) any later version, together
     20   with the eCos exception, as follows:
     21 
     22     As a special exception, if other files instantiate templates or
     23     use macros or inline functions from this file, or you compile this
     24     file and link it with other works to produce a work based on this
     25     file, this file does not by itself cause the resulting work to be
     26     covered by the GNU General Public License. However the source code
     27     for this file must still be made available in accordance with
     28     section (3) of the GNU General Public License v2.
     29 
     30     This exception does not invalidate any other reasons why a work
     31     based on this file might be covered by the GNU General Public
     32     License.
     33 
     34   You should have received copies of the GNU Lesser General Public
     35   License and the GNU General Public License along with this library;
     36   if not, see <https://www.gnu.org/licenses/>.
     37 */
     38 
     39 /**
     40  * @file src/test/unit/unit_h2_huffman_coding.c
     41  * @brief  The tests for HTTP/2 Huffman coding function
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 
     46 #include "mhd_sys_options.h"
     47 
     48 #include "h2/hpack/h2_huffman_codec.h"
     49 
     50 #include <stdio.h>
     51 #include <string.h>
     52 
     53 #include "sys_base_types.h"
     54 #include "mhd_str_types.h"
     55 #include "mhd_str_macros.h"
     56 
     57 #include "mhdt_has_in_name.h"
     58 #include "mhdt_has_param.h"
     59 
     60 #ifndef MHD_ENABLE_SLOW_TESTS
     61 static int enable_deep_tests = 0;
     62 #else
     63 static int enable_deep_tests = ! 0;
     64 #endif
     65 
     66 struct mhdt_HEcondedData
     67 {
     68   const size_t size;
     69   const uint8_t data[640];
     70 };
     71 
     72 struct mhdt_HTestData
     73 {
     74   const struct MHD_String str;
     75   const struct mhdt_HEcondedData enc;
     76 };
     77 
     78 static const struct mhdt_HTestData h_data[] = {
     79   /*
     80    **  These test data entries are extracted from RFC 7541 examples **
     81    */
     82   {
     83     mhd_MSTR_INIT ("www.example.com"),
     84     {
     85       12u,
     86       {
     87         0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90,
     88         0xf4, 0xff
     89       }
     90     }
     91   }
     92   ,
     93   {
     94     mhd_MSTR_INIT ("no-cache"),
     95     {
     96       6u,
     97       {
     98         0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf
     99       }
    100     }
    101   }
    102   ,
    103   {
    104     mhd_MSTR_INIT ("custom-key"),
    105     {
    106       8u,
    107       {
    108         0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f
    109       }
    110     }
    111   }
    112   ,
    113   {
    114     mhd_MSTR_INIT ("custom-value"),
    115     {
    116       9u,
    117       {
    118         0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4, 0xbf
    119       }
    120     }
    121   }
    122   ,
    123   {
    124     mhd_MSTR_INIT ("302"),
    125     {
    126       2u,
    127       {
    128         0x64, 0x02
    129       }
    130     }
    131   }
    132   ,
    133   {
    134     mhd_MSTR_INIT ("private"),
    135     {
    136       5u,
    137       {
    138         0xae, 0xc3, 0x77, 0x1a, 0x4b
    139       }
    140     }
    141   }
    142   ,
    143   {
    144     mhd_MSTR_INIT ("Mon, 21 Oct 2013 20:13:21 GMT"),
    145     {
    146       22u,
    147       {
    148         0xd0, 0x7a, 0xbe, 0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05,
    149         0x95, 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6, 0x2d, 0x1b, 0xff
    150       }
    151     }
    152   }
    153   ,
    154   {
    155     mhd_MSTR_INIT ("https://www.example.com"),
    156     {
    157       17u,
    158       {
    159         0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8, 0xe9,
    160         0xae, 0x82, 0xae, 0x43, 0xd3
    161       }
    162     }
    163   }
    164   ,
    165   {
    166     mhd_MSTR_INIT ("307"),
    167     {
    168       3u,
    169       {
    170         0x64, 0x0e, 0xff
    171       }
    172     }
    173   }
    174   ,
    175   {
    176     mhd_MSTR_INIT ("gzip"),
    177     {
    178       3u,
    179       {
    180         0x9b, 0xd9, 0xab
    181       }
    182     }
    183   }
    184   ,
    185   {
    186     mhd_MSTR_INIT ("foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
    187     {
    188       45u,
    189       {
    190         0x94, 0xe7, 0x82, 0x1d, 0xd7, 0xf2, 0xe6, 0xc7, 0xb3, 0x35, 0xdf, 0xdf,
    191         0xcd, 0x5b, 0x39, 0x60, 0xd5, 0xaf, 0x27, 0x08, 0x7f, 0x36, 0x72, 0xc1,
    192         0xab, 0x27, 0x0f, 0xb5, 0x29, 0x1f, 0x95, 0x87, 0x31, 0x60, 0x65, 0xc0,
    193         0x03, 0xed, 0x4e, 0xe5, 0xb1, 0x06, 0x3d, 0x50, 0x07
    194       }
    195     }
    196   }
    197   /*
    198    **  Hand-crafted test entries **
    199    */
    200   ,
    201   {
    202     mhd_MSTR_INIT ("Hello, Huffman coding!"),
    203     {
    204       17u,
    205       {
    206         0xC6, 0x5A, 0x28, 0x3F, 0xD2, 0x98, 0xED, 0x96, 0x5A, 0x47, 0x52, 0x84,
    207         0x3C, 0x86, 0xAA, 0x6F, 0xE3
    208       }
    209     }
    210   }
    211   ,
    212   {
    213     mhd_MSTR_INIT ("nginx"),
    214     {
    215       4u,
    216       {
    217         0xAA, 0x63, 0x55, 0xE7
    218       }
    219     }
    220   }
    221   ,
    222   {
    223     mhd_MSTR_INIT ("apache"),
    224     {
    225       4u,
    226       {
    227         0x1D, 0x63, 0x24, 0xE5
    228       }
    229     }
    230   }
    231   ,
    232   {
    233     mhd_MSTR_INIT (" "),
    234     {
    235       1u,
    236       {
    237         0x53
    238       }
    239     }
    240   }
    241   ,
    242   {
    243     mhd_MSTR_INIT ("0"),
    244     {
    245       1u,
    246       {
    247         0x07
    248       }
    249     }
    250   }
    251   ,
    252   {   /* Empty */
    253     mhd_MSTR_INIT (""),
    254     {
    255       0u,
    256       {
    257         0
    258       }
    259     }
    260   }
    261   ,
    262   {   /* Long codes */
    263     mhd_MSTR_INIT ("\x0A" "\x0D" "\x16" "\x0A" "\x0D" "\x16" "\x0A" \
    264                    "\x0D" "\x16" "\x0A"),
    265     {
    266       38u,
    267       {
    268         0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF,
    269         0xBF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF,
    270         0xEF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF,
    271         0xFB, 0xFF, 0xFF, 0xFF, 0xCF
    272       }
    273     }
    274   }
    275   ,
    276   {   /* Shortest + longest codes */
    277     mhd_MSTR_INIT ("0" "\x0A" "1"),
    278     {
    279       5u,
    280       {
    281         0x07, 0xFF, 0xFF, 0xFF, 0x81
    282       }
    283     }
    284   }
    285   ,
    286   {   /* Shortest + longest codes */
    287     mhd_MSTR_INIT ("\x0D" "2a" "\x16" "ce" "\x0A"),
    288     {
    289       14u,
    290       {
    291         0xFF, 0xFF, 0xFF, 0xF4, 0x43, 0xFF, 0xFF, 0xFF, 0xF8, 0x85, 0xFF, 0xFF,
    292         0xFF, 0xF3
    293       }
    294     }
    295   }
    296   ,
    297   {   /* Shortest + longest codes */
    298     mhd_MSTR_INIT ("01" "\x0A" "2" "\x0D" "ac" "\x16" "ei" "\x0A" \
    299                    "os" "\x0D" "t"),
    300     {
    301       25u,
    302       {
    303         0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x17, 0xFF, 0xFF, 0xFF, 0xA3, 0x27, 0xFF,
    304         0xFF, 0xFF, 0xC5, 0x37, 0xFF, 0xFF, 0xFF, 0x87, 0x47, 0xFF, 0xFF, 0xFF,
    305         0xA9
    306       }
    307     }
    308   }
    309   ,
    310   {   /* Short + long codes */
    311     mhd_MSTR_INIT ("0 :&!'#" "\x00" "^<\\" "\x80" "\x99" "\x81" \
    312                    "\x01" "\x09" "\xC7" "\xC0" "\xCB" "\x02" "\x0A"),
    313     {
    314       46u,
    315       {
    316         0x02, 0x97, 0x3E, 0x3F, 0x8F, 0xF5, 0xFF, 0x5F, 0xF8, 0xFF, 0xF3, 0xFF,
    317         0xE7, 0xFF, 0xF0, 0xFF, 0xFE, 0x6F, 0xFF, 0xEE, 0x7F, 0xFF, 0xA5, 0xFF,
    318         0xFF, 0x63, 0xFF, 0xFF, 0xAB, 0xFF, 0xFF, 0xD9, 0xFF, 0xFF, 0xF0, 0x7F,
    319         0xFF, 0xFD, 0xEF, 0xFF, 0xFF, 0xE2, 0xFF, 0xFF, 0xFF, 0xF3
    320       }
    321     }
    322   }
    323   ,
    324   {   /* All printable chars */
    325     mhd_MSTR_INIT (" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ" \
    326                    "KLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"),
    327     {
    328       93u,
    329       {
    330         0x53, 0xF8, 0xFE, 0x7F, 0xEB, 0xFF, 0x2A, 0xFC, 0x7F, 0xAF, 0xEB, 0xFB,
    331         0xF9, 0xFF, 0x7F, 0x4B, 0x2E, 0xC0, 0x02, 0x26, 0x5A, 0x6D, 0xC7, 0x5E,
    332         0x7E, 0xE7, 0xDF, 0xFF, 0xC8, 0x3F, 0xEF, 0xFC, 0xFF, 0xD4, 0x37, 0x6F,
    333         0x5F, 0xC1, 0x87, 0x16, 0x3C, 0x99, 0x73, 0x67, 0xD1, 0xA7, 0x56, 0xBD,
    334         0x9B, 0x77, 0x6F, 0xE1, 0xC7, 0x97, 0xE7, 0x3F, 0xDF, 0xFD, 0xFF, 0xFF,
    335         0x0F, 0xFE, 0x7F, 0xF9, 0x17, 0xFF, 0xD1, 0xC6, 0x49, 0x0B, 0x2C, 0xD3,
    336         0x9B, 0xA7, 0x5A, 0x29, 0xA8, 0xF5, 0xF6, 0xB1, 0x09, 0xB7, 0xBF, 0x8F,
    337         0x3E, 0xBD, 0xFF, 0xFE, 0xFF, 0x9F, 0xFE, 0xFF, 0xF7
    338       }
    339     }
    340   }
    341   ,
    342   {   /* All printable chars in reverse */
    343     mhd_MSTR_INIT ("~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUT" \
    344                    "SRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#\"! "),
    345     {
    346       93u,
    347       {
    348         0xFF, 0xEF, 0xFF, 0xBF, 0xF3, 0xFF, 0xF7, 0xBF, 0x5E, 0x7C, 0x77, 0xB5,
    349         0x28, 0xB3, 0xB5, 0x67, 0xAA, 0x9A, 0x3A, 0xF4, 0x34, 0xF3, 0x4A, 0x59,
    350         0x09, 0x18, 0xFF, 0xFE, 0xC5, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF, 0x87, 0xFE,
    351         0xFF, 0x79, 0xFE, 0x72, 0xE3, 0xC3, 0x7E, 0xED, 0xBB, 0x35, 0xEA, 0xD3,
    352         0xA3, 0x3E, 0x6C, 0xB9, 0x31, 0xE2, 0xC3, 0x82, 0xFD, 0xEB, 0xB0, 0xFF,
    353         0xEB, 0xFC, 0xFF, 0xB8, 0x3F, 0xFE, 0x7D, 0xDC, 0x7D, 0xE7, 0x5C, 0x6D,
    354         0xA6, 0x44, 0x10, 0x30, 0xBA, 0xDF, 0x5F, 0xEF, 0xE7, 0xFB, 0xFE, 0xBF,
    355         0xD7, 0xC2, 0xBF, 0xF9, 0xFF, 0xAF, 0xE7, 0xF8, 0x53
    356       }
    357     }
    358   }
    359   ,
    360   {   /* All chars */
    361     mhd_MSTR_INIT ("\x00" "\x01" "\x02" "\x03" "\x04" "\x05" "\x06" "\x07" \
    362                    "\x08" "\x09" "\x0A" "\x0B" "\x0C" "\x0D" "\x0E" "\x0F" \
    363                    "\x10" "\x11" "\x12" "\x13" "\x14" "\x15" "\x16" "\x17" \
    364                    "\x18" "\x19" "\x1A" "\x1B" "\x1C" "\x1D" "\x1E" "\x1F" \
    365                    " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQR" \
    366                    "STUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" "\x7F" \
    367                    "\x80" "\x81" "\x82" "\x83" "\x84" "\x85" "\x86" "\x87" \
    368                    "\x88" "\x89" "\x8A" "\x8B" "\x8C" "\x8D" "\x8E" "\x8F" \
    369                    "\x90" "\x91" "\x92" "\x93" "\x94" "\x95" "\x96" "\x97" \
    370                    "\x98" "\x99" "\x9A" "\x9B" "\x9C" "\x9D" "\x9E" "\x9F" \
    371                    "\xA0" "\xA1" "\xA2" "\xA3" "\xA4" "\xA5" "\xA6" "\xA7" \
    372                    "\xA8" "\xA9" "\xAA" "\xAB" "\xAC" "\xAD" "\xAE" "\xAF" \
    373                    "\xB0" "\xB1" "\xB2" "\xB3" "\xB4" "\xB5" "\xB6" "\xB7" \
    374                    "\xB8" "\xB9" "\xBA" "\xBB" "\xBC" "\xBD" "\xBE" "\xBF" \
    375                    "\xC0" "\xC1" "\xC2" "\xC3" "\xC4" "\xC5" "\xC6" "\xC7" \
    376                    "\xC8" "\xC9" "\xCA" "\xCB" "\xCC" "\xCD" "\xCE" "\xCF" \
    377                    "\xD0" "\xD1" "\xD2" "\xD3" "\xD4" "\xD5" "\xD6" "\xD7" \
    378                    "\xD8" "\xD9" "\xDA" "\xDB" "\xDC" "\xDD" "\xDE" "\xDF" \
    379                    "\xE0" "\xE1" "\xE2" "\xE3" "\xE4" "\xE5" "\xE6" "\xE7" \
    380                    "\xE8" "\xE9" "\xEA" "\xEB" "\xEC" "\xED" "\xEE" "\xEF" \
    381                    "\xF0" "\xF1" "\xF2" "\xF3" "\xF4" "\xF5" "\xF6" "\xF7" \
    382                    "\xF8" "\xF9" "\xFA" "\xFB" "\xFC" "\xFD" "\xFE" "\xFF"),
    383     {
    384       583u,
    385       {
    386         0xFF, 0xC7, 0xFF, 0xFD, 0x8F, 0xFF, 0xFF, 0xE2, 0xFF, 0xFF, 0xFE, 0x3F,
    387         0xFF, 0xFF, 0xE4, 0xFF, 0xFF, 0xFE, 0x5F, 0xFF, 0xFF, 0xE6, 0xFF, 0xFF,
    388         0xFE, 0x7F, 0xFF, 0xFF, 0xE8, 0xFF, 0xFF, 0xEA, 0xFF, 0xFF, 0xFF, 0xF3,
    389         0xFF, 0xFF, 0xFA, 0x7F, 0xFF, 0xFF, 0xAB, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF,
    390         0xFF, 0xEB, 0xFF, 0xFF, 0xFE, 0xCF, 0xFF, 0xFF, 0xED, 0xFF, 0xFF, 0xFE,
    391         0xEF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xF1, 0xFF,
    392         0xFF, 0xFF, 0x2F, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF,
    393         0xFD, 0x3F, 0xFF, 0xFF, 0xD7, 0xFF, 0xFF, 0xFD, 0xBF, 0xFF, 0xFF, 0xDF,
    394         0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFE, 0xBF, 0xFF,
    395         0xFF, 0xED, 0x4F, 0xE3, 0xF9, 0xFF, 0xAF, 0xFC, 0xAB, 0xF1, 0xFE, 0xBF,
    396         0xAF, 0xEF, 0xE7, 0xFD, 0xFD, 0x2C, 0xBB, 0x00, 0x08, 0x99, 0x69, 0xB7,
    397         0x1D, 0x79, 0xFB, 0x9F, 0x7F, 0xFF, 0x20, 0xFF, 0xBF, 0xF3, 0xFF, 0x50,
    398         0xDD, 0xBD, 0x7F, 0x06, 0x1C, 0x58, 0xF2, 0x65, 0xCD, 0x9F, 0x46, 0x9D,
    399         0x5A, 0xF6, 0x6D, 0xDD, 0xBF, 0x87, 0x1E, 0x5F, 0x9C, 0xFF, 0x7F, 0xF7,
    400         0xFF, 0xFC, 0x3F, 0xF9, 0xFF, 0xE4, 0x5F, 0xFF, 0x47, 0x19, 0x24, 0x2C,
    401         0xB3, 0x4E, 0x6E, 0x9D, 0x68, 0xA6, 0xA3, 0xD7, 0xDA, 0xC4, 0x26, 0xDE,
    402         0xFE, 0x3C, 0xFA, 0xF7, 0xFF, 0xFB, 0xFE, 0x7F, 0xFB, 0xFF, 0xDF, 0xFF,
    403         0xFF, 0xFC, 0xFF, 0xFE, 0x6F, 0xFF, 0xF4, 0xBF, 0xFF, 0x9F, 0xFF, 0xFA,
    404         0x3F, 0xFF, 0xD3, 0xFF, 0xFF, 0x53, 0xFF, 0xFD, 0x5F, 0xFF, 0xFB, 0x3F,
    405         0xFF, 0xEB, 0x7F, 0xFF, 0xDA, 0xFF, 0xFF, 0xB7, 0xFF, 0xFF, 0x73, 0xFF,
    406         0xFE, 0xEF, 0xFF, 0xFD, 0xEF, 0xFF, 0xFE, 0xBF, 0xFF, 0xFB, 0xFF, 0xFF,
    407         0xFD, 0x9F, 0xFF, 0xFD, 0xBF, 0xFF, 0xEB, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF,
    408         0xEE, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0x8B, 0xFF, 0xFF, 0x1F, 0xFF, 0xFE,
    409         0x4F, 0xFF, 0xEE, 0x7F, 0xFF, 0xB1, 0xFF, 0xFF, 0x97, 0xFF, 0xFD, 0x9F,
    410         0xFF, 0xFC, 0xDF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xDA, 0xFF,
    411         0xFE, 0xEF, 0xFF, 0xF4, 0xFF, 0xFF, 0xB7, 0xFF, 0xFE, 0xE7, 0xFF, 0xFE,
    412         0x8F, 0xFF, 0xFD, 0x3F, 0xFF, 0xDE, 0xFF, 0xFF, 0xD5, 0xFF, 0xFE, 0xEF,
    413         0xFF, 0xFB, 0xDF, 0xFF, 0xFE, 0x1F, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF,
    414         0xFF, 0x5F, 0xFF, 0xFE, 0xCF, 0xFF, 0xF0, 0x7F, 0xFF, 0x87, 0xFF, 0xFE,
    415         0x0F, 0xFF, 0xF1, 0x7F, 0xFF, 0xED, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0x77,
    416         0xFF, 0xFE, 0xFF, 0xFF, 0xEA, 0xFF, 0xFF, 0x8B, 0xFF, 0xFE, 0x3F, 0xFF,
    417         0xF9, 0x3F, 0xFF, 0xF8, 0x7F, 0xFF, 0xCB, 0xFF, 0xFF, 0x37, 0xFF, 0xFF,
    418         0x1F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xE1, 0xFF, 0xFE, 0xBF, 0xFF, 0xE3,
    419         0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x2F, 0xFF, 0xFA, 0x3F, 0xFF, 0xFD, 0x9F,
    420         0xFF, 0xFF, 0x17, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xF2, 0x7F, 0xFF, 0xFD,
    421         0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xF2, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF,
    422         0xFB, 0x7F, 0xFF, 0x97, 0xFF, 0xF8, 0xFF, 0xFF, 0xFE, 0x6F, 0xFF, 0xFF,
    423         0xC1, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xC5, 0xFF,
    424         0xFF, 0xE5, 0xFF, 0xFE, 0x4F, 0xFF, 0xF2, 0xFF, 0xFF, 0xFD, 0x1F, 0xFF,
    425         0xFF, 0x4F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xC9,
    426         0xFF, 0xFF, 0xF9, 0x7F, 0xFF, 0xB3, 0xFF, 0xFF, 0xCF, 0xFF, 0xFB, 0x7F,
    427         0xFF, 0xCD, 0xFF, 0xFF, 0x4F, 0xFF, 0xF9, 0xFF, 0xFF, 0xD1, 0xFF, 0xFF,
    428         0xCF, 0xFF, 0xFE, 0xAF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFD, 0xDF, 0xFF, 0xFE,
    429         0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xAB, 0xFF, 0xFF,
    430         0xA7, 0xFF, 0xFF, 0xD7, 0xFF, 0xFF, 0xF9, 0xBF, 0xFF, 0xFE, 0xCF, 0xFF,
    431         0xFF, 0xB7, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFE, 0x8F, 0xFF, 0xFF, 0xD3,
    432         0xFF, 0xFF, 0xFA, 0xBF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
    433         0xFE, 0xCF, 0xFF, 0xFF, 0xDB, 0xFF, 0xFF, 0xFB, 0xBF, 0xFF, 0xFF, 0x7F,
    434         0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFB, 0xBF
    435       }
    436     }
    437   }
    438   ,
    439   {   /* All chars in reverse */
    440     mhd_MSTR_INIT ("\xFF" "\xFE" "\xFD" "\xFC" "\xFB" "\xFA" "\xF9" "\xF8" \
    441                    "\xF7" "\xF6" "\xF5" "\xF4" "\xF3" "\xF2" "\xF1" "\xF0" \
    442                    "\xEF" "\xEE" "\xED" "\xEC" "\xEB" "\xEA" "\xE9" "\xE8" \
    443                    "\xE7" "\xE6" "\xE5" "\xE4" "\xE3" "\xE2" "\xE1" "\xE0" \
    444                    "\xDF" "\xDE" "\xDD" "\xDC" "\xDB" "\xDA" "\xD9" "\xD8" \
    445                    "\xD7" "\xD6" "\xD5" "\xD4" "\xD3" "\xD2" "\xD1" "\xD0" \
    446                    "\xCF" "\xCE" "\xCD" "\xCC" "\xCB" "\xCA" "\xC9" "\xC8" \
    447                    "\xC7" "\xC6" "\xC5" "\xC4" "\xC3" "\xC2" "\xC1" "\xC0" \
    448                    "\xBF" "\xBE" "\xBD" "\xBC" "\xBB" "\xBA" "\xB9" "\xB8" \
    449                    "\xB7" "\xB6" "\xB5" "\xB4" "\xB3" "\xB2" "\xB1" "\xB0" \
    450                    "\xAF" "\xAE" "\xAD" "\xAC" "\xAB" "\xAA" "\xA9" "\xA8" \
    451                    "\xA7" "\xA6" "\xA5" "\xA4" "\xA3" "\xA2" "\xA1" "\xA0" \
    452                    "\x9F" "\x9E" "\x9D" "\x9C" "\x9B" "\x9A" "\x99" "\x98" \
    453                    "\x97" "\x96" "\x95" "\x94" "\x93" "\x92" "\x91" "\x90" \
    454                    "\x8F" "\x8E" "\x8D" "\x8C" "\x8B" "\x8A" "\x89" "\x88" \
    455                    "\x87" "\x86" "\x85" "\x84" "\x83" "\x82" "\x81" "\x80" \
    456                    "\x7F" "~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUTS" \
    457                    "RQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#\"! " \
    458                    "\x1F" "\x1E" "\x1D" "\x1C" "\x1B" "\x1A" "\x19" "\x18" \
    459                    "\x17" "\x16" "\x15" "\x14" "\x13" "\x12" "\x11" "\x10" \
    460                    "\x0F" "\x0E" "\x0D" "\x0C" "\x0B" "\x0A" "\x09" "\x08" \
    461                    "\x07" "\x06" "\x05" "\x04" "\x03" "\x02" "\x01" "\x00"),
    462     {
    463       583u,
    464       {
    465         0xFF, 0xFF, 0xFB, 0xBF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xEF,
    466         0xFF, 0xFF, 0xFD, 0xDF, 0xFF, 0xFF, 0xB7, 0xFF, 0xFF, 0xF6,
    467         0x7F, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEB, 0xFF, 0xFF, 0xFD,
    468         0x5F, 0xFF, 0xFF, 0xA7, 0xFF, 0xFF, 0xF4, 0x7F, 0xFF, 0xFE,
    469         0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0xFF, 0xEC, 0xFF, 0xFF, 0xFC,
    470         0xDF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xAB,
    471         0xFF, 0xFF, 0xD7, 0xFF, 0xFF, 0xD3, 0xFF, 0xFF, 0xDF, 0xFF,
    472         0xFF, 0xEE, 0xFF, 0xFF, 0xAF, 0xFF, 0xFE, 0xAF, 0xFF, 0xFE,
    473         0x7F, 0xFF, 0xE8, 0xFF, 0xFF, 0x3F, 0xFF, 0xFD, 0x3F, 0xFF,
    474         0xE6, 0xFF, 0xFE, 0xDF, 0xFF, 0xFF, 0x3F, 0xFF, 0xEC, 0xFF,
    475         0xFF, 0xFC, 0xBF, 0xFF, 0xFF, 0x93, 0xFF, 0xFF, 0xF1, 0xFF,
    476         0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xD3, 0xFF, 0xFF, 0xF4, 0x7F,
    477         0xFF, 0x97, 0xFF, 0xFC, 0x9F, 0xFF, 0xFE, 0x5F, 0xFF, 0xFF,
    478         0x8B, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF,
    479         0x83, 0xFF, 0xFF, 0xE6, 0xFF, 0xFF, 0x1F, 0xFF, 0xF2, 0xFF,
    480         0xFF, 0xF6, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFC, 0xBF, 0xFF,
    481         0xFF, 0x7F, 0xFF, 0xFF, 0xEF, 0x7F, 0xFF, 0xFC, 0x9F, 0xFF,
    482         0xFF, 0x1F, 0xFF, 0xFF, 0xC5, 0xFF, 0xFF, 0xEC, 0xFF, 0xFF,
    483         0xA3, 0xFF, 0xFF, 0x97, 0xFF, 0xFC, 0xFF, 0xFF, 0xC7, 0xFF,
    484         0xFA, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF,
    485         0x8F, 0xFF, 0xFC, 0xDF, 0xFF, 0xF2, 0xFF, 0xFF, 0xF0, 0xFF,
    486         0xFF, 0x93, 0xFF, 0xFE, 0x3F, 0xFF, 0xF8, 0xBF, 0xFF, 0xAB,
    487         0xFF, 0xFF, 0x7F, 0xFF, 0xFE, 0xEF, 0xFF, 0xF8, 0x7F, 0xFF,
    488         0xF6, 0xFF, 0xFF, 0x8B, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, 0xFF,
    489         0xFF, 0x83, 0xFF, 0xFF, 0x67, 0xFF, 0xFE, 0xBF, 0xFF, 0xF7,
    490         0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFE, 0xF7, 0xFF,
    491         0xFB, 0xBF, 0xFF, 0xFA, 0xBF, 0xFF, 0xBD, 0xFF, 0xFF, 0xA7,
    492         0xFF, 0xFF, 0x47, 0xFF, 0xFB, 0x9F, 0xFF, 0xED, 0xFF, 0xFF,
    493         0x4F, 0xFF, 0xF7, 0x7F, 0xFF, 0xDA, 0xFF, 0xFF, 0xEF, 0xFF,
    494         0xFF, 0xCF, 0xFF, 0xFF, 0x9B, 0xFF, 0xFD, 0x9F, 0xFF, 0xFC,
    495         0xBF, 0xFF, 0xEC, 0x7F, 0xFF, 0x73, 0xFF, 0xFF, 0x27, 0xFF,
    496         0xFE, 0x3F, 0xFF, 0xFC, 0x5F, 0xFF, 0xF8, 0x7F, 0xFF, 0xFB,
    497         0xBF, 0xFF, 0xF0, 0x7F, 0xFF, 0xAF, 0xFF, 0xFF, 0xDB, 0xFF,
    498         0xFF, 0xD9, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xAF, 0xFF, 0xFE,
    499         0xF7, 0xFF, 0xFD, 0xDF, 0xFF, 0xFB, 0x9F, 0xFF, 0xF6, 0xFF,
    500         0xFF, 0xED, 0x7F, 0xFF, 0xAD, 0xFF, 0xFF, 0x67, 0xFF, 0xFD,
    501         0x5F, 0xFF, 0xF5, 0x3F, 0xFF, 0xD3, 0xFF, 0xFE, 0x8F, 0xFF,
    502         0xE7, 0xFF, 0xFF, 0x4B, 0xFF, 0xF9, 0xBF, 0xFF, 0xFF, 0xF3,
    503         0xFF, 0xBF, 0xFE, 0xFF, 0xCF, 0xFF, 0xDE, 0xFD, 0x79, 0xF1,
    504         0xDE, 0xD4, 0xA2, 0xCE, 0xD5, 0x9E, 0xAA, 0x68, 0xEB, 0xD0,
    505         0xD3, 0xCD, 0x29, 0x64, 0x24, 0x63, 0xFF, 0xFB, 0x17, 0xFF,
    506         0x9F, 0xFC, 0xFF, 0xFE, 0x1F, 0xFB, 0xFD, 0xE7, 0xF9, 0xCB,
    507         0x8F, 0x0D, 0xFB, 0xB6, 0xEC, 0xD7, 0xAB, 0x4E, 0x8C, 0xF9,
    508         0xB2, 0xE4, 0xC7, 0x8B, 0x0E, 0x0B, 0xF7, 0xAE, 0xC3, 0xFF,
    509         0xAF, 0xF3, 0xFE, 0xE0, 0xFF, 0xF9, 0xF7, 0x71, 0xF7, 0x9D,
    510         0x71, 0xB6, 0x99, 0x10, 0x40, 0xC2, 0xEB, 0x7D, 0x7F, 0xBF,
    511         0x9F, 0xEF, 0xFA, 0xFF, 0x5F, 0x0A, 0xFF, 0xE7, 0xFE, 0xBF,
    512         0x9F, 0xE1, 0x4F, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xAF,
    513         0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF7,
    514         0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF,
    515         0x4F, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF,
    516         0xFC, 0xBF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF,
    517         0xFF, 0xBF, 0xFF, 0xFF, 0xFB, 0xBF, 0xFF, 0xFF, 0xB7, 0xFF,
    518         0xFF, 0xFB, 0x3F, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xDF,
    519         0xFF, 0xFF, 0xEA, 0xFF, 0xFF, 0xFE, 0x9F, 0xFF, 0xFF, 0xFF,
    520         0x3F, 0xFF, 0xFA, 0xBF, 0xFF, 0xFF, 0xA3, 0xFF, 0xFF, 0xF9,
    521         0xFF, 0xFF, 0xFF, 0x9B, 0xFF, 0xFF, 0xF9, 0x7F, 0xFF, 0xFF,
    522         0x93, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8B, 0xFF, 0xFE,
    523         0xC7, 0xFE, 0x3F
    524       }
    525     }
    526   }
    527   /* Various paddings */
    528   ,
    529   {   /* Zero bits padding */
    530     mhd_MSTR_INIT ("aaaaaaaa"),
    531     {
    532       5u,
    533       {
    534         0x18, 0xC6, 0x31, 0x8C, 0x63
    535       }
    536     }
    537   }
    538   ,
    539   {   /* 1 bit padding */
    540     mhd_MSTR_INIT ("aaa"),
    541     {
    542       2u,
    543       {
    544         0x18, 0xC7
    545       }
    546     }
    547   }
    548   ,
    549   {   /* 2 bits padding */
    550     mhd_MSTR_INIT ("aaaaaa"),
    551     {
    552       4u,
    553       {
    554         0x18, 0xC6, 0x31, 0x8F
    555       }
    556     }
    557   }
    558   ,
    559   {   /* 3 bits padding */
    560     mhd_MSTR_INIT ("a"),
    561     {
    562       1u,
    563       {
    564         0x1F
    565       }
    566     }
    567   }
    568   ,
    569   {   /* 4 bits padding */
    570     mhd_MSTR_INIT ("aaaa"),
    571     {
    572       3u,
    573       {
    574         0x18, 0xC6, 0x3F
    575       }
    576     }
    577   }
    578   ,
    579   {   /* 5 bits padding */
    580     mhd_MSTR_INIT ("aaaaaaa"),
    581     {
    582       5u,
    583       {
    584         0x18, 0xC6, 0x31, 0x8C, 0x7F
    585       }
    586     }
    587   }
    588   ,
    589   {   /* 6 bits padding */
    590     mhd_MSTR_INIT ("aa"),
    591     {
    592       2u,
    593       {
    594         0x18, 0xFF
    595       }
    596     }
    597   }
    598   ,
    599   {   /* 7 bits padding */
    600     mhd_MSTR_INIT ("aaaaa"),
    601     {
    602       4u,
    603       {
    604         0x18, 0xC6, 0x31, 0xFF
    605       }
    606     }
    607   }
    608 };
    609 
    610 
    611 static void
    612 print_hex (FILE *stream, size_t hex_size, const uint8_t *hex)
    613 {
    614   size_t i;
    615   if (0 == hex_size)
    616     return;
    617   fprintf (stream, "%02X", (unsigned int) hex[0]);
    618   for (i = 1; i < hex_size; ++i)
    619     fprintf (stream, " %02X", (unsigned int) hex[i]);
    620 }
    621 
    622 
    623 /* Not thread-safe! Assuming that the function is called only in one thread */
    624 static const char *
    625 print_mixed (size_t str_len, const char *str)
    626 {
    627   static char tmp_bufs[8][2048]; /* Should be enough for testing */
    628   static size_t cur_buf_idx = 0;
    629   static const size_t buf_size = sizeof(tmp_bufs[0]);
    630   char *buf;
    631   size_t i;
    632   size_t out_idx;
    633   int quote_open = 0;
    634 
    635   buf = tmp_bufs[(cur_buf_idx++) % (sizeof(tmp_bufs) / sizeof(tmp_bufs[0]))];
    636 
    637   for (i = 0, out_idx = 0; i < str_len; ++i)
    638   {
    639     const char c = str[i];
    640     if (0x20 <= c && 0x7E >= c)
    641     {
    642       if (! quote_open)
    643       {
    644         if (0 != i)
    645         {
    646           if (buf_size <= out_idx + 3)
    647             break;
    648           buf[out_idx++] = ' ';
    649         }
    650         else if (buf_size <= out_idx + 2)
    651           break;
    652 
    653         buf[out_idx++] = '"';
    654         quote_open = ! 0;
    655       }
    656       else if (buf_size <= out_idx + 1)
    657         break;
    658 
    659       buf[out_idx++] = c;
    660     }
    661     else
    662     {
    663       const uint8_t digit1 = ((uint8_t) c) & 0xFu;
    664       const uint8_t digit2 = ((uint8_t) c) >> 4;
    665       if (quote_open)
    666       {
    667         if (buf_size <= out_idx + 8)
    668           break;
    669         buf[out_idx++] = '"';
    670         quote_open = 0;
    671         buf[out_idx++] = ' ';
    672       }
    673       else if (buf_size <= out_idx + 6)
    674         break;
    675       buf[out_idx++] = '"';
    676       buf[out_idx++] = '\\';
    677       buf[out_idx++] = 'x';
    678       buf[out_idx++] =
    679         (char) ((digit1 < 10) ? ('0' + digit1) : ('A' + digit1 - 10));
    680       buf[out_idx++] =
    681         (char) ((digit2 < 10) ? ('0' + digit2) : ('A' + digit2 - 10));
    682       buf[out_idx++] = '"';
    683     }
    684   }
    685   if (i < str_len)
    686     return "[TOO LARGE STRING]";
    687 
    688   if (quote_open)
    689   {
    690     if (buf_size <= out_idx + 2)
    691       return "[TOO LARGE STRING]";
    692     buf[out_idx++] = '"';
    693   }
    694 
    695   if (buf_size <= out_idx + 1)
    696     return "[TOO LARGE STRING]";
    697 
    698   buf[out_idx++] = 0;
    699 
    700   return buf;
    701 }
    702 
    703 
    704 /* non-zero error code on error, zero on success */
    705 static int
    706 basic_data_check (void)
    707 {
    708   size_t i;
    709   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
    710   {
    711     /* Check the input data */
    712 #if 0 /* Disabled check, such data is used for checks */
    713     if (0 == h_data[i].str.len)
    714     {
    715       fflush (stdout);
    716       fprintf (stderr, "ERROR: wrong zero length of the string data for "
    717                "the entry number %lu\n",
    718                (unsigned long) i);
    719       return 99;
    720     }
    721 #endif /* Disabled check */
    722     if (NULL == h_data[i].str.cstr)
    723     {
    724       fflush (stdout);
    725       fprintf (stderr, "ERROR: wrong zero NULL pointer for the string data for "
    726                "the entry number %lu\n",
    727                (unsigned long) i);
    728       return 99;
    729     }
    730     else if (h_data[i].str.len < strlen (h_data[i].str.cstr))
    731     {
    732       fflush (stdout);
    733       fprintf (stderr, "ERROR: unterminated string data for "
    734                "the entry number %lu\n",
    735                (unsigned long) i);
    736       return 99;
    737     }
    738     if (0 != h_data[i].str.cstr[h_data[i].str.len])
    739     {
    740       fflush (stdout);
    741       fprintf (stderr, "ERROR: unterminated string for the string data for "
    742                "the entry number %lu\n",
    743                (unsigned long) i);
    744       return 99;
    745     }
    746     if ((0 == h_data[i].enc.size)
    747         && (0 != h_data[i].str.len))
    748     {
    749       fflush (stdout);
    750       fprintf (stderr, "ERROR: wrong zero length of encoded data for "
    751                "the entry with with the string data \"%s\"\n",
    752                h_data[i].str.cstr);
    753       return 99;
    754     }
    755     if (((sizeof(h_data[i].enc.data) != h_data[i].enc.size)) &&
    756         (0 != h_data[i].enc.data[h_data[i].enc.size]))
    757     {
    758       fflush (stdout);
    759       fprintf (stderr, "ERROR: wrong length of encoded data for "
    760                "the entry with with the string data \"%s\"\n",
    761                h_data[i].str.cstr);
    762       return 99;
    763     }
    764   }
    765   return 0;
    766 }
    767 
    768 
    769 /* ------------------ Encode testing ------------------- */
    770 
    771 
    772 /* non-zero error code on error, zero on success */
    773 static int
    774 perform_single_enc_check (size_t str_len,
    775                           const char *restrict str,
    776                           size_t valid_enc_size,
    777                           const uint8_t *restrict valid_enc,
    778                           size_t use_buff_size)
    779 {
    780   uint8_t buff[sizeof(h_data[0].enc.data) * 4];
    781   size_t res;
    782 
    783   if (sizeof(buff) < use_buff_size)
    784   {
    785     fflush (stdout);
    786     fprintf (stderr, "ERROR: wrong size of the buffer specified for "
    787              "the check.\n"
    788              "The specified size:        %lu\n"
    789              "The maximum possible size: %lu\n",
    790              (unsigned long) use_buff_size,
    791              (unsigned long) sizeof(buff));
    792     return 99;
    793   }
    794   memset (buff, 0, sizeof(buff));
    795 
    796   res = mhd_h2_huffman_encode (str_len,
    797                                str,
    798                                use_buff_size,
    799                                buff);
    800   if (valid_enc_size > use_buff_size)
    801   {
    802     if (0 == res)
    803       return 0; /* Failed as required */
    804     fflush (stdout);
    805     fprintf (stderr, "FAILED: mhd_h2_huffman_encode(%lu, %s, %lu, buffer) "
    806              "returned value %lu, while expected ZERO\n"
    807              "If the buffer would have enough space then "
    808              "the encoded data must be:",
    809              (unsigned long) str_len,
    810              print_mixed (str_len, str),
    811              (unsigned long) use_buff_size,
    812              (unsigned long) res);
    813     print_hex (stderr, valid_enc_size, valid_enc);
    814     fprintf (stderr, "\nResulting encoded data: ");
    815     print_hex (stderr, res, buff);
    816     fprintf (stderr, "\n");
    817     return 3;
    818   }
    819 
    820   if (valid_enc_size != res)
    821   {
    822     fflush (stdout);
    823     fprintf (stderr, "FAILED: mhd_h2_huffman_encode(%lu, %s, %lu, buffer) "
    824              "returned value %lu, while expected %lu\n",
    825              (unsigned long) str_len,
    826              print_mixed (str_len, str),
    827              (unsigned long) valid_enc_size,
    828              (unsigned long) res,
    829              (unsigned long) valid_enc_size);
    830     return 1;
    831   }
    832   if (0 != memcmp (valid_enc, buff, res))
    833   {
    834     fflush (stdout);
    835     fprintf (stderr, "FAILED: mhd_h2_huffman_encode(%lu, %s, %lu, buffer) "
    836              "returned expected value %lu, "
    837              "but the data is encoded incorrectly in the output buffer.\n",
    838              (unsigned long) str_len,
    839              print_mixed (str_len, str),
    840              (unsigned long) valid_enc_size,
    841              (unsigned long) res);
    842     fprintf (stderr,   "Expected encoded data:  ");
    843     print_hex (stderr, valid_enc_size, valid_enc);
    844     fprintf (stderr, "\nResulting encoded data: ");
    845     print_hex (stderr, res, buff);
    846     fprintf (stderr, "\n");
    847     return 2;
    848   }
    849 
    850   return 0;
    851 }
    852 
    853 
    854 /* non-zero error code on error, zero on success */
    855 static int
    856 check_h2_h_encode_perfect_size (void)
    857 {
    858   size_t i;
    859   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
    860   {
    861     int res;
    862 
    863     res = perform_single_enc_check (h_data[i].str.len,
    864                                     h_data[i].str.cstr,
    865                                     h_data[i].enc.size,
    866                                     h_data[i].enc.data,
    867                                     h_data[i].enc.size);
    868 
    869     if (0 != res)
    870       return res;
    871   }
    872   return 0;
    873 }
    874 
    875 
    876 /* non-zero error code on error, zero on success */
    877 static int
    878 check_h2_h_encode_larger_size (void)
    879 {
    880   size_t i;
    881   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
    882   {
    883     int res;
    884 
    885     res = perform_single_enc_check (h_data[i].str.len,
    886                                     h_data[i].str.cstr,
    887                                     h_data[i].enc.size,
    888                                     h_data[i].enc.data,
    889                                     h_data[i].enc.size + 1);
    890 
    891     if (0 != res)
    892       return res;
    893   }
    894   return 0;
    895 }
    896 
    897 
    898 /* non-zero error code on error, zero on success */
    899 static int
    900 check_h2_h_encode_smaller_size (void)
    901 {
    902   size_t i;
    903   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
    904   {
    905     int res;
    906     if (0 == h_data[i].enc.size)
    907       continue;
    908 
    909     res = perform_single_enc_check (h_data[i].str.len,
    910                                     h_data[i].str.cstr,
    911                                     h_data[i].enc.size,
    912                                     h_data[i].enc.data,
    913                                     h_data[i].enc.size - 1);
    914 
    915     if (0 != res)
    916       return res;
    917   }
    918   return 0;
    919 }
    920 
    921 
    922 /* non-zero error code on error, zero on success */
    923 static int
    924 check_h2_h_encode_fixed_size (size_t use_size)
    925 {
    926   size_t i;
    927   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
    928   {
    929     int res;
    930 
    931     res = perform_single_enc_check (h_data[i].str.len,
    932                                     h_data[i].str.cstr,
    933                                     h_data[i].enc.size,
    934                                     h_data[i].enc.data,
    935                                     use_size);
    936 
    937     if (0 != res)
    938       return res;
    939   }
    940   return 0;
    941 }
    942 
    943 
    944 /* non-zero error code on error, zero on success */
    945 static int
    946 check_h2_h_encode_fixed_sizes (void)
    947 {
    948   size_t i;
    949   for (i = 0; i <= 16; ++i)
    950   {
    951     int res;
    952 
    953     res = check_h2_h_encode_fixed_size (i);
    954 
    955     if (0 != res)
    956       return res;
    957   }
    958   return 0;
    959 }
    960 
    961 
    962 /* non-zero error code on error, zero on success */
    963 static int
    964 test_encode (void)
    965 {
    966   int res;
    967 
    968   printf ("Checking H2 Huffman encoding with"
    969           " precise output buffer size...\n");
    970   res = check_h2_h_encode_perfect_size ();
    971   if (0 != res)
    972     return res;
    973   printf ("Succeed\n");
    974 
    975   printf ("Checking H2 Huffman encoding with"
    976           " larger output buffer size...\n");
    977   res = check_h2_h_encode_larger_size ();
    978   if (0 != res)
    979     return res;
    980   printf ("Succeed\n");
    981 
    982   printf ("Checking H2 Huffman encoding with"
    983           " smaller output buffer size...\n");
    984   res = check_h2_h_encode_smaller_size ();
    985   if (0 != res)
    986     return res;
    987   printf ("Succeed\n");
    988 
    989   printf ("Checking H2 Huffman encoding with"
    990           " various fixed output buffer sizes...\n");
    991   res = check_h2_h_encode_fixed_sizes ();
    992   if (0 != res)
    993     return res;
    994   printf ("Succeed\n");
    995 
    996   return 0;
    997 }
    998 
    999 
   1000 /* ------------------ Decode testing ------------------- */
   1001 
   1002 static const char *
   1003 decode_result_to_string (enum mhd_H2HuffDecodeRes res)
   1004 {
   1005   switch (res)
   1006   {
   1007   case MHD_H2_HUFF_DEC_RES_OK:
   1008     return "'OK'";
   1009   case MHD_H2_HUFF_DEC_RES_NO_SPACE:
   1010     return "'NO_SPACE'";
   1011   case MHD_H2_HUFF_DEC_RES_BROKEN_DATA:
   1012     return "'BROKEN_DATA'";
   1013   default:
   1014     break;
   1015   }
   1016   return "[UNKNOWN RESULT]";
   1017 }
   1018 
   1019 
   1020 /* non-zero error code on error, zero on success */
   1021 static int
   1022 perform_single_dec_valid_check (size_t enc_size,
   1023                                 const uint8_t *restrict enc,
   1024                                 size_t valid_str_len,
   1025                                 const char *restrict valid_str,
   1026                                 size_t use_buff_size)
   1027 {
   1028   char buff[257 * 2];
   1029   enum mhd_H2HuffDecodeRes res;
   1030   size_t ret_size;
   1031 
   1032   if (sizeof(buff) < use_buff_size)
   1033   {
   1034     fflush (stdout);
   1035     fprintf (stderr, "ERROR: wrong size of the buffer specified for "
   1036              "the check.\n"
   1037              "The specified size:        %lu\n"
   1038              "The maximum possible size: %lu\n",
   1039              (unsigned long) use_buff_size,
   1040              (unsigned long) sizeof(buff));
   1041     return 99;
   1042   }
   1043   memset (buff, 0, sizeof(buff));
   1044 
   1045   ret_size = mhd_h2_huffman_decode (enc_size,
   1046                                     enc,
   1047                                     use_buff_size,
   1048                                     buff,
   1049                                     &res);
   1050   if (valid_str_len > use_buff_size)
   1051   {
   1052     if ((0 == ret_size) && (MHD_H2_HUFF_DEC_RES_NO_SPACE == res))
   1053       return 0; /* Failed as required */
   1054     fflush (stdout);
   1055     fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1056              "%lu, %s%s, ->%s) returned %lu\n",
   1057              (unsigned long) enc_size,
   1058              (unsigned long) use_buff_size,
   1059              (0 == ret_size) ? "buffer" : "->",
   1060              (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1061              decode_result_to_string (res),
   1062              (unsigned long) ret_size);
   1063     if (0 != ret_size)
   1064       fprintf (stderr, "The function returned value %lu, while expected ZERO\n",
   1065                (unsigned long) ret_size);
   1066     else
   1067       fprintf (stderr, "The function returned ZERO as expected, but the status "
   1068                "must be 'NO_SPACE'\n");
   1069 
   1070     fprintf (stderr, "The encoded data is: ");
   1071     print_hex (stderr, enc_size, enc);
   1072     fprintf (stderr, "\nIf the buffer would have enough space then "
   1073              "the decoded string must be: %s\n",
   1074              print_mixed (valid_str_len, valid_str));
   1075     return 3;
   1076   }
   1077 
   1078   if ((valid_str_len != ret_size) ||
   1079       ((MHD_H2_HUFF_DEC_RES_OK != res)))
   1080   {
   1081     fflush (stdout);
   1082     fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1083              "%lu, %s%s, ->%s) returned %lu\n",
   1084              (unsigned long) enc_size,
   1085              (unsigned long) use_buff_size,
   1086              (0 == ret_size) ? "buffer" : "->",
   1087              (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1088              decode_result_to_string (res),
   1089              (unsigned long) ret_size);
   1090 
   1091     if (valid_str_len != ret_size)
   1092       fprintf (stderr, "The function returned value %lu, while expected %lu\n",
   1093                (unsigned long) ret_size, (unsigned long) valid_str_len);
   1094     else
   1095       fprintf (stderr, "The function returned expected value %lu, "
   1096                "but the status must be 'OK'\n",
   1097                (unsigned long) ret_size);
   1098 
   1099     fprintf (stderr, "The encoded data is: ");
   1100     print_hex (stderr, enc_size, enc);
   1101     fprintf (stderr, "\nThe expected decoded string: %s\n",
   1102              print_mixed (valid_str_len, valid_str));
   1103 
   1104     return 1;
   1105   }
   1106   if (0 != memcmp (valid_str, buff, ret_size))
   1107   {
   1108     fflush (stdout);
   1109     fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1110              "%lu, buffer, ->%s) returned %lu\n",
   1111              (unsigned long) enc_size,
   1112              (unsigned long) use_buff_size,
   1113              decode_result_to_string (res),
   1114              (unsigned long) ret_size);
   1115     fprintf (stderr,"The function returned expected value %lu and set "
   1116              "correct 'OK' status, but the data is decoded incorrectly "
   1117              "in the output buffer.\n",
   1118              (unsigned long) ret_size);
   1119     fprintf (stderr, "The decoded string:  %s\n",
   1120              print_mixed (ret_size, buff));
   1121     fprintf (stderr, "The expected string: %s\n",
   1122              print_mixed (valid_str_len, valid_str));
   1123     fprintf (stderr, "The encoded data is: ");
   1124     print_hex (stderr, enc_size, enc);
   1125     fprintf (stderr, "\n");
   1126     return 2;
   1127   }
   1128 
   1129   return 0;
   1130 }
   1131 
   1132 
   1133 /* non-zero error code on error, zero on success */
   1134 static int
   1135 check_h2_h_decode_perfect_size (void)
   1136 {
   1137   size_t i;
   1138   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
   1139   {
   1140     int res;
   1141 
   1142     res = perform_single_dec_valid_check (h_data[i].enc.size,
   1143                                           h_data[i].enc.data,
   1144                                           h_data[i].str.len,
   1145                                           h_data[i].str.cstr,
   1146                                           h_data[i].str.len);
   1147 
   1148     if (0 != res)
   1149       return res;
   1150   }
   1151   return 0;
   1152 }
   1153 
   1154 
   1155 /* non-zero error code on error, zero on success */
   1156 static int
   1157 check_h2_h_decode_larger_size (void)
   1158 {
   1159   size_t i;
   1160   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
   1161   {
   1162     int res;
   1163 
   1164     res = perform_single_dec_valid_check (h_data[i].enc.size,
   1165                                           h_data[i].enc.data,
   1166                                           h_data[i].str.len,
   1167                                           h_data[i].str.cstr,
   1168                                           h_data[i].str.len + 1);
   1169 
   1170     if (0 != res)
   1171       return res;
   1172   }
   1173   return 0;
   1174 }
   1175 
   1176 
   1177 /* non-zero error code on error, zero on success */
   1178 static int
   1179 check_h2_h_decode_smaller_size (void)
   1180 {
   1181   size_t i;
   1182   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
   1183   {
   1184     int res;
   1185     if (0 == h_data[i].enc.size)
   1186       continue;
   1187 
   1188     res = perform_single_dec_valid_check (h_data[i].enc.size,
   1189                                           h_data[i].enc.data,
   1190                                           h_data[i].str.len,
   1191                                           h_data[i].str.cstr,
   1192                                           h_data[i].str.len - 1);
   1193 
   1194     if (0 != res)
   1195       return res;
   1196   }
   1197   return 0;
   1198 }
   1199 
   1200 
   1201 /* non-zero error code on error, zero on success */
   1202 static int
   1203 check_h2_h_decode_fixed_size (size_t use_size)
   1204 {
   1205   size_t i;
   1206   for (i = 0; i < sizeof(h_data) / sizeof(h_data[0]); ++i)
   1207   {
   1208     int res;
   1209 
   1210     res = perform_single_dec_valid_check (h_data[i].enc.size,
   1211                                           h_data[i].enc.data,
   1212                                           h_data[i].str.len,
   1213                                           h_data[i].str.cstr,
   1214                                           use_size);
   1215 
   1216     if (0 != res)
   1217       return res;
   1218   }
   1219   return 0;
   1220 }
   1221 
   1222 
   1223 /* non-zero error code on error, zero on success */
   1224 static int
   1225 check_h2_h_decode_fixed_sizes (void)
   1226 {
   1227   size_t i;
   1228   for (i = 0; i <= 16; ++i)
   1229   {
   1230     int res;
   1231 
   1232     res = check_h2_h_decode_fixed_size (i);
   1233 
   1234     if (0 != res)
   1235       return res;
   1236   }
   1237   return 0;
   1238 }
   1239 
   1240 
   1241 /* This function tries to decode the data and it is succeed, checks
   1242  * whether the decoded string can be encoded back to the original encoded
   1243  * data.
   1244  * The check does not detect situations when a valid encoded string
   1245  * cannot be decoded, however as correct codes are re-checked by encoder
   1246  * and the total number of valid codes is counted, this check is strong
   1247  * enough (unless decoder and encoder have symmetric bugs).
   1248  */
   1249 /* non-zero error code on error, zero on success */
   1250 static int
   1251 perform_single_dec_unknow_seq_check (size_t enc_size,
   1252                                      const uint8_t *restrict enc,
   1253                                      uint_fast32_t *valid_codes_counter)
   1254 {
   1255   char buff[8 * 4];
   1256   static const size_t buff_size = sizeof(buff);
   1257   enum mhd_H2HuffDecodeRes res;
   1258   size_t ret_size;
   1259 
   1260   if (buff_size < enc_size * 4)
   1261   {
   1262     fflush (stdout);
   1263     fprintf (stderr, "ERROR: wrong size of the value specified for "
   1264              "the check.\n"
   1265              "The specified size:        %lu\n"
   1266              "The maximum possible size: %lu\n",
   1267              (unsigned long) enc_size,
   1268              (unsigned long) buff_size / 4);
   1269     return 99;
   1270   }
   1271   if (0 == enc_size)
   1272   {
   1273     fflush (stdout);
   1274     fprintf (stderr, "ERROR: zero size of the value specified for "
   1275              "the check.\n");
   1276     return 99;
   1277   }
   1278 
   1279   ret_size = mhd_h2_huffman_decode (enc_size,
   1280                                     enc,
   1281                                     buff_size,
   1282                                     buff,
   1283                                     &res);
   1284 
   1285   if (0 == ret_size && MHD_H2_HUFF_DEC_RES_OK == res)
   1286   {
   1287     fflush (stdout);
   1288     fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1289              "%lu, %s%s, ->%s) returned %lu\n",
   1290              (unsigned long) enc_size,
   1291              (unsigned long) buff_size,
   1292              (0 == ret_size) ? "buffer" : "->",
   1293              (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1294              decode_result_to_string (res),
   1295              (unsigned long) ret_size);
   1296     fprintf (stderr, "The function returned ZERO, but the status was not "
   1297              "set to 'OK' (actual: %s), while the size of the input data"
   1298              " is not ZERO.\n",
   1299              decode_result_to_string (res));
   1300     return 5;
   1301   }
   1302   if (0 != ret_size && MHD_H2_HUFF_DEC_RES_OK != res)
   1303   {
   1304     fflush (stdout);
   1305     fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1306              "%lu, %s%s, ->%s) returned %lu\n",
   1307              (unsigned long) enc_size,
   1308              (unsigned long) buff_size,
   1309              (0 == ret_size) ? "buffer" : "->",
   1310              (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1311              decode_result_to_string (res),
   1312              (unsigned long) ret_size);
   1313     fprintf (stderr, "The function returned non-ZERO, but the status was "
   1314              "set to 'OK'.\n");
   1315     return 5;
   1316   }
   1317   if (MHD_H2_HUFF_DEC_RES_NO_SPACE == res)
   1318   {
   1319     fflush (stdout);
   1320     fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1321              "%lu, %s%s, ->%s) returned %lu\n",
   1322              (unsigned long) enc_size,
   1323              (unsigned long) buff_size,
   1324              (0 == ret_size) ? "buffer" : "->",
   1325              (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1326              decode_result_to_string (res),
   1327              (unsigned long) ret_size);
   1328     fprintf (stderr, "The function set the status set to 'NO_SPACE', but "
   1329              "the buffer should be enough to hold the result.\n");
   1330     return 6;
   1331   }
   1332   if (MHD_H2_HUFF_DEC_RES_OK == res)
   1333   {
   1334     uint8_t check_enc_buf[128];
   1335     size_t check_enc_size;
   1336 
   1337     check_enc_size = mhd_h2_huffman_encode (ret_size,
   1338                                             buff,
   1339                                             sizeof(check_enc_buf),
   1340                                             check_enc_buf);
   1341     if (0 == check_enc_size)
   1342     {
   1343       fflush (stdout);
   1344       fprintf (stderr, "ERROR: mhd_h2_huffman_decode(%lu, encoded_data, "
   1345                "%lu, %s%s, ->%s) returned %lu\n",
   1346                (unsigned long) enc_size,
   1347                (unsigned long) buff_size,
   1348                (0 == ret_size) ? "buffer" : "->",
   1349                (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1350                decode_result_to_string (res),
   1351                (unsigned long) check_enc_size);
   1352       fprintf (stderr, "However, when checking the decoded result by "
   1353                "encoding it back to H2 Huffman encoding the function "
   1354                "mhd_h2_huffman_encode(%lu, %s, %lu, buffer) returned "
   1355                "ZERO, which should not happen as the output "
   1356                "buffer is large enough.\n",
   1357                (unsigned long) ret_size,
   1358                print_mixed (ret_size, buff),
   1359                (unsigned long) sizeof(check_enc_buf));
   1360       return 99;
   1361     }
   1362     if ((enc_size != check_enc_size) ||
   1363         (0 != memcmp (enc, check_enc_buf, check_enc_size)))
   1364     {
   1365       fflush (stdout);
   1366       fprintf (stderr, "FAILED: mhd_h2_huffman_decode(%lu, encoded_data, "
   1367                "%lu, %s%s, ->%s) returned %lu\n",
   1368                (unsigned long) enc_size,
   1369                (unsigned long) buff_size,
   1370                (0 == ret_size) ? "buffer" : "->",
   1371                (0 == ret_size) ? "" : print_mixed (ret_size, buff),
   1372                decode_result_to_string (res),
   1373                (unsigned long) ret_size);
   1374       if (enc_size != check_enc_size)
   1375         fprintf (stderr, "However, when checking the decoded result by "
   1376                  "encoding it back to H2 Huffman encoding the function "
   1377                  "mhd_h2_huffman_encode(%lu, %s, %lu, buffer) returned "
   1378                  "%lu, which does not match the original data size.\n",
   1379                  (unsigned long) ret_size,
   1380                  print_mixed (ret_size, buff),
   1381                  (unsigned long) sizeof(check_enc_buf),
   1382                  (unsigned long) check_enc_size);
   1383       else
   1384         fprintf (stderr, "However, when checking the decoded result by "
   1385                  "encoding it back to H2 Huffman encoding the function "
   1386                  "mhd_h2_huffman_encode(%lu, %s, %lu, buffer) returned "
   1387                  "%lu (as expected), but the encoded data does not match "
   1388                  "original encoded data.\n",
   1389                  (unsigned long) ret_size,
   1390                  print_mixed (ret_size, buff),
   1391                  (unsigned long) sizeof(check_enc_buf),
   1392                  (unsigned long) ret_size);
   1393 
   1394       fprintf (stderr, "The decoded string:  %s\n",
   1395                print_mixed (ret_size, buff));
   1396       fprintf (stderr, "The original encoded data is: ");
   1397       print_hex (stderr, enc_size, enc);
   1398       fprintf (stderr, "\n"
   1399                "The string encoded back is:   ");
   1400       print_hex (stderr, check_enc_size, check_enc_buf);
   1401       fprintf (stderr, "\n");
   1402 
   1403       return 7;
   1404     }
   1405     *valid_codes_counter += 1;
   1406   }
   1407 
   1408   return 0;
   1409 }
   1410 
   1411 
   1412 /* non-zero error code on error, zero on success */
   1413 static int
   1414 check_h2_h_decode_all_one_byte_values (void)
   1415 {
   1416   static const uint_fast32_t known_valid_codes = 74u;
   1417   uint_fast32_t valid_codes_counter;
   1418   uint_fast16_t i;
   1419 
   1420   valid_codes_counter = 0;
   1421   i = 0;
   1422   do
   1423   {
   1424     uint8_t test_data[1];
   1425     int res;
   1426     test_data[0] = (uint8_t) i;
   1427 
   1428     res = perform_single_dec_unknow_seq_check (sizeof(test_data),
   1429                                                test_data,
   1430                                                &valid_codes_counter);
   1431 
   1432     if (0 != res)
   1433       return res;
   1434   } while (0xFFu > i++);
   1435 
   1436   if (known_valid_codes != valid_codes_counter)
   1437   {
   1438     fflush (stdout);
   1439     fprintf (stderr, "The check found %lu valid code values, while"
   1440              "the expected number of valid code values is %lu.\n",
   1441              (unsigned long) valid_codes_counter,
   1442              (unsigned long) known_valid_codes);
   1443     return 9;
   1444   }
   1445 
   1446   return 0;
   1447 }
   1448 
   1449 
   1450 /* non-zero error code on error, zero on success */
   1451 static int
   1452 check_h2_h_decode_all_two_bytes_values (void)
   1453 {
   1454   static const uint_fast32_t known_valid_codes = 14717u;
   1455   uint_fast32_t valid_codes_counter;
   1456   uint_fast16_t i;
   1457 
   1458   valid_codes_counter = 0;
   1459   i = 0;
   1460   do
   1461   {
   1462     uint8_t test_data[2];
   1463     int res;
   1464     test_data[0] = (uint8_t) i & 0xFFu;
   1465     test_data[1] = (uint8_t) ((i & 0xFF00u) >> 8u);
   1466 
   1467     res = perform_single_dec_unknow_seq_check (sizeof(test_data),
   1468                                                test_data,
   1469                                                &valid_codes_counter);
   1470 
   1471     if (0 != res)
   1472       return res;
   1473   } while (0xFFFFu > i++);
   1474 
   1475   if (known_valid_codes != valid_codes_counter)
   1476   {
   1477     fflush (stdout);
   1478     fprintf (stderr, "The check found %lu valid code values, while "
   1479              "the expected number of valid code values is %lu.\n",
   1480              (unsigned long) valid_codes_counter,
   1481              (unsigned long) known_valid_codes);
   1482     return 9;
   1483   }
   1484 
   1485   return 0;
   1486 }
   1487 
   1488 
   1489 /* non-zero error code on error, zero on success */
   1490 static int
   1491 check_h2_h_decode_all_three_bytes_values (void)
   1492 {
   1493   static const uint_fast32_t known_valid_codes = 6759631u;
   1494   static const uint_fast32_t one_pct_step = 0xFFFFFFu / 100u;
   1495   uint_fast32_t valid_codes_counter;
   1496   uint_fast32_t i;
   1497 
   1498   valid_codes_counter = 0;
   1499   i = 0;
   1500   printf ("Completed: 00%% ");
   1501   fflush (stdout);
   1502   do
   1503   {
   1504     uint8_t test_data[3];
   1505     int res;
   1506     test_data[0] = (uint8_t) i & 0xFFu;
   1507     test_data[1] = (uint8_t) ((i & 0xFF00u) >> 8u);
   1508     test_data[2] = (uint8_t) ((i & 0xFF0000u) >> 16u);
   1509 
   1510     res = perform_single_dec_unknow_seq_check (sizeof(test_data),
   1511                                                test_data,
   1512                                                &valid_codes_counter);
   1513 
   1514     if (0 != res)
   1515       return res;
   1516 
   1517     /* Imperfect calculations, but enough for tracking the progress */
   1518     if (0u == (i % one_pct_step))
   1519     {
   1520       printf ("\b\b\b\b%02u%% ", (unsigned int) (i / one_pct_step));
   1521       fflush (stdout);
   1522     }
   1523   } while (0xFFFFFFu > i++);
   1524   printf ("\n");
   1525 
   1526   if (known_valid_codes != valid_codes_counter)
   1527   {
   1528     fflush (stdout);
   1529     fprintf (stderr, "The check found %lu valid code values, while "
   1530              "the expected number of valid code values is %lu.\n",
   1531              (unsigned long) valid_codes_counter,
   1532              (unsigned long) known_valid_codes);
   1533     return 9;
   1534   }
   1535 
   1536   return 0;
   1537 }
   1538 
   1539 
   1540 /* non-zero error code on error, zero on success */
   1541 static int
   1542 check_h2_h_decode_all_four_bytes_values (void)
   1543 {
   1544   static const uint_fast32_t known_valid_codes = 1395134146u;
   1545   static const uint_fast32_t one_pct_step = 0xFFFFFFFFu / 100u;
   1546   uint_fast32_t valid_codes_counter;
   1547   uint_fast32_t i;
   1548 
   1549   valid_codes_counter = 0;
   1550   i = 0;
   1551   printf ("Completed: 00%% ");
   1552   fflush (stdout);
   1553   do
   1554   {
   1555     uint8_t test_data[4];
   1556     int res;
   1557     test_data[0] = (uint8_t) i & 0xFFu;
   1558     test_data[1] = (uint8_t) ((i & 0xFF00u) >> 8u);
   1559     test_data[2] = (uint8_t) ((i & 0xFF0000u) >> 16u);
   1560     test_data[3] = (uint8_t) ((i & 0xFF000000u) >> 24u);
   1561 
   1562     res = perform_single_dec_unknow_seq_check (sizeof(test_data),
   1563                                                test_data,
   1564                                                &valid_codes_counter);
   1565 
   1566     if (0 != res)
   1567       return res;
   1568 
   1569     /* Imperfect calculations, but enough for tracking the progress */
   1570     if (0u == (i % one_pct_step))
   1571     {
   1572       printf ("\b\b\b\b%02u%% ", (unsigned int) (i / one_pct_step));
   1573       fflush (stdout);
   1574     }
   1575   } while (0xFFFFFFFFu > i++);
   1576   printf ("\n");
   1577 
   1578   if (known_valid_codes != valid_codes_counter)
   1579   {
   1580     fflush (stdout);
   1581     fprintf (stderr, "The check found %lu valid code values, while "
   1582              "the expected number of valid code values is %lu.\n",
   1583              (unsigned long) valid_codes_counter,
   1584              (unsigned long) known_valid_codes);
   1585     return 9;
   1586   }
   1587 
   1588   return 0;
   1589 }
   1590 
   1591 
   1592 /* non-zero error code on error, zero on success */
   1593 static int
   1594 test_decode (void)
   1595 {
   1596   int res;
   1597 
   1598   mhd_h2_huffman_init ();
   1599 
   1600   printf ("Checking H2 Huffman decoding with"
   1601           " precise output buffer size...\n");
   1602   res = check_h2_h_decode_perfect_size ();
   1603   if (0 != res)
   1604     return res;
   1605   printf ("Succeed\n");
   1606 
   1607   printf ("Checking H2 Huffman decoding with"
   1608           " larger output buffer size...\n");
   1609   res = check_h2_h_decode_larger_size ();
   1610   if (0 != res)
   1611     return res;
   1612   printf ("Succeed\n");
   1613 
   1614   printf ("Checking H2 Huffman decoding with"
   1615           " smaller output buffer size...\n");
   1616   res = check_h2_h_decode_smaller_size ();
   1617   if (0 != res)
   1618     return res;
   1619   printf ("Succeed\n");
   1620 
   1621   printf ("Checking H2 Huffman decoding with"
   1622           " various fixed output buffer sizes...\n");
   1623   res = check_h2_h_decode_fixed_sizes ();
   1624   if (0 != res)
   1625     return res;
   1626   printf ("Succeed\n");
   1627 
   1628   printf ("Checking H2 Huffman decoding with"
   1629           " all one byte values...\n");
   1630   res = check_h2_h_decode_all_one_byte_values ();
   1631   if (0 != res)
   1632     return res;
   1633   printf ("Succeed\n");
   1634 
   1635   printf ("Checking H2 Huffman decoding with"
   1636           " all combinations of two bytes values...\n");
   1637   res = check_h2_h_decode_all_two_bytes_values ();
   1638   if (0 != res)
   1639     return res;
   1640   printf ("Succeed\n");
   1641 
   1642   printf ("Checking H2 Huffman decoding with"
   1643           " all combinations of three bytes values...\n");
   1644   printf ("This check may take up to a minute.\n");
   1645   res = check_h2_h_decode_all_three_bytes_values ();
   1646   if (0 != res)
   1647     return res;
   1648   printf ("Succeed\n");
   1649 
   1650   if (enable_deep_tests)
   1651   {
   1652     printf ("Checking H2 Huffman decoding with"
   1653             " all combinations of four bytes values...\n");
   1654     printf ("This check may take between 1 minute and 2 hours.\n");
   1655     res = check_h2_h_decode_all_four_bytes_values ();
   1656     if (0 != res)
   1657       return res;
   1658     printf ("Succeed\n");
   1659   }
   1660   else
   1661   {
   1662     printf ("Skipping checking H2 Huffman decoding with"
   1663             " all combinations of four bytes values as deep tests "
   1664             "are not enabled.\n");
   1665   }
   1666 
   1667   return 0;
   1668 }
   1669 
   1670 
   1671 int
   1672 main (int argc,
   1673       char *const *argv)
   1674 {
   1675   if (argc < 1)
   1676     return 99;
   1677 
   1678   if (! enable_deep_tests)
   1679     enable_deep_tests = mhdt_has_param (argc, argv, "--deep");
   1680 
   1681   if (0 != basic_data_check ())
   1682     return 99;
   1683 
   1684   if (mhdt_has_in_name (argv[0], "_decode"))
   1685     return test_decode ();
   1686 
   1687   return test_encode ();
   1688 
   1689 }