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 }