libmicrohttpd2

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

test_str_pct.c (38162B)


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