libmicrohttpd2

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

test_str_bin_hex.c (15093B)


      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_bin_hex.c
     22  * @brief  Unit tests for hex strings <-> binary data 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 (2 * 1024)
     95 
     96 /* return zero if succeed, number of failures otherwise */
     97 static unsigned int
     98 expect_decoded_n (const char *const hex, const size_t hex_len,
     99                   const uint8_t *const bin, const size_t bin_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 != hex);
    108   mhd_assert (NULL != bin);
    109   mhd_assert (TEST_BIN_MAX_SIZE > bin_size + 1);
    110   mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1);
    111   mhd_assert (hex_len >= bin_size);
    112   mhd_assert (1 >= hex_len || hex_len > bin_size);
    113 
    114   ret = 0;
    115 
    116   /* check mhd_hex_to_bin() */
    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_hex_to_bin (hex, hex_len, buf);
    123     if (res_size != bin_size)
    124     {
    125       check_res = 1;
    126       fprintf (stderr,
    127                "'MHD_hex_to_bin ()' FAILED: "
    128                "Wrong returned value:\n");
    129     }
    130     else
    131     {
    132       if ((0 != bin_size) &&
    133           (0 != memcmp (buf, bin, bin_size)))
    134       {
    135         check_res = 1;
    136         fprintf (stderr,
    137                  "'MHD_hex_to_bin ()' FAILED: "
    138                  "Wrong output data:\n");
    139       }
    140     }
    141     if (((0 == res_size) && (fill_chr != buf[bin_size]))
    142         || ((0 != res_size) && (fill_chr != buf[res_size])))
    143     {
    144       check_res = 1;
    145       fprintf (stderr,
    146                "'mhd_hex_to_bin ()' FAILED: "
    147                "A char written outside the buffer:\n");
    148     }
    149     if (0 != check_res)
    150     {
    151       ret++;
    152       fprintf (stderr,
    153                "\tRESULT  : mhd_hex_to_bin (\"%s\", %u, "
    154                "->\"%s\") -> %u\n",
    155                n_prnt (hex, hex_len), (unsigned) hex_len,
    156                n_prnt (buf, res_size),
    157                (unsigned) res_size);
    158       fprintf (stderr,
    159                "\tEXPECTED: mhd_hex_to_bin (\"%s\", %u, "
    160                "->\"%s\") -> %u\n",
    161                n_prnt (hex, hex_len), (unsigned) hex_len,
    162                n_prnt ((const char *) bin, bin_size),
    163                (unsigned) bin_size);
    164     }
    165   }
    166 
    167   /* check mhd_bin_to_hex() */
    168   if (0 == hex_len % 2)
    169   {
    170     unsigned int check_res = 0;
    171 
    172     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    173     res_size = mhd_bin_to_hex_z (bin, bin_size, buf);
    174 
    175     if (res_size != hex_len)
    176     {
    177       check_res = 1;
    178       fprintf (stderr,
    179                "'mhd_bin_to_hex ()' FAILED: "
    180                "Wrong returned value:\n");
    181     }
    182     else
    183     {
    184       if ((0 != hex_len) &&
    185           (! mhd_str_equal_caseless_bin_n (buf, hex, hex_len)))
    186       {
    187         check_res = 1;
    188         fprintf (stderr,
    189                  "'mhd_bin_to_hex ()' FAILED: "
    190                  "Wrong output string:\n");
    191       }
    192     }
    193     if (fill_chr != buf[res_size + 1])
    194     {
    195       check_res = 1;
    196       fprintf (stderr,
    197                "'mhd_bin_to_hex ()' FAILED: "
    198                "A char written outside the buffer:\n");
    199     }
    200     if (0 != buf[res_size])
    201     {
    202       check_res = 1;
    203       fprintf (stderr,
    204                "'mhd_bin_to_hex ()' FAILED: "
    205                "The result is not zero-terminated:\n");
    206     }
    207     if (0 != check_res)
    208     {
    209       ret++;
    210       fprintf (stderr,
    211                "\tRESULT  : mhd_bin_to_hex (\"%s\", %u, "
    212                "->\"%s\") -> %u\n",
    213                n_prnt ((const char *) bin, bin_size), (unsigned) bin_size,
    214                n_prnt (buf, res_size),
    215                (unsigned) res_size);
    216       fprintf (stderr,
    217                "\tEXPECTED: mhd_bin_to_hex (\"%s\", %u, "
    218                "->(lower case)\"%s\") -> %u\n",
    219                n_prnt ((const char *) bin, bin_size), (unsigned) bin_size,
    220                n_prnt (hex, hex_len),
    221                (unsigned) bin_size);
    222     }
    223   }
    224 
    225   if (0 != ret)
    226   {
    227     fprintf (stderr,
    228              "The check is at line: %u\n\n", line_num);
    229   }
    230   return ret;
    231 }
    232 
    233 
    234 #define expect_decoded_arr(h,a) \
    235         expect_decoded_n (h,MHD_STATICSTR_LEN_ (h), \
    236                           a,(sizeof(a) / sizeof(a[0])), \
    237                           __LINE__)
    238 
    239 static unsigned int
    240 check_decode_bin (void)
    241 {
    242   unsigned int r = 0; /**< The number of errors */
    243 
    244   if (1)
    245   {
    246     static const uint8_t bin[256] =
    247     {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
    248      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
    249      0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    250      0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    251      0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    252      0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
    253      0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
    254      0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
    255      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    256      0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
    257      0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
    258      0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
    259      0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
    260      0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
    261      0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
    262      0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
    263      0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
    264      0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
    265      0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
    266      0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
    267      0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
    268      0xff };
    269     /* The lower case */
    270     r += expect_decoded_arr ("000102030405060708090a0b0c0d0e" \
    271                              "0f101112131415161718191a1b1c1d" \
    272                              "1e1f202122232425262728292a2b2c" \
    273                              "2d2e2f303132333435363738393a3b" \
    274                              "3c3d3e3f404142434445464748494a" \
    275                              "4b4c4d4e4f50515253545556575859" \
    276                              "5a5b5c5d5e5f606162636465666768" \
    277                              "696a6b6c6d6e6f7071727374757677" \
    278                              "78797a7b7c7d7e7f80818283848586" \
    279                              "8788898a8b8c8d8e8f909192939495" \
    280                              "969798999a9b9c9d9e9fa0a1a2a3a4" \
    281                              "a5a6a7a8a9aaabacadaeafb0b1b2b3" \
    282                              "b4b5b6b7b8b9babbbcbdbebfc0c1c2" \
    283                              "c3c4c5c6c7c8c9cacbcccdcecfd0d1" \
    284                              "d2d3d4d5d6d7d8d9dadbdcdddedfe0" \
    285                              "e1e2e3e4e5e6e7e8e9eaebecedeeef" \
    286                              "f0f1f2f3f4f5f6f7f8f9fafbfcfdfe" \
    287                              "ff", bin);
    288   }
    289 
    290   if (1)
    291   {
    292     static const uint8_t bin[256] =
    293     {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
    294      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
    295      0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    296      0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    297      0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    298      0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
    299      0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
    300      0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
    301      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    302      0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
    303      0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
    304      0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
    305      0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
    306      0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
    307      0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
    308      0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
    309      0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
    310      0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
    311      0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
    312      0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
    313      0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
    314      0xff };
    315     /* The upper case */
    316     r += expect_decoded_arr ("000102030405060708090A0B0C0D0E" \
    317                              "0F101112131415161718191A1B1C1D" \
    318                              "1E1F202122232425262728292A2B2C" \
    319                              "2D2E2F303132333435363738393A3B" \
    320                              "3C3D3E3F404142434445464748494A" \
    321                              "4B4C4D4E4F50515253545556575859" \
    322                              "5A5B5C5D5E5F606162636465666768" \
    323                              "696A6B6C6D6E6F7071727374757677" \
    324                              "78797A7B7C7D7E7F80818283848586" \
    325                              "8788898A8B8C8D8E8F909192939495" \
    326                              "969798999A9B9C9D9E9FA0A1A2A3A4" \
    327                              "A5A6A7A8A9AAABACADAEAFB0B1B2B3" \
    328                              "B4B5B6B7B8B9BABBBCBDBEBFC0C1C2" \
    329                              "C3C4C5C6C7C8C9CACBCCCDCECFD0D1" \
    330                              "D2D3D4D5D6D7D8D9DADBDCDDDEDFE0" \
    331                              "E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" \
    332                              "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" \
    333                              "FF", bin);
    334   }
    335   if (1)
    336   {
    337     static const uint8_t bin[3] =
    338     {0x1, 0x2, 0x3};
    339     r += expect_decoded_arr ("010203", bin);
    340   }
    341   if (1)
    342   {
    343     static const uint8_t bin[3] =
    344     {0x1, 0x2, 0x3};
    345     r += expect_decoded_arr ("10203", bin);
    346   }
    347   if (1)
    348   {
    349     static const uint8_t bin[1] =
    350     {0x1};
    351     r += expect_decoded_arr ("01", bin);
    352   }
    353   if (1)
    354   {
    355     static const uint8_t bin[1] =
    356     {0x1};
    357     r += expect_decoded_arr ("1", bin);
    358   }
    359 
    360   return r;
    361 }
    362 
    363 
    364 /* return zero if succeed, number of failures otherwise */
    365 static unsigned int
    366 expect_failed_n (const char *const hex, const size_t hex_len,
    367                  const unsigned int line_num)
    368 {
    369   static const char fill_chr = '#';
    370   static char buf[TEST_BIN_MAX_SIZE];
    371   size_t res_size;
    372   unsigned int ret;
    373 
    374   mhd_assert (NULL != hex);
    375   mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1);
    376 
    377   ret = 0;
    378 
    379   /* check mhd_hex_to_bin() */
    380   if (1)
    381   {
    382     unsigned int check_res = 0;
    383 
    384     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    385     res_size = mhd_hex_to_bin (hex, hex_len, buf);
    386     if (res_size != 0)
    387     {
    388       check_res = 1;
    389       fprintf (stderr,
    390                "'mhd_hex_to_bin ()' FAILED: "
    391                "Wrong returned value:\n");
    392     }
    393     if (0 != check_res)
    394     {
    395       ret++;
    396       fprintf (stderr,
    397                "\tRESULT  : mhd_hex_to_bin (\"%s\", %u, "
    398                "->\"%s\") -> %u\n",
    399                n_prnt (hex, hex_len), (unsigned) hex_len,
    400                n_prnt (buf, res_size),
    401                (unsigned) res_size);
    402       fprintf (stderr,
    403                "\tEXPECTED: mhd_hex_to_bin (\"%s\", %u, "
    404                "->(not defined)) -> 0\n",
    405                n_prnt (hex, hex_len), (unsigned) hex_len);
    406     }
    407   }
    408 
    409   if (0 != ret)
    410   {
    411     fprintf (stderr,
    412              "The check is at line: %u\n\n", line_num);
    413   }
    414   return ret;
    415 }
    416 
    417 
    418 #define expect_failed(h) \
    419         expect_failed_n (h,MHD_STATICSTR_LEN_ (h), \
    420                          __LINE__)
    421 
    422 
    423 static unsigned int
    424 check_broken_str (void)
    425 {
    426   unsigned int r = 0; /**< The number of errors */
    427 
    428   r += expect_failed ("abcx");
    429   r += expect_failed ("X");
    430   r += expect_failed ("!");
    431   r += expect_failed ("01z");
    432   r += expect_failed ("0z");
    433   r += expect_failed ("00z");
    434   r += expect_failed ("000Y");
    435 
    436   return r;
    437 }
    438 
    439 
    440 int
    441 main (int argc, char *argv[])
    442 {
    443   unsigned int errcount = 0;
    444   (void) argc; (void) argv; /* Unused. Silent compiler warning. */
    445   errcount += check_decode_bin ();
    446   errcount += check_broken_str ();
    447   if (0 == errcount)
    448     printf ("All tests have been passed without errors.\n");
    449   return errcount == 0 ? 0 : 1;
    450 }