libmicrohttpd2

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

unit_str_bin_hex.c (15082B)


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