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 }