libmicrohttpd2

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

unit_str_pct.c (38151B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2022 Karlson2k (Evgeny Grin)
      4 
      5   This test tool is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 2, or
      8   (at your option) any later version.
      9 
     10   This test tool is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library; if not, write to the Free Software
     17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18 */
     19 
     20 /**
     21  * @file src/tests/unit/unit_str_pct.c
     22  * @brief  Unit tests for percent (URL) encoded strings processing
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #include "mhd_sys_options.h"
     27 #include <string.h>
     28 #include <stdio.h>
     29 
     30 #include "mhd_str.h"
     31 #include "mhd_str.c"
     32 #include "mhd_assert.h"
     33 
     34 #ifndef MHD_STATICSTR_LEN_
     35 /**
     36  * Determine length of static string / macro strings at compile time.
     37  */
     38 #define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
     39 #endif /* ! MHD_STATICSTR_LEN_ */
     40 
     41 
     42 static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */
     43 static size_t buf_idx = 0;
     44 
     45 /* print non-printable chars as char codes */
     46 static char *
     47 n_prnt (const char *str, size_t len)
     48 {
     49   static char *buf;  /* should be enough for testing */
     50   static const size_t buf_size = sizeof(tmp_bufs[0]);
     51   size_t r_pos = 0;
     52   size_t w_pos = 0;
     53   if (++buf_idx >= (sizeof(tmp_bufs) / sizeof(tmp_bufs[0])))
     54     buf_idx = 0;
     55   buf = tmp_bufs[buf_idx];
     56 
     57   while (len > r_pos && w_pos + 1 < buf_size)
     58   {
     59     const unsigned char c = (unsigned char) str[r_pos];
     60     if ((c == '\\') || (c == '"') )
     61     {
     62       if (w_pos + 2 >= buf_size)
     63         break;
     64       buf[w_pos++] = '\\';
     65       buf[w_pos++] = (char) c;
     66     }
     67     else if ((c >= 0x20) && (c <= 0x7E) )
     68       buf[w_pos++] = (char) c;
     69     else
     70     {
     71       if (w_pos + 4 >= buf_size)
     72         break;
     73       if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned
     74                                                                 int) c) != 4)
     75         break;
     76       w_pos += 4;
     77     }
     78     r_pos++;
     79   }
     80 
     81   if (len != r_pos)
     82   {   /* not full string is printed */
     83       /* enough space for "..." ? */
     84     if (w_pos + 3 > buf_size)
     85       w_pos = buf_size - 4;
     86     buf[w_pos++] = '.';
     87     buf[w_pos++] = '.';
     88     buf[w_pos++] = '.';
     89   }
     90   buf[w_pos] = 0;
     91   return buf;
     92 }
     93 
     94 
     95 #define TEST_BIN_MAX_SIZE 1024
     96 
     97 /* return zero if succeed, number of failures otherwise */
     98 static unsigned int
     99 expect_decoded_n (const char *const encoded, const size_t encoded_len,
    100                   const char *const decoded, const size_t decoded_size,
    101                   const unsigned int line_num)
    102 {
    103   static const char fill_chr = '#';
    104   static char buf[TEST_BIN_MAX_SIZE];
    105   size_t res_size;
    106   unsigned int ret;
    107 
    108   mhd_assert (NULL != encoded);
    109   mhd_assert (NULL != decoded);
    110   mhd_assert (TEST_BIN_MAX_SIZE > decoded_size + 1);
    111   mhd_assert (TEST_BIN_MAX_SIZE > encoded_len + 1);
    112   mhd_assert (encoded_len >= decoded_size);
    113 
    114   ret = 0;
    115 
    116   /* check mhd_str_pct_decode_strict_n() with small out buffer */
    117   if (1)
    118   {
    119     unsigned int check_res = 0;
    120 
    121     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    122     res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf,
    123                                             decoded_size + 1);
    124     if (res_size != decoded_size)
    125     {
    126       check_res = 1;
    127       fprintf (stderr,
    128                "'mhd_str_pct_decode_strict_n ()' FAILED: "
    129                "Wrong returned value:\n");
    130     }
    131     else
    132     {
    133       if (fill_chr != buf[res_size])
    134       {
    135         check_res = 1;
    136         fprintf (stderr,
    137                  "'mhd_str_pct_decode_strict_n ()' FAILED: "
    138                  "A char written outside the buffer:\n");
    139       }
    140       else
    141       {
    142         memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    143         res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf,
    144                                                 decoded_size);
    145         if (res_size != decoded_size)
    146         {
    147           check_res = 1;
    148           fprintf (stderr,
    149                    "'mhd_str_pct_decode_strict_n ()' FAILED: "
    150                    "Wrong returned value:\n");
    151         }
    152       }
    153       if ((res_size == decoded_size) && (0 != decoded_size) &&
    154           (0 != memcmp (buf, decoded, decoded_size)))
    155       {
    156         check_res = 1;
    157         fprintf (stderr,
    158                  "'mhd_str_pct_decode_strict_n ()' FAILED: "
    159                  "Wrong output string:\n");
    160       }
    161     }
    162     if (0 != check_res)
    163     {
    164       ret++;
    165       fprintf (stderr,
    166                "\tRESULT  : mhd_str_pct_decode_strict_n (\"%s\", %u, "
    167                "->\"%s\", %u) -> %u\n",
    168                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    169                n_prnt (buf, res_size), (unsigned) decoded_size,
    170                (unsigned) res_size);
    171       fprintf (stderr,
    172                "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, "
    173                "->\"%s\", %u) -> %u\n",
    174                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    175                n_prnt (decoded, decoded_size), (unsigned) decoded_size,
    176                (unsigned) decoded_size);
    177     }
    178   }
    179 
    180   /* check mhd_str_pct_decode_strict_n() with large out buffer */
    181   if (1)
    182   {
    183     unsigned int check_res = 0;
    184 
    185     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    186     res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf,
    187                                             encoded_len + 1);
    188     if (res_size != decoded_size)
    189     {
    190       check_res = 1;
    191       fprintf (stderr,
    192                "'mhd_str_pct_decode_strict_n ()' FAILED: "
    193                "Wrong returned value:\n");
    194     }
    195     else
    196     {
    197       if (fill_chr != buf[res_size])
    198       {
    199         check_res = 1;
    200         fprintf (stderr,
    201                  "'mhd_str_pct_decode_strict_n ()' FAILED: "
    202                  "A char written outside the buffer:\n");
    203       }
    204       if ((res_size == decoded_size) && (0 != decoded_size) &&
    205           (0 != memcmp (buf, decoded, decoded_size)))
    206       {
    207         check_res = 1;
    208         fprintf (stderr,
    209                  "'mhd_str_pct_decode_strict_n ()' FAILED: "
    210                  "Wrong output string:\n");
    211       }
    212     }
    213     if (0 != check_res)
    214     {
    215       ret++;
    216       fprintf (stderr,
    217                "\tRESULT  : mhd_str_pct_decode_strict_n (\"%s\", %u, "
    218                "->\"%s\", %u) -> %u\n",
    219                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    220                n_prnt (buf, res_size), (unsigned) (encoded_len + 1),
    221                (unsigned) res_size);
    222       fprintf (stderr,
    223                "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, "
    224                "->\"%s\", %u) -> %u\n",
    225                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    226                n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1),
    227                (unsigned) decoded_size);
    228     }
    229   }
    230 
    231   /* check mhd_str_pct_decode_lenient_n() with small out buffer */
    232   if (1)
    233   {
    234     unsigned int check_res = 0;
    235     bool is_broken = true;
    236 
    237     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    238     res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf,
    239                                              decoded_size + 1, &is_broken);
    240     if (res_size != decoded_size)
    241     {
    242       check_res = 1;
    243       fprintf (stderr,
    244                "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    245                "Wrong returned value:\n");
    246     }
    247     else
    248     {
    249       if (fill_chr != buf[res_size])
    250       {
    251         check_res = 1;
    252         fprintf (stderr,
    253                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    254                  "A char written outside the buffer:\n");
    255       }
    256       else
    257       {
    258         is_broken = true;
    259         memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    260         res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf,
    261                                                  decoded_size, &is_broken);
    262         if (res_size != decoded_size)
    263         {
    264           check_res = 1;
    265           fprintf (stderr,
    266                    "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    267                    "Wrong returned value:\n");
    268         }
    269       }
    270       if (is_broken)
    271       {
    272         check_res = 1;
    273         fprintf (stderr,
    274                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    275                  "Wrong 'broken_encoding' result:\n");
    276       }
    277       if ((res_size == decoded_size) && (0 != decoded_size) &&
    278           (0 != memcmp (buf, decoded, decoded_size)))
    279       {
    280         check_res = 1;
    281         fprintf (stderr,
    282                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    283                  "Wrong output string:\n");
    284       }
    285     }
    286     if (0 != check_res)
    287     {
    288       ret++;
    289       fprintf (stderr,
    290                "\tRESULT  : mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    291                "->\"%s\", %u, ->%s) -> %u\n",
    292                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    293                n_prnt (buf, res_size), (unsigned) decoded_size,
    294                is_broken ? "true" : "false",
    295                (unsigned) res_size);
    296       fprintf (stderr,
    297                "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    298                "->\"%s\", %u, ->false) -> %u\n",
    299                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    300                n_prnt (decoded, decoded_size), (unsigned) decoded_size,
    301                (unsigned) decoded_size);
    302     }
    303   }
    304 
    305   /* check mhd_str_pct_decode_lenient_n() with large out buffer */
    306   if (1)
    307   {
    308     unsigned int check_res = 0;
    309     bool is_broken = true;
    310 
    311     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    312     res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf,
    313                                              encoded_len + 1, &is_broken);
    314     if (res_size != decoded_size)
    315     {
    316       check_res = 1;
    317       fprintf (stderr,
    318                "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    319                "Wrong returned value:\n");
    320     }
    321     else
    322     {
    323       if (fill_chr != buf[res_size])
    324       {
    325         check_res = 1;
    326         fprintf (stderr,
    327                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    328                  "A char written outside the buffer:\n");
    329       }
    330       if (is_broken)
    331       {
    332         check_res = 1;
    333         fprintf (stderr,
    334                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    335                  "Wrong 'broken_encoding' result:\n");
    336       }
    337       if ((res_size == decoded_size) && (0 != decoded_size) &&
    338           (0 != memcmp (buf, decoded, decoded_size)))
    339       {
    340         check_res = 1;
    341         fprintf (stderr,
    342                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    343                  "Wrong output string:\n");
    344       }
    345     }
    346     if (0 != check_res)
    347     {
    348       ret++;
    349       fprintf (stderr,
    350                "\tRESULT  : mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    351                "->\"%s\", %u, ->%s) -> %u\n",
    352                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    353                n_prnt (buf, res_size), (unsigned) (encoded_len + 1),
    354                is_broken ? "true" : "false",
    355                (unsigned) res_size);
    356       fprintf (stderr,
    357                "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    358                "->\"%s\", %u, ->false) -> %u\n",
    359                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    360                n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1),
    361                (unsigned) decoded_size);
    362     }
    363   }
    364 
    365   if (strlen (encoded) == encoded_len)
    366   {
    367     /* check mhd_str_pct_decode_in_place_strict() */
    368     if (1)
    369     {
    370       unsigned int check_res = 0;
    371 
    372       memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    373       memcpy (buf, encoded, encoded_len);
    374       buf[encoded_len] = 0;
    375       res_size = mhd_str_pct_decode_in_place_strict (buf);
    376       if (res_size != decoded_size)
    377       {
    378         check_res = 1;
    379         fprintf (stderr,
    380                  "'mhd_str_pct_decode_in_place_strict ()' FAILED: "
    381                  "Wrong returned value:\n");
    382       }
    383       else
    384       {
    385         if (0 != buf[res_size])
    386         {
    387           check_res = 1;
    388           fprintf (stderr,
    389                    "'mhd_str_pct_decode_in_place_strict ()' FAILED: "
    390                    "The result is not zero-terminated:\n");
    391         }
    392         if (((res_size + 1) < encoded_len) ?
    393             (encoded[res_size + 1] != buf[res_size + 1]) :
    394             (fill_chr != buf[res_size + 1]))
    395         {
    396           check_res = 1;
    397           fprintf (stderr,
    398                    "'mhd_str_pct_decode_in_place_strict ()' FAILED: "
    399                    "A char written outside the buffer:\n");
    400         }
    401         if ((res_size == decoded_size) && (0 != decoded_size) &&
    402             (0 != memcmp (buf, decoded, decoded_size)))
    403         {
    404           check_res = 1;
    405           fprintf (stderr,
    406                    "'mhd_str_pct_decode_in_place_strict ()' FAILED: "
    407                    "Wrong output string:\n");
    408         }
    409       }
    410       if (0 != check_res)
    411       {
    412         ret++;
    413         fprintf (stderr,
    414                  "\tRESULT  : mhd_str_pct_decode_in_place_strict (\"%s\" "
    415                  "-> \"%s\") -> %u\n",
    416                  n_prnt (encoded, encoded_len),
    417                  n_prnt (buf, res_size),
    418                  (unsigned) res_size);
    419         fprintf (stderr,
    420                  "\tEXPECTED: mhd_str_pct_decode_in_place_strict (\"%s\" "
    421                  "-> \"%s\") -> %u\n",
    422                  n_prnt (encoded, encoded_len),
    423                  n_prnt (decoded, decoded_size),
    424                  (unsigned) decoded_size);
    425       }
    426     }
    427 
    428     /* check mhd_str_pct_decode_in_place_lenient() */
    429     if (1)
    430     {
    431       unsigned int check_res = 0;
    432       bool is_broken = true;
    433 
    434       memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    435       memcpy (buf, encoded, encoded_len);
    436       buf[encoded_len] = 0;
    437       res_size = mhd_str_pct_decode_in_place_lenient (buf, &is_broken);
    438       if (res_size != decoded_size)
    439       {
    440         check_res = 1;
    441         fprintf (stderr,
    442                  "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    443                  "Wrong returned value:\n");
    444       }
    445       else
    446       {
    447         if (0 != buf[res_size])
    448         {
    449           check_res = 1;
    450           fprintf (stderr,
    451                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    452                    "The result is not zero-terminated:\n");
    453         }
    454         if (((res_size + 1) < encoded_len) ?
    455             (encoded[res_size + 1] != buf[res_size + 1]) :
    456             (fill_chr != buf[res_size + 1]))
    457         {
    458           check_res = 1;
    459           fprintf (stderr,
    460                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    461                    "A char written outside the buffer:\n");
    462         }
    463         if (is_broken)
    464         {
    465           check_res = 1;
    466           fprintf (stderr,
    467                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    468                    "Wrong 'broken_encoding' result:\n");
    469         }
    470         if ((res_size == decoded_size) && (0 != decoded_size) &&
    471             (0 != memcmp (buf, decoded, decoded_size)))
    472         {
    473           check_res = 1;
    474           fprintf (stderr,
    475                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    476                    "Wrong output string:\n");
    477         }
    478       }
    479       if (0 != check_res)
    480       {
    481         ret++;
    482         fprintf (stderr,
    483                  "\tRESULT  : mhd_str_pct_decode_in_place_lenient (\"%s\" "
    484                  "-> \"%s\", ->%s) -> %u\n",
    485                  n_prnt (encoded, encoded_len),
    486                  n_prnt (buf, res_size),
    487                  is_broken ? "true" : "false",
    488                  (unsigned) res_size);
    489         fprintf (stderr,
    490                  "\tEXPECTED: mhd_str_pct_decode_in_place_lenient (\"%s\" "
    491                  "-> \"%s\", ->false) -> %u\n",
    492                  n_prnt (encoded, encoded_len),
    493                  n_prnt (decoded, decoded_size),
    494                  (unsigned) decoded_size);
    495       }
    496     }
    497   }
    498 
    499   if (0 != ret)
    500   {
    501     fprintf (stderr,
    502              "The check is at line: %u\n\n", line_num);
    503   }
    504   return ret;
    505 }
    506 
    507 
    508 #define expect_decoded(e,d) \
    509         expect_decoded_n (e,MHD_STATICSTR_LEN_ (e), \
    510                           d,MHD_STATICSTR_LEN_ (d), \
    511                           __LINE__)
    512 
    513 static unsigned int
    514 check_decode_str (void)
    515 {
    516   unsigned int r = 0; /**< The number of errors */
    517 
    518   r += expect_decoded ("", "");
    519 
    520   /* Base sequences without percent symbol */
    521   r += expect_decoded ("aaa", "aaa");
    522   r += expect_decoded ("bbb", "bbb");
    523   r += expect_decoded ("ccc", "ccc");
    524   r += expect_decoded ("ddd", "ddd");
    525   r += expect_decoded ("lll", "lll");
    526   r += expect_decoded ("mmm", "mmm");
    527   r += expect_decoded ("nnn", "nnn");
    528   r += expect_decoded ("ooo", "ooo");
    529   r += expect_decoded ("www", "www");
    530   r += expect_decoded ("xxx", "xxx");
    531   r += expect_decoded ("yyy", "yyy");
    532   r += expect_decoded ("zzz", "zzz");
    533   r += expect_decoded ("AAA", "AAA");
    534   r += expect_decoded ("GGG", "GGG");
    535   r += expect_decoded ("MMM", "MMM");
    536   r += expect_decoded ("TTT", "TTT");
    537   r += expect_decoded ("ZZZ", "ZZZ");
    538   r += expect_decoded ("012", "012");
    539   r += expect_decoded ("345", "345");
    540   r += expect_decoded ("678", "678");
    541   r += expect_decoded ("901", "901");
    542   r += expect_decoded ("aaaaaa", "aaaaaa");
    543   r += expect_decoded ("bbbbbb", "bbbbbb");
    544   r += expect_decoded ("cccccc", "cccccc");
    545   r += expect_decoded ("dddddd", "dddddd");
    546   r += expect_decoded ("llllll", "llllll");
    547   r += expect_decoded ("mmmmmm", "mmmmmm");
    548   r += expect_decoded ("nnnnnn", "nnnnnn");
    549   r += expect_decoded ("oooooo", "oooooo");
    550   r += expect_decoded ("wwwwww", "wwwwww");
    551   r += expect_decoded ("xxxxxx", "xxxxxx");
    552   r += expect_decoded ("yyyyyy", "yyyyyy");
    553   r += expect_decoded ("zzzzzz", "zzzzzz");
    554   r += expect_decoded ("AAAAAA", "AAAAAA");
    555   r += expect_decoded ("GGGGGG", "GGGGGG");
    556   r += expect_decoded ("MMMMMM", "MMMMMM");
    557   r += expect_decoded ("TTTTTT", "TTTTTT");
    558   r += expect_decoded ("ZZZZZZ", "ZZZZZZ");
    559   r += expect_decoded ("012012", "012012");
    560   r += expect_decoded ("345345", "345345");
    561   r += expect_decoded ("678678", "678678");
    562   r += expect_decoded ("901901", "901901");
    563   r += expect_decoded ("a", "a");
    564   r += expect_decoded ("bc", "bc");
    565   r += expect_decoded ("DEFG", "DEFG");
    566   r += expect_decoded ("123t", "123t");
    567   r += expect_decoded ("12345", "12345");
    568   r += expect_decoded ("TestStr", "TestStr");
    569   r += expect_decoded ("Teststring", "Teststring");
    570   r += expect_decoded ("Teststring.", "Teststring.");
    571   r += expect_decoded ("Longerstring", "Longerstring");
    572   r += expect_decoded ("Longerstring.", "Longerstring.");
    573   r += expect_decoded ("Longerstring2.", "Longerstring2.");
    574 
    575   /* Simple percent-encoded strings */
    576   r += expect_decoded ("Test%20string", "Test string");
    577   r += expect_decoded ("Test%3Fstring.", "Test?string.");
    578   r += expect_decoded ("100%25", "100%");
    579   r += expect_decoded ("a%2C%20b%3Dc%26e%3Dg", "a, b=c&e=g");
    580   r += expect_decoded ("%20%21%23%24%25%26%27%28%29%2A%2B%2C"
    581                        "%2F%3A%3B%3D%3F%40%5B%5D%09",
    582                        " !#$%&'()*+,/:;=?@[]\t");
    583 
    584   return r;
    585 }
    586 
    587 
    588 #define expect_decoded_arr(e,a) \
    589         expect_decoded_n (e,MHD_STATICSTR_LEN_ (e), \
    590                           (const char *) a,(sizeof(a) / sizeof(a[0])), \
    591                           __LINE__)
    592 
    593 static unsigned int
    594 check_decode_bin (void)
    595 {
    596   unsigned int r = 0; /**< The number of errors */
    597 
    598   if (1)
    599   {
    600     static const uint8_t bin[256] =
    601     {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
    602      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
    603      0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    604      0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    605      0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    606      0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
    607      0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
    608      0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
    609      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    610      0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
    611      0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
    612      0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
    613      0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
    614      0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
    615      0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
    616      0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
    617      0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
    618      0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
    619      0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
    620      0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
    621      0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
    622      0xff };
    623     /* The lower case */
    624     r += expect_decoded_arr ("%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e" \
    625                              "%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d" \
    626                              "%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c" \
    627                              "%2d%2e%2f%30%31%32%33%34%35%36%37%38%39%3a%3b" \
    628                              "%3c%3d%3e%3f%40%41%42%43%44%45%46%47%48%49%4a" \
    629                              "%4b%4c%4d%4e%4f%50%51%52%53%54%55%56%57%58%59" \
    630                              "%5a%5b%5c%5d%5e%5f%60%61%62%63%64%65%66%67%68" \
    631                              "%69%6a%6b%6c%6d%6e%6f%70%71%72%73%74%75%76%77" \
    632                              "%78%79%7a%7b%7c%7d%7e%7f%80%81%82%83%84%85%86" \
    633                              "%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95" \
    634                              "%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4" \
    635                              "%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3" \
    636                              "%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2" \
    637                              "%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1" \
    638                              "%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0" \
    639                              "%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef" \
    640                              "%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe" \
    641                              "%ff", bin);
    642   }
    643 
    644   if (1)
    645   {
    646     static const uint8_t bin[256] =
    647     {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
    648      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
    649      0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    650      0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    651      0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    652      0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
    653      0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
    654      0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
    655      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    656      0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
    657      0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
    658      0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
    659      0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
    660      0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
    661      0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
    662      0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
    663      0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
    664      0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
    665      0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
    666      0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
    667      0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
    668      0xff };
    669     /* The upper case */
    670     r += expect_decoded_arr ("%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E" \
    671                              "%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D" \
    672                              "%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C" \
    673                              "%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B" \
    674                              "%3C%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A" \
    675                              "%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59" \
    676                              "%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68" \
    677                              "%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77" \
    678                              "%78%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86" \
    679                              "%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95" \
    680                              "%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4" \
    681                              "%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3" \
    682                              "%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2" \
    683                              "%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1" \
    684                              "%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0" \
    685                              "%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" \
    686                              "%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE" \
    687                              "%FF", bin);
    688   }
    689 
    690   return r;
    691 }
    692 
    693 
    694 /* return zero if succeed, number of failures otherwise */
    695 static unsigned int
    696 expect_decoded_bad_n (const char *const encoded, const size_t encoded_len,
    697                       const char *const decoded, const size_t decoded_size,
    698                       const unsigned int line_num)
    699 {
    700   static const char fill_chr = '#';
    701   static char buf[TEST_BIN_MAX_SIZE];
    702   size_t res_size;
    703   unsigned int ret;
    704 
    705   mhd_assert (NULL != encoded);
    706   mhd_assert (NULL != decoded);
    707   mhd_assert (TEST_BIN_MAX_SIZE > decoded_size + 1);
    708   mhd_assert (TEST_BIN_MAX_SIZE > encoded_len + 1);
    709   mhd_assert (encoded_len >= decoded_size);
    710 
    711   ret = 0;
    712 
    713   /* check mhd_str_pct_decode_strict_n() with small out buffer */
    714   if (1)
    715   {
    716     unsigned int check_res = 0;
    717 
    718     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    719     res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf,
    720                                             decoded_size);
    721     if (res_size != 0)
    722     {
    723       check_res = 1;
    724       fprintf (stderr,
    725                "'mhd_str_pct_decode_strict_n ()' FAILED: "
    726                "Wrong returned value:\n");
    727     }
    728     if (0 != check_res)
    729     {
    730       ret++;
    731       fprintf (stderr,
    732                "\tRESULT  : mhd_str_pct_decode_strict_n (\"%s\", %u, "
    733                "->\"%s\", %u) -> %u\n",
    734                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    735                n_prnt (buf, res_size), (unsigned) decoded_size,
    736                (unsigned) res_size);
    737       fprintf (stderr,
    738                "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, "
    739                "->(not defined), %u) -> 0\n",
    740                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    741                (unsigned) decoded_size);
    742     }
    743   }
    744 
    745   /* check mhd_str_pct_decode_strict_n() with large out buffer */
    746   if (1)
    747   {
    748     unsigned int check_res = 0;
    749 
    750     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    751     res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf,
    752                                             encoded_len + 1);
    753     if (res_size != 0)
    754     {
    755       check_res = 1;
    756       fprintf (stderr,
    757                "'mhd_str_pct_decode_strict_n ()' FAILED: "
    758                "Wrong returned value:\n");
    759     }
    760     if (0 != check_res)
    761     {
    762       ret++;
    763       fprintf (stderr,
    764                "\tRESULT  : mhd_str_pct_decode_strict_n (\"%s\", %u, "
    765                "->\"%s\", %u) -> %u\n",
    766                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    767                n_prnt (buf, res_size), (unsigned) (encoded_len + 1),
    768                (unsigned) res_size);
    769       fprintf (stderr,
    770                "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, "
    771                "->(not defined), %u) -> 0\n",
    772                n_prnt (encoded, encoded_len), (unsigned) (encoded_len + 1),
    773                (unsigned) decoded_size);
    774     }
    775   }
    776 
    777   /* check mhd_str_pct_decode_lenient_n() with small out buffer */
    778   if (1)
    779   {
    780     unsigned int check_res = 0;
    781     bool is_broken = false;
    782 
    783     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    784     res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf,
    785                                              decoded_size + 1, &is_broken);
    786     if (res_size != decoded_size)
    787     {
    788       check_res = 1;
    789       fprintf (stderr,
    790                "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    791                "Wrong returned value:\n");
    792     }
    793     else
    794     {
    795       if (fill_chr != buf[res_size])
    796       {
    797         check_res = 1;
    798         fprintf (stderr,
    799                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    800                  "A char written outside the buffer:\n");
    801       }
    802       else
    803       {
    804         is_broken = false;
    805         memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    806         res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf,
    807                                                  decoded_size, &is_broken);
    808         if (res_size != decoded_size)
    809         {
    810           check_res = 1;
    811           fprintf (stderr,
    812                    "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    813                    "Wrong returned value:\n");
    814         }
    815       }
    816       if (! is_broken)
    817       {
    818         check_res = 1;
    819         fprintf (stderr,
    820                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    821                  "Wrong 'broken_encoding' result:\n");
    822       }
    823       if ((res_size == decoded_size) && (0 != decoded_size) &&
    824           (0 != memcmp (buf, decoded, decoded_size)))
    825       {
    826         check_res = 1;
    827         fprintf (stderr,
    828                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    829                  "Wrong output string:\n");
    830       }
    831     }
    832     if (0 != check_res)
    833     {
    834       ret++;
    835       fprintf (stderr,
    836                "\tRESULT  : mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    837                "->\"%s\", %u, ->%s) -> %u\n",
    838                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    839                n_prnt (buf, res_size), (unsigned) decoded_size,
    840                is_broken ? "true" : "false",
    841                (unsigned) res_size);
    842       fprintf (stderr,
    843                "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    844                "->\"%s\", %u, ->true) -> %u\n",
    845                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    846                n_prnt (decoded, decoded_size), (unsigned) decoded_size,
    847                (unsigned) decoded_size);
    848     }
    849   }
    850 
    851   /* check mhd_str_pct_decode_lenient_n() with large out buffer */
    852   if (1)
    853   {
    854     unsigned int check_res = 0;
    855     bool is_broken = false;
    856 
    857     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    858     res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf,
    859                                              encoded_len + 1, &is_broken);
    860     if (res_size != decoded_size)
    861     {
    862       check_res = 1;
    863       fprintf (stderr,
    864                "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    865                "Wrong returned value:\n");
    866     }
    867     else
    868     {
    869       if (fill_chr != buf[res_size])
    870       {
    871         check_res = 1;
    872         fprintf (stderr,
    873                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    874                  "A char written outside the buffer:\n");
    875       }
    876       if (! is_broken)
    877       {
    878         check_res = 1;
    879         fprintf (stderr,
    880                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    881                  "Wrong 'broken_encoding' result:\n");
    882       }
    883       if ((res_size == decoded_size) && (0 != decoded_size) &&
    884           (0 != memcmp (buf, decoded, decoded_size)))
    885       {
    886         check_res = 1;
    887         fprintf (stderr,
    888                  "'mhd_str_pct_decode_lenient_n ()' FAILED: "
    889                  "Wrong output string:\n");
    890       }
    891     }
    892     if (0 != check_res)
    893     {
    894       ret++;
    895       fprintf (stderr,
    896                "\tRESULT  : mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    897                "->\"%s\", %u, ->%s) -> %u\n",
    898                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    899                n_prnt (buf, res_size), (unsigned) (encoded_len + 1),
    900                is_broken ? "true" : "false",
    901                (unsigned) res_size);
    902       fprintf (stderr,
    903                "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, "
    904                "->\"%s\", %u, ->true) -> %u\n",
    905                n_prnt (encoded, encoded_len), (unsigned) encoded_len,
    906                n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1),
    907                (unsigned) decoded_size);
    908     }
    909   }
    910 
    911   if (strlen (encoded) == encoded_len)
    912   {
    913     /* check mhd_str_pct_decode_in_place_strict() */
    914     if (1)
    915     {
    916       unsigned int check_res = 0;
    917 
    918       memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    919       memcpy (buf, encoded, encoded_len);
    920       buf[encoded_len] = 0;
    921       res_size = mhd_str_pct_decode_in_place_strict (buf);
    922       if (res_size != 0)
    923       {
    924         check_res = 1;
    925         fprintf (stderr,
    926                  "'mhd_str_pct_decode_in_place_strict ()' FAILED: "
    927                  "Wrong returned value:\n");
    928       }
    929       if (0 != check_res)
    930       {
    931         ret++;
    932         fprintf (stderr,
    933                  "\tRESULT  : mhd_str_pct_decode_in_place_strict (\"%s\" "
    934                  "-> \"%s\") -> %u\n",
    935                  n_prnt (encoded, encoded_len),
    936                  n_prnt (buf, res_size),
    937                  (unsigned) res_size);
    938         fprintf (stderr,
    939                  "\tEXPECTED: mhd_str_pct_decode_in_place_strict (\"%s\" "
    940                  "-> (not defined)) -> 0\n",
    941                  n_prnt (encoded, encoded_len));
    942       }
    943     }
    944 
    945     /* check mhd_str_pct_decode_in_place_lenient() */
    946     if (1)
    947     {
    948       unsigned int check_res = 0;
    949       bool is_broken = false;
    950 
    951       memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    952       memcpy (buf, encoded, encoded_len);
    953       buf[encoded_len] = 0;
    954       res_size = mhd_str_pct_decode_in_place_lenient (buf, &is_broken);
    955       if (res_size != decoded_size)
    956       {
    957         check_res = 1;
    958         fprintf (stderr,
    959                  "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    960                  "Wrong returned value:\n");
    961       }
    962       else
    963       {
    964         if (0 != buf[res_size])
    965         {
    966           check_res = 1;
    967           fprintf (stderr,
    968                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    969                    "The result is not zero-terminated:\n");
    970         }
    971         if (((res_size + 1) < encoded_len) ?
    972             (encoded[res_size + 1] != buf[res_size + 1]) :
    973             (fill_chr != buf[res_size + 1]))
    974         {
    975           check_res = 1;
    976           fprintf (stderr,
    977                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    978                    "A char written outside the buffer:\n");
    979         }
    980         if (! is_broken)
    981         {
    982           check_res = 1;
    983           fprintf (stderr,
    984                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    985                    "Wrong 'broken_encoding' result:\n");
    986         }
    987         if ((res_size == decoded_size) && (0 != decoded_size) &&
    988             (0 != memcmp (buf, decoded, decoded_size)))
    989         {
    990           check_res = 1;
    991           fprintf (stderr,
    992                    "'mhd_str_pct_decode_in_place_lenient ()' FAILED: "
    993                    "Wrong output string:\n");
    994         }
    995       }
    996       if (0 != check_res)
    997       {
    998         ret++;
    999         fprintf (stderr,
   1000                  "\tRESULT  : mhd_str_pct_decode_in_place_lenient (\"%s\" "
   1001                  "-> \"%s\", ->%s) -> %u\n",
   1002                  n_prnt (encoded, encoded_len),
   1003                  n_prnt (buf, res_size),
   1004                  is_broken ? "true" : "false",
   1005                  (unsigned) res_size);
   1006         fprintf (stderr,
   1007                  "\tEXPECTED: mhd_str_pct_decode_in_place_lenient (\"%s\" "
   1008                  "-> \"%s\", ->true) -> %u\n",
   1009                  n_prnt (encoded, encoded_len),
   1010                  n_prnt (decoded, decoded_size),
   1011                  (unsigned) decoded_size);
   1012       }
   1013     }
   1014   }
   1015 
   1016   if (0 != ret)
   1017   {
   1018     fprintf (stderr,
   1019              "The check is at line: %u\n\n", line_num);
   1020   }
   1021   return ret;
   1022 }
   1023 
   1024 
   1025 #define expect_decoded_bad(e,d) \
   1026         expect_decoded_bad_n (e,MHD_STATICSTR_LEN_ (e), \
   1027                               d,MHD_STATICSTR_LEN_ (d), \
   1028                               __LINE__)
   1029 
   1030 static unsigned int
   1031 check_decode_bad_str (void)
   1032 {
   1033   unsigned int r = 0; /**< The number of errors */
   1034 
   1035   r += expect_decoded_bad ("50%/50%", "50%/50%");
   1036   r += expect_decoded_bad ("This is 100% incorrect.",
   1037                            "This is 100% incorrect.");
   1038   r += expect_decoded_bad ("Some %%", "Some %%");
   1039   r += expect_decoded_bad ("1 %", "1 %");
   1040   r += expect_decoded_bad ("%", "%");
   1041   r += expect_decoded_bad ("%a", "%a");
   1042   r += expect_decoded_bad ("%0", "%0");
   1043   r += expect_decoded_bad ("%0x", "%0x");
   1044   r += expect_decoded_bad ("%FX", "%FX");
   1045   r += expect_decoded_bad ("Valid%20and%2invalid", "Valid and%2invalid");
   1046 
   1047   return r;
   1048 }
   1049 
   1050 
   1051 int
   1052 main (int argc, char *argv[])
   1053 {
   1054   unsigned int errcount = 0;
   1055   (void) argc; (void) argv; /* Unused. Silent compiler warning. */
   1056   errcount += check_decode_str ();
   1057   errcount += check_decode_bin ();
   1058   errcount += check_decode_bad_str ();
   1059   if (0 == errcount)
   1060     printf ("All tests have been passed without errors.\n");
   1061   return errcount == 0 ? 0 : 1;
   1062 }