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