libmicrohttpd2

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

commit 2752c3eddc34e3024696153aeb0c65297d57a11f
parent 0688507f0d5eafbba86beec15382922789a5ee73
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Mon,  1 Dec 2025 13:27:42 +0100

add string tests, one fails

Diffstat:
Mcontrib/precommit_hook.sh | 4++--
Msrc/tests/unit/Makefile.am | 31++++++++++++++++++++++++++++++-
Asrc/tests/unit/test_helpers.h | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_sha256.c | 547+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_sha512_256.c | 602+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_base64.c | 795+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_bin_hex.c | 450+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_compare.c | 879+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_from_value.c | 1815+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_pct.c | 1061+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_quote.c | 798+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_to_value.c | 2614+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_token.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_token_remove.c | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests/unit/test_str_tokens_remove.c | 291++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/tests/unit/unit_md5.c | 157+++++++++++++++++++++++++++++++++++++++----------------------------------------
Asrc/tests/unit/unit_str.c | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 10590 insertions(+), 83 deletions(-)

diff --git a/contrib/precommit_hook.sh b/contrib/precommit_hook.sh @@ -13,8 +13,8 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -# Enable 'pipefail' if supported -set -o pipefail 2>/dev/null || : +# Enable 'pipefail' if supported -- this breaks git commit if -o piefail is not supported! +# set -o pipefail 2>/dev/null || : # Redirect all output to stderr exec 1>&2 diff --git a/src/tests/unit/Makefile.am b/src/tests/unit/Makefile.am @@ -27,7 +27,15 @@ endif LDADD = $(MHD_LIBDEPS) check_PROGRAMS = \ - $(EMPTY_ITEM) + test_str_compare \ + test_str_to_value \ + test_str_from_value \ + test_str_token \ + test_str_token_remove \ + test_str_tokens_remove \ + test_str_pct \ + test_str_bin_hex \ + unit_str if MHD_SUPPORT_HTTP2 check_PROGRAMS += \ @@ -46,6 +54,26 @@ endif TESTS = $(check_PROGRAMS) +unit_str_SOURCES = unit_str.c + +test_str_compare_SOURCES = \ + test_str_compare.c test_helpers.h + +test_str_to_value_SOURCES = \ + test_str_to_value.c test_helpers.h + +test_str_from_value_SOURCES = \ + test_str_from_value.c test_helpers.h + +test_str_token_SOURCES = \ + test_str_token.c + +test_str_token_remove_SOURCES = \ + test_str_token_remove.c + +test_str_tokens_remove_SOURCES = \ + test_str_tokens_remove.c + unit_h2_huffman_encode_SOURCES = \ unit_h2_huffman_codec.c \ $(srcdir)/../mhdt_has_in_name.h \ @@ -64,6 +92,7 @@ unit_hpack_tables_static_SOURCES = $(unit_hpack_tables_dynamic_SOURCES) unit_hpack_tables_combined_SOURCES = $(unit_hpack_tables_dynamic_SOURCES) + unit_md5_SOURCES = unit_md5.c if MHD_MD5_EXTR diff --git a/src/tests/unit/test_helpers.h b/src/tests/unit/test_helpers.h @@ -0,0 +1,92 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2016 Karlson2k (Evgeny Grin) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_helpers.h + * @brief Static functions and macros helpers for testsuite. + * @author Karlson2k (Evgeny Grin) + */ + +#include <string.h> + +/** + * Check whether program name contains specific @a marker string. + * Only last component in pathname is checked for marker presence, + * all leading directories names (if any) are ignored. Directories + * separators are handled correctly on both non-W32 and W32 + * platforms. + * @param prog_name program name, may include path + * @param marker marker to look for. + * @return zero if any parameter is NULL or empty string or + * @a prog_name ends with slash or @a marker is not found in + * program name, non-zero if @a maker is found in program + * name. + */ +static int +has_in_name (const char *prog_name, const char *marker) +{ + size_t name_pos; + size_t pos; + + if (! prog_name || ! marker || ! prog_name[0] || ! marker[0]) + return 0; + + pos = 0; + name_pos = 0; + while (prog_name[pos]) + { + if ('/' == prog_name[pos]) + name_pos = pos + 1; +#if defined(_WIN32) || defined(__CYGWIN__) + else if ('\\' == prog_name[pos]) + name_pos = pos + 1; +#endif /* _WIN32 || __CYGWIN__ */ + pos++; + } + if (name_pos == pos) + return 0; + return strstr (prog_name + name_pos, marker) != (char *) 0; +} + + +/** + * Check whether one of strings in array is equal to @a param. + * String @a argv[0] is ignored. + * @param argc number of strings in @a argv, as passed to main function + * @param argv array of strings, as passed to main function + * @param param parameter to look for. + * @return zero if @a argv is NULL, @a param is NULL or empty string, + * @a argc is less then 2 or @a param is not found in @a argv, + * non-zero if one of strings in @a argv is equal to @a param. + */ +static int +has_param (int argc, char *const argv[], const char *param) +{ + int i; + if (! argv || ! param || ! param[0]) + return 0; + + for (i = 1; i < argc; i++) + { + if (argv[i] && (strcmp (argv[i], param) == 0) ) + return ! 0; + } + + return 0; +} diff --git a/src/tests/unit/test_sha256.c b/src/tests/unit/test_sha256.c @@ -0,0 +1,547 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2019-2023 Evgeny Grin (Karlson2k) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_sha256.h + * @brief Unit tests for SHA-256 functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_options.h" +#include "mhd_sha256_wrap.h" +#include "test_helpers.h" +#include <stdio.h> +#include <stdlib.h> + +#if defined(MHD_SHA256_TLSLIB) && defined(MHD_HTTPS_REQUIRE_GCRYPT) +#define NEED_GCRYP_INIT 1 +#include <gcrypt.h> +#endif /* MHD_SHA256_TLSLIB && MHD_HTTPS_REQUIRE_GCRYPT */ + +static int verbose = 0; /* verbose level (0-1)*/ + + +struct str_with_len +{ + const char *const str; + const size_t len; +}; + +#define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} + +struct data_unit1 +{ + const struct str_with_len str_l; + const uint8_t digest[SHA256_DIGEST_SIZE]; +}; + +static const struct data_unit1 data_units1[] = { + {D_STR_W_LEN ("abc"), + {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, + 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, + 0xf2, 0x00, 0x15, 0xad}}, + {D_STR_W_LEN ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), + {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, + 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, + 0x19, 0xdb, 0x06, 0xc1}}, + {D_STR_W_LEN (""), + {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, + 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, + 0x78, 0x52, 0xb8, 0x55}}, + {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."), + {0x2f, 0xad, 0x7a, 0xff, 0x7d, 0xfe, 0xcd, 0x78, 0xe4, 0xa6, 0xf3, 0x85, + 0x97, 0x9d, 0xdc, 0x39, + 0x55, 0x24, 0x35, 0x4a, 0x00, 0x6f, 0x42, 0x72, 0x41, 0xc1, 0x52, 0xa7, + 0x01, 0x0b, 0x2c, 0x41}}, + {D_STR_W_LEN ("Simple string."), + {0x01, 0x73, 0x17, 0xc4, 0x0a, 0x9a, 0x0e, 0x81, 0xb3, 0xa4, 0xb1, 0x8e, + 0xe9, 0xd6, 0xc2, 0xdf, + 0xfa, 0x7d, 0x53, 0x4e, 0xa1, 0xda, 0xb2, 0x5a, 0x75, 0xbb, 0x2c, 0x30, + 0x2f, 0x5f, 0x7a, 0xf4}}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"), + {0x71, 0xc4, 0x80, 0xdf, 0x93, 0xd6, 0xae, 0x2f, 0x1e, 0xfa, 0xd1, 0x44, + 0x7c, 0x66, 0xc9, 0x52, + 0x5e, 0x31, 0x62, 0x18, 0xcf, 0x51, 0xfc, 0x8d, 0x9e, 0xd8, 0x32, 0xf2, + 0xda, 0xf1, 0x8b, 0x73}}, + {D_STR_W_LEN ("zyxwvutsrqponMLKJIHGFEDCBA"), + {0xce, 0x7d, 0xde, 0xb6, 0x1f, 0x7c, 0x1d, 0x83, 0x7c, 0x60, 0xd8, 0x36, + 0x73, 0x82, 0xac, 0x92, + 0xca, 0x37, 0xfd, 0x72, 0x8b, 0x0c, 0xd1, 0x6c, 0x55, 0xd5, 0x88, 0x98, + 0x24, 0xfa, 0x16, 0xf2}}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA" \ + "abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA"), + {0x27, 0xd1, 0xe8, 0xbc, 0x6a, 0x79, 0x16, 0x83, 0x61, 0x73, 0xa9, 0xa8, + 0x9b, 0xaf, 0xaf, 0xcf, + 0x47, 0x4d, 0x09, 0xef, 0x6d, 0x50, 0x35, 0x12, 0x25, 0x72, 0xd8, 0x68, + 0xdc, 0x1f, 0xd2, 0xf4}}, + {D_STR_W_LEN ("/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/path?with%20some=parameters"), + {0x73, 0x85, 0xc5, 0xb9, 0x8f, 0xaf, 0x7d, 0x5e, 0xad, 0xd8, 0x0b, 0x8e, + 0x12, 0xdb, 0x28, 0x60, 0xc7, 0xc7, 0x55, 0x05, 0x2f, 0x7c, 0x6f, 0xfa, + 0xd1, 0xe3, 0xe1, 0x7b, 0x04, 0xd4, 0xb0, 0x21}} +}; + +static const size_t units1_num = sizeof(data_units1) / sizeof(data_units1[0]); + +struct bin_with_len +{ + const uint8_t bin[512]; + const size_t len; +}; + +struct data_unit2 +{ + const struct bin_with_len bin_l; + const uint8_t digest[SHA256_DIGEST_SIZE]; +}; + +/* Size must be less than 512 bytes! */ +static const struct data_unit2 data_units2[] = { + { { {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122}, 26}, /* a..z ASCII sequence */ + {0x71, 0xc4, 0x80, 0xdf, 0x93, 0xd6, 0xae, 0x2f, 0x1e, 0xfa, 0xd1, 0x44, + 0x7c, 0x66, 0xc9, 0x52, + 0x5e, 0x31, 0x62, 0x18, 0xcf, 0x51, 0xfc, 0x8d, 0x9e, 0xd8, 0x32, 0xf2, + 0xda, 0xf1, 0x8b, 0x73}}, + { { {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65}, 72 },/* 'A' x 72 times */ + {0x6a, 0x6d, 0x69, 0x1a, 0xc9, 0xba, 0x70, 0x95, 0x50, 0x46, 0x75, 0x7c, + 0xd6, 0x85, 0xb6, 0x25, + 0x77, 0x73, 0xff, 0x3a, 0xd9, 0x3f, 0x43, 0xd4, 0xd4, 0x81, 0x2c, 0x5b, + 0x10, 0x6f, 0x4b, 0x5b}}, + { { {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73}, 55}, /* 19..73 sequence */ + {0x06, 0xe4, 0xb3, 0x9e, 0xf1, 0xfb, 0x6c, 0xcf, 0xd7, 0x3f, 0x50, 0x9e, + 0xf4, 0x16, 0x17, 0xd4, + 0x63, 0x7c, 0x39, 0x1e, 0xa8, 0x0f, 0xa9, 0x88, 0x03, 0x44, 0x98, 0x0e, + 0x95, 0x81, 0xf0, 0x2a}}, + { { {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69}, 63}, /* 7..69 sequence */ + {0x4a, 0xd3, 0xc6, 0x87, 0x1f, 0xd1, 0xc5, 0xe2, 0x3e, 0x52, 0xdc, 0x22, + 0xd1, 0x10, 0xd2, 0x05, + 0x15, 0x23, 0xcd, 0x15, 0xac, 0x24, 0x88, 0x26, 0x02, 0x00, 0x70, 0x78, + 0x9f, 0x17, 0xf8, 0xd9}}, + { { {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92}, 55}, /* 38..92 sequence */ + {0xe6, 0x03, 0x0f, 0xc9, 0x0d, 0xca, 0x0c, 0x26, 0x41, 0xcf, 0x43, 0x27, + 0xec, 0xd6, 0x28, 0x2a, + 0x98, 0x24, 0x55, 0xd3, 0x5a, 0xed, 0x8b, 0x32, 0x19, 0x78, 0xeb, 0x83, + 0x1d, 0x19, 0x92, 0x79}}, + { { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72}, + 72},/* 1..72 sequence */ + {0x87, 0xa2, 0xfa, 0x2e, 0xec, 0x53, 0x05, 0x3c, 0xb1, 0xee, 0x07, 0xd7, + 0x59, 0x70, 0xf6, 0x50, + 0xcd, 0x9d, 0xc5, 0x8b, 0xdc, 0xb8, 0x65, 0x30, 0x4f, 0x70, 0x82, 0x9e, + 0xbd, 0xe2, 0x7d, 0xac}}, + { { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255}, 256}, /* 0..255 sequence */ + {0x40, 0xaf, 0xf2, 0xe9, 0xd2, 0xd8, 0x92, 0x2e, 0x47, 0xaf, 0xd4, 0x64, + 0x8e, 0x69, 0x67, 0x49, + 0x71, 0x58, 0x78, 0x5f, 0xbd, 0x1d, 0xa8, 0x70, 0xe7, 0x11, 0x02, 0x66, + 0xbf, 0x94, 0x48, 0x80}}, + { { {199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, + 185, 184, 183, 182, 181, 180, + 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 164, 163, 162, 161, 160, + 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, + 145, 144, 143, 142, 141, 140, + 139}, 61}, /* 199..139 sequence */ + {0x85, 0xf8, 0xa2, 0x83, 0xd6, 0x3c, 0x76, 0x8e, 0xea, 0x8f, 0x1c, 0x57, + 0x2d, 0x85, 0xb6, 0xff, + 0xd8, 0x33, 0x57, 0x62, 0x1d, 0x37, 0xae, 0x0e, 0xfc, 0x22, 0xd3, 0xd5, + 0x8f, 0x53, 0x21, 0xb7}}, + { { {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, + 241, 240, 239, 238, 237, 236, + 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, + 221, 220, 219, 218, 217, 216, + 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, + 201, 200, 199, 198, 197, 196, + 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, + 181, 180, 179, 178, 177, 176, + 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, + 161, 160, 159, 158, 157, 156, + 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, + 141, 140, 139, 138, 137, 136, + 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, + 121, 120, 119, 118, 117, 116, + 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, + 101, 100, 99, 98, 97, 96, 95, + 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, + 76, 75, 74, 73, 72, 71, 70, + 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, + 51, 50, 49, 48, 47, 46, 45, + 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, + 26, 25, 24, 23, 22, 21, 20, + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 255}, /* 255..1 sequence */ + {0x61, 0x86, 0x96, 0xab, 0x3e, 0xaa, 0x0e, 0x64, 0xb2, 0xf7, 0x2d, 0x75, + 0x47, 0x5a, 0x14, 0x97, + 0xa3, 0x3d, 0x59, 0xa4, 0x08, 0xd9, 0x9e, 0x73, 0xf2, 0x78, 0x00, 0x5b, + 0x4b, 0x55, 0xca, 0x43}}, + { { {41, 35, 190, 132, 225, 108, 214, 174, 82, 144, 73, 241, 241, 187, 233, + 235, 179, 166, 219, 60, 135, + 12, 62, 153, 36, 94, 13, 28, 6, 183, 71, 222, 179, 18, 77, 200, 67, 187, + 139, 166, 31, 3, 90, 125, 9, + 56, 37, 31, 93, 212, 203, 252, 150, 245, 69, 59, 19, 13, 137, 10, 28, + 219, 174, 50, 32, 154, 80, 238, + 64, 120, 54, 253, 18, 73, 50, 246, 158, 125, 73, 220, 173, 79, 20, 242, + 68, 64, 102, 208, 107, 196, + 48, 183, 50, 59, 161, 34, 246, 34, 145, 157, 225, 139, 31, 218, 176, 202, + 153, 2, 185, 114, 157, 73, + 44, 128, 126, 197, 153, 213, 233, 128, 178, 234, 201, 204, 83, 191, 103, + 214, 191, 20, 214, 126, 45, + 220, 142, 102, 131, 239, 87, 73, 97, 255, 105, 143, 97, 205, 209, 30, + 157, 156, 22, 114, 114, 230, + 29, 240, 132, 79, 74, 119, 2, 215, 232, 57, 44, 83, 203, 201, 18, 30, 51, + 116, 158, 12, 244, 213, + 212, 159, 212, 164, 89, 126, 53, 207, 50, 34, 244, 204, 207, 211, 144, + 45, 72, 211, 143, 117, 230, + 217, 29, 42, 229, 192, 247, 43, 120, 129, 135, 68, 14, 95, 80, 0, 212, + 97, 141, 190, 123, 5, 21, 7, + 59, 51, 130, 31, 24, 112, 146, 218, 100, 84, 206, 177, 133, 62, 105, 21, + 248, 70, 106, 4, 150, 115, + 14, 217, 22, 47, 103, 104, 212, 247, 74, 74, 208, 87, 104}, 255}, /* pseudo-random data */ + {0x08, 0x7f, 0x86, 0xac, 0xe2, 0x2e, 0x28, 0x56, 0x74, 0x53, 0x4f, 0xc0, + 0xfb, 0xb8, 0x79, 0x57, + 0xc5, 0xc8, 0xd1, 0xb7, 0x47, 0xb7, 0xd9, 0xea, 0x97, 0xa8, 0x67, 0xe9, + 0x26, 0x93, 0xee, 0xa3}} +}; + +static const size_t units2_num = sizeof(data_units2) / sizeof(data_units2[0]); + + +/* + * Helper functions + */ + +/** + * Print bin as hex + * + * @param bin binary data + * @param len number of bytes in bin + * @param hex pointer to len*2+1 bytes buffer + */ +static void +bin2hex (const uint8_t *bin, + size_t len, + char *hex) +{ + while (len-- > 0) + { + unsigned int b1, b2; + b1 = (*bin >> 4) & 0xf; + *hex++ = (char) ((b1 > 9) ? (b1 + 'A' - 10) : (b1 + '0')); + b2 = *bin++ & 0xf; + *hex++ = (char) ((b2 > 9) ? (b2 + 'A' - 10) : (b2 + '0')); + } + *hex = 0; +} + + +static int +check_result (const char *test_name, + unsigned int check_num, + const uint8_t calculated[SHA256_DIGEST_SIZE], + const uint8_t expected[SHA256_DIGEST_SIZE]) +{ + int failed = memcmp (calculated, expected, SHA256_DIGEST_SIZE); + check_num++; /* Print 1-based numbers */ + if (failed) + { + char calc_str[SHA256_DIGEST_STRING_SIZE]; + char expc_str[SHA256_DIGEST_STRING_SIZE]; + bin2hex (calculated, SHA256_DIGEST_SIZE, calc_str); + bin2hex (expected, SHA256_DIGEST_SIZE, expc_str); + fprintf (stderr, + "FAILED: %s check %u: calculated digest %s, expected digest %s.\n", + test_name, check_num, calc_str, expc_str); + fflush (stderr); + } + else if (verbose) + { + char calc_str[SHA256_DIGEST_STRING_SIZE]; + bin2hex (calculated, SHA256_DIGEST_SIZE, calc_str); + printf ("PASSED: %s check %u: calculated digest %s " + "matches expected digest.\n", + test_name, check_num, calc_str); + fflush (stdout); + } + return failed ? 1 : 0; +} + + +/* + * Tests + */ + +/* Calculated SHA-256 as one pass for whole data */ +static int +test1_str (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha256CtxWr ctx; + + MHD_SHA256_init_one_time (&ctx); + for (i = 0; i < units1_num; i++) + { + uint8_t digest[SHA256_DIGEST_SIZE]; + + MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, + data_units1[i].str_l.len); + MHD_SHA256_finish_reset (&ctx, digest); +#ifdef MHD_SHA256_HAS_EXT_ERROR + if (0 != ctx.ext_error) + { + fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error); + exit (99); + } +#endif /* MHD_SHA256_HAS_EXT_ERROR */ + num_failed += check_result (MHD_FUNC_, i, digest, + data_units1[i].digest); + } + MHD_SHA256_deinit (&ctx); + return num_failed; +} + + +static int +test1_bin (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha256CtxWr ctx; + + MHD_SHA256_init_one_time (&ctx); + for (i = 0; i < units2_num; i++) + { + uint8_t digest[SHA256_DIGEST_SIZE]; + + MHD_SHA256_update (&ctx, data_units2[i].bin_l.bin, + data_units2[i].bin_l.len); + MHD_SHA256_finish_reset (&ctx, digest); +#ifdef MHD_SHA256_HAS_EXT_ERROR + if (0 != ctx.ext_error) + { + fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error); + exit (99); + } +#endif /* MHD_SHA256_HAS_EXT_ERROR */ + num_failed += check_result (MHD_FUNC_, i, digest, + data_units2[i].digest); + } + MHD_SHA256_deinit (&ctx); + return num_failed; +} + + +/* Calculated SHA-256 as two iterations for whole data */ +static int +test2_str (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha256CtxWr ctx; + + MHD_SHA256_init_one_time (&ctx); + for (i = 0; i < units1_num; i++) + { + uint8_t digest[SHA256_DIGEST_SIZE]; + size_t part_s = data_units1[i].str_l.len / 4; + + MHD_SHA256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, + part_s); + MHD_SHA256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str + + part_s, + data_units1[i].str_l.len - part_s); + MHD_SHA256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA256_finish_reset (&ctx, digest); +#ifdef MHD_SHA256_HAS_EXT_ERROR + if (0 != ctx.ext_error) + { + fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error); + exit (99); + } +#endif /* MHD_SHA256_HAS_EXT_ERROR */ + num_failed += check_result (MHD_FUNC_, i, digest, + data_units1[i].digest); + } + MHD_SHA256_deinit (&ctx); + return num_failed; +} + + +static int +test2_bin (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha256CtxWr ctx; + + MHD_SHA256_init_one_time (&ctx); + for (i = 0; i < units2_num; i++) + { + uint8_t digest[SHA256_DIGEST_SIZE]; + size_t part_s = data_units2[i].bin_l.len * 2 / 3; + + MHD_SHA256_update (&ctx, data_units2[i].bin_l.bin, part_s); + MHD_SHA256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA256_update (&ctx, data_units2[i].bin_l.bin + part_s, + data_units2[i].bin_l.len - part_s); + MHD_SHA256_finish_reset (&ctx, digest); +#ifdef MHD_SHA256_HAS_EXT_ERROR + if (0 != ctx.ext_error) + { + fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error); + exit (99); + } +#endif /* MHD_SHA256_HAS_EXT_ERROR */ + num_failed += check_result (MHD_FUNC_, i, digest, + data_units2[i].digest); + } + MHD_SHA256_deinit (&ctx); + return num_failed; +} + + +/* Use data set number 7 as it has the longest sequence */ +#define DATA_POS 6 +#define MAX_OFFSET 31 + +static int +test_unaligned (void) +{ + int num_failed = 0; + unsigned int offset; + uint8_t *buf; + uint8_t *digest_buf; + struct Sha256CtxWr ctx; + + const struct data_unit2 *const tdata = data_units2 + DATA_POS; + + MHD_SHA256_init_one_time (&ctx); + buf = malloc (tdata->bin_l.len + MAX_OFFSET); + digest_buf = malloc (SHA256_DIGEST_SIZE + MAX_OFFSET); + if ((NULL == buf) || (NULL == digest_buf)) + exit (99); + + for (offset = MAX_OFFSET; offset >= 1; --offset) + { + uint8_t *unaligned_digest; + uint8_t *unaligned_buf; + + unaligned_buf = buf + offset; + memcpy (unaligned_buf, tdata->bin_l.bin, tdata->bin_l.len); + unaligned_digest = digest_buf + MAX_OFFSET - offset; + memset (unaligned_digest, 0, SHA256_DIGEST_SIZE); + + MHD_SHA256_update (&ctx, unaligned_buf, tdata->bin_l.len); + MHD_SHA256_finish_reset (&ctx, unaligned_digest); +#ifdef MHD_SHA256_HAS_EXT_ERROR + if (0 != ctx.ext_error) + { + fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error); + exit (99); + } +#endif /* MHD_SHA256_HAS_EXT_ERROR */ + num_failed += check_result (MHD_FUNC_, MAX_OFFSET - offset, + unaligned_digest, tdata->digest); + } + free (digest_buf); + free (buf); + MHD_SHA256_deinit (&ctx); + return num_failed; +} + + +int +main (int argc, char *argv[]) +{ + int num_failed = 0; + (void) has_in_name; /* Mute compiler warning. */ + if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose")) + verbose = 1; + +#ifdef NEED_GCRYP_INIT + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); +#ifdef GCRYCTL_INITIALIZATION_FINISHED + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); +#endif /* GCRYCTL_INITIALIZATION_FINISHED */ +#endif /* NEED_GCRYP_INIT */ + + num_failed += test1_str (); + num_failed += test1_bin (); + + num_failed += test2_str (); + num_failed += test2_bin (); + + num_failed += test_unaligned (); + + return num_failed ? 1 : 0; +} diff --git a/src/tests/unit/test_sha512_256.c b/src/tests/unit/test_sha512_256.c @@ -0,0 +1,602 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2019-2022 Evgeny Grin (Karlson2k) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_sha512_256.h + * @brief Unit tests for SHA-512/256 functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_options.h" +#include "sha512_256.h" +#include "test_helpers.h" +#include <stdio.h> +#include <stdlib.h> + +static int verbose = 0; /* verbose level (0-1)*/ + + +struct str_with_len +{ + const char *const str; + const size_t len; +}; + +#define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} + +struct data_unit1 +{ + const struct str_with_len str_l; + const uint8_t digest[SHA512_256_DIGEST_SIZE]; +}; + +static const struct data_unit1 data_units1[] = { + {D_STR_W_LEN ("abc"), + {0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, 0x9B, 0x2E, 0x29, 0xB7, + 0x6B, 0x4C, 0x7D, 0xAB, 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, + 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23}}, + {D_STR_W_LEN ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" \ + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), + {0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, 0x40, 0xDA, 0x39, 0x88, + 0x12, 0x1D, 0x31, 0xBE, 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, + 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A}}, + {D_STR_W_LEN (""), /* The empty zero-size input */ + {0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28, 0xab, 0x87, 0xc3, 0x62, + 0x2c, 0x51, 0x14, 0x06, 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74, + 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a}}, + {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."), + {0xc8, 0x7c, 0x5a, 0x55, 0x27, 0x77, 0x1b, 0xe7, 0x69, 0x3c, 0x50, 0x79, + 0x32, 0xad, 0x7c, 0x79, 0xe9, 0x60, 0xa0, 0x18, 0xb7, 0x78, 0x2b, 0x6f, + 0xa9, 0x7b, 0xa3, 0xa0, 0xb5, 0x18, 0x17, 0xa5}}, + {D_STR_W_LEN ("Simple string."), + {0xde, 0xcb, 0x3c, 0x81, 0x65, 0x4b, 0xa0, 0xf5, 0xf0, 0x45, 0x6b, 0x7e, + 0x61, 0xf5, 0x0d, 0xf5, 0x38, 0xa4, 0xfc, 0xb1, 0x8a, 0x95, 0xff, 0x59, + 0xbc, 0x04, 0x82, 0xcf, 0x23, 0xb2, 0x32, 0x56}}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"), + {0xfc, 0x31, 0x89, 0x44, 0x3f, 0x9c, 0x26, 0x8f, 0x62, 0x6a, 0xea, 0x08, + 0xa7, 0x56, 0xab, 0xe7, 0xb7, 0x26, 0xb0, 0x5f, 0x70, 0x1c, 0xb0, 0x82, + 0x22, 0x31, 0x2c, 0xcf, 0xd6, 0x71, 0x0a, 0x26, }}, + {D_STR_W_LEN ("zyxwvutsrqponMLKJIHGFEDCBA"), + {0xd2, 0x6d, 0x24, 0x81, 0xa4, 0xf9, 0x0a, 0x72, 0xd2, 0x7f, 0xc1, 0xac, + 0xac, 0xe1, 0xc0, 0x6b, 0x39, 0x94, 0xac, 0x73, 0x50, 0x2e, 0x27, 0x97, + 0xa3, 0x65, 0x37, 0x4e, 0xbb, 0x5c, 0x27, 0xe9}}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA" \ + "abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA"), + {0xad, 0xe9, 0x5d, 0x55, 0x3b, 0x9e, 0x45, 0x69, 0xdb, 0x53, 0xa4, 0x04, + 0x92, 0xe7, 0x87, 0x94, 0xff, 0xc9, 0x98, 0x5f, 0x93, 0x03, 0x86, 0x45, + 0xe1, 0x97, 0x17, 0x72, 0x7c, 0xbc, 0x31, 0x15}}, + {D_STR_W_LEN ("/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/long/long/long/long/long/long/long" \ + "/long/long/long/long/path?with%20some=parameters"), + {0xbc, 0xab, 0xc6, 0x2c, 0x0a, 0x22, 0xd5, 0xcb, 0xac, 0xac, 0xe9, 0x25, + 0xcf, 0xce, 0xaa, 0xaf, 0x0e, 0xa1, 0xed, 0x42, 0x46, 0x8a, 0xe2, 0x01, + 0xee, 0x2f, 0xdb, 0x39, 0x75, 0x47, 0x73, 0xf1}} +}; + +static const size_t units1_num = sizeof(data_units1) / sizeof(data_units1[0]); + +struct bin_with_len +{ + const uint8_t bin[512]; + const size_t len; +}; + +struct data_unit2 +{ + const struct bin_with_len bin_l; + const uint8_t digest[SHA512_256_DIGEST_SIZE]; +}; + +/* Size must be less than 512 bytes! */ +static const struct data_unit2 data_units2[] = { + { { {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}, 26}, /* a..z ASCII sequence */ + {0xfc, 0x31, 0x89, 0x44, 0x3f, 0x9c, 0x26, 0x8f, 0x62, 0x6a, 0xea, 0x08, + 0xa7, 0x56, 0xab, 0xe7, 0xb7, 0x26, 0xb0, 0x5f, 0x70, 0x1c, 0xb0, 0x82, + 0x22, 0x31, 0x2c, 0xcf, 0xd6, 0x71, 0x0a, 0x26}}, + { { {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, + 72 }, /* 'A' x 72 times */ + {0x36, 0x5d, 0x41, 0x0e, 0x55, 0xd1, 0xfd, 0xe6, 0xc3, 0xb8, 0x68, 0xcc, + 0xed, 0xeb, 0xcd, 0x0d, 0x2e, 0x34, 0xb2, 0x5c, 0xdf, 0xe7, 0x79, 0xe2, + 0xe9, 0x65, 0x07, 0x33, 0x78, 0x0d, 0x01, 0x89}}, + { { {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73}, 55}, /* 19..73 sequence */ + {0xb9, 0xe5, 0x74, 0x11, 0xbf, 0xa2, 0x0e, 0x98, 0xbe, 0x08, 0x69, 0x2e, + 0x17, 0x9e, 0xc3, 0xfe, 0x61, 0xe3, 0x7a, 0x80, 0x2e, 0x25, 0x8c, 0xf3, + 0x76, 0xda, 0x9f, 0x5f, 0xcd, 0x87, 0x48, 0x0d}}, + { { {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69}, 63}, /* 7..69 sequence */ + {0x80, 0x15, 0x83, 0xed, 0x7d, 0xef, 0x9f, 0xdf, 0xfb, 0x83, 0x1f, 0xc5, + 0x8b, 0x50, 0x37, 0x81, 0x00, 0xc3, 0x4f, 0xfd, 0xfe, 0xc2, 0x9b, 0xaf, + 0xfe, 0x15, 0x66, 0xe5, 0x08, 0x42, 0x5e, 0xae}}, + { { {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92}, 55}, /* 38..92 sequence */ + {0x76, 0x2f, 0x27, 0x4d, 0xfa, 0xd5, 0xa9, 0x21, 0x4e, 0xe9, 0x56, 0x22, + 0x54, 0x38, 0x71, 0x3e, 0xef, 0x14, 0xa9, 0x22, 0x37, 0xf3, 0xb0, 0x50, + 0x3d, 0x95, 0x40, 0xb7, 0x08, 0x64, 0xa9, 0xfd}}, + { { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72}, 72}, /* 1..72 sequence */ + {0x3f, 0x5c, 0xd3, 0xec, 0x40, 0xc4, 0xb9, 0x78, 0x35, 0x57, 0xc6, 0x4f, + 0x3e, 0x46, 0x82, 0xdc, 0xd4, 0x46, 0x11, 0xd0, 0xb3, 0x0a, 0xbb, 0x89, + 0xf1, 0x1d, 0x34, 0xb5, 0xf9, 0xd5, 0x10, 0x35}}, + { { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 254, 255}, 256}, /* 0..255 sequence */ + {0x08, 0x37, 0xa1, 0x1d, 0x99, 0x4d, 0x5a, 0xa8, 0x60, 0xd0, 0x69, 0x17, + 0xa8, 0xa0, 0xf6, 0x3e, 0x31, 0x11, 0xb9, 0x56, 0x33, 0xde, 0xeb, 0x15, + 0xee, 0xd9, 0x94, 0x93, 0x76, 0xf3, 0x7d, 0x36, }}, + { { {199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, + 185, 184, 183, 182, 181, 180, + 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 164, 163, 162, 161, 160, + 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, + 145, 144, 143, 142, 141, 140, + 139}, 61}, /* 199..139 sequence */ + {0xcf, 0x21, 0x4b, 0xb2, 0xdd, 0x40, 0x98, 0xdf, 0x3a, 0xb7, 0x21, 0xb4, + 0x69, 0x0e, 0x19, 0x36, 0x24, 0xa9, 0xbe, 0x30, 0xf7, 0xd0, 0x75, 0xb0, + 0x39, 0x94, 0x82, 0xda, 0x55, 0x97, 0xe4, 0x79}}, + { { {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, + 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, + 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, + 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, + 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, + 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, + 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, + 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, + 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, + 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, + 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, + 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, + 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, + 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 255}, /* 255..1 sequence */ + {0x22, 0x31, 0xf2, 0xa1, 0xb4, 0x89, 0xb2, 0x44, 0xf7, 0x66, 0xa0, 0xb8, + 0x31, 0xed, 0xb7, 0x73, 0x8a, 0x34, 0xdc, 0x11, 0xc8, 0x2c, 0xf2, 0xb5, + 0x88, 0x60, 0x39, 0x6b, 0x5c, 0x06, 0x70, 0x37}}, + { { {41, 35, 190, 132, 225, 108, 214, 174, 82, 144, 73, 241, 241, 187, 233, + 235, 179, 166, 219, 60, 135, 12, 62, 153, 36, 94, 13, 28, 6, 183, 71, + 222, 179, 18, 77, 200, 67, 187, 139, 166, 31, 3, 90, 125, 9, 56, 37, + 31, 93, 212, 203, 252, 150, 245, 69, 59, 19, 13, 137, 10, 28, 219, 174, + 50, 32, 154, 80, 238, 64, 120, 54, 253, 18, 73, 50, 246, 158, 125, 73, + 220, 173, 79, 20, 242, 68, 64, 102, 208, 107, 196, 48, 183, 50, 59, + 161, 34, 246, 34, 145, 157, 225, 139, 31, 218, 176, 202, 153, 2, 185, + 114, 157, 73, 44, 128, 126, 197, 153, 213, 233, 128, 178, 234, 201, + 204, 83, 191, 103, 214, 191, 20, 214, 126, 45, 220, 142, 102, 131, 239, + 87, 73, 97, 255, 105, 143, 97, 205, 209, 30, 157, 156, 22, 114, 114, + 230, 29, 240, 132, 79, 74, 119, 2, 215, 232, 57, 44, 83, 203, 201, 18, + 30, 51, 116, 158, 12, 244, 213, 212, 159, 212, 164, 89, 126, 53, 207, + 50, 34, 244, 204, 207, 211, 144, 45, 72, 211, 143, 117, 230, 217, 29, + 42, 229, 192, 247, 43, 120, 129, 135, 68, 14, 95, 80, 0, 212, 97, 141, + 190, 123, 5, 21, 7, 59, 51, 130, 31, 24, 112, 146, 218, 100, 84, 206, + 177, 133, 62, 105, 21, 248, 70, 106, 4, 150, 115, 14, 217, 22, 47, 103, + 104, 212, 247, 74, 74, 208, 87, 104}, 255}, /* pseudo-random data */ + {0xb8, 0xdb, 0x2c, 0x2e, 0xf3, 0x12, 0x77, 0x14, 0xf9, 0x34, 0x2d, 0xfa, + 0xda, 0x42, 0xbe, 0xfe, 0x67, 0x3a, 0x8a, 0xf6, 0x71, 0x36, 0x00, 0xff, + 0x77, 0xa5, 0x83, 0x14, 0x55, 0x2a, 0x05, 0xaf}}, + { { {66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66}, 110}, /* 'B' x 110 times */ + {0xc8, 0x9e, 0x0d, 0x8f, 0x7b, 0x35, 0xfd, 0x3e, 0xdc, 0x90, 0x87, 0x64, + 0x45, 0x94, 0x94, 0x21, 0xb3, 0x8e, 0xb5, 0xc7, 0x54, 0xc8, 0xee, 0xde, + 0xfc, 0x77, 0xd6, 0xe3, 0x9f, 0x81, 0x8e, 0x78}}, + { { {67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 67, 67, 67}, 111}, /* 'C' x 111 times */ + {0x86, 0xca, 0x6d, 0x2a, 0x72, 0xe2, 0x8c, 0x17, 0x89, 0x86, 0x89, 0x1b, + 0x36, 0xf9, 0x6d, 0xda, 0x8c, 0xd6, 0x30, 0xb2, 0xd3, 0x60, 0x39, 0xfb, + 0xc9, 0x04, 0xc5, 0x11, 0xcd, 0x2d, 0xe3, 0x62}}, + { { {68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68}, 112}, /* 'D' x 112 times */ + {0xdf, 0x9d, 0x4a, 0xcf, 0x81, 0x0d, 0x3a, 0xd4, 0x8e, 0xa4, 0x65, 0x9e, + 0x1e, 0x15, 0xe4, 0x15, 0x1b, 0x37, 0xb6, 0xeb, 0x17, 0xab, 0xf6, 0xb1, + 0xbc, 0x30, 0x46, 0x34, 0x24, 0x56, 0x1c, 0x06}}, + { { {69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69}, 113}, /* 'E' x 113 times */ + {0xa5, 0xf1, 0x47, 0x74, 0xf8, 0x2b, 0xed, 0x23, 0xe4, 0x10, 0x59, 0x8f, + 0x7e, 0xb1, 0x30, 0xe5, 0x7e, 0xd1, 0x4b, 0xbc, 0x72, 0x58, 0x58, 0x81, + 0xbb, 0xa0, 0xa5, 0xb6, 0x15, 0x39, 0x49, 0xa1}}, + { { {70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70}, 114}, /* 'F' x 114 times */ + {0xe6, 0xa3, 0xc9, 0x63, 0xd5, 0x28, 0x6e, 0x2d, 0xfb, 0x71, 0xdf, 0xd4, + 0xff, 0xc2, 0xd4, 0x2b, 0x5d, 0x9b, 0x76, 0x28, 0xd2, 0xcb, 0x15, 0xc8, + 0x81, 0x57, 0x14, 0x09, 0xc3, 0x8e, 0x92, 0xce}}, + { { {76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76}, 127}, /* 'L' x 127 times */ + {0x5d, 0x18, 0xff, 0xd7, 0xbe, 0x23, 0xb2, 0xb2, 0xbd, 0xe3, 0x13, 0x12, + 0x1c, 0x16, 0x89, 0x14, 0x4a, 0x42, 0xb4, 0x3f, 0xab, 0xc8, 0x41, 0x14, + 0x62, 0x00, 0xb5, 0x53, 0xa7, 0xd6, 0xd5, 0x35}}, + { { {77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77}, 128}, /* 'M' x 128 times */ + {0x6e, 0xf0, 0xda, 0x81, 0x3d, 0x50, 0x1d, 0x31, 0xf1, 0x4a, 0xf8, 0xd9, + 0x7d, 0xd2, 0x13, 0xdd, 0xa4, 0x46, 0x15, 0x0b, 0xb8, 0x5a, 0x8a, 0xc6, + 0x1e, 0x3a, 0x1f, 0x21, 0x35, 0xa2, 0xbb, 0x4f}}, + { { {78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78}, 129}, /* 'N' x 129 times */ + {0xee, 0xce, 0xd5, 0x34, 0xab, 0x14, 0x13, 0x9e, 0x8f, 0x5c, 0xb4, 0xef, + 0xac, 0xaf, 0xc5, 0xeb, 0x1d, 0x2f, 0xe3, 0xc5, 0xca, 0x09, 0x29, 0x96, + 0xfa, 0x84, 0xff, 0x12, 0x26, 0x6a, 0x50, 0x49}}, + { { {97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97}, 238}, /* 'a' x 238 times */ + {0xb4, 0x24, 0xe5, 0x7b, 0xa7, 0x37, 0xe3, 0xc4, 0xac, 0x35, 0x21, 0x17, + 0x98, 0xec, 0xb9, 0xae, 0x45, 0x13, 0x24, 0xa4, 0x2c, 0x76, 0xae, 0x7d, + 0x17, 0x75, 0x27, 0x8a, 0xaa, 0x4a, 0x48, 0x60}}, + { { {98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98}, 239}, /* 'b' x 239 times */ + {0xcd, 0x93, 0xb8, 0xab, 0x6a, 0x74, 0xbd, 0x34, 0x8c, 0x43, 0x76, 0x0c, + 0x2a, 0xd0, 0x6e, 0xd8, 0x76, 0xcf, 0xdf, 0x2a, 0x21, 0x04, 0xfb, 0xf6, + 0x16, 0x53, 0x68, 0xf6, 0x10, 0xc3, 0xa1, 0xac}}, + { { {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99}, 240}, /* 'c' x 240 times */ + {0x5f, 0x60, 0xea, 0x44, 0xb6, 0xc6, 0x9e, 0xfe, 0xfc, 0x0e, 0x6a, 0x0a, + 0x99, 0x40, 0x1b, 0x61, 0x43, 0x58, 0xba, 0x4a, 0x0a, 0xee, 0x6b, 0x52, + 0x10, 0xdb, 0x32, 0xd9, 0x7f, 0x12, 0xba, 0x70}}, + { { {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48}, 241}, /* '0' x 241 times */ + {0x3c, 0xcb, 0xcf, 0x50, 0x79, 0xd5, 0xb6, 0xf5, 0xbf, 0x25, 0x07, 0xfb, + 0x4d, 0x1f, 0xa3, 0x77, 0xc3, 0x6f, 0xe8, 0xe3, 0xc4, 0x4b, 0xf8, 0xcd, + 0x90, 0x93, 0xf1, 0x3e, 0x08, 0x09, 0xa7, 0x69}} +}; + +static const size_t units2_num = sizeof(data_units2) / sizeof(data_units2[0]); + + +/* + * Helper functions + */ + +/** + * Print bin as hex + * + * @param bin binary data + * @param len number of bytes in bin + * @param hex pointer to len*2+1 bytes buffer + */ +static void +bin2hex (const uint8_t *bin, + size_t len, + char *hex) +{ + while (len-- > 0) + { + unsigned int b1, b2; + b1 = (*bin >> 4) & 0xf; + *hex++ = (char) ((b1 > 9) ? (b1 + 'A' - 10) : (b1 + '0')); + b2 = *bin++ & 0xf; + *hex++ = (char) ((b2 > 9) ? (b2 + 'A' - 10) : (b2 + '0')); + } + *hex = 0; +} + + +static int +check_result (const char *test_name, + unsigned int check_num, + const uint8_t calculated[SHA512_256_DIGEST_SIZE], + const uint8_t expected[SHA512_256_DIGEST_SIZE]) +{ + int failed = memcmp (calculated, expected, SHA512_256_DIGEST_SIZE); + check_num++; /* Print 1-based numbers */ + if (failed) + { + char calc_str[SHA512_256_DIGEST_SIZE * 2 + 1]; + char expc_str[SHA512_256_DIGEST_SIZE * 2 + 1]; + bin2hex (calculated, SHA512_256_DIGEST_SIZE, calc_str); + bin2hex (expected, SHA512_256_DIGEST_SIZE, expc_str); + fprintf (stderr, + "FAILED: %s check %u: calculated digest %s, expected digest %s.\n", + test_name, check_num, calc_str, expc_str); + fflush (stderr); + } + else if (verbose) + { + char calc_str[SHA512_256_DIGEST_SIZE * 2 + 1]; + bin2hex (calculated, SHA512_256_DIGEST_SIZE, calc_str); + printf ("PASSED: %s check %u: calculated digest %s matches " \ + "expected digest.\n", + test_name, check_num, calc_str); + fflush (stdout); + } + return failed ? 1 : 0; +} + + +/* + * Tests + */ + +/* Calculated SHA-512/256 as one pass for whole data */ +static int +test1_str (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha512_256Ctx ctx; + + for (i = 0; i < units1_num; i++) + { + uint8_t digest[SHA512_256_DIGEST_SIZE]; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, + data_units1[i].str_l.len); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units1[i].digest); + } + return num_failed; +} + + +static int +test1_bin (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha512_256Ctx ctx; + + for (i = 0; i < units2_num; i++) + { + uint8_t digest[SHA512_256_DIGEST_SIZE]; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, data_units2[i].bin_l.bin, + data_units2[i].bin_l.len); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units2[i].digest); + } + return num_failed; +} + + +/* Calculated SHA-512/256 as two iterations for whole data */ +static int +test2_str (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha512_256Ctx ctx; + + for (i = 0; i < units1_num; i++) + { + uint8_t digest[SHA512_256_DIGEST_SIZE]; + size_t part_s = data_units1[i].str_l.len / 4; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA512_256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, + part_s); + MHD_SHA512_256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA512_256_update (&ctx, (const uint8_t *) data_units1[i].str_l.str + + part_s, + data_units1[i].str_l.len - part_s); + MHD_SHA512_256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units1[i].digest); + } + return num_failed; +} + + +static int +test2_bin (void) +{ + int num_failed = 0; + unsigned int i; + struct Sha512_256Ctx ctx; + + for (i = 0; i < units2_num; i++) + { + uint8_t digest[SHA512_256_DIGEST_SIZE]; + size_t part_s = data_units2[i].bin_l.len * 2 / 3; + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, data_units2[i].bin_l.bin, part_s); + MHD_SHA512_256_update (&ctx, (const uint8_t *) "", 0); + MHD_SHA512_256_update (&ctx, data_units2[i].bin_l.bin + part_s, + data_units2[i].bin_l.len - part_s); + MHD_SHA512_256_finish (&ctx, digest); + num_failed += check_result (__FUNCTION__, i, digest, + data_units2[i].digest); + } + return num_failed; +} + + +/* Use data set number 7 as it has the longest sequence */ +#define DATA_POS 6 +#define MAX_OFFSET 63 + +static int +test_unaligned (void) +{ + int num_failed = 0; + unsigned int offset; + uint8_t *buf; + uint8_t *digest_buf; + struct Sha512_256Ctx ctx; + + const struct data_unit2 *const tdata = data_units2 + DATA_POS; + + buf = malloc (tdata->bin_l.len + MAX_OFFSET); + digest_buf = malloc (SHA512_256_DIGEST_SIZE + MAX_OFFSET); + if ((NULL == buf) || (NULL == digest_buf)) + exit (99); + + for (offset = MAX_OFFSET; offset >= 1; --offset) + { + uint8_t *unaligned_digest; + uint8_t *unaligned_buf; + + unaligned_buf = buf + offset; + memcpy (unaligned_buf, tdata->bin_l.bin, tdata->bin_l.len); + unaligned_digest = digest_buf + MAX_OFFSET - offset; + memset (unaligned_digest, 0, SHA512_256_DIGEST_SIZE); + + MHD_SHA512_256_init (&ctx); + MHD_SHA512_256_update (&ctx, unaligned_buf, tdata->bin_l.len); + MHD_SHA512_256_finish (&ctx, unaligned_digest); + num_failed += check_result (__FUNCTION__, MAX_OFFSET - offset, + unaligned_digest, tdata->digest); + } + free (digest_buf); + free (buf); + return num_failed; +} + + +int +main (int argc, char *argv[]) +{ + int num_failed = 0; + (void) has_in_name; /* Mute compiler warning. */ + if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose")) + verbose = 1; + + num_failed += test1_str (); + num_failed += test1_bin (); + + num_failed += test2_str (); + num_failed += test2_bin (); + + num_failed += test_unaligned (); + + return num_failed ? 1 : 0; +} diff --git a/src/tests/unit/test_str_base64.c b/src/tests/unit/test_str_base64.c @@ -0,0 +1,795 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2022 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_base64.c + * @brief Unit tests for base64 strings processing + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_options.h" +#include <string.h> +#include <stdio.h> +#include "mhd_str.h" +#include "mhd_assert.h" + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +#define TEST_BIN_MAX_SIZE 1024 + +/* return zero if succeed, one otherwise */ +static unsigned int +expect_decoded_n (const char *const encoded, const size_t encoded_len, + const uint8_t *const decoded, const size_t decoded_size, + const unsigned int line_num) +{ + static const char fill_chr = '#'; + static uint8_t buf[TEST_BIN_MAX_SIZE]; + size_t res_size; + unsigned int ret; + + mhd_assert (NULL != encoded); + mhd_assert (NULL != decoded); + mhd_assert (TEST_BIN_MAX_SIZE > decoded_size); + mhd_assert (encoded_len >= decoded_size); + mhd_assert (0 == encoded_len || encoded_len > decoded_size); + + ret = 0; + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = MHD_base64_to_bin_n (encoded, encoded_len, buf, decoded_size); + + if (res_size != decoded_size) + { + ret = 1; + fprintf (stderr, + "'MHD_base64_to_bin_n ()' FAILED: Wrong returned value:\n"); + } + else if ((0 != decoded_size) && (0 != memcmp (buf, decoded, decoded_size))) + { + ret = 1; + fprintf (stderr, + "'MHD_base64_to_bin_n ()' FAILED: Wrong output binary:\n"); + } + if (0 != ret) + { + static char prnt[TEST_BIN_MAX_SIZE * 2 + 1]; + size_t prnt_size; + if (TEST_BIN_MAX_SIZE <= res_size * 2) + { + fprintf (stderr, + "\tRESULT : MHD_base64_to_bin_n ('%.*s', %u, ->(too long), %u)" + " -> %u\n", + (int) encoded_len, encoded, (unsigned) encoded_len, + (unsigned) decoded_size, (unsigned) res_size); + } + else + { + prnt_size = MHD_bin_to_hex_z (buf, res_size, prnt); + mhd_assert (2 * res_size == prnt_size); + + fprintf (stderr, + "\tRESULT : MHD_base64_to_bin_n ('%.*s', %u, ->%.*sh, %u)" + " -> %u\n", + (int) encoded_len, encoded, (unsigned) encoded_len, + (int) prnt_size, prnt, (unsigned) decoded_size, + (unsigned) res_size); + } + prnt_size = MHD_bin_to_hex_z (decoded, decoded_size, prnt); + mhd_assert (2 * decoded_size == prnt_size); + fprintf (stderr, + "\tEXPECTED: MHD_base64_to_bin_n ('%.*s', %u, ->%.*sh, %u)" + " -> %u\n", + (int) encoded_len, encoded, (unsigned) encoded_len, + (int) prnt_size, prnt, (unsigned) decoded_size, + (unsigned) decoded_size); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + return ret; +} + + +#define expect_decoded(e,d) \ + expect_decoded_n (e,MHD_STATICSTR_LEN_ (e), \ + (const uint8_t*) (d),MHD_STATICSTR_LEN_ (d), \ + __LINE__) + +static unsigned int +check_decode_str (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_decoded ("", ""); + + /* Base sequences without padding */ + r += expect_decoded ("YWFh", "aaa"); + r += expect_decoded ("YmJi", "bbb"); + r += expect_decoded ("Y2Nj", "ccc"); + r += expect_decoded ("ZGRk", "ddd"); + r += expect_decoded ("bGxs", "lll"); + r += expect_decoded ("bW1t", "mmm"); + r += expect_decoded ("bm5u", "nnn"); + r += expect_decoded ("b29v", "ooo"); + r += expect_decoded ("d3d3", "www"); + r += expect_decoded ("eHh4", "xxx"); + r += expect_decoded ("eXl5", "yyy"); + r += expect_decoded ("enp6", "zzz"); + r += expect_decoded ("QUFB", "AAA"); + r += expect_decoded ("R0dH", "GGG"); + r += expect_decoded ("TU1N", "MMM"); + r += expect_decoded ("VFRU", "TTT"); + r += expect_decoded ("Wlpa", "ZZZ"); + r += expect_decoded ("MDEy", "012"); + r += expect_decoded ("MzQ1", "345"); + r += expect_decoded ("Njc4", "678"); + r += expect_decoded ("OTAx", "901"); + r += expect_decoded ("YWFhYWFh", "aaaaaa"); + r += expect_decoded ("YmJiYmJi", "bbbbbb"); + r += expect_decoded ("Y2NjY2Nj", "cccccc"); + r += expect_decoded ("ZGRkZGRk", "dddddd"); + r += expect_decoded ("bGxsbGxs", "llllll"); + r += expect_decoded ("bW1tbW1t", "mmmmmm"); + r += expect_decoded ("bm5ubm5u", "nnnnnn"); + r += expect_decoded ("b29vb29v", "oooooo"); + r += expect_decoded ("d3d3d3d3", "wwwwww"); + r += expect_decoded ("eHh4eHh4", "xxxxxx"); + r += expect_decoded ("eXl5eXl5", "yyyyyy"); + r += expect_decoded ("enp6enp6", "zzzzzz"); + r += expect_decoded ("QUFBQUFB", "AAAAAA"); + r += expect_decoded ("R0dHR0dH", "GGGGGG"); + r += expect_decoded ("TU1NTU1N", "MMMMMM"); + r += expect_decoded ("VFRUVFRU", "TTTTTT"); + r += expect_decoded ("WlpaWlpa", "ZZZZZZ"); + r += expect_decoded ("MDEyMDEy", "012012"); + r += expect_decoded ("MzQ1MzQ1", "345345"); + r += expect_decoded ("Njc4Njc4", "678678"); + r += expect_decoded ("OTAxOTAx", "901901"); + + /* Various lengths */ + r += expect_decoded ("YQ==", "a"); + r += expect_decoded ("YmM=", "bc"); + r += expect_decoded ("REVGRw==", "DEFG"); + r += expect_decoded ("MTIzdA==", "123t"); + r += expect_decoded ("MTIzNDU=", "12345"); + r += expect_decoded ("VGVzdCBTdHI=", "Test Str"); + r += expect_decoded ("VGVzdCBzdHJpbmc=", "Test string"); + r += expect_decoded ("VGVzdCBzdHJpbmcu", "Test string."); + r += expect_decoded ("TG9uZ2VyIHN0cmluZw==", "Longer string"); + r += expect_decoded ("TG9uZ2VyIHN0cmluZy4=", "Longer string."); + r += expect_decoded ("TG9uZ2VyIHN0cmluZzIu", "Longer string2."); + + return r; +} + + +#define expect_decoded_arr(e,a) \ + expect_decoded_n (e,MHD_STATICSTR_LEN_ (e), \ + a,(sizeof(a) / sizeof(a[0])), \ + __LINE__) + +static unsigned int +check_decode_bin (void) +{ + unsigned int r = 0; /**< The number of errors */ + + if (1) + { + static const uint8_t bin[256] = + {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff }; + r += expect_decoded_arr ("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISI" \ + "jJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERU" \ + "ZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoa" \ + "WprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouM" \ + "jY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+" \ + "wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0t" \ + "PU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19" \ + "vf4+fr7/P3+/w==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, + 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x0 }; + r += expect_decoded_arr ("AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiM" \ + "kJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRk" \ + "dISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpa" \ + "mtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yN" \ + "jo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7C" \ + "xsrO0tba3uLm6u7y9vr/AwcLDxMXGx8jJysvMzc7P0NHS09" \ + "TV1tfY2drb3N3e3+Dh4uPk5ebn6Onq6+zt7u/w8fLz9PX29" \ + "/j5+vv8/f7/AA==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, + 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, + 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, + 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, + 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x0, + 0x1 }; + r += expect_decoded_arr ("AgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQ" \ + "lJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0" \ + "hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa" \ + "2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SFhoeIiYqLjI2O" \ + "j5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLG" \ + "ys7S1tre4ubq7vL2+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1N" \ + "XW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+" \ + "Pn6+/z9/v8AAQ==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, + 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, + 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, + 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, + 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x0, + 0x1, 0x2 }; + r += expect_decoded_arr ("AwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCU" \ + "mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSE" \ + "lKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprb" \ + "G1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P" \ + "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbK" \ + "ztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1d" \ + "bX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+" \ + "fr7/P3+/wABAg==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, + 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, + 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, + 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, + 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, + 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, + 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, + 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, + 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, + 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, + 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, + 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, + 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, + 0x0 }; + r += expect_decoded_arr ("//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3" \ + "c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7ur" \ + "m4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXl" \ + "pWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRz" \ + "cnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVB" \ + "PTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLS" \ + "wrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKC" \ + "QgHBgUEAwIBAA==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, + 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, + 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, + 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, + 0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, + 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, + 0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, + 0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, + 0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, + 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, + 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, + 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, + 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, + 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, + 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, + 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, + 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, + 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, + 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, + 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, + 0x2, 0x1}; + r += expect_decoded_arr ("AP/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397" \ + "d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7" \ + "q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl" \ + "5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0" \ + "c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlF" \ + "QT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi" \ + "0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLC" \ + "gkIBwYFBAMCAQ==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x1, 0x0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, + 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, + 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, + 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, + 0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, + 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, + 0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, + 0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, + 0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, + 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, + 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, + 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, + 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, + 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, + 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, + 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, + 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, + 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, + 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, + 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, + 0x2}; + r += expect_decoded_arr ("AQD//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/" \ + "e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vL" \ + "u6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZm" \ + "JeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1" \ + "dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1J" \ + "RUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy" \ + "4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MC" \ + "woJCAcGBQQDAg==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x2, 0x1, 0x0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, + 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, + 0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, + 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, + 0xd1, 0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, + 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, + 0xb9, 0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, + 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, + 0xa1, 0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, + 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, + 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, + 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, + 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, + 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, + 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, + 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, + 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, + 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, + 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, + 0x3}; + r += expect_decoded_arr ("AgEA//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eD" \ + "f3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vb" \ + "y7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuam" \ + "ZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2" \ + "dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFN" \ + "SUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC" \ + "8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4ND" \ + "AsKCQgHBgUEAw==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, + 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, + 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, + 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, + 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, + 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, + 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xab, + 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f, + 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, + 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, + 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, + 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, + 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, + 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, + 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, + 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, + 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, + 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, + 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, + 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, + 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, + 0xff}; + r += expect_decoded_arr ("/v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dz" \ + "b2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ub" \ + "i3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWl" \ + "ZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNy" \ + "cXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9" \ + "OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLC" \ + "sqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJC" \ + "AcGBQQDAgEA/w==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, + 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, + 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, + 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, 0xce, + 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, + 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6, + 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, + 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f, 0x9e, + 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, + 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, + 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, + 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, + 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, + 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, + 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, + 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, + 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, + 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, + 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, + 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, 0xe, 0xd, + 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xff, + 0xfe}; + r += expect_decoded_arr ("/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nv" \ + "a2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uL" \ + "e2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVl" \ + "JOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3Jx" \ + "cG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05" \ + "NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKy" \ + "opKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIB" \ + "wYFBAMCAQD//g==", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, + 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, 0xe5, + 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, + 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, 0xce, 0xcd, + 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, + 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6, 0xb5, + 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, + 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f, 0x9e, 0x9d, + 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, + 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, + 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, + 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, + 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, + 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, + 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, + 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, 0x3d, + 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, + 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, + 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, + 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, 0xe, 0xd, 0xc, + 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xff, 0xfe, + 0xfd }; + r += expect_decoded_arr ("/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29r" \ + "Z2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7" \ + "a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk" \ + "5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFw" \ + "b25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1" \ + "MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKi" \ + "koJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHB" \ + "gUEAwIBAP/+/Q==", bin); + } + + if (1) + { + static const uint8_t bin[48] = + {0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8b, 0x30, 0xd3, 0x8f, + 0x41, 0x14, 0x93, 0x51, 0x55, 0x97, 0x61, 0x96, 0x9b, 0x71, 0xd7, 0x9f, + 0x82, 0x18, 0xa3, 0x92, 0x59, 0xa7, 0xa2, 0x9a, 0xab, 0xb2, 0xdb, 0xaf, + 0xc3, 0x1c, 0xb3, 0xd3, 0x5d, 0xb7, 0xe3, 0x9e, 0xbb, 0xf3, 0xdf, 0xbf }; + r += expect_decoded_arr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz0123456789+/", bin); + } + + if (1) + { + static const uint8_t bin[49] = + {0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8b, 0x30, 0xd3, 0x8f, + 0x41, 0x14, 0x93, 0x51, 0x55, 0x97, 0x61, 0x96, 0x9b, 0x71, 0xd7, 0x9f, + 0x82, 0x18, 0xa3, 0x92, 0x59, 0xa7, 0xa2, 0x9a, 0xab, 0xb2, 0xdb, 0xaf, + 0xc3, 0x1c, 0xb3, 0xd3, 0x5d, 0xb7, 0xe3, 0x9e, 0xbb, 0xf3, 0xdf, 0xbf, + 0x00 }; + r += expect_decoded_arr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz0123456789+/" \ + "AA==", bin); + } + + if (1) + { + static const uint8_t bin[48] = + {0xff, 0xef, 0x7c, 0xef, 0xae, 0x78, 0xdf, 0x6d, 0x74, 0xcf, 0x2c, 0x70, + 0xbe, 0xeb, 0x6c, 0xae, 0xaa, 0x68, 0x9e, 0x69, 0x64, 0x8e, 0x28, 0x60, + 0x7d, 0xe7, 0x5c, 0x6d, 0xa6, 0x58, 0x5d, 0x65, 0x54, 0x4d, 0x24, 0x50, + 0x3c, 0xe3, 0x4c, 0x2c, 0xa2, 0x48, 0x1c, 0x61, 0x44, 0x0c, 0x20, 0x40 }; + r += expect_decoded_arr ("/+9876543210zyxwvutsrqponmlkjihgfedcba" \ + "ZYXWVUTSRQPONMLKJIHGFEDCBA", bin); + } + + if (1) + { + static const uint8_t bin[49] = + {0xff, 0xef, 0x7c, 0xef, 0xae, 0x78, 0xdf, 0x6d, 0x74, 0xcf, 0x2c, 0x70, + 0xbe, 0xeb, 0x6c, 0xae, 0xaa, 0x68, 0x9e, 0x69, 0x64, 0x8e, 0x28, 0x60, + 0x7d, 0xe7, 0x5c, 0x6d, 0xa6, 0x58, 0x5d, 0x65, 0x54, 0x4d, 0x24, 0x50, + 0x3c, 0xe3, 0x4c, 0x2c, 0xa2, 0x48, 0x1c, 0x61, 0x44, 0x0c, 0x20, 0x40, + 0x00 }; + r += expect_decoded_arr ("/+9876543210zyxwvutsrqponmlkjihgfedcba" \ + "ZYXWVUTSRQPONMLKJIHGFEDCBAAA==", bin); + } + + return r; +} + + +/* return zero if succeed, one otherwise */ +static unsigned int +expect_fail_n (const char *const encoded, const size_t encoded_len, + const unsigned int line_num) +{ + static const char fill_chr = '#'; + static uint8_t buf[TEST_BIN_MAX_SIZE]; + size_t res_size; + unsigned int ret; + + mhd_assert (NULL != encoded); + mhd_assert (TEST_BIN_MAX_SIZE > encoded_len); + + ret = 0; + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = MHD_base64_to_bin_n (encoded, encoded_len, buf, sizeof(buf)); + + if (res_size != 0) + { + ret = 1; + fprintf (stderr, + "'MHD_base64_to_bin_n ()' FAILED: Wrong returned value:\n"); + } + if (0 != ret) + { + static char prnt[TEST_BIN_MAX_SIZE * 2 + 1]; + size_t prnt_size; + if (TEST_BIN_MAX_SIZE <= res_size * 2) + { + fprintf (stderr, + "\tRESULT : MHD_base64_to_bin_n ('%.*s', %u, ->(too long), %u)" + " -> %u\n", + (int) encoded_len, encoded, (unsigned) encoded_len, + (unsigned) sizeof(buf), (unsigned) res_size); + } + else + { + prnt_size = MHD_bin_to_hex_z (buf, res_size, prnt); + mhd_assert (2 * res_size == prnt_size); + + fprintf (stderr, + "\tRESULT : MHD_base64_to_bin_n ('%.*s', %u, ->%.*sh, %u)" + " -> %u\n", + (int) encoded_len, encoded, (unsigned) encoded_len, + (int) prnt_size, prnt, (unsigned) sizeof(buf), + (unsigned) res_size); + } + fprintf (stderr, + "\tEXPECTED: MHD_base64_to_bin_n ('%.*s', %u, ->(empty), %u)" + " -> 0\n", + (int) encoded_len, encoded, (unsigned) encoded_len, + (unsigned) sizeof(buf)); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + return ret; +} + + +#define expect_fail(e) \ + expect_fail_n (e,MHD_STATICSTR_LEN_ (e),__LINE__) + + +static unsigned int +check_fail (void) +{ + unsigned int r = 0; /**< The number of errors */ + + /* Base sequences with wrong length */ + r += expect_fail ("YWFh/"); + r += expect_fail ("YWFh/Q"); + r += expect_fail ("YWFhE/Q"); + r += expect_fail ("bW1tbW1t/"); + r += expect_fail ("bW1tbW1t/Q"); + r += expect_fail ("bW1tbW1tE/Q"); + + /* Base sequences with wrong char */ + r += expect_fail ("%mJi"); + r += expect_fail ("Y%Nj"); + r += expect_fail ("ZG%k"); + r += expect_fail ("bGx%"); + r += expect_fail ("#W1t"); + r += expect_fail ("b#5u"); + r += expect_fail ("b2#v"); + r += expect_fail ("d3d#"); + r += expect_fail ("^Hh4"); + r += expect_fail ("e^l5"); + r += expect_fail ("en^6"); + r += expect_fail ("QUF^"); + r += expect_fail ("~0dH"); + r += expect_fail ("T~1N"); + r += expect_fail ("VF~U"); + r += expect_fail ("Wlp~"); + r += expect_fail ("*DEy"); + r += expect_fail ("M*Q1"); + r += expect_fail ("Nj*4"); + r += expect_fail ("OTA*"); + r += expect_fail ("&WFhYWFh"); + r += expect_fail ("Y&JiYmJi"); + r += expect_fail ("Y2&jY2Nj"); + r += expect_fail ("ZGR&ZGRk"); + r += expect_fail ("bGxs&Gxs"); + r += expect_fail ("bW1tb&1t"); + r += expect_fail ("bm5ubm&u"); + r += expect_fail ("b29vb29&"); + r += expect_fail ("!3d3d3d3"); + r += expect_fail ("e!h4eHh4"); + r += expect_fail ("eX!5eXl5"); + r += expect_fail ("enp!enp6"); + r += expect_fail ("QUFB!UFB"); + r += expect_fail ("R0dHR!dH"); + r += expect_fail ("TU1NTU!N"); + r += expect_fail ("VFRUVFR!"); + + /* Bad high-ASCII char */ + r += expect_fail ("\xff" "WFhYWFh"); + r += expect_fail ("Y\xfe" "JiYmJi"); + r += expect_fail ("Y2\xfd" "jY2Nj"); + r += expect_fail ("ZGR\xfc" "ZGRk"); + r += expect_fail ("bGxs\xfb" "Gxs"); + r += expect_fail ("bW1tbW\xfa" "1t"); + r += expect_fail ("bm5ubm\xf9" "u"); + r += expect_fail ("b29vb29\xf8"); + r += expect_fail ("d3d3d3d\x80"); + r += expect_fail ("eHh4eH\x81" "4"); + r += expect_fail ("eXl5e\x82" "l5"); + r += expect_fail ("enp6\x83" "np6"); + r += expect_fail ("QUF\x84" "QUFB"); + r += expect_fail ("TU\x85" "NTU1N"); + r += expect_fail ("V\x86" "RUVFRU"); + r += expect_fail ("\x87" "lpaWlpa"); + + /* Base sequences with wrong padding char */ + r += expect_fail ("=lpaWlpa"); + r += expect_fail ("M=EyMDEy"); + r += expect_fail ("Mz=1MzQ1"); + r += expect_fail ("Njc=Njc4"); + r += expect_fail ("OTAx=TAx"); + r += expect_fail ("ZGRkZ=Rk"); + r += expect_fail ("bGxsbG=s"); + r += expect_fail ("bW1tb==="); + r += expect_fail ("bm5u===="); + + /* Bad last char (valid for Base64, but padding part is not zero */ + r += expect_fail ("TG9uZ2VyIHN0cmluZo=="); + r += expect_fail ("TG9uZ2VyIHN0cmluZyK="); + + return r; +} + + +int +main (int argc, char *argv[]) +{ + unsigned int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_decode_str (); + errcount += check_decode_bin (); + errcount += check_fail (); + if (0 == errcount) + printf ("All tests were passed without errors.\n"); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/test_str_bin_hex.c b/src/tests/unit/test_str_bin_hex.c @@ -0,0 +1,450 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2022 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_bin_hex.c + * @brief Unit tests for hex strings <-> binary data processing + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include <string.h> +#include <stdio.h> +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "mhd_assert.h" + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */ +static size_t buf_idx = 0; + +/* print non-printable chars as char codes */ +static char * +n_prnt (const char *str, size_t len) +{ + static char *buf; /* should be enough for testing */ + static const size_t buf_size = sizeof(tmp_bufs[0]); + size_t r_pos = 0; + size_t w_pos = 0; + if (++buf_idx >= (sizeof(tmp_bufs) / sizeof(tmp_bufs[0]))) + buf_idx = 0; + buf = tmp_bufs[buf_idx]; + + while (len > r_pos && w_pos + 1 < buf_size) + { + const unsigned char c = (unsigned char) str[r_pos]; + if ((c == '\\') || (c == '"') ) + { + if (w_pos + 2 >= buf_size) + break; + buf[w_pos++] = '\\'; + buf[w_pos++] = (char) c; + } + else if ((c >= 0x20) && (c <= 0x7E) ) + buf[w_pos++] = (char) c; + else + { + if (w_pos + 4 >= buf_size) + break; + if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned + int) c) != 4) + break; + w_pos += 4; + } + r_pos++; + } + + if (len != r_pos) + { /* not full string is printed */ + /* enough space for "..." ? */ + if (w_pos + 3 > buf_size) + w_pos = buf_size - 4; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + } + buf[w_pos] = 0; + return buf; +} + + +#define TEST_BIN_MAX_SIZE (2 * 1024) + +/* return zero if succeed, number of failures otherwise */ +static unsigned int +expect_decoded_n (const char *const hex, const size_t hex_len, + const uint8_t *const bin, const size_t bin_size, + const unsigned int line_num) +{ + static const char fill_chr = '#'; + static char buf[TEST_BIN_MAX_SIZE]; + size_t res_size; + unsigned int ret; + + mhd_assert (NULL != hex); + mhd_assert (NULL != bin); + mhd_assert (TEST_BIN_MAX_SIZE > bin_size + 1); + mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1); + mhd_assert (hex_len >= bin_size); + mhd_assert (1 >= hex_len || hex_len > bin_size); + + ret = 0; + + /* check mhd_hex_to_bin() */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_hex_to_bin (hex, hex_len, buf); + if (res_size != bin_size) + { + check_res = 1; + fprintf (stderr, + "'MHD_hex_to_bin ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if ((0 != bin_size) && + (0 != memcmp (buf, bin, bin_size))) + { + check_res = 1; + fprintf (stderr, + "'MHD_hex_to_bin ()' FAILED: " + "Wrong output data:\n"); + } + } + if (((0 == res_size) && (fill_chr != buf[bin_size])) + || ((0 != res_size) && (fill_chr != buf[res_size]))) + { + check_res = 1; + fprintf (stderr, + "'mhd_hex_to_bin ()' FAILED: " + "A char written outside the buffer:\n"); + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_hex_to_bin (\"%s\", %u, " + "->\"%s\") -> %u\n", + n_prnt (hex, hex_len), (unsigned) hex_len, + n_prnt (buf, res_size), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_hex_to_bin (\"%s\", %u, " + "->\"%s\") -> %u\n", + n_prnt (hex, hex_len), (unsigned) hex_len, + n_prnt ((const char *) bin, bin_size), + (unsigned) bin_size); + } + } + + /* check mhd_bin_to_hex() */ + if (0 == hex_len % 2) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_bin_to_hex_z (bin, bin_size, buf); + + if (res_size != hex_len) + { + check_res = 1; + fprintf (stderr, + "'mhd_bin_to_hex ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if ((0 != hex_len) && + (! mhd_str_equal_caseless_bin_n (buf, hex, hex_len))) + { + check_res = 1; + fprintf (stderr, + "'mhd_bin_to_hex ()' FAILED: " + "Wrong output string:\n"); + } + } + if (fill_chr != buf[res_size + 1]) + { + check_res = 1; + fprintf (stderr, + "'mhd_bin_to_hex ()' FAILED: " + "A char written outside the buffer:\n"); + } + if (0 != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_bin_to_hex ()' FAILED: " + "The result is not zero-terminated:\n"); + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_bin_to_hex (\"%s\", %u, " + "->\"%s\") -> %u\n", + n_prnt ((const char *) bin, bin_size), (unsigned) bin_size, + n_prnt (buf, res_size), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_bin_to_hex (\"%s\", %u, " + "->(lower case)\"%s\") -> %u\n", + n_prnt ((const char *) bin, bin_size), (unsigned) bin_size, + n_prnt (hex, hex_len), + (unsigned) bin_size); + } + } + + if (0 != ret) + { + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + return ret; +} + + +#define expect_decoded_arr(h,a) \ + expect_decoded_n (h,MHD_STATICSTR_LEN_ (h), \ + a,(sizeof(a) / sizeof(a[0])), \ + __LINE__) + +static unsigned int +check_decode_bin (void) +{ + unsigned int r = 0; /**< The number of errors */ + + if (1) + { + static const uint8_t bin[256] = + {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff }; + /* The lower case */ + r += expect_decoded_arr ("000102030405060708090a0b0c0d0e" \ + "0f101112131415161718191a1b1c1d" \ + "1e1f202122232425262728292a2b2c" \ + "2d2e2f303132333435363738393a3b" \ + "3c3d3e3f404142434445464748494a" \ + "4b4c4d4e4f50515253545556575859" \ + "5a5b5c5d5e5f606162636465666768" \ + "696a6b6c6d6e6f7071727374757677" \ + "78797a7b7c7d7e7f80818283848586" \ + "8788898a8b8c8d8e8f909192939495" \ + "969798999a9b9c9d9e9fa0a1a2a3a4" \ + "a5a6a7a8a9aaabacadaeafb0b1b2b3" \ + "b4b5b6b7b8b9babbbcbdbebfc0c1c2" \ + "c3c4c5c6c7c8c9cacbcccdcecfd0d1" \ + "d2d3d4d5d6d7d8d9dadbdcdddedfe0" \ + "e1e2e3e4e5e6e7e8e9eaebecedeeef" \ + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfe" \ + "ff", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff }; + /* The upper case */ + r += expect_decoded_arr ("000102030405060708090A0B0C0D0E" \ + "0F101112131415161718191A1B1C1D" \ + "1E1F202122232425262728292A2B2C" \ + "2D2E2F303132333435363738393A3B" \ + "3C3D3E3F404142434445464748494A" \ + "4B4C4D4E4F50515253545556575859" \ + "5A5B5C5D5E5F606162636465666768" \ + "696A6B6C6D6E6F7071727374757677" \ + "78797A7B7C7D7E7F80818283848586" \ + "8788898A8B8C8D8E8F909192939495" \ + "969798999A9B9C9D9E9FA0A1A2A3A4" \ + "A5A6A7A8A9AAABACADAEAFB0B1B2B3" \ + "B4B5B6B7B8B9BABBBCBDBEBFC0C1C2" \ + "C3C4C5C6C7C8C9CACBCCCDCECFD0D1" \ + "D2D3D4D5D6D7D8D9DADBDCDDDEDFE0" \ + "E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" \ + "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" \ + "FF", bin); + } + if (1) + { + static const uint8_t bin[3] = + {0x1, 0x2, 0x3}; + r += expect_decoded_arr ("010203", bin); + } + if (1) + { + static const uint8_t bin[3] = + {0x1, 0x2, 0x3}; + r += expect_decoded_arr ("10203", bin); + } + if (1) + { + static const uint8_t bin[1] = + {0x1}; + r += expect_decoded_arr ("01", bin); + } + if (1) + { + static const uint8_t bin[1] = + {0x1}; + r += expect_decoded_arr ("1", bin); + } + + return r; +} + + +/* return zero if succeed, number of failures otherwise */ +static unsigned int +expect_failed_n (const char *const hex, const size_t hex_len, + const unsigned int line_num) +{ + static const char fill_chr = '#'; + static char buf[TEST_BIN_MAX_SIZE]; + size_t res_size; + unsigned int ret; + + mhd_assert (NULL != hex); + mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1); + + ret = 0; + + /* check mhd_hex_to_bin() */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_hex_to_bin (hex, hex_len, buf); + if (res_size != 0) + { + check_res = 1; + fprintf (stderr, + "'mhd_hex_to_bin ()' FAILED: " + "Wrong returned value:\n"); + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_hex_to_bin (\"%s\", %u, " + "->\"%s\") -> %u\n", + n_prnt (hex, hex_len), (unsigned) hex_len, + n_prnt (buf, res_size), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_hex_to_bin (\"%s\", %u, " + "->(not defined)) -> 0\n", + n_prnt (hex, hex_len), (unsigned) hex_len); + } + } + + if (0 != ret) + { + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + return ret; +} + + +#define expect_failed(h) \ + expect_failed_n (h,MHD_STATICSTR_LEN_ (h), \ + __LINE__) + + +static unsigned int +check_broken_str (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_failed ("abcx"); + r += expect_failed ("X"); + r += expect_failed ("!"); + r += expect_failed ("01z"); + r += expect_failed ("0z"); + r += expect_failed ("00z"); + r += expect_failed ("000Y"); + + return r; +} + + +int +main (int argc, char *argv[]) +{ + unsigned int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_decode_bin (); + errcount += check_broken_str (); + if (0 == errcount) + printf ("All tests have been passed without errors.\n"); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/test_str_compare.c b/src/tests/unit/test_str_compare.c @@ -0,0 +1,879 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2016 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/unit_str_test.h + * @brief Unit tests for mhd_str functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "../mhdt_checks.h" + +#include <stdio.h> +#include <locale.h> +#include <string.h> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else /* ! HAVE_INTTYPES_H */ +#define PRIu64 "llu" +#define PRIuPTR "u" +#define PRIX64 "llX" +#endif /* ! HAVE_INTTYPES_H */ +#include <stdint.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif /* HAVE_STDLIB_H */ +#include "mhd_limits.h" +#include "mhd_str.h" +#include "test_helpers.h" + + +static int verbose = 0; /* verbose level (0-3)*/ + +/* Locale names to test. + * Functions must not depend of current current locale, + * so result must be the same in any locale. + */ +static const char *const locale_names[] = { + "C", + "", /* System default locale */ +#if defined(_WIN32) && ! defined(__CYGWIN__) + ".OCP", /* W32 system default OEM code page */ + ".ACP", /* W32 system default ANSI code page */ + ".65001", /* UTF-8 */ + ".437", + ".850", + ".857", + ".866", + ".1250", + ".1251", + ".1252", + "en", + "english", + "French_France", + "Turkish_Turkey.1254", + "de", + "zh-Hans", + "ru-RU.1251" +#if 0 /* Disabled extra checks */ + , + ".1254", + ".20866", /* number for KOI8-R */ + ".28591", /* number for ISO-8859-1 */ + ".28595", /* number for ISO-8859-5 */ + ".28599", /* number for ISO-8859-9 */ + ".28605", /* number for ISO-8859-15 */ + "en-US", + "English-US", + "en-US.437", + "English_United States.437", + "en-US.1252", + "English_United States.1252", + "English_United States.28591", + "English_United States.65001", + "fra", + "french", + "fr-FR", + "fr-FR.850", + "french_france.850", + "fr-FR.1252", + "French_france.1252", + "French_france.28605", + "French_France.65001", + "de-DE", + "de-DE.850", + "German_Germany.850", + "German_Germany.1250", + "de-DE.1252", + "German_Germany.1252", + "German_Germany.28605", + "German_Germany.65001", + "tr", + "trk", + "turkish", + "tr-TR", + "tr-TR.1254", + "tr-TR.857", + "Turkish_Turkey.857", + "Turkish_Turkey.28599", + "Turkish_Turkey.65001", + "ru", + "ru-RU", + "Russian", + "ru-RU.866", + "Russian_Russia.866", + "Russian_Russia.1251", + "Russian_Russia.20866", + "Russian_Russia.28595", + "Russian_Russia.65001", + "zh-Hans.936", + "chinese-simplified" +#endif /* Disabled extra checks */ +#else /* ! _WIN32 || __CYGWIN__ */ + "C.UTF-8", + "POSIX", + "en", + "en_US", + "en_US.ISO-8859-1", + "en_US.ISO_8859-1", + "en_US.ISO8859-1", + "en_US.iso88591", + "en_US.ISO-8859-15", + "en_US.DIS_8859-15", + "en_US.ISO8859-15", + "en_US.iso885915", + "en_US.1252", + "en_US.CP1252", + "en_US.UTF-8", + "en_US.utf8", + "fr", + "fr_FR", + "fr_FR.850", + "fr_FR.IBM850", + "fr_FR.1252", + "fr_FR.CP1252", + "fr_FR.ISO-8859-1", + "fr_FR.ISO_8859-1", + "fr_FR.ISO8859-1", + "fr_FR.iso88591", + "fr_FR.ISO-8859-15", + "fr_FR.DIS_8859-15", + "fr_FR.ISO8859-15", + "fr_FR.iso8859-15", + "fr_FR.UTF-8", + "fr_FR.utf8", + "de", + "de_DE", + "de_DE.850", + "de_DE.IBM850", + "de_DE.1250", + "de_DE.CP1250", + "de_DE.1252", + "de_DE.CP1252", + "de_DE.ISO-8859-1", + "de_DE.ISO_8859-1", + "de_DE.ISO8859-1", + "de_DE.iso88591", + "de_DE.ISO-8859-15", + "de_DE.DIS_8859-15", + "de_DE.ISO8859-15", + "de_DE.iso885915", + "de_DE.UTF-8", + "de_DE.utf8", + "tr", + "tr_TR", + "tr_TR.1254", + "tr_TR.CP1254", + "tr_TR.857", + "tr_TR.IBM857", + "tr_TR.ISO-8859-9", + "tr_TR.ISO8859-9", + "tr_TR.iso88599", + "tr_TR.UTF-8", + "tr_TR.utf8", + "ru", + "ru_RU", + "ru_RU.1251", + "ru_RU.CP1251", + "ru_RU.866", + "ru_RU.IBM866", + "ru_RU.KOI8-R", + "ru_RU.koi8-r", + "ru_RU.KOI8-RU", + "ru_RU.ISO-8859-5", + "ru_RU.ISO_8859-5", + "ru_RU.ISO8859-5", + "ru_RU.iso88595", + "ru_RU.UTF-8", + "zh_CN", + "zh_CN.GB2312", + "zh_CN.UTF-8", +#endif /* ! _WIN32 || __CYGWIN__ */ +}; + +static const unsigned int locale_name_count = sizeof(locale_names) + / sizeof(locale_names[0]); + + +/* + * Helper functions + */ + +static int +set_test_locale (size_t num) +{ + if (num >= locale_name_count) + { + fprintf (stderr, "Unexpected number of locale.\n"); + exit (99); + } + if (verbose > 2) + printf ("Setting locale \"%s\":", locale_names[num]); + if (setlocale (LC_ALL, locale_names[num])) + { + if (verbose > 2) + printf (" succeed.\n"); + return 1; + } + if (verbose > 2) + printf (" failed.\n"); + return 0; +} + + +static const char * +get_current_locale_str (void) +{ + char const *loc_str = setlocale (LC_ALL, NULL); + return loc_str ? loc_str : "unknown"; +} + + +static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */ +static size_t buf_idx = 0; + +/* print non-printable chars as char codes */ +static char * +n_prnt (const char *str) +{ + static char *buf; /* should be enough for testing */ + static const size_t buf_size = sizeof(tmp_bufs[0]); + const unsigned char *p = (const unsigned char *) str; + size_t w_pos = 0; + if (++buf_idx > 3) + buf_idx = 0; + buf = tmp_bufs[buf_idx]; + + while (*p && w_pos + 1 < buf_size) + { + const unsigned char c = *p; + if ((c == '\\') || (c == '"') ) + { + if (w_pos + 2 >= buf_size) + break; + buf[w_pos++] = '\\'; + buf[w_pos++] = (char) c; + } + else if ((c >= 0x20) && (c <= 0x7E) ) + buf[w_pos++] = (char) c; + else + { + if (w_pos + 4 >= buf_size) + break; + if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned + int) c) != 4) + break; + w_pos += 4; + } + p++; + } + if (*p) + { /* not full string is printed */ + /* enough space for "..." ? */ + if (w_pos + 3 > buf_size) + w_pos = buf_size - 4; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + } + buf[w_pos] = 0; + return buf; +} + + +struct str_with_len +{ + const char *const str; + const size_t len; +}; + +#define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} + +/* + * String caseless equality functions tests + */ + +struct two_eq_strs +{ + const struct str_with_len s1; + const struct str_with_len s2; +}; + +static const struct two_eq_strs eq_strings[] = { + {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."), + D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`.")}, + {D_STR_W_LEN ("Simple string."), D_STR_W_LEN ("Simple string.")}, + {D_STR_W_LEN ("SIMPLE STRING."), D_STR_W_LEN ("SIMPLE STRING.")}, + {D_STR_W_LEN ("simple string."), D_STR_W_LEN ("simple string.")}, + {D_STR_W_LEN ("simple string."), D_STR_W_LEN ("Simple String.")}, + {D_STR_W_LEN ("sImPlE StRiNg."), D_STR_W_LEN ("SiMpLe sTrInG.")}, + {D_STR_W_LEN ("SIMPLE STRING."), D_STR_W_LEN ("simple string.")}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"), + D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz")}, + {D_STR_W_LEN ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + D_STR_W_LEN ("ABCDEFGHIJKLMNOPQRSTUVWXYZ")}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"), + D_STR_W_LEN ("ABCDEFGHIJKLMNOPQRSTUVWXYZ")}, + {D_STR_W_LEN ("zyxwvutsrqponMLKJIHGFEDCBA"), + D_STR_W_LEN ("ZYXWVUTSRQPONmlkjihgfedcba")}, + + {D_STR_W_LEN ("Cha\x8cne pour le test."), + D_STR_W_LEN ("Cha\x8cne pour le test.")}, /* "Chaîne pour le test." in CP850 */ + {D_STR_W_LEN ("cha\x8cne pOur Le TEst."), + D_STR_W_LEN ("Cha\x8cne poUr Le teST.")}, + {D_STR_W_LEN ("Cha\xeene pour le test."), + D_STR_W_LEN ("Cha\xeene pour le test.")}, /* "Chaîne pour le test." in CP1252/ISO-8859-1/ISO-8859-15 */ + {D_STR_W_LEN ("CHa\xeene POUR le test."), + D_STR_W_LEN ("Cha\xeeNe pour lE TEST.")}, + {D_STR_W_LEN ("Cha\xc3\xaene pour le Test."), + D_STR_W_LEN ("Cha\xc3\xaene pour le Test.")}, /* "Chaîne pour le test." in UTF-8 */ + {D_STR_W_LEN ("ChA\xc3\xaene pouR lE TesT."), + D_STR_W_LEN ("Cha\xc3\xaeNe Pour le teSt.")}, + + {D_STR_W_LEN (".Beispiel Zeichenfolge"), + D_STR_W_LEN (".Beispiel Zeichenfolge")}, + {D_STR_W_LEN (".bEisPiel ZEIchenfoLgE"), + D_STR_W_LEN (".BEiSpiEl zeIcheNfolge")}, + + {D_STR_W_LEN ("Do\xa7rulama \x87izgi!"), + D_STR_W_LEN ("Do\xa7rulama \x87izgi!")}, /* "Doğrulama çizgi!" in CP857 */ + {D_STR_W_LEN ("Do\xa7rulama \x87IzgI!"), /* Spelling intentionally incorrect here */ + D_STR_W_LEN ("Do\xa7rulama \x87izgi!")}, /* Note: 'i' is not caseless equal to 'I' in Turkish */ + {D_STR_W_LEN ("Do\xf0rulama \xe7izgi!"), + D_STR_W_LEN ("Do\xf0rulama \xe7izgi!")}, /* "Doğrulama çizgi!" in CP1254/ISO-8859-9 */ + {D_STR_W_LEN ("Do\xf0rulamA \xe7Izgi!"), + D_STR_W_LEN ("do\xf0rulama \xe7izgi!")}, + {D_STR_W_LEN ("Do\xc4\x9frulama \xc3\xa7izgi!"), + D_STR_W_LEN ("Do\xc4\x9frulama \xc3\xa7izgi!")}, /* "Doğrulama çizgi!" in UTF-8 */ + {D_STR_W_LEN ("do\xc4\x9fruLAMA \xc3\xa7Izgi!"), /* Spelling intentionally incorrect here */ + D_STR_W_LEN ("DO\xc4\x9frulama \xc3\xa7izgI!")}, /* Spelling intentionally incorrect here */ + + {D_STR_W_LEN ("\x92\xa5\xe1\xe2\xae\xa2\xa0\xef \x91\xe2\xe0\xae\xaa\xa0."), + D_STR_W_LEN ("\x92\xa5\xe1\xe2\xae\xa2\xa0\xef \x91\xe2\xe0\xae\xaa\xa0.")}, /* "Тестовая Строка." in CP866 */ + {D_STR_W_LEN ("\xd2\xe5\xf1\xf2\xee\xe2\xe0\xff \xd1\xf2\xf0\xee\xea\xe0."), + D_STR_W_LEN ("\xd2\xe5\xf1\xf2\xee\xe2\xe0\xff \xd1\xf2\xf0\xee\xea\xe0.")}, /* "Тестовая Строка." in CP1251 */ + {D_STR_W_LEN ("\xf4\xc5\xd3\xd4\xcf\xd7\xc1\xd1 \xf3\xd4\xd2\xcf\xcb\xc1."), + D_STR_W_LEN ("\xf4\xc5\xd3\xd4\xcf\xd7\xc1\xd1 \xf3\xd4\xd2\xcf\xcb\xc1.")}, /* "Тестовая Строка." in KOI8-R */ + {D_STR_W_LEN ("\xc2\xd5\xe1\xe2\xde\xd2\xd0\xef \xc1\xe2\xe0\xde\xda\xd0."), + D_STR_W_LEN ("\xc2\xd5\xe1\xe2\xde\xd2\xd0\xef \xc1\xe2\xe0\xde\xda\xd0.")}, /* "Тестовая Строка." in ISO-8859-5 */ + {D_STR_W_LEN ("\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbe\xd0\xb2\xd0\xb0\xd1" + "\x8f \xd0\xa1\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0."), + D_STR_W_LEN ("\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbe\xd0\xb2\xd0\xb0\xd1" + "\x8f \xd0\xa1\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0.")}, /* "Тестовая Строка." in UTF-8 */ + + {D_STR_W_LEN ( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@[\\]" + "^_`{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4" + "\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" + "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc" + "\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4" + "\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"), + D_STR_W_LEN ( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@[\\]" + "^_`{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4" + "\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" + "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc" + "\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4" + "\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")}, /* Full sequence without a-z */ + {D_STR_W_LEN ( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@AB" + "CDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83" + "\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab" + "\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3" + "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb" + "\xfc\xfd\xfe\xff"), + D_STR_W_LEN ( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@AB" + "CDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83" + "\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab" + "\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3" + "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb" + "\xfc\xfd\xfe\xff")}, /* Full sequence */ + {D_STR_W_LEN ( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@AB" + "CDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" + "\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d" + "\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1" + "\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5" + "\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" + "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed" + "\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff") + , + D_STR_W_LEN ( + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ab" + "cdefghijklmnopqrstuvwxyz[\\]^_`{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" + "\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d" + "\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1" + "\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5" + "\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" + "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed" + "\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff") + } /* Full with A/a match */ +}; + +struct two_neq_strs +{ + const struct str_with_len s1; + const struct str_with_len s2; + const size_t dif_pos; +}; + +static const struct two_neq_strs neq_strings[] = { + {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."), + D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`"), 27}, + {D_STR_W_LEN (".1234567890!@~%&$@#{}[]\\/!?`."), + D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`"), 0}, + {D_STR_W_LEN ("Simple string."), D_STR_W_LEN ("Simple ctring."), 7}, + {D_STR_W_LEN ("simple string."), D_STR_W_LEN ("simple string"), 13}, + {D_STR_W_LEN ("simple strings"), D_STR_W_LEN ("Simple String."), 13}, + {D_STR_W_LEN ("sImPlE StRiNg."), D_STR_W_LEN ("SYMpLe sTrInG."), 1}, + {D_STR_W_LEN ("SIMPLE STRING."), D_STR_W_LEN ("simple string.2"), 14}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz,"), + D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz."), 26}, + {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz!"), + D_STR_W_LEN ("ABCDEFGHIJKLMNOPQRSTUVWXYZ?"), 26}, + {D_STR_W_LEN ("zyxwvutsrqponwMLKJIHGFEDCBA"), + D_STR_W_LEN ("ZYXWVUTSRQPON%mlkjihgfedcba"), 13}, + + {D_STR_W_LEN ("S\xbdur veulent plus d'\xbdufs."), /* "Sœur veulent plus d'œufs." in ISO-8859-15 */ + D_STR_W_LEN ("S\xbcUR VEULENT PLUS D'\xbcUFS."), 1}, /* "SŒUR VEULENT PLUS D'ŒUFS." in ISO-8859-15 */ + {D_STR_W_LEN ("S\x9cur veulent plus d'\x9cufs."), /* "Sœur veulent plus d'œufs." in CP1252 */ + D_STR_W_LEN ("S\x8cUR VEULENT PLUS D'\x8cUFS."), 1}, /* "SŒUR VEULENT PLUS D'ŒUFS." in CP1252 */ + {D_STR_W_LEN ("S\xc5\x93ur veulent plus d'\xc5\x93ufs."), /* "Sœur veulent plus d'œufs." in UTF-8 */ + D_STR_W_LEN ("S\xc5\x92UR VEULENT PLUS D'\xc5\x92UFS."), 2}, /* "SŒUR VEULENT PLUS D'ŒUFS." in UTF-8 */ + + {D_STR_W_LEN ("Um ein sch\x94nes M\x84" "dchen zu k\x81ssen."), /* "Um ein schönes Mädchen zu küssen." in CP850 */ + D_STR_W_LEN ("UM EIN SCH\x99NES M\x8e" "DCHEN ZU K\x9aSSEN."), 10}, /* "UM EIN SCHÖNES MÄDCHEN ZU KÜSSEN." in CP850 */ + {D_STR_W_LEN ("Um ein sch\xf6nes M\xe4" "dchen zu k\xfcssen."), /* "Um ein schönes Mädchen zu küssen." in ISO-8859-1/ISO-8859-15/CP1250/CP1252 */ + D_STR_W_LEN ("UM EIN SCH\xd6NES M\xc4" "DCHEN ZU K\xdcSSEN."), 10}, /* "UM EIN SCHÖNES MÄDCHEN ZU KÜSSEN." in ISO-8859-1/ISO-8859-15/CP1250/CP1252 */ + {D_STR_W_LEN ("Um ein sch\xc3\xb6nes M\xc3\xa4" "dchen zu k\xc3\xbcssen."), /* "Um ein schönes Mädchen zu küssen." in UTF-8 */ + D_STR_W_LEN ("UM EIN SCH\xc3\x96NES M\xc3\x84" "DCHEN ZU K\xc3\x9cSSEN."), + 11}, /* "UM EIN SCHÖNES MÄDCHEN ZU KÜSSEN." in UTF-8 */ + + {D_STR_W_LEN ("\x98stanbul"), /* "İstanbul" in CP857 */ + D_STR_W_LEN ("istanbul"), 0}, /* "istanbul" in CP857 */ + {D_STR_W_LEN ("\xddstanbul"), /* "İstanbul" in ISO-8859-9/CP1254 */ + D_STR_W_LEN ("istanbul"), 0}, /* "istanbul" in ISO-8859-9/CP1254 */ + {D_STR_W_LEN ("\xc4\xb0stanbul"), /* "İstanbul" in UTF-8 */ + D_STR_W_LEN ("istanbul"), 0}, /* "istanbul" in UTF-8 */ + {D_STR_W_LEN ("Diyarbak\x8dr"), /* "Diyarbakır" in CP857 */ + D_STR_W_LEN ("DiyarbakIR"), 8}, /* "DiyarbakIR" in CP857 */ + {D_STR_W_LEN ("Diyarbak\xfdr"), /* "Diyarbakır" in ISO-8859-9/CP1254 */ + D_STR_W_LEN ("DiyarbakIR"), 8}, /* "DiyarbakIR" in ISO-8859-9/CP1254 */ + {D_STR_W_LEN ("Diyarbak\xc4\xb1r"), /* "Diyarbakır" in UTF-8 */ + D_STR_W_LEN ("DiyarbakIR"), 8}, /* "DiyarbakIR" in UTF-8 */ + + {D_STR_W_LEN ("\x92\xa5\xe1\xe2\xae\xa2\xa0\xef \x91\xe2\xe0\xae\xaa\xa0."), /* "Тестовая Строка." in CP866 */ + D_STR_W_LEN ("\x92\x85\x91\x92\x8e\x82\x80\x9f \x91\x92\x90\x8e\x8a\x80."), + 1}, /* "ТЕСТОВАЯ СТРОКА." in CP866 */ + {D_STR_W_LEN ("\xd2\xe5\xf1\xf2\xee\xe2\xe0\xff \xd1\xf2\xf0\xee\xea\xe0."), /* "Тестовая Строка." in CP1251 */ + D_STR_W_LEN ("\xd2\xc5\xd1\xd2\xce\xc2\xc0\xdf \xd1\xd2\xd0\xce\xca\xc0."), + 1}, /* "ТЕСТОВАЯ СТРОКА." in CP1251 */ + {D_STR_W_LEN ("\xf4\xc5\xd3\xd4\xcf\xd7\xc1\xd1 \xf3\xd4\xd2\xcf\xcb\xc1."), /* "Тестовая Строка." in KOI8-R */ + D_STR_W_LEN ("\xf4\xe5\xf3\xf4\xef\xf7\xe1\xf1 \xf3\xf4\xf2\xef\xeb\xe1."), + 1}, /* "ТЕСТОВАЯ СТРОКА." in KOI8-R */ + {D_STR_W_LEN ("\xc2\xd5\xe1\xe2\xde\xd2\xd0\xef \xc1\xe2\xe0\xde\xda\xd0."), /* "Тестовая Строка." in ISO-8859-5 */ + D_STR_W_LEN ("\xc2\xb5\xc1\xc2\xbe\xb2\xb0\xcf \xc1\xc2\xc0\xbe\xba\xb0."), + 1}, /* "ТЕСТОВАЯ СТРОКА." in ISO-8859-5 */ + {D_STR_W_LEN ("\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbe\xd0\xb2\xd0\xb0\xd1" + "\x8f \xd0\xa1\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0."), /* "Тестовая Строка." in UTF-8 */ + D_STR_W_LEN ("\xd0\xa2\xd0\x95\xd0\xa1\xd0\xa2\xd0\x9e\xd0\x92\xd0\x90\xd0" + "\xaf \xd0\xa1\xd0\xa2\xd0\xa0\xd0\x9e\xd0\x9a\xd0\x90."), 3} /* "ТЕСТОВАЯ СТРОКА." in UTF-8 */ +}; + + +static size_t +check_eq_strings (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(eq_strings) / sizeof(eq_strings[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + const struct two_eq_strs *const t = eq_strings + i; + if (c_failed[i]) + continue; /* skip already failed checks */ + if (! mhd_str_equal_caseless (t->s1.str, t->s2.str)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless(\"%s\", \"%s\") returned zero, while expected non-zero." + " Locale: %s\n", n_prnt (t->s1.str), n_prnt (t->s2.str), + get_current_locale_str ()); + } + else if (! mhd_str_equal_caseless (t->s2.str, t->s1.str)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless(\"%s\", \"%s\") returned zero, while expected non-zero." + " Locale: %s\n", n_prnt (t->s2.str), n_prnt (t->s1.str), + get_current_locale_str ()); + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_equal_caseless(\"%s\", \"%s\") != 0 && \\\n" + " mhd_str_equal_caseless(\"%s\", \"%s\") != 0\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), + n_prnt (t->s2.str), n_prnt (t->s1.str)); + } + } + return t_failed; +} + + +static size_t +check_neq_strings (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(neq_strings) / sizeof(neq_strings[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + const struct two_neq_strs *const t = neq_strings + i; + if (c_failed[i]) + continue; /* skip already failed checks */ + if (mhd_str_equal_caseless (t->s1.str, t->s2.str)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless(\"%s\", \"%s\") returned non-zero, while expected zero." + " Locale: %s\n", n_prnt (t->s1.str), n_prnt (t->s2.str), + get_current_locale_str ()); + } + else if (mhd_str_equal_caseless (t->s2.str, t->s1.str)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless(\"%s\", \"%s\") returned non-zero, while expected zero." + " Locale: %s\n", n_prnt (t->s2.str), n_prnt (t->s1.str), + get_current_locale_str ()); + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_equal_caseless(\"%s\", \"%s\") == 0 && \\\n" + " mhd_str_equal_caseless(\"%s\", \"%s\") == 0\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), + n_prnt (t->s2.str), n_prnt (t->s1.str)); + } + } + return t_failed; +} + + +static size_t +check_eq_strings_n (void) +{ + size_t t_failed = 0; + size_t i, j, k; + int c_failed[sizeof(eq_strings) / sizeof(eq_strings[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t m_len; + const struct two_eq_strs *const t = eq_strings + i; + m_len = (t->s1.len > t->s2.len) ? t->s1.len : t->s2.len; + for (k = 0; k <= m_len + 1 && ! c_failed[i]; k++) + { + if (! mhd_str_equal_caseless_n (t->s1.str, t->s2.str, k)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless_n(\"%s\", \"%s\", %u) returned zero," + " while expected non-zero. Locale: %s\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), (unsigned int) k, + get_current_locale_str ()); + } + else if (! mhd_str_equal_caseless_n (t->s2.str, t->s1.str, k)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless_n(\"%s\", \"%s\", %u) returned zero," + " while expected non-zero. Locale: %s\n", + n_prnt (t->s2.str), n_prnt (t->s1.str), (unsigned int) k, + get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_equal_caseless_n(\"%s\", \"%s\", N) " \ + "!= 0 && \\\n" \ + " mhd_str_equal_caseless_n(\"%s\", \"%s\", N) " \ + "!= 0, where N is 0..%u\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), n_prnt (t->s2.str), + n_prnt (t->s1.str), (unsigned int) m_len + 1); + } + } + return t_failed; +} + + +static size_t +check_neq_strings_n (void) +{ + size_t t_failed = 0; + size_t i, j, k; + int c_failed[sizeof(neq_strings) / sizeof(neq_strings[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t m_len; + const struct two_neq_strs *const t = neq_strings + i; + m_len = t->s1.len > t->s2.len ? t->s1.len : t->s2.len; + if (t->dif_pos >= m_len) + { + fprintf (stderr, + "ERROR: neq_strings[%u] has wrong dif_pos (%u): dif_pos is expected to be less than " + "s1.len (%u) or s2.len (%u).\n", (unsigned int) i, (unsigned + int) t-> + dif_pos, + (unsigned int) t->s1.len, (unsigned int) t->s2.len); + exit (99); + } + if (t->dif_pos > t->s1.len) + { + fprintf (stderr, + "ERROR: neq_strings[%u] has wrong dif_pos (%u): dif_pos is expected to be less or " + "equal to s1.len (%u).\n", (unsigned int) i, (unsigned + int) t->dif_pos, + (unsigned int) t->s1.len); + exit (99); + } + if (t->dif_pos > t->s2.len) + { + fprintf (stderr, + "ERROR: neq_strings[%u] has wrong dif_pos (%u): dif_pos is expected to be less or " + "equal to s2.len (%u).\n", (unsigned int) i, (unsigned + int) t->dif_pos, + (unsigned int) t->s2.len); + exit (99); + } + for (k = 0; k <= m_len + 1 && ! c_failed[i]; k++) + { + if (k <= t->dif_pos) + { + if (! mhd_str_equal_caseless_n (t->s1.str, t->s2.str, k)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless_n(\"%s\", \"%s\", %u) returned zero," + " while expected non-zero. Locale: %s\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), (unsigned int) k, + get_current_locale_str ()); + } + else if (! mhd_str_equal_caseless_n (t->s2.str, t->s1.str, k)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless_n(\"%s\", \"%s\", %u) returned zero," + " while expected non-zero. Locale: %s\n", + n_prnt (t->s2.str), n_prnt (t->s1.str), (unsigned int) k, + get_current_locale_str ()); + } + } + else + { + if (mhd_str_equal_caseless_n (t->s1.str, t->s2.str, k)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless_n(\"%s\", \"%s\", %u) returned non-zero," + " while expected zero. Locale: %s\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), (unsigned int) k, + get_current_locale_str ()); + } + else if (mhd_str_equal_caseless_n (t->s2.str, t->s1.str, k)) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_equal_caseless_n(\"%s\", \"%s\", %u) returned non-zero," + " while expected zero. Locale: %s\n", + n_prnt (t->s2.str), n_prnt (t->s1.str), (unsigned int) k, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + { + printf ( + "PASSED: mhd_str_equal_caseless_n(\"%s\", \"%s\", N) != 0 && \\\n" + " mhd_str_equal_caseless_n(\"%s\", \"%s\", N) != 0, where N is 0..%u\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), n_prnt (t->s2.str), + n_prnt (t->s1.str), + (unsigned int) t->dif_pos); + + printf ( + "PASSED: mhd_str_equal_caseless_n(\"%s\", \"%s\", N) == 0 && \\\n" + " mhd_str_equal_caseless_n(\"%s\", \"%s\", N) == 0, where N is %u..%u\n", + n_prnt (t->s1.str), n_prnt (t->s2.str), n_prnt (t->s2.str), + n_prnt (t->s1.str), + (unsigned int) t->dif_pos + 1, (unsigned int) m_len + 1); + } + } + } + return t_failed; +} + + +/* + * Run eq/neq strings tests + */ +static int +run_eq_neq_str_tests (void) +{ + size_t str_equal_caseless_fails = 0; + size_t str_equal_caseless_n_fails = 0; + size_t res; + + res = check_eq_strings (); + if (res != 0) + { + str_equal_caseless_fails += res; + fprintf (stderr, "FAILED: testcase check_eq_strings() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_eq_strings() successfully passed.\n\n"); + + res = check_neq_strings (); + if (res != 0) + { + str_equal_caseless_fails += res; + fprintf (stderr, "FAILED: testcase check_neq_strings() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_neq_strings() successfully passed.\n\n"); + + if (str_equal_caseless_fails) + fprintf (stderr, + "FAILED: function mhd_str_equal_caseless() failed %lu time%s.\n\n", + (unsigned long) str_equal_caseless_fails, + str_equal_caseless_fails == 1 ? "" : + "s"); + else if (verbose > 0) + printf ( + "PASSED: function mhd_str_equal_caseless() successfully passed all checks.\n\n"); + + res = check_eq_strings_n (); + if (res != 0) + { + str_equal_caseless_n_fails += res; + fprintf (stderr, "FAILED: testcase check_eq_strings_n() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_eq_strings_n() successfully passed.\n\n"); + + res = check_neq_strings_n (); + if (res != 0) + { + str_equal_caseless_n_fails += res; + fprintf (stderr, "FAILED: testcase check_neq_strings_n() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_neq_strings_n() successfully passed.\n\n"); + + if (str_equal_caseless_n_fails) + fprintf (stderr, + "FAILED: function mhd_str_equal_caseless_n() failed %lu time%s.\n\n", + (unsigned long) str_equal_caseless_n_fails, + str_equal_caseless_n_fails == 1 ? "" : + "s"); + else if (verbose > 0) + printf ( + "PASSED: function mhd_str_equal_caseless_n() successfully passed all checks.\n\n"); + + if (str_equal_caseless_fails || str_equal_caseless_n_fails) + { + if (verbose > 0) + printf ("At least one test failed.\n"); + + return 1; + } + + if (verbose > 0) + printf ("All tests passed successfully.\n"); + + return 0; +} + + +int +main (int argc, + char *argv[]) +{ + if (has_param (argc, argv, "-v") || + has_param (argc, argv, "--verbose") || + has_param (argc, argv, "--verbose1")) + MHDT_set_verbosity (MHDT_VERB_LVL_BASIC); + if (has_param (argc, argv, "-vv") || + has_param (argc, argv, "--verbose2")) + MHDT_set_verbosity (MHDT_VERB_LVL_VERBOSE); + + return run_eq_neq_str_tests (); +} diff --git a/src/tests/unit/test_str_from_value.c b/src/tests/unit/test_str_from_value.c @@ -0,0 +1,1815 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2016 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/unit_str_test.h + * @brief Unit tests for mhd_str functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "../mhdt_checks.h" + +#include <stdio.h> +#include <locale.h> +#include <string.h> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else /* ! HAVE_INTTYPES_H */ +#define PRIu64 "llu" +#define PRIuPTR "u" +#define PRIX64 "llX" +#endif /* ! HAVE_INTTYPES_H */ +#include <stdint.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif /* HAVE_STDLIB_H */ +#include "mhd_limits.h" +#include "mhd_str.h" +#include "test_helpers.h" + + +static int verbose = 0; /* verbose level (0-3)*/ + +/* Locale names to test. + * Functions must not depend of current current locale, + * so result must be the same in any locale. + */ +static const char *const locale_names[] = { + "C", + "", /* System default locale */ +#if defined(_WIN32) && ! defined(__CYGWIN__) + ".OCP", /* W32 system default OEM code page */ + ".ACP", /* W32 system default ANSI code page */ + ".65001", /* UTF-8 */ + ".437", + ".850", + ".857", + ".866", + ".1250", + ".1251", + ".1252", + "en", + "english", + "French_France", + "Turkish_Turkey.1254", + "de", + "zh-Hans", + "ru-RU.1251" +#if 0 /* Disabled extra checks */ + , + ".1254", + ".20866", /* number for KOI8-R */ + ".28591", /* number for ISO-8859-1 */ + ".28595", /* number for ISO-8859-5 */ + ".28599", /* number for ISO-8859-9 */ + ".28605", /* number for ISO-8859-15 */ + "en-US", + "English-US", + "en-US.437", + "English_United States.437", + "en-US.1252", + "English_United States.1252", + "English_United States.28591", + "English_United States.65001", + "fra", + "french", + "fr-FR", + "fr-FR.850", + "french_france.850", + "fr-FR.1252", + "French_france.1252", + "French_france.28605", + "French_France.65001", + "de-DE", + "de-DE.850", + "German_Germany.850", + "German_Germany.1250", + "de-DE.1252", + "German_Germany.1252", + "German_Germany.28605", + "German_Germany.65001", + "tr", + "trk", + "turkish", + "tr-TR", + "tr-TR.1254", + "tr-TR.857", + "Turkish_Turkey.857", + "Turkish_Turkey.28599", + "Turkish_Turkey.65001", + "ru", + "ru-RU", + "Russian", + "ru-RU.866", + "Russian_Russia.866", + "Russian_Russia.1251", + "Russian_Russia.20866", + "Russian_Russia.28595", + "Russian_Russia.65001", + "zh-Hans.936", + "chinese-simplified" +#endif /* Disabled extra checks */ +#else /* ! _WIN32 || __CYGWIN__ */ + "C.UTF-8", + "POSIX", + "en", + "en_US", + "en_US.ISO-8859-1", + "en_US.ISO_8859-1", + "en_US.ISO8859-1", + "en_US.iso88591", + "en_US.ISO-8859-15", + "en_US.DIS_8859-15", + "en_US.ISO8859-15", + "en_US.iso885915", + "en_US.1252", + "en_US.CP1252", + "en_US.UTF-8", + "en_US.utf8", + "fr", + "fr_FR", + "fr_FR.850", + "fr_FR.IBM850", + "fr_FR.1252", + "fr_FR.CP1252", + "fr_FR.ISO-8859-1", + "fr_FR.ISO_8859-1", + "fr_FR.ISO8859-1", + "fr_FR.iso88591", + "fr_FR.ISO-8859-15", + "fr_FR.DIS_8859-15", + "fr_FR.ISO8859-15", + "fr_FR.iso8859-15", + "fr_FR.UTF-8", + "fr_FR.utf8", + "de", + "de_DE", + "de_DE.850", + "de_DE.IBM850", + "de_DE.1250", + "de_DE.CP1250", + "de_DE.1252", + "de_DE.CP1252", + "de_DE.ISO-8859-1", + "de_DE.ISO_8859-1", + "de_DE.ISO8859-1", + "de_DE.iso88591", + "de_DE.ISO-8859-15", + "de_DE.DIS_8859-15", + "de_DE.ISO8859-15", + "de_DE.iso885915", + "de_DE.UTF-8", + "de_DE.utf8", + "tr", + "tr_TR", + "tr_TR.1254", + "tr_TR.CP1254", + "tr_TR.857", + "tr_TR.IBM857", + "tr_TR.ISO-8859-9", + "tr_TR.ISO8859-9", + "tr_TR.iso88599", + "tr_TR.UTF-8", + "tr_TR.utf8", + "ru", + "ru_RU", + "ru_RU.1251", + "ru_RU.CP1251", + "ru_RU.866", + "ru_RU.IBM866", + "ru_RU.KOI8-R", + "ru_RU.koi8-r", + "ru_RU.KOI8-RU", + "ru_RU.ISO-8859-5", + "ru_RU.ISO_8859-5", + "ru_RU.ISO8859-5", + "ru_RU.iso88595", + "ru_RU.UTF-8", + "zh_CN", + "zh_CN.GB2312", + "zh_CN.UTF-8", +#endif /* ! _WIN32 || __CYGWIN__ */ +}; + +static const unsigned int locale_name_count = sizeof(locale_names) + / sizeof(locale_names[0]); + + +/* + * Helper functions + */ + +static int +set_test_locale (size_t num) +{ + if (num >= locale_name_count) + { + fprintf (stderr, "Unexpected number of locale.\n"); + exit (99); + } + if (verbose > 2) + printf ("Setting locale \"%s\":", locale_names[num]); + if (setlocale (LC_ALL, locale_names[num])) + { + if (verbose > 2) + printf (" succeed.\n"); + return 1; + } + if (verbose > 2) + printf (" failed.\n"); + return 0; +} + + +static const char * +get_current_locale_str (void) +{ + char const *loc_str = setlocale (LC_ALL, NULL); + return loc_str ? loc_str : "unknown"; +} + + +struct str_with_len +{ + const char *const str; + const size_t len; +}; + +#define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} + +/* + * Digits in string -> value tests + */ + +struct str_with_value +{ + const struct str_with_len str; + const size_t num_of_digt; + const uint64_t val; +}; + +/* valid string for conversion to unsigned integer value */ +static const struct str_with_value dstrs_w_values[] = { + /* simplest strings */ + {D_STR_W_LEN ("1"), 1, 1}, + {D_STR_W_LEN ("0"), 1, 0}, + {D_STR_W_LEN ("10000"), 5, 10000}, + + /* all digits */ + {D_STR_W_LEN ("1234"), 4, 1234}, + {D_STR_W_LEN ("4567"), 4, 4567}, + {D_STR_W_LEN ("7890"), 4, 7890}, + {D_STR_W_LEN ("8021"), 4, 8021}, + {D_STR_W_LEN ("9754"), 4, 9754}, + {D_STR_W_LEN ("6392"), 4, 6392}, + + /* various prefixes */ + {D_STR_W_LEN ("00000000"), 8, 0}, + {D_STR_W_LEN ("0755"), 4, 755}, /* not to be interpreted as octal value! */ + {D_STR_W_LEN ("002"), 3, 2}, + {D_STR_W_LEN ("0001"), 4, 1}, + {D_STR_W_LEN ("00000000000000000000000031295483"), 32, 31295483}, + + /* numbers below and above limits */ + {D_STR_W_LEN ("127"), 3, 127}, /* 0x7F, SCHAR_MAX */ + {D_STR_W_LEN ("128"), 3, 128}, /* 0x80, SCHAR_MAX+1 */ + {D_STR_W_LEN ("255"), 3, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("256"), 3, 256}, /* 0x100, UCHAR_MAX+1 */ + {D_STR_W_LEN ("32767"), 5, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("32768"), 5, 32768}, /* 0x8000, INT16_MAX+1 */ + {D_STR_W_LEN ("65535"), 5, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("65536"), 5, 65536}, /* 0x10000, UINT16_MAX+1 */ + {D_STR_W_LEN ("2147483647"), 10, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("2147483648"), 10, UINT64_C (2147483648)}, /* 0x80000000, INT32_MAX+1 */ + {D_STR_W_LEN ("4294967295"), 10, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("4294967296"), 10, UINT64_C (4294967296)}, /* 0x100000000, UINT32_MAX+1 */ + {D_STR_W_LEN ("9223372036854775807"), 19, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("9223372036854775808"), 19, UINT64_C (9223372036854775808)}, /* 0x8000000000000000, INT64_MAX+1 */ + {D_STR_W_LEN ("18446744073709551615"), 20, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + + /* random numbers */ + {D_STR_W_LEN ("10186753"), 8, 10186753}, + {D_STR_W_LEN ("144402566"), 9, 144402566}, + {D_STR_W_LEN ("151903144"), 9, 151903144}, + {D_STR_W_LEN ("139264621"), 9, 139264621}, + {D_STR_W_LEN ("730348"), 6, 730348}, + {D_STR_W_LEN ("21584377"), 8, 21584377}, + {D_STR_W_LEN ("709"), 3, 709}, + {D_STR_W_LEN ("54"), 2, 54}, + {D_STR_W_LEN ("8452"), 4, 8452}, + {D_STR_W_LEN ("17745098750013624977"), 20, UINT64_C (17745098750013624977)}, + {D_STR_W_LEN ("06786878769931678000"), 20, UINT64_C (6786878769931678000)}, + + /* non-digit suffixes */ + {D_STR_W_LEN ("1234oa"), 4, 1234}, + {D_STR_W_LEN ("20h"), 2, 20}, /* not to be interpreted as hex value! */ + {D_STR_W_LEN ("0x1F"), 1, 0}, /* not to be interpreted as hex value! */ + {D_STR_W_LEN ("0564`~}"), 4, 564}, + {D_STR_W_LEN ("7240146.724"), 7, 7240146}, + {D_STR_W_LEN ("2,9"), 1, 2}, + {D_STR_W_LEN ("200+1"), 3, 200}, + {D_STR_W_LEN ("1a"), 1, 1}, + {D_STR_W_LEN ("2E"), 1, 2}, + {D_STR_W_LEN ("6c"), 1, 6}, + {D_STR_W_LEN ("8F"), 1, 8}, + {D_STR_W_LEN ("287416997! And the not too long string."), 9, 287416997} +}; + + +/* valid hex string for conversion to unsigned integer value */ +static const struct str_with_value xdstrs_w_values[] = { + /* simplest strings */ + {D_STR_W_LEN ("1"), 1, 0x1}, + {D_STR_W_LEN ("0"), 1, 0x0}, + {D_STR_W_LEN ("10000"), 5, 0x10000}, + + /* all digits */ + {D_STR_W_LEN ("1234"), 4, 0x1234}, + {D_STR_W_LEN ("4567"), 4, 0x4567}, + {D_STR_W_LEN ("7890"), 4, 0x7890}, + {D_STR_W_LEN ("8021"), 4, 0x8021}, + {D_STR_W_LEN ("9754"), 4, 0x9754}, + {D_STR_W_LEN ("6392"), 4, 0x6392}, + {D_STR_W_LEN ("abcd"), 4, 0xABCD}, + {D_STR_W_LEN ("cdef"), 4, 0xCDEF}, + {D_STR_W_LEN ("FEAB"), 4, 0xFEAB}, + {D_STR_W_LEN ("BCED"), 4, 0xBCED}, + {D_STR_W_LEN ("bCeD"), 4, 0xBCED}, + {D_STR_W_LEN ("1A5F"), 4, 0x1A5F}, + {D_STR_W_LEN ("12AB"), 4, 0x12AB}, + {D_STR_W_LEN ("CD34"), 4, 0xCD34}, + {D_STR_W_LEN ("56EF"), 4, 0x56EF}, + {D_STR_W_LEN ("7a9f"), 4, 0x7A9F}, + + /* various prefixes */ + {D_STR_W_LEN ("00000000"), 8, 0x0}, + {D_STR_W_LEN ("0755"), 4, 0x755}, /* not to be interpreted as octal value! */ + {D_STR_W_LEN ("002"), 3, 0x2}, + {D_STR_W_LEN ("0001"), 4, 0x1}, + {D_STR_W_LEN ("00a"), 3, 0xA}, + {D_STR_W_LEN ("0F"), 2, 0xF}, + {D_STR_W_LEN ("0000000000000000000000003A29e4C3"), 32, 0x3A29E4C3}, + + /* numbers below and above limits */ + {D_STR_W_LEN ("7F"), 2, 127}, /* 0x7F, SCHAR_MAX */ + {D_STR_W_LEN ("7f"), 2, 127}, /* 0x7F, SCHAR_MAX */ + {D_STR_W_LEN ("80"), 2, 128}, /* 0x80, SCHAR_MAX+1 */ + {D_STR_W_LEN ("fF"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("Ff"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("FF"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("ff"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("100"), 3, 256}, /* 0x100, UCHAR_MAX+1 */ + {D_STR_W_LEN ("7fff"), 4, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("7FFF"), 4, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("7Fff"), 4, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("8000"), 4, 32768}, /* 0x8000, INT16_MAX+1 */ + {D_STR_W_LEN ("ffff"), 4, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("FFFF"), 4, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("FffF"), 4, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("10000"), 5, 65536}, /* 0x10000, UINT16_MAX+1 */ + {D_STR_W_LEN ("7FFFFFFF"), 8, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("7fffffff"), 8, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("7FFffFff"), 8, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("80000000"), 8, UINT64_C (2147483648)}, /* 0x80000000, INT32_MAX+1 */ + {D_STR_W_LEN ("FFFFFFFF"), 8, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("ffffffff"), 8, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("FfFfFfFf"), 8, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("100000000"), 9, UINT64_C (4294967296)}, /* 0x100000000, UINT32_MAX+1 */ + {D_STR_W_LEN ("7fffffffffffffff"), 16, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("7FFFFFFFFFFFFFFF"), 16, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("7FfffFFFFffFFffF"), 16, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("8000000000000000"), 16, UINT64_C (9223372036854775808)}, /* 0x8000000000000000, INT64_MAX+1 */ + {D_STR_W_LEN ("ffffffffffffffff"), 16, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + {D_STR_W_LEN ("FFFFFFFFFFFFFFFF"), 16, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + {D_STR_W_LEN ("FffFffFFffFFfFFF"), 16, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + + /* random numbers */ + {D_STR_W_LEN ("10186753"), 8, 0x10186753}, + {D_STR_W_LEN ("144402566"), 9, 0x144402566}, + {D_STR_W_LEN ("151903144"), 9, 0x151903144}, + {D_STR_W_LEN ("139264621"), 9, 0x139264621}, + {D_STR_W_LEN ("730348"), 6, 0x730348}, + {D_STR_W_LEN ("21584377"), 8, 0x21584377}, + {D_STR_W_LEN ("709"), 3, 0x709}, + {D_STR_W_LEN ("54"), 2, 0x54}, + {D_STR_W_LEN ("8452"), 4, 0x8452}, + {D_STR_W_LEN ("22353EC6"), 8, 0x22353EC6}, + {D_STR_W_LEN ("307F1655"), 8, 0x307F1655}, + {D_STR_W_LEN ("1FCB7226"), 8, 0x1FCB7226}, + {D_STR_W_LEN ("82480560"), 8, 0x82480560}, + {D_STR_W_LEN ("7386D95"), 7, 0x7386D95}, + {D_STR_W_LEN ("EC3AB"), 5, 0xEC3AB}, + {D_STR_W_LEN ("6DD05"), 5, 0x6DD05}, + {D_STR_W_LEN ("C5DF"), 4, 0xC5DF}, + {D_STR_W_LEN ("6CE"), 3, 0x6CE}, + {D_STR_W_LEN ("CE6"), 3, 0xCE6}, + {D_STR_W_LEN ("ce6"), 3, 0xCE6}, + {D_STR_W_LEN ("F27"), 3, 0xF27}, + {D_STR_W_LEN ("8497D54277D7E1"), 14, UINT64_C (37321639124785121)}, + {D_STR_W_LEN ("8497d54277d7e1"), 14, UINT64_C (37321639124785121)}, + {D_STR_W_LEN ("8497d54277d7E1"), 14, UINT64_C (37321639124785121)}, + {D_STR_W_LEN ("8C8112D0A06"), 11, UINT64_C (9655374645766)}, + {D_STR_W_LEN ("8c8112d0a06"), 11, UINT64_C (9655374645766)}, + {D_STR_W_LEN ("8c8112d0A06"), 11, UINT64_C (9655374645766)}, + {D_STR_W_LEN ("1774509875001362"), 16, UINT64_C (1690064375898968930)}, + {D_STR_W_LEN ("0678687876998000"), 16, UINT64_C (466237428027981824)}, + + /* non-digit suffixes */ + {D_STR_W_LEN ("1234oa"), 4, 0x1234}, + {D_STR_W_LEN ("20h"), 2, 0x20}, + {D_STR_W_LEN ("2CH"), 2, 0x2C}, + {D_STR_W_LEN ("2ch"), 2, 0x2C}, + {D_STR_W_LEN ("0x1F"), 1, 0x0}, /* not to be interpreted as hex prefix! */ + {D_STR_W_LEN ("0564`~}"), 4, 0x564}, + {D_STR_W_LEN ("0A64`~}"), 4, 0xA64}, + {D_STR_W_LEN ("056c`~}"), 4, 0X56C}, + {D_STR_W_LEN ("7240146.724"), 7, 0x7240146}, + {D_STR_W_LEN ("7E4c1AB.724"), 7, 0X7E4C1AB}, + {D_STR_W_LEN ("F24B1B6.724"), 7, 0xF24B1B6}, + {D_STR_W_LEN ("2,9"), 1, 0x2}, + {D_STR_W_LEN ("a,9"), 1, 0xA}, + {D_STR_W_LEN ("200+1"), 3, 0x200}, + {D_STR_W_LEN ("2cc+1"), 3, 0x2CC}, + {D_STR_W_LEN ("2cC+1"), 3, 0x2CC}, + {D_STR_W_LEN ("27416997! And the not too long string."), 8, 0x27416997}, + {D_STR_W_LEN ("27555416997! And the not too long string."), 11, + 0x27555416997}, + {D_STR_W_LEN ("416997And the not too long string."), 7, 0x416997A}, + {D_STR_W_LEN ("0F4C3Dabstract addition to make string even longer"), 8, + 0xF4C3DAB} +}; + + +static size_t +check_str_from_uint16 (void) +{ + size_t t_failed = 0; + size_t i, j; + char buf[70]; + const char *erase = + "-@=sd#+&(pdiren456qwe#@C3S!DAS45AOIPUQWESAdFzxcv1s*()&#$%34`" + "32452d098poiden45SADFFDA3S4D3SDFdfgsdfgsSADFzxdvs$*()&#2342`" + "adsf##$$@&*^%*^&56qwe#3C@S!DAScFAOIP$#%#$Ad1zs3v1$*()&#1228`"; + int c_failed[sizeof(dstrs_w_values) + / sizeof(dstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + const struct str_with_value *const t = dstrs_w_values + i; + size_t b_size; + size_t rs; + + if (c_failed[i]) + continue; /* skip already failed checks */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + if ('0' == t->str.str[0]) + continue; /* Skip strings prefixed with zeros */ + if (t->num_of_digt != t->str.len) + continue; /* Skip strings with suffixes */ + if (UINT16_MAX < t->val) + continue; /* Too large value to convert */ + if (sizeof(buf) < t->str.len + 1) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has too long (%u) string, " + "size of 'buf' should be increased.\n", + (unsigned int) i, (unsigned int) t->str.len); + exit (99); + } + rs = 0; /* Only to mute compiler warning */ + for (b_size = 0; b_size <= t->str.len + 1; ++b_size) + { + /* fill buffer with pseudo-random values */ + memcpy (buf, erase, sizeof(buf)); + + rs = mhd_uint16_to_str ((uint16_t) t->val, buf, b_size); + + if (t->num_of_digt > b_size) + { + /* Must fail, buffer is too small for result */ + if (0 != rs) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint16_to_str(%" PRIu64 ", -> buf," + " %d) returned %" PRIuPTR + ", while expecting 0." + " Locale: %s\n", t->val, (int) b_size, (uintptr_t) rs, + get_current_locale_str ()); + } + } + else + { + if (t->num_of_digt != rs) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint16_to_str(%" PRIu64 ", -> buf," + " %d) returned %" PRIuPTR + ", while expecting %d." + " Locale: %s\n", t->val, (int) b_size, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + else if (0 != memcmp (buf, t->str.str, t->num_of_digt)) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint16_to_str(%" PRIu64 ", -> \"%.*s\"," + " %d) returned %" PRIuPTR "." + " Locale: %s\n", t->val, (int) rs, buf, (int) b_size, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs)) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint16_to_str(%" PRIu64 ", -> \"%.*s\"," + " %d) returned %" PRIuPTR + " and touched data after the resulting string." + " Locale: %s\n", t->val, (int) rs, buf, (int) b_size, + (uintptr_t) rs, get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_uint16_to_str(%" PRIu64 ", -> \"%.*s\", %d) " + "== %" PRIuPTR "\n", + t->val, (int) rs, buf, (int) b_size - 1, (uintptr_t) rs); + } + } + return t_failed; +} + + +static size_t +check_str_from_uint64 (void) +{ + size_t t_failed = 0; + size_t i, j; + char buf[70]; + const char *erase = + "-@=sd#+&(pdirenDSFGSe#@C&S!DAS*!AOIPUQWESAdFzxcvSs*()&#$%KH`" + "32452d098poiden45SADFFDA3S4D3SDFdfgsdfgsSADFzxdvs$*()&#2342`" + "adsf##$$@&*^%*^&56qwe#3C@S!DAScFAOIP$#%#$Ad1zs3v1$*()&#1228`"; + int c_failed[sizeof(dstrs_w_values) + / sizeof(dstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + const struct str_with_value *const t = dstrs_w_values + i; + size_t b_size; + size_t rs; + + if (c_failed[i]) + continue; /* skip already failed checks */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + if ('0' == t->str.str[0]) + continue; /* Skip strings prefixed with zeros */ + if (t->num_of_digt != t->str.len) + continue; /* Skip strings with suffixes */ + if (sizeof(buf) < t->str.len + 1) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has too long (%u) string, " + "size of 'buf' should be increased.\n", + (unsigned int) i, (unsigned int) t->str.len); + exit (99); + } + rs = 0; /* Only to mute compiler warning */ + for (b_size = 0; b_size <= t->str.len + 1; ++b_size) + { + /* fill buffer with pseudo-random values */ + memcpy (buf, erase, sizeof(buf)); + + rs = mhd_uint64_to_str (t->val, buf, b_size); + + if (t->num_of_digt > b_size) + { + /* Must fail, buffer is too small for result */ + if (0 != rs) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint64_to_str(%" PRIu64 ", -> buf," + " %d) returned %" PRIuPTR + ", while expecting 0." + " Locale: %s\n", t->val, (int) b_size, (uintptr_t) rs, + get_current_locale_str ()); + } + } + else + { + if (t->num_of_digt != rs) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint64_to_str(%" PRIu64 ", -> buf," + " %d) returned %" PRIuPTR + ", while expecting %d." + " Locale: %s\n", t->val, (int) b_size, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + else if (0 != memcmp (buf, t->str.str, t->num_of_digt)) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint64_to_str(%" PRIu64 ", -> \"%.*s\"," + " %d) returned %" PRIuPTR "." + " Locale: %s\n", t->val, (int) rs, buf, (int) b_size, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs)) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint64_to_str(%" PRIu64 ", -> \"%.*s\"," + " %d) returned %" PRIuPTR + " and touched data after the resulting string." + " Locale: %s\n", t->val, (int) rs, buf, (int) b_size, + (uintptr_t) rs, get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_uint64_to_str(%" PRIu64 ", -> \"%.*s\", %d) " + "== %" PRIuPTR "\n", + t->val, (int) rs, buf, (int) b_size - 1, (uintptr_t) rs); + } + } + return t_failed; +} + + +static size_t +check_strx_from_uint32 (void) +{ + size_t t_failed = 0; + size_t i, j; + char buf[70]; + const char *erase = + "jrlkjssfhjfvrjntJHLJ$@%$#adsfdkj;k$##$%#$%FGDF%$#^FDFG%$#$D`" + ";skjdhjflsdkjhdjfalskdjhdfalkjdhf$%##%$$#%FSDGFSDDGDFSSDSDF`" + "#5#$%#$#$DFSFDDFSGSDFSDF354FDDSGFDFfdssfddfswqemn,.zxih,.sx`"; + int c_failed[sizeof(xdstrs_w_values) + / sizeof(xdstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + const struct str_with_value *const t = xdstrs_w_values + i; + size_t b_size; + size_t rs; + + if (c_failed[i]) + continue; /* skip already failed checks */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + if ('0' == t->str.str[0]) + continue; /* Skip strings prefixed with zeros */ + if (t->num_of_digt != t->str.len) + continue; /* Skip strings with suffixes */ + if (UINT32_MAX < t->val) + continue; /* Too large value to convert */ + if (sizeof(buf) < t->str.len + 1) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has too long (%u) string, " + "size of 'buf' should be increased.\n", + (unsigned int) i, (unsigned int) t->str.len); + exit (99); + } + rs = 0; /* Only to mute compiler warning */ + for (b_size = 0; b_size <= t->str.len + 1; ++b_size) + { + /* fill buffer with pseudo-random values */ + memcpy (buf, erase, sizeof(buf)); + + rs = mhd_uint32_to_strx ((uint32_t) t->val, buf, b_size); + + if (t->num_of_digt > b_size) + { + /* Must fail, buffer is too small for result */ + if (0 != rs) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint32_to_strx(0x%" PRIX64 ", -> buf," + " %d) returned %" PRIuPTR + ", while expecting 0." + " Locale: %s\n", t->val, (int) b_size, (uintptr_t) rs, + get_current_locale_str ()); + } + } + else + { + if (t->num_of_digt != rs) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint32_to_strx(0x%" PRIX64 ", -> buf," + " %d) returned %" PRIuPTR + ", while expecting %d." + " Locale: %s\n", t->val, (int) b_size, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + else if (0 == mhd_str_equal_caseless_bin_n (buf, t->str.str, + t->num_of_digt)) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint32_to_strx(0x%" PRIX64 ", -> \"%.*s\"," + " %d) returned %" PRIuPTR "." + " Locale: %s\n", t->val, (int) rs, buf, (int) b_size, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (sizeof(buf) <= rs) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has string with too many" + "(%u) digits, size of 'buf' should be increased.\n", + (unsigned int) i, (unsigned int) rs); + exit (99); + } + else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs)) + { + if (0 == c_failed[i]) + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_uint32_to_strx(0x%" PRIX64 ", -> \"%.*s\"," + " %d) returned %" PRIuPTR + " and touched data after the resulting string." + " Locale: %s\n", t->val, (int) rs, buf, (int) b_size, + (uintptr_t) rs, get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_uint32_to_strx(0x%" PRIX64 ", -> \"%.*s\", %d) " + "== %" PRIuPTR "\n", + t->val, (int) rs, buf, (int) b_size - 1, (uintptr_t) rs); + } + } + return t_failed; +} + + +static const struct str_with_value duint8_w_values_p1[] = { + {D_STR_W_LEN ("0"), 1, 0}, + {D_STR_W_LEN ("1"), 1, 1}, + {D_STR_W_LEN ("2"), 1, 2}, + {D_STR_W_LEN ("3"), 1, 3}, + {D_STR_W_LEN ("4"), 1, 4}, + {D_STR_W_LEN ("5"), 1, 5}, + {D_STR_W_LEN ("6"), 1, 6}, + {D_STR_W_LEN ("7"), 1, 7}, + {D_STR_W_LEN ("8"), 1, 8}, + {D_STR_W_LEN ("9"), 1, 9}, + {D_STR_W_LEN ("10"), 2, 10}, + {D_STR_W_LEN ("11"), 2, 11}, + {D_STR_W_LEN ("12"), 2, 12}, + {D_STR_W_LEN ("13"), 2, 13}, + {D_STR_W_LEN ("14"), 2, 14}, + {D_STR_W_LEN ("15"), 2, 15}, + {D_STR_W_LEN ("16"), 2, 16}, + {D_STR_W_LEN ("17"), 2, 17}, + {D_STR_W_LEN ("18"), 2, 18}, + {D_STR_W_LEN ("19"), 2, 19}, + {D_STR_W_LEN ("20"), 2, 20}, + {D_STR_W_LEN ("21"), 2, 21}, + {D_STR_W_LEN ("22"), 2, 22}, + {D_STR_W_LEN ("23"), 2, 23}, + {D_STR_W_LEN ("24"), 2, 24}, + {D_STR_W_LEN ("25"), 2, 25}, + {D_STR_W_LEN ("26"), 2, 26}, + {D_STR_W_LEN ("27"), 2, 27}, + {D_STR_W_LEN ("28"), 2, 28}, + {D_STR_W_LEN ("29"), 2, 29}, + {D_STR_W_LEN ("30"), 2, 30}, + {D_STR_W_LEN ("31"), 2, 31}, + {D_STR_W_LEN ("32"), 2, 32}, + {D_STR_W_LEN ("33"), 2, 33}, + {D_STR_W_LEN ("34"), 2, 34}, + {D_STR_W_LEN ("35"), 2, 35}, + {D_STR_W_LEN ("36"), 2, 36}, + {D_STR_W_LEN ("37"), 2, 37}, + {D_STR_W_LEN ("38"), 2, 38}, + {D_STR_W_LEN ("39"), 2, 39}, + {D_STR_W_LEN ("40"), 2, 40}, + {D_STR_W_LEN ("41"), 2, 41}, + {D_STR_W_LEN ("42"), 2, 42}, + {D_STR_W_LEN ("43"), 2, 43}, + {D_STR_W_LEN ("44"), 2, 44}, + {D_STR_W_LEN ("45"), 2, 45}, + {D_STR_W_LEN ("46"), 2, 46}, + {D_STR_W_LEN ("47"), 2, 47}, + {D_STR_W_LEN ("48"), 2, 48}, + {D_STR_W_LEN ("49"), 2, 49}, + {D_STR_W_LEN ("50"), 2, 50}, + {D_STR_W_LEN ("51"), 2, 51}, + {D_STR_W_LEN ("52"), 2, 52}, + {D_STR_W_LEN ("53"), 2, 53}, + {D_STR_W_LEN ("54"), 2, 54}, + {D_STR_W_LEN ("55"), 2, 55}, + {D_STR_W_LEN ("56"), 2, 56}, + {D_STR_W_LEN ("57"), 2, 57}, + {D_STR_W_LEN ("58"), 2, 58}, + {D_STR_W_LEN ("59"), 2, 59}, + {D_STR_W_LEN ("60"), 2, 60}, + {D_STR_W_LEN ("61"), 2, 61}, + {D_STR_W_LEN ("62"), 2, 62}, + {D_STR_W_LEN ("63"), 2, 63}, + {D_STR_W_LEN ("64"), 2, 64}, + {D_STR_W_LEN ("65"), 2, 65}, + {D_STR_W_LEN ("66"), 2, 66}, + {D_STR_W_LEN ("67"), 2, 67}, + {D_STR_W_LEN ("68"), 2, 68}, + {D_STR_W_LEN ("69"), 2, 69}, + {D_STR_W_LEN ("70"), 2, 70}, + {D_STR_W_LEN ("71"), 2, 71}, + {D_STR_W_LEN ("72"), 2, 72}, + {D_STR_W_LEN ("73"), 2, 73}, + {D_STR_W_LEN ("74"), 2, 74}, + {D_STR_W_LEN ("75"), 2, 75}, + {D_STR_W_LEN ("76"), 2, 76}, + {D_STR_W_LEN ("77"), 2, 77}, + {D_STR_W_LEN ("78"), 2, 78}, + {D_STR_W_LEN ("79"), 2, 79}, + {D_STR_W_LEN ("80"), 2, 80}, + {D_STR_W_LEN ("81"), 2, 81}, + {D_STR_W_LEN ("82"), 2, 82}, + {D_STR_W_LEN ("83"), 2, 83}, + {D_STR_W_LEN ("84"), 2, 84}, + {D_STR_W_LEN ("85"), 2, 85}, + {D_STR_W_LEN ("86"), 2, 86}, + {D_STR_W_LEN ("87"), 2, 87}, + {D_STR_W_LEN ("88"), 2, 88}, + {D_STR_W_LEN ("89"), 2, 89}, + {D_STR_W_LEN ("90"), 2, 90}, + {D_STR_W_LEN ("91"), 2, 91}, + {D_STR_W_LEN ("92"), 2, 92}, + {D_STR_W_LEN ("93"), 2, 93}, + {D_STR_W_LEN ("94"), 2, 94}, + {D_STR_W_LEN ("95"), 2, 95}, + {D_STR_W_LEN ("96"), 2, 96}, + {D_STR_W_LEN ("97"), 2, 97}, + {D_STR_W_LEN ("98"), 2, 98}, + {D_STR_W_LEN ("99"), 2, 99}, + {D_STR_W_LEN ("100"), 3, 100}, + {D_STR_W_LEN ("101"), 3, 101}, + {D_STR_W_LEN ("102"), 3, 102}, + {D_STR_W_LEN ("103"), 3, 103}, + {D_STR_W_LEN ("104"), 3, 104}, + {D_STR_W_LEN ("105"), 3, 105}, + {D_STR_W_LEN ("106"), 3, 106}, + {D_STR_W_LEN ("107"), 3, 107}, + {D_STR_W_LEN ("108"), 3, 108}, + {D_STR_W_LEN ("109"), 3, 109}, + {D_STR_W_LEN ("110"), 3, 110}, + {D_STR_W_LEN ("111"), 3, 111}, + {D_STR_W_LEN ("112"), 3, 112}, + {D_STR_W_LEN ("113"), 3, 113}, + {D_STR_W_LEN ("114"), 3, 114}, + {D_STR_W_LEN ("115"), 3, 115}, + {D_STR_W_LEN ("116"), 3, 116}, + {D_STR_W_LEN ("117"), 3, 117}, + {D_STR_W_LEN ("118"), 3, 118}, + {D_STR_W_LEN ("119"), 3, 119}, + {D_STR_W_LEN ("120"), 3, 120}, + {D_STR_W_LEN ("121"), 3, 121}, + {D_STR_W_LEN ("122"), 3, 122}, + {D_STR_W_LEN ("123"), 3, 123}, + {D_STR_W_LEN ("124"), 3, 124}, + {D_STR_W_LEN ("125"), 3, 125}, + {D_STR_W_LEN ("126"), 3, 126}, + {D_STR_W_LEN ("127"), 3, 127}, + {D_STR_W_LEN ("128"), 3, 128}, + {D_STR_W_LEN ("129"), 3, 129}, + {D_STR_W_LEN ("130"), 3, 130}, + {D_STR_W_LEN ("131"), 3, 131}, + {D_STR_W_LEN ("132"), 3, 132}, + {D_STR_W_LEN ("133"), 3, 133}, + {D_STR_W_LEN ("134"), 3, 134}, + {D_STR_W_LEN ("135"), 3, 135}, + {D_STR_W_LEN ("136"), 3, 136}, + {D_STR_W_LEN ("137"), 3, 137}, + {D_STR_W_LEN ("138"), 3, 138}, + {D_STR_W_LEN ("139"), 3, 139}, + {D_STR_W_LEN ("140"), 3, 140}, + {D_STR_W_LEN ("141"), 3, 141}, + {D_STR_W_LEN ("142"), 3, 142}, + {D_STR_W_LEN ("143"), 3, 143}, + {D_STR_W_LEN ("144"), 3, 144}, + {D_STR_W_LEN ("145"), 3, 145}, + {D_STR_W_LEN ("146"), 3, 146}, + {D_STR_W_LEN ("147"), 3, 147}, + {D_STR_W_LEN ("148"), 3, 148}, + {D_STR_W_LEN ("149"), 3, 149}, + {D_STR_W_LEN ("150"), 3, 150}, + {D_STR_W_LEN ("151"), 3, 151}, + {D_STR_W_LEN ("152"), 3, 152}, + {D_STR_W_LEN ("153"), 3, 153}, + {D_STR_W_LEN ("154"), 3, 154}, + {D_STR_W_LEN ("155"), 3, 155}, + {D_STR_W_LEN ("156"), 3, 156}, + {D_STR_W_LEN ("157"), 3, 157}, + {D_STR_W_LEN ("158"), 3, 158}, + {D_STR_W_LEN ("159"), 3, 159}, + {D_STR_W_LEN ("160"), 3, 160}, + {D_STR_W_LEN ("161"), 3, 161}, + {D_STR_W_LEN ("162"), 3, 162}, + {D_STR_W_LEN ("163"), 3, 163}, + {D_STR_W_LEN ("164"), 3, 164}, + {D_STR_W_LEN ("165"), 3, 165}, + {D_STR_W_LEN ("166"), 3, 166}, + {D_STR_W_LEN ("167"), 3, 167}, + {D_STR_W_LEN ("168"), 3, 168}, + {D_STR_W_LEN ("169"), 3, 169}, + {D_STR_W_LEN ("170"), 3, 170}, + {D_STR_W_LEN ("171"), 3, 171}, + {D_STR_W_LEN ("172"), 3, 172}, + {D_STR_W_LEN ("173"), 3, 173}, + {D_STR_W_LEN ("174"), 3, 174}, + {D_STR_W_LEN ("175"), 3, 175}, + {D_STR_W_LEN ("176"), 3, 176}, + {D_STR_W_LEN ("177"), 3, 177}, + {D_STR_W_LEN ("178"), 3, 178}, + {D_STR_W_LEN ("179"), 3, 179}, + {D_STR_W_LEN ("180"), 3, 180}, + {D_STR_W_LEN ("181"), 3, 181}, + {D_STR_W_LEN ("182"), 3, 182}, + {D_STR_W_LEN ("183"), 3, 183}, + {D_STR_W_LEN ("184"), 3, 184}, + {D_STR_W_LEN ("185"), 3, 185}, + {D_STR_W_LEN ("186"), 3, 186}, + {D_STR_W_LEN ("187"), 3, 187}, + {D_STR_W_LEN ("188"), 3, 188}, + {D_STR_W_LEN ("189"), 3, 189}, + {D_STR_W_LEN ("190"), 3, 190}, + {D_STR_W_LEN ("191"), 3, 191}, + {D_STR_W_LEN ("192"), 3, 192}, + {D_STR_W_LEN ("193"), 3, 193}, + {D_STR_W_LEN ("194"), 3, 194}, + {D_STR_W_LEN ("195"), 3, 195}, + {D_STR_W_LEN ("196"), 3, 196}, + {D_STR_W_LEN ("197"), 3, 197}, + {D_STR_W_LEN ("198"), 3, 198}, + {D_STR_W_LEN ("199"), 3, 199}, + {D_STR_W_LEN ("200"), 3, 200}, + {D_STR_W_LEN ("201"), 3, 201}, + {D_STR_W_LEN ("202"), 3, 202}, + {D_STR_W_LEN ("203"), 3, 203}, + {D_STR_W_LEN ("204"), 3, 204}, + {D_STR_W_LEN ("205"), 3, 205}, + {D_STR_W_LEN ("206"), 3, 206}, + {D_STR_W_LEN ("207"), 3, 207}, + {D_STR_W_LEN ("208"), 3, 208}, + {D_STR_W_LEN ("209"), 3, 209}, + {D_STR_W_LEN ("210"), 3, 210}, + {D_STR_W_LEN ("211"), 3, 211}, + {D_STR_W_LEN ("212"), 3, 212}, + {D_STR_W_LEN ("213"), 3, 213}, + {D_STR_W_LEN ("214"), 3, 214}, + {D_STR_W_LEN ("215"), 3, 215}, + {D_STR_W_LEN ("216"), 3, 216}, + {D_STR_W_LEN ("217"), 3, 217}, + {D_STR_W_LEN ("218"), 3, 218}, + {D_STR_W_LEN ("219"), 3, 219}, + {D_STR_W_LEN ("220"), 3, 220}, + {D_STR_W_LEN ("221"), 3, 221}, + {D_STR_W_LEN ("222"), 3, 222}, + {D_STR_W_LEN ("223"), 3, 223}, + {D_STR_W_LEN ("224"), 3, 224}, + {D_STR_W_LEN ("225"), 3, 225}, + {D_STR_W_LEN ("226"), 3, 226}, + {D_STR_W_LEN ("227"), 3, 227}, + {D_STR_W_LEN ("228"), 3, 228}, + {D_STR_W_LEN ("229"), 3, 229}, + {D_STR_W_LEN ("230"), 3, 230}, + {D_STR_W_LEN ("231"), 3, 231}, + {D_STR_W_LEN ("232"), 3, 232}, + {D_STR_W_LEN ("233"), 3, 233}, + {D_STR_W_LEN ("234"), 3, 234}, + {D_STR_W_LEN ("235"), 3, 235}, + {D_STR_W_LEN ("236"), 3, 236}, + {D_STR_W_LEN ("237"), 3, 237}, + {D_STR_W_LEN ("238"), 3, 238}, + {D_STR_W_LEN ("239"), 3, 239}, + {D_STR_W_LEN ("240"), 3, 240}, + {D_STR_W_LEN ("241"), 3, 241}, + {D_STR_W_LEN ("242"), 3, 242}, + {D_STR_W_LEN ("243"), 3, 243}, + {D_STR_W_LEN ("244"), 3, 244}, + {D_STR_W_LEN ("245"), 3, 245}, + {D_STR_W_LEN ("246"), 3, 246}, + {D_STR_W_LEN ("247"), 3, 247}, + {D_STR_W_LEN ("248"), 3, 248}, + {D_STR_W_LEN ("249"), 3, 249}, + {D_STR_W_LEN ("250"), 3, 250}, + {D_STR_W_LEN ("251"), 3, 251}, + {D_STR_W_LEN ("252"), 3, 252}, + {D_STR_W_LEN ("253"), 3, 253}, + {D_STR_W_LEN ("254"), 3, 254}, + {D_STR_W_LEN ("255"), 3, 255}, +}; + +static const struct str_with_value duint8_w_values_p2[] = { + {D_STR_W_LEN ("00"), 2, 0}, + {D_STR_W_LEN ("01"), 2, 1}, + {D_STR_W_LEN ("02"), 2, 2}, + {D_STR_W_LEN ("03"), 2, 3}, + {D_STR_W_LEN ("04"), 2, 4}, + {D_STR_W_LEN ("05"), 2, 5}, + {D_STR_W_LEN ("06"), 2, 6}, + {D_STR_W_LEN ("07"), 2, 7}, + {D_STR_W_LEN ("08"), 2, 8}, + {D_STR_W_LEN ("09"), 2, 9}, + {D_STR_W_LEN ("10"), 2, 10}, + {D_STR_W_LEN ("11"), 2, 11}, + {D_STR_W_LEN ("12"), 2, 12}, + {D_STR_W_LEN ("13"), 2, 13}, + {D_STR_W_LEN ("14"), 2, 14}, + {D_STR_W_LEN ("15"), 2, 15}, + {D_STR_W_LEN ("16"), 2, 16}, + {D_STR_W_LEN ("17"), 2, 17}, + {D_STR_W_LEN ("18"), 2, 18}, + {D_STR_W_LEN ("19"), 2, 19}, + {D_STR_W_LEN ("20"), 2, 20}, + {D_STR_W_LEN ("21"), 2, 21}, + {D_STR_W_LEN ("22"), 2, 22}, + {D_STR_W_LEN ("23"), 2, 23}, + {D_STR_W_LEN ("24"), 2, 24}, + {D_STR_W_LEN ("25"), 2, 25}, + {D_STR_W_LEN ("26"), 2, 26}, + {D_STR_W_LEN ("27"), 2, 27}, + {D_STR_W_LEN ("28"), 2, 28}, + {D_STR_W_LEN ("29"), 2, 29}, + {D_STR_W_LEN ("30"), 2, 30}, + {D_STR_W_LEN ("31"), 2, 31}, + {D_STR_W_LEN ("32"), 2, 32}, + {D_STR_W_LEN ("33"), 2, 33}, + {D_STR_W_LEN ("34"), 2, 34}, + {D_STR_W_LEN ("35"), 2, 35}, + {D_STR_W_LEN ("36"), 2, 36}, + {D_STR_W_LEN ("37"), 2, 37}, + {D_STR_W_LEN ("38"), 2, 38}, + {D_STR_W_LEN ("39"), 2, 39}, + {D_STR_W_LEN ("40"), 2, 40}, + {D_STR_W_LEN ("41"), 2, 41}, + {D_STR_W_LEN ("42"), 2, 42}, + {D_STR_W_LEN ("43"), 2, 43}, + {D_STR_W_LEN ("44"), 2, 44}, + {D_STR_W_LEN ("45"), 2, 45}, + {D_STR_W_LEN ("46"), 2, 46}, + {D_STR_W_LEN ("47"), 2, 47}, + {D_STR_W_LEN ("48"), 2, 48}, + {D_STR_W_LEN ("49"), 2, 49}, + {D_STR_W_LEN ("50"), 2, 50}, + {D_STR_W_LEN ("51"), 2, 51}, + {D_STR_W_LEN ("52"), 2, 52}, + {D_STR_W_LEN ("53"), 2, 53}, + {D_STR_W_LEN ("54"), 2, 54}, + {D_STR_W_LEN ("55"), 2, 55}, + {D_STR_W_LEN ("56"), 2, 56}, + {D_STR_W_LEN ("57"), 2, 57}, + {D_STR_W_LEN ("58"), 2, 58}, + {D_STR_W_LEN ("59"), 2, 59}, + {D_STR_W_LEN ("60"), 2, 60}, + {D_STR_W_LEN ("61"), 2, 61}, + {D_STR_W_LEN ("62"), 2, 62}, + {D_STR_W_LEN ("63"), 2, 63}, + {D_STR_W_LEN ("64"), 2, 64}, + {D_STR_W_LEN ("65"), 2, 65}, + {D_STR_W_LEN ("66"), 2, 66}, + {D_STR_W_LEN ("67"), 2, 67}, + {D_STR_W_LEN ("68"), 2, 68}, + {D_STR_W_LEN ("69"), 2, 69}, + {D_STR_W_LEN ("70"), 2, 70}, + {D_STR_W_LEN ("71"), 2, 71}, + {D_STR_W_LEN ("72"), 2, 72}, + {D_STR_W_LEN ("73"), 2, 73}, + {D_STR_W_LEN ("74"), 2, 74}, + {D_STR_W_LEN ("75"), 2, 75}, + {D_STR_W_LEN ("76"), 2, 76}, + {D_STR_W_LEN ("77"), 2, 77}, + {D_STR_W_LEN ("78"), 2, 78}, + {D_STR_W_LEN ("79"), 2, 79}, + {D_STR_W_LEN ("80"), 2, 80}, + {D_STR_W_LEN ("81"), 2, 81}, + {D_STR_W_LEN ("82"), 2, 82}, + {D_STR_W_LEN ("83"), 2, 83}, + {D_STR_W_LEN ("84"), 2, 84}, + {D_STR_W_LEN ("85"), 2, 85}, + {D_STR_W_LEN ("86"), 2, 86}, + {D_STR_W_LEN ("87"), 2, 87}, + {D_STR_W_LEN ("88"), 2, 88}, + {D_STR_W_LEN ("89"), 2, 89}, + {D_STR_W_LEN ("90"), 2, 90}, + {D_STR_W_LEN ("91"), 2, 91}, + {D_STR_W_LEN ("92"), 2, 92}, + {D_STR_W_LEN ("93"), 2, 93}, + {D_STR_W_LEN ("94"), 2, 94}, + {D_STR_W_LEN ("95"), 2, 95}, + {D_STR_W_LEN ("96"), 2, 96}, + {D_STR_W_LEN ("97"), 2, 97}, + {D_STR_W_LEN ("98"), 2, 98}, + {D_STR_W_LEN ("99"), 2, 99}, + {D_STR_W_LEN ("100"), 3, 100}, + {D_STR_W_LEN ("101"), 3, 101}, + {D_STR_W_LEN ("102"), 3, 102}, + {D_STR_W_LEN ("103"), 3, 103}, + {D_STR_W_LEN ("104"), 3, 104}, + {D_STR_W_LEN ("105"), 3, 105}, + {D_STR_W_LEN ("106"), 3, 106}, + {D_STR_W_LEN ("107"), 3, 107}, + {D_STR_W_LEN ("108"), 3, 108}, + {D_STR_W_LEN ("109"), 3, 109}, + {D_STR_W_LEN ("110"), 3, 110}, + {D_STR_W_LEN ("111"), 3, 111}, + {D_STR_W_LEN ("112"), 3, 112}, + {D_STR_W_LEN ("113"), 3, 113}, + {D_STR_W_LEN ("114"), 3, 114}, + {D_STR_W_LEN ("115"), 3, 115}, + {D_STR_W_LEN ("116"), 3, 116}, + {D_STR_W_LEN ("117"), 3, 117}, + {D_STR_W_LEN ("118"), 3, 118}, + {D_STR_W_LEN ("119"), 3, 119}, + {D_STR_W_LEN ("120"), 3, 120}, + {D_STR_W_LEN ("121"), 3, 121}, + {D_STR_W_LEN ("122"), 3, 122}, + {D_STR_W_LEN ("123"), 3, 123}, + {D_STR_W_LEN ("124"), 3, 124}, + {D_STR_W_LEN ("125"), 3, 125}, + {D_STR_W_LEN ("126"), 3, 126}, + {D_STR_W_LEN ("127"), 3, 127}, + {D_STR_W_LEN ("128"), 3, 128}, + {D_STR_W_LEN ("129"), 3, 129}, + {D_STR_W_LEN ("130"), 3, 130}, + {D_STR_W_LEN ("131"), 3, 131}, + {D_STR_W_LEN ("132"), 3, 132}, + {D_STR_W_LEN ("133"), 3, 133}, + {D_STR_W_LEN ("134"), 3, 134}, + {D_STR_W_LEN ("135"), 3, 135}, + {D_STR_W_LEN ("136"), 3, 136}, + {D_STR_W_LEN ("137"), 3, 137}, + {D_STR_W_LEN ("138"), 3, 138}, + {D_STR_W_LEN ("139"), 3, 139}, + {D_STR_W_LEN ("140"), 3, 140}, + {D_STR_W_LEN ("141"), 3, 141}, + {D_STR_W_LEN ("142"), 3, 142}, + {D_STR_W_LEN ("143"), 3, 143}, + {D_STR_W_LEN ("144"), 3, 144}, + {D_STR_W_LEN ("145"), 3, 145}, + {D_STR_W_LEN ("146"), 3, 146}, + {D_STR_W_LEN ("147"), 3, 147}, + {D_STR_W_LEN ("148"), 3, 148}, + {D_STR_W_LEN ("149"), 3, 149}, + {D_STR_W_LEN ("150"), 3, 150}, + {D_STR_W_LEN ("151"), 3, 151}, + {D_STR_W_LEN ("152"), 3, 152}, + {D_STR_W_LEN ("153"), 3, 153}, + {D_STR_W_LEN ("154"), 3, 154}, + {D_STR_W_LEN ("155"), 3, 155}, + {D_STR_W_LEN ("156"), 3, 156}, + {D_STR_W_LEN ("157"), 3, 157}, + {D_STR_W_LEN ("158"), 3, 158}, + {D_STR_W_LEN ("159"), 3, 159}, + {D_STR_W_LEN ("160"), 3, 160}, + {D_STR_W_LEN ("161"), 3, 161}, + {D_STR_W_LEN ("162"), 3, 162}, + {D_STR_W_LEN ("163"), 3, 163}, + {D_STR_W_LEN ("164"), 3, 164}, + {D_STR_W_LEN ("165"), 3, 165}, + {D_STR_W_LEN ("166"), 3, 166}, + {D_STR_W_LEN ("167"), 3, 167}, + {D_STR_W_LEN ("168"), 3, 168}, + {D_STR_W_LEN ("169"), 3, 169}, + {D_STR_W_LEN ("170"), 3, 170}, + {D_STR_W_LEN ("171"), 3, 171}, + {D_STR_W_LEN ("172"), 3, 172}, + {D_STR_W_LEN ("173"), 3, 173}, + {D_STR_W_LEN ("174"), 3, 174}, + {D_STR_W_LEN ("175"), 3, 175}, + {D_STR_W_LEN ("176"), 3, 176}, + {D_STR_W_LEN ("177"), 3, 177}, + {D_STR_W_LEN ("178"), 3, 178}, + {D_STR_W_LEN ("179"), 3, 179}, + {D_STR_W_LEN ("180"), 3, 180}, + {D_STR_W_LEN ("181"), 3, 181}, + {D_STR_W_LEN ("182"), 3, 182}, + {D_STR_W_LEN ("183"), 3, 183}, + {D_STR_W_LEN ("184"), 3, 184}, + {D_STR_W_LEN ("185"), 3, 185}, + {D_STR_W_LEN ("186"), 3, 186}, + {D_STR_W_LEN ("187"), 3, 187}, + {D_STR_W_LEN ("188"), 3, 188}, + {D_STR_W_LEN ("189"), 3, 189}, + {D_STR_W_LEN ("190"), 3, 190}, + {D_STR_W_LEN ("191"), 3, 191}, + {D_STR_W_LEN ("192"), 3, 192}, + {D_STR_W_LEN ("193"), 3, 193}, + {D_STR_W_LEN ("194"), 3, 194}, + {D_STR_W_LEN ("195"), 3, 195}, + {D_STR_W_LEN ("196"), 3, 196}, + {D_STR_W_LEN ("197"), 3, 197}, + {D_STR_W_LEN ("198"), 3, 198}, + {D_STR_W_LEN ("199"), 3, 199}, + {D_STR_W_LEN ("200"), 3, 200}, + {D_STR_W_LEN ("201"), 3, 201}, + {D_STR_W_LEN ("202"), 3, 202}, + {D_STR_W_LEN ("203"), 3, 203}, + {D_STR_W_LEN ("204"), 3, 204}, + {D_STR_W_LEN ("205"), 3, 205}, + {D_STR_W_LEN ("206"), 3, 206}, + {D_STR_W_LEN ("207"), 3, 207}, + {D_STR_W_LEN ("208"), 3, 208}, + {D_STR_W_LEN ("209"), 3, 209}, + {D_STR_W_LEN ("210"), 3, 210}, + {D_STR_W_LEN ("211"), 3, 211}, + {D_STR_W_LEN ("212"), 3, 212}, + {D_STR_W_LEN ("213"), 3, 213}, + {D_STR_W_LEN ("214"), 3, 214}, + {D_STR_W_LEN ("215"), 3, 215}, + {D_STR_W_LEN ("216"), 3, 216}, + {D_STR_W_LEN ("217"), 3, 217}, + {D_STR_W_LEN ("218"), 3, 218}, + {D_STR_W_LEN ("219"), 3, 219}, + {D_STR_W_LEN ("220"), 3, 220}, + {D_STR_W_LEN ("221"), 3, 221}, + {D_STR_W_LEN ("222"), 3, 222}, + {D_STR_W_LEN ("223"), 3, 223}, + {D_STR_W_LEN ("224"), 3, 224}, + {D_STR_W_LEN ("225"), 3, 225}, + {D_STR_W_LEN ("226"), 3, 226}, + {D_STR_W_LEN ("227"), 3, 227}, + {D_STR_W_LEN ("228"), 3, 228}, + {D_STR_W_LEN ("229"), 3, 229}, + {D_STR_W_LEN ("230"), 3, 230}, + {D_STR_W_LEN ("231"), 3, 231}, + {D_STR_W_LEN ("232"), 3, 232}, + {D_STR_W_LEN ("233"), 3, 233}, + {D_STR_W_LEN ("234"), 3, 234}, + {D_STR_W_LEN ("235"), 3, 235}, + {D_STR_W_LEN ("236"), 3, 236}, + {D_STR_W_LEN ("237"), 3, 237}, + {D_STR_W_LEN ("238"), 3, 238}, + {D_STR_W_LEN ("239"), 3, 239}, + {D_STR_W_LEN ("240"), 3, 240}, + {D_STR_W_LEN ("241"), 3, 241}, + {D_STR_W_LEN ("242"), 3, 242}, + {D_STR_W_LEN ("243"), 3, 243}, + {D_STR_W_LEN ("244"), 3, 244}, + {D_STR_W_LEN ("245"), 3, 245}, + {D_STR_W_LEN ("246"), 3, 246}, + {D_STR_W_LEN ("247"), 3, 247}, + {D_STR_W_LEN ("248"), 3, 248}, + {D_STR_W_LEN ("249"), 3, 249}, + {D_STR_W_LEN ("250"), 3, 250}, + {D_STR_W_LEN ("251"), 3, 251}, + {D_STR_W_LEN ("252"), 3, 252}, + {D_STR_W_LEN ("253"), 3, 253}, + {D_STR_W_LEN ("254"), 3, 254}, + {D_STR_W_LEN ("255"), 3, 255} +}; + +static const struct str_with_value duint8_w_values_p3[] = { + {D_STR_W_LEN ("000"), 3, 0}, + {D_STR_W_LEN ("001"), 3, 1}, + {D_STR_W_LEN ("002"), 3, 2}, + {D_STR_W_LEN ("003"), 3, 3}, + {D_STR_W_LEN ("004"), 3, 4}, + {D_STR_W_LEN ("005"), 3, 5}, + {D_STR_W_LEN ("006"), 3, 6}, + {D_STR_W_LEN ("007"), 3, 7}, + {D_STR_W_LEN ("008"), 3, 8}, + {D_STR_W_LEN ("009"), 3, 9}, + {D_STR_W_LEN ("010"), 3, 10}, + {D_STR_W_LEN ("011"), 3, 11}, + {D_STR_W_LEN ("012"), 3, 12}, + {D_STR_W_LEN ("013"), 3, 13}, + {D_STR_W_LEN ("014"), 3, 14}, + {D_STR_W_LEN ("015"), 3, 15}, + {D_STR_W_LEN ("016"), 3, 16}, + {D_STR_W_LEN ("017"), 3, 17}, + {D_STR_W_LEN ("018"), 3, 18}, + {D_STR_W_LEN ("019"), 3, 19}, + {D_STR_W_LEN ("020"), 3, 20}, + {D_STR_W_LEN ("021"), 3, 21}, + {D_STR_W_LEN ("022"), 3, 22}, + {D_STR_W_LEN ("023"), 3, 23}, + {D_STR_W_LEN ("024"), 3, 24}, + {D_STR_W_LEN ("025"), 3, 25}, + {D_STR_W_LEN ("026"), 3, 26}, + {D_STR_W_LEN ("027"), 3, 27}, + {D_STR_W_LEN ("028"), 3, 28}, + {D_STR_W_LEN ("029"), 3, 29}, + {D_STR_W_LEN ("030"), 3, 30}, + {D_STR_W_LEN ("031"), 3, 31}, + {D_STR_W_LEN ("032"), 3, 32}, + {D_STR_W_LEN ("033"), 3, 33}, + {D_STR_W_LEN ("034"), 3, 34}, + {D_STR_W_LEN ("035"), 3, 35}, + {D_STR_W_LEN ("036"), 3, 36}, + {D_STR_W_LEN ("037"), 3, 37}, + {D_STR_W_LEN ("038"), 3, 38}, + {D_STR_W_LEN ("039"), 3, 39}, + {D_STR_W_LEN ("040"), 3, 40}, + {D_STR_W_LEN ("041"), 3, 41}, + {D_STR_W_LEN ("042"), 3, 42}, + {D_STR_W_LEN ("043"), 3, 43}, + {D_STR_W_LEN ("044"), 3, 44}, + {D_STR_W_LEN ("045"), 3, 45}, + {D_STR_W_LEN ("046"), 3, 46}, + {D_STR_W_LEN ("047"), 3, 47}, + {D_STR_W_LEN ("048"), 3, 48}, + {D_STR_W_LEN ("049"), 3, 49}, + {D_STR_W_LEN ("050"), 3, 50}, + {D_STR_W_LEN ("051"), 3, 51}, + {D_STR_W_LEN ("052"), 3, 52}, + {D_STR_W_LEN ("053"), 3, 53}, + {D_STR_W_LEN ("054"), 3, 54}, + {D_STR_W_LEN ("055"), 3, 55}, + {D_STR_W_LEN ("056"), 3, 56}, + {D_STR_W_LEN ("057"), 3, 57}, + {D_STR_W_LEN ("058"), 3, 58}, + {D_STR_W_LEN ("059"), 3, 59}, + {D_STR_W_LEN ("060"), 3, 60}, + {D_STR_W_LEN ("061"), 3, 61}, + {D_STR_W_LEN ("062"), 3, 62}, + {D_STR_W_LEN ("063"), 3, 63}, + {D_STR_W_LEN ("064"), 3, 64}, + {D_STR_W_LEN ("065"), 3, 65}, + {D_STR_W_LEN ("066"), 3, 66}, + {D_STR_W_LEN ("067"), 3, 67}, + {D_STR_W_LEN ("068"), 3, 68}, + {D_STR_W_LEN ("069"), 3, 69}, + {D_STR_W_LEN ("070"), 3, 70}, + {D_STR_W_LEN ("071"), 3, 71}, + {D_STR_W_LEN ("072"), 3, 72}, + {D_STR_W_LEN ("073"), 3, 73}, + {D_STR_W_LEN ("074"), 3, 74}, + {D_STR_W_LEN ("075"), 3, 75}, + {D_STR_W_LEN ("076"), 3, 76}, + {D_STR_W_LEN ("077"), 3, 77}, + {D_STR_W_LEN ("078"), 3, 78}, + {D_STR_W_LEN ("079"), 3, 79}, + {D_STR_W_LEN ("080"), 3, 80}, + {D_STR_W_LEN ("081"), 3, 81}, + {D_STR_W_LEN ("082"), 3, 82}, + {D_STR_W_LEN ("083"), 3, 83}, + {D_STR_W_LEN ("084"), 3, 84}, + {D_STR_W_LEN ("085"), 3, 85}, + {D_STR_W_LEN ("086"), 3, 86}, + {D_STR_W_LEN ("087"), 3, 87}, + {D_STR_W_LEN ("088"), 3, 88}, + {D_STR_W_LEN ("089"), 3, 89}, + {D_STR_W_LEN ("090"), 3, 90}, + {D_STR_W_LEN ("091"), 3, 91}, + {D_STR_W_LEN ("092"), 3, 92}, + {D_STR_W_LEN ("093"), 3, 93}, + {D_STR_W_LEN ("094"), 3, 94}, + {D_STR_W_LEN ("095"), 3, 95}, + {D_STR_W_LEN ("096"), 3, 96}, + {D_STR_W_LEN ("097"), 3, 97}, + {D_STR_W_LEN ("098"), 3, 98}, + {D_STR_W_LEN ("099"), 3, 99}, + {D_STR_W_LEN ("100"), 3, 100}, + {D_STR_W_LEN ("101"), 3, 101}, + {D_STR_W_LEN ("102"), 3, 102}, + {D_STR_W_LEN ("103"), 3, 103}, + {D_STR_W_LEN ("104"), 3, 104}, + {D_STR_W_LEN ("105"), 3, 105}, + {D_STR_W_LEN ("106"), 3, 106}, + {D_STR_W_LEN ("107"), 3, 107}, + {D_STR_W_LEN ("108"), 3, 108}, + {D_STR_W_LEN ("109"), 3, 109}, + {D_STR_W_LEN ("110"), 3, 110}, + {D_STR_W_LEN ("111"), 3, 111}, + {D_STR_W_LEN ("112"), 3, 112}, + {D_STR_W_LEN ("113"), 3, 113}, + {D_STR_W_LEN ("114"), 3, 114}, + {D_STR_W_LEN ("115"), 3, 115}, + {D_STR_W_LEN ("116"), 3, 116}, + {D_STR_W_LEN ("117"), 3, 117}, + {D_STR_W_LEN ("118"), 3, 118}, + {D_STR_W_LEN ("119"), 3, 119}, + {D_STR_W_LEN ("120"), 3, 120}, + {D_STR_W_LEN ("121"), 3, 121}, + {D_STR_W_LEN ("122"), 3, 122}, + {D_STR_W_LEN ("123"), 3, 123}, + {D_STR_W_LEN ("124"), 3, 124}, + {D_STR_W_LEN ("125"), 3, 125}, + {D_STR_W_LEN ("126"), 3, 126}, + {D_STR_W_LEN ("127"), 3, 127}, + {D_STR_W_LEN ("128"), 3, 128}, + {D_STR_W_LEN ("129"), 3, 129}, + {D_STR_W_LEN ("130"), 3, 130}, + {D_STR_W_LEN ("131"), 3, 131}, + {D_STR_W_LEN ("132"), 3, 132}, + {D_STR_W_LEN ("133"), 3, 133}, + {D_STR_W_LEN ("134"), 3, 134}, + {D_STR_W_LEN ("135"), 3, 135}, + {D_STR_W_LEN ("136"), 3, 136}, + {D_STR_W_LEN ("137"), 3, 137}, + {D_STR_W_LEN ("138"), 3, 138}, + {D_STR_W_LEN ("139"), 3, 139}, + {D_STR_W_LEN ("140"), 3, 140}, + {D_STR_W_LEN ("141"), 3, 141}, + {D_STR_W_LEN ("142"), 3, 142}, + {D_STR_W_LEN ("143"), 3, 143}, + {D_STR_W_LEN ("144"), 3, 144}, + {D_STR_W_LEN ("145"), 3, 145}, + {D_STR_W_LEN ("146"), 3, 146}, + {D_STR_W_LEN ("147"), 3, 147}, + {D_STR_W_LEN ("148"), 3, 148}, + {D_STR_W_LEN ("149"), 3, 149}, + {D_STR_W_LEN ("150"), 3, 150}, + {D_STR_W_LEN ("151"), 3, 151}, + {D_STR_W_LEN ("152"), 3, 152}, + {D_STR_W_LEN ("153"), 3, 153}, + {D_STR_W_LEN ("154"), 3, 154}, + {D_STR_W_LEN ("155"), 3, 155}, + {D_STR_W_LEN ("156"), 3, 156}, + {D_STR_W_LEN ("157"), 3, 157}, + {D_STR_W_LEN ("158"), 3, 158}, + {D_STR_W_LEN ("159"), 3, 159}, + {D_STR_W_LEN ("160"), 3, 160}, + {D_STR_W_LEN ("161"), 3, 161}, + {D_STR_W_LEN ("162"), 3, 162}, + {D_STR_W_LEN ("163"), 3, 163}, + {D_STR_W_LEN ("164"), 3, 164}, + {D_STR_W_LEN ("165"), 3, 165}, + {D_STR_W_LEN ("166"), 3, 166}, + {D_STR_W_LEN ("167"), 3, 167}, + {D_STR_W_LEN ("168"), 3, 168}, + {D_STR_W_LEN ("169"), 3, 169}, + {D_STR_W_LEN ("170"), 3, 170}, + {D_STR_W_LEN ("171"), 3, 171}, + {D_STR_W_LEN ("172"), 3, 172}, + {D_STR_W_LEN ("173"), 3, 173}, + {D_STR_W_LEN ("174"), 3, 174}, + {D_STR_W_LEN ("175"), 3, 175}, + {D_STR_W_LEN ("176"), 3, 176}, + {D_STR_W_LEN ("177"), 3, 177}, + {D_STR_W_LEN ("178"), 3, 178}, + {D_STR_W_LEN ("179"), 3, 179}, + {D_STR_W_LEN ("180"), 3, 180}, + {D_STR_W_LEN ("181"), 3, 181}, + {D_STR_W_LEN ("182"), 3, 182}, + {D_STR_W_LEN ("183"), 3, 183}, + {D_STR_W_LEN ("184"), 3, 184}, + {D_STR_W_LEN ("185"), 3, 185}, + {D_STR_W_LEN ("186"), 3, 186}, + {D_STR_W_LEN ("187"), 3, 187}, + {D_STR_W_LEN ("188"), 3, 188}, + {D_STR_W_LEN ("189"), 3, 189}, + {D_STR_W_LEN ("190"), 3, 190}, + {D_STR_W_LEN ("191"), 3, 191}, + {D_STR_W_LEN ("192"), 3, 192}, + {D_STR_W_LEN ("193"), 3, 193}, + {D_STR_W_LEN ("194"), 3, 194}, + {D_STR_W_LEN ("195"), 3, 195}, + {D_STR_W_LEN ("196"), 3, 196}, + {D_STR_W_LEN ("197"), 3, 197}, + {D_STR_W_LEN ("198"), 3, 198}, + {D_STR_W_LEN ("199"), 3, 199}, + {D_STR_W_LEN ("200"), 3, 200}, + {D_STR_W_LEN ("201"), 3, 201}, + {D_STR_W_LEN ("202"), 3, 202}, + {D_STR_W_LEN ("203"), 3, 203}, + {D_STR_W_LEN ("204"), 3, 204}, + {D_STR_W_LEN ("205"), 3, 205}, + {D_STR_W_LEN ("206"), 3, 206}, + {D_STR_W_LEN ("207"), 3, 207}, + {D_STR_W_LEN ("208"), 3, 208}, + {D_STR_W_LEN ("209"), 3, 209}, + {D_STR_W_LEN ("210"), 3, 210}, + {D_STR_W_LEN ("211"), 3, 211}, + {D_STR_W_LEN ("212"), 3, 212}, + {D_STR_W_LEN ("213"), 3, 213}, + {D_STR_W_LEN ("214"), 3, 214}, + {D_STR_W_LEN ("215"), 3, 215}, + {D_STR_W_LEN ("216"), 3, 216}, + {D_STR_W_LEN ("217"), 3, 217}, + {D_STR_W_LEN ("218"), 3, 218}, + {D_STR_W_LEN ("219"), 3, 219}, + {D_STR_W_LEN ("220"), 3, 220}, + {D_STR_W_LEN ("221"), 3, 221}, + {D_STR_W_LEN ("222"), 3, 222}, + {D_STR_W_LEN ("223"), 3, 223}, + {D_STR_W_LEN ("224"), 3, 224}, + {D_STR_W_LEN ("225"), 3, 225}, + {D_STR_W_LEN ("226"), 3, 226}, + {D_STR_W_LEN ("227"), 3, 227}, + {D_STR_W_LEN ("228"), 3, 228}, + {D_STR_W_LEN ("229"), 3, 229}, + {D_STR_W_LEN ("230"), 3, 230}, + {D_STR_W_LEN ("231"), 3, 231}, + {D_STR_W_LEN ("232"), 3, 232}, + {D_STR_W_LEN ("233"), 3, 233}, + {D_STR_W_LEN ("234"), 3, 234}, + {D_STR_W_LEN ("235"), 3, 235}, + {D_STR_W_LEN ("236"), 3, 236}, + {D_STR_W_LEN ("237"), 3, 237}, + {D_STR_W_LEN ("238"), 3, 238}, + {D_STR_W_LEN ("239"), 3, 239}, + {D_STR_W_LEN ("240"), 3, 240}, + {D_STR_W_LEN ("241"), 3, 241}, + {D_STR_W_LEN ("242"), 3, 242}, + {D_STR_W_LEN ("243"), 3, 243}, + {D_STR_W_LEN ("244"), 3, 244}, + {D_STR_W_LEN ("245"), 3, 245}, + {D_STR_W_LEN ("246"), 3, 246}, + {D_STR_W_LEN ("247"), 3, 247}, + {D_STR_W_LEN ("248"), 3, 248}, + {D_STR_W_LEN ("249"), 3, 249}, + {D_STR_W_LEN ("250"), 3, 250}, + {D_STR_W_LEN ("251"), 3, 251}, + {D_STR_W_LEN ("252"), 3, 252}, + {D_STR_W_LEN ("253"), 3, 253}, + {D_STR_W_LEN ("254"), 3, 254}, + {D_STR_W_LEN ("255"), 3, 255} +}; + + +static const struct str_with_value *duint8_w_values_p[3] = +{duint8_w_values_p1, duint8_w_values_p2, duint8_w_values_p3}; + +static size_t +check_str_from_uint8_pad (void) +{ + int i; + uint8_t pad; + size_t t_failed = 0; + + if ((256 != sizeof(duint8_w_values_p1) / sizeof(duint8_w_values_p1[0])) || + (256 != sizeof(duint8_w_values_p2) / sizeof(duint8_w_values_p2[0])) || + (256 != sizeof(duint8_w_values_p3) / sizeof(duint8_w_values_p3[0]))) + { + fprintf (stderr, + "ERROR: wrong number of items in duint8_w_values_p*.\n"); + exit (99); + } + for (pad = 0; pad <= 3; pad++) + { + size_t table_num; + if (0 != pad) + table_num = pad - 1; + else + table_num = 0; + + for (i = 0; i <= 255; i++) + { + const struct str_with_value *const t = duint8_w_values_p[table_num] + i; + size_t b_size; + size_t rs; + char buf[8]; + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + if (sizeof(buf) < t->str.len + 1) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has too long (%u) string, " + "size of 'buf' should be increased.\n", + (unsigned int) i, (unsigned int) t->str.len); + exit (99); + } + for (b_size = 0; b_size <= t->str.len + 1; ++b_size) + { + /* fill buffer with pseudo-random values */ + memset (buf, '#', sizeof(buf)); + + rs = mhd_uint8_to_str_pad ((uint8_t) t->val, pad, buf, b_size); + + if (t->num_of_digt > b_size) + { + /* Must fail, buffer is too small for result */ + if (0 != rs) + { + t_failed++; + fprintf (stderr, + "FAILED: mhd_uint8_to_str_pad(%" PRIu64 ", %d, -> buf," + " %d) returned %" PRIuPTR + ", while expecting 0.\n", t->val, (int) pad, (int) b_size, + (uintptr_t) rs); + } + } + else + { + if (t->num_of_digt != rs) + { + t_failed++; + fprintf (stderr, + "FAILED: mhd_uint8_to_str_pad(%" PRIu64 ", %d, -> buf," + " %d) returned %" PRIuPTR + ", while expecting %d.\n", t->val, (int) pad, + (int) b_size, (uintptr_t) rs, (int) t->num_of_digt); + } + else if (0 != memcmp (buf, t->str.str, t->num_of_digt)) + { + t_failed++; + fprintf (stderr, + "FAILED: mhd_uint8_to_str_pad(%" PRIu64 ", %d, " + "-> \"%.*s\", %d) returned %" PRIuPTR ".\n", + t->val, (int) pad, (int) rs, buf, + (int) b_size, (uintptr_t) rs); + } + else if (0 != memcmp (buf + rs, "########", sizeof(buf) - rs)) + { + t_failed++; + fprintf (stderr, + "FAILED: mhd_uint8_to_str_pad(%" PRIu64 ", %d," + " -> \"%.*s\", %d) returned %" PRIuPTR + " and touched data after the resulting string.\n", + t->val, (int) pad, (int) rs, buf, (int) b_size, + (uintptr_t) rs); + } + } + } + } + } + if ((verbose > 1) && (0 == t_failed)) + printf ("PASSED: mhd_uint8_to_str_pad.\n"); + + return t_failed; +} + + +static int +run_str_from_X_tests (void) +{ + size_t str_from_uint16; + size_t str_from_uint64; + size_t strx_from_uint32; + size_t str_from_uint8_pad; + size_t failures; + + failures = 0; + + str_from_uint16 = check_str_from_uint16 (); + if (str_from_uint16 != 0) + { + fprintf (stderr, + "FAILED: testcase check_str_from_uint16() failed.\n\n"); + failures += str_from_uint16; + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_from_uint16() successfully " + "passed.\n\n"); + + str_from_uint64 = check_str_from_uint64 (); + if (str_from_uint64 != 0) + { + fprintf (stderr, + "FAILED: testcase check_str_from_uint16() failed.\n\n"); + failures += str_from_uint64; + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_from_uint16() successfully " + "passed.\n\n"); + strx_from_uint32 = check_strx_from_uint32 (); + if (strx_from_uint32 != 0) + { + fprintf (stderr, + "FAILED: testcase check_strx_from_uint32() failed.\n\n"); + failures += strx_from_uint32; + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_from_uint32() successfully " + "passed.\n\n"); + + str_from_uint8_pad = check_str_from_uint8_pad (); + if (str_from_uint8_pad != 0) + { + fprintf (stderr, + "FAILED: testcase check_str_from_uint8_pad() failed.\n\n"); + failures += str_from_uint8_pad; + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_from_uint8_pad() successfully " + "passed.\n\n"); + + if (failures) + { + if (verbose > 0) + printf ("At least one test failed.\n"); + + return 1; + } + + if (verbose > 0) + printf ("All tests passed successfully.\n"); + + return 0; +} + + +int +main (int argc, char *argv[]) +{ + if (has_param (argc, argv, "-v") || + has_param (argc, argv, "--verbose") || + has_param (argc, argv, "--verbose1")) + MHDT_set_verbosity (MHDT_VERB_LVL_BASIC); + if (has_param (argc, argv, "-vv") || + has_param (argc, argv, "--verbose2")) + MHDT_set_verbosity (MHDT_VERB_LVL_VERBOSE); + + return run_str_from_X_tests (); +} diff --git a/src/tests/unit/test_str_pct.c b/src/tests/unit/test_str_pct.c @@ -0,0 +1,1061 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2022 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_pct.c + * @brief Unit tests for percent (URL) encoded strings processing + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include <string.h> +#include <stdio.h> +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "mhd_assert.h" + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */ +static size_t buf_idx = 0; + +/* print non-printable chars as char codes */ +static char * +n_prnt (const char *str, size_t len) +{ + static char *buf; /* should be enough for testing */ + static const size_t buf_size = sizeof(tmp_bufs[0]); + size_t r_pos = 0; + size_t w_pos = 0; + if (++buf_idx >= (sizeof(tmp_bufs) / sizeof(tmp_bufs[0]))) + buf_idx = 0; + buf = tmp_bufs[buf_idx]; + + while (len > r_pos && w_pos + 1 < buf_size) + { + const unsigned char c = (unsigned char) str[r_pos]; + if ((c == '\\') || (c == '"') ) + { + if (w_pos + 2 >= buf_size) + break; + buf[w_pos++] = '\\'; + buf[w_pos++] = (char) c; + } + else if ((c >= 0x20) && (c <= 0x7E) ) + buf[w_pos++] = (char) c; + else + { + if (w_pos + 4 >= buf_size) + break; + if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned + int) c) != 4) + break; + w_pos += 4; + } + r_pos++; + } + + if (len != r_pos) + { /* not full string is printed */ + /* enough space for "..." ? */ + if (w_pos + 3 > buf_size) + w_pos = buf_size - 4; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + } + buf[w_pos] = 0; + return buf; +} + + +#define TEST_BIN_MAX_SIZE 1024 + +/* return zero if succeed, number of failures otherwise */ +static unsigned int +expect_decoded_n (const char *const encoded, const size_t encoded_len, + const char *const decoded, const size_t decoded_size, + const unsigned int line_num) +{ + static const char fill_chr = '#'; + static char buf[TEST_BIN_MAX_SIZE]; + size_t res_size; + unsigned int ret; + + mhd_assert (NULL != encoded); + mhd_assert (NULL != decoded); + mhd_assert (TEST_BIN_MAX_SIZE > decoded_size + 1); + mhd_assert (TEST_BIN_MAX_SIZE > encoded_len + 1); + mhd_assert (encoded_len >= decoded_size); + + ret = 0; + + /* check mhd_str_pct_decode_strict_n() with small out buffer */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf, + decoded_size + 1); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (fill_chr != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "A char written outside the buffer:\n"); + } + else + { + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf, + decoded_size); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong returned value:\n"); + } + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->\"%s\", %u) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) decoded_size, + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->\"%s\", %u) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (decoded, decoded_size), (unsigned) decoded_size, + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_strict_n() with large out buffer */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf, + encoded_len + 1); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (fill_chr != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "A char written outside the buffer:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->\"%s\", %u) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) (encoded_len + 1), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->\"%s\", %u) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1), + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_lenient_n() with small out buffer */ + if (1) + { + unsigned int check_res = 0; + bool is_broken = true; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf, + decoded_size + 1, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (fill_chr != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "A char written outside the buffer:\n"); + } + else + { + is_broken = true; + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf, + decoded_size, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong returned value:\n"); + } + } + if (is_broken) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong 'broken_encoding' result:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->%s) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) decoded_size, + is_broken ? "true" : "false", + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->false) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (decoded, decoded_size), (unsigned) decoded_size, + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_lenient_n() with large out buffer */ + if (1) + { + unsigned int check_res = 0; + bool is_broken = true; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf, + encoded_len + 1, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (fill_chr != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "A char written outside the buffer:\n"); + } + if (is_broken) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong 'broken_encoding' result:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->%s) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) (encoded_len + 1), + is_broken ? "true" : "false", + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->false) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1), + (unsigned) decoded_size); + } + } + + if (strlen (encoded) == encoded_len) + { + /* check mhd_str_pct_decode_in_place_strict() */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + memcpy (buf, encoded, encoded_len); + buf[encoded_len] = 0; + res_size = mhd_str_pct_decode_in_place_strict (buf); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_strict ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (0 != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_strict ()' FAILED: " + "The result is not zero-terminated:\n"); + } + if (((res_size + 1) < encoded_len) ? + (encoded[res_size + 1] != buf[res_size + 1]) : + (fill_chr != buf[res_size + 1])) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_strict ()' FAILED: " + "A char written outside the buffer:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_strict ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_in_place_strict (\"%s\" " + "-> \"%s\") -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (buf, res_size), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_in_place_strict (\"%s\" " + "-> \"%s\") -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (decoded, decoded_size), + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_in_place_lenient() */ + if (1) + { + unsigned int check_res = 0; + bool is_broken = true; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + memcpy (buf, encoded, encoded_len); + buf[encoded_len] = 0; + res_size = mhd_str_pct_decode_in_place_lenient (buf, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (0 != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "The result is not zero-terminated:\n"); + } + if (((res_size + 1) < encoded_len) ? + (encoded[res_size + 1] != buf[res_size + 1]) : + (fill_chr != buf[res_size + 1])) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "A char written outside the buffer:\n"); + } + if (is_broken) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "Wrong 'broken_encoding' result:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_in_place_lenient (\"%s\" " + "-> \"%s\", ->%s) -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (buf, res_size), + is_broken ? "true" : "false", + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_in_place_lenient (\"%s\" " + "-> \"%s\", ->false) -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (decoded, decoded_size), + (unsigned) decoded_size); + } + } + } + + if (0 != ret) + { + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + return ret; +} + + +#define expect_decoded(e,d) \ + expect_decoded_n (e,MHD_STATICSTR_LEN_ (e), \ + d,MHD_STATICSTR_LEN_ (d), \ + __LINE__) + +static unsigned int +check_decode_str (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_decoded ("", ""); + + /* Base sequences without percent symbol */ + r += expect_decoded ("aaa", "aaa"); + r += expect_decoded ("bbb", "bbb"); + r += expect_decoded ("ccc", "ccc"); + r += expect_decoded ("ddd", "ddd"); + r += expect_decoded ("lll", "lll"); + r += expect_decoded ("mmm", "mmm"); + r += expect_decoded ("nnn", "nnn"); + r += expect_decoded ("ooo", "ooo"); + r += expect_decoded ("www", "www"); + r += expect_decoded ("xxx", "xxx"); + r += expect_decoded ("yyy", "yyy"); + r += expect_decoded ("zzz", "zzz"); + r += expect_decoded ("AAA", "AAA"); + r += expect_decoded ("GGG", "GGG"); + r += expect_decoded ("MMM", "MMM"); + r += expect_decoded ("TTT", "TTT"); + r += expect_decoded ("ZZZ", "ZZZ"); + r += expect_decoded ("012", "012"); + r += expect_decoded ("345", "345"); + r += expect_decoded ("678", "678"); + r += expect_decoded ("901", "901"); + r += expect_decoded ("aaaaaa", "aaaaaa"); + r += expect_decoded ("bbbbbb", "bbbbbb"); + r += expect_decoded ("cccccc", "cccccc"); + r += expect_decoded ("dddddd", "dddddd"); + r += expect_decoded ("llllll", "llllll"); + r += expect_decoded ("mmmmmm", "mmmmmm"); + r += expect_decoded ("nnnnnn", "nnnnnn"); + r += expect_decoded ("oooooo", "oooooo"); + r += expect_decoded ("wwwwww", "wwwwww"); + r += expect_decoded ("xxxxxx", "xxxxxx"); + r += expect_decoded ("yyyyyy", "yyyyyy"); + r += expect_decoded ("zzzzzz", "zzzzzz"); + r += expect_decoded ("AAAAAA", "AAAAAA"); + r += expect_decoded ("GGGGGG", "GGGGGG"); + r += expect_decoded ("MMMMMM", "MMMMMM"); + r += expect_decoded ("TTTTTT", "TTTTTT"); + r += expect_decoded ("ZZZZZZ", "ZZZZZZ"); + r += expect_decoded ("012012", "012012"); + r += expect_decoded ("345345", "345345"); + r += expect_decoded ("678678", "678678"); + r += expect_decoded ("901901", "901901"); + r += expect_decoded ("a", "a"); + r += expect_decoded ("bc", "bc"); + r += expect_decoded ("DEFG", "DEFG"); + r += expect_decoded ("123t", "123t"); + r += expect_decoded ("12345", "12345"); + r += expect_decoded ("TestStr", "TestStr"); + r += expect_decoded ("Teststring", "Teststring"); + r += expect_decoded ("Teststring.", "Teststring."); + r += expect_decoded ("Longerstring", "Longerstring"); + r += expect_decoded ("Longerstring.", "Longerstring."); + r += expect_decoded ("Longerstring2.", "Longerstring2."); + + /* Simple percent-encoded strings */ + r += expect_decoded ("Test%20string", "Test string"); + r += expect_decoded ("Test%3Fstring.", "Test?string."); + r += expect_decoded ("100%25", "100%"); + r += expect_decoded ("a%2C%20b%3Dc%26e%3Dg", "a, b=c&e=g"); + r += expect_decoded ("%20%21%23%24%25%26%27%28%29%2A%2B%2C" + "%2F%3A%3B%3D%3F%40%5B%5D%09", + " !#$%&'()*+,/:;=?@[]\t"); + + return r; +} + + +#define expect_decoded_arr(e,a) \ + expect_decoded_n (e,MHD_STATICSTR_LEN_ (e), \ + (const char *) a,(sizeof(a) / sizeof(a[0])), \ + __LINE__) + +static unsigned int +check_decode_bin (void) +{ + unsigned int r = 0; /**< The number of errors */ + + if (1) + { + static const uint8_t bin[256] = + {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff }; + /* The lower case */ + r += expect_decoded_arr ("%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e" \ + "%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d" \ + "%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c" \ + "%2d%2e%2f%30%31%32%33%34%35%36%37%38%39%3a%3b" \ + "%3c%3d%3e%3f%40%41%42%43%44%45%46%47%48%49%4a" \ + "%4b%4c%4d%4e%4f%50%51%52%53%54%55%56%57%58%59" \ + "%5a%5b%5c%5d%5e%5f%60%61%62%63%64%65%66%67%68" \ + "%69%6a%6b%6c%6d%6e%6f%70%71%72%73%74%75%76%77" \ + "%78%79%7a%7b%7c%7d%7e%7f%80%81%82%83%84%85%86" \ + "%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95" \ + "%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4" \ + "%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3" \ + "%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2" \ + "%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1" \ + "%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0" \ + "%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef" \ + "%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe" \ + "%ff", bin); + } + + if (1) + { + static const uint8_t bin[256] = + {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff }; + /* The upper case */ + r += expect_decoded_arr ("%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E" \ + "%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D" \ + "%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C" \ + "%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B" \ + "%3C%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A" \ + "%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59" \ + "%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68" \ + "%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77" \ + "%78%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86" \ + "%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95" \ + "%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4" \ + "%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3" \ + "%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2" \ + "%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1" \ + "%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0" \ + "%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" \ + "%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE" \ + "%FF", bin); + } + + return r; +} + + +/* return zero if succeed, number of failures otherwise */ +static unsigned int +expect_decoded_bad_n (const char *const encoded, const size_t encoded_len, + const char *const decoded, const size_t decoded_size, + const unsigned int line_num) +{ + static const char fill_chr = '#'; + static char buf[TEST_BIN_MAX_SIZE]; + size_t res_size; + unsigned int ret; + + mhd_assert (NULL != encoded); + mhd_assert (NULL != decoded); + mhd_assert (TEST_BIN_MAX_SIZE > decoded_size + 1); + mhd_assert (TEST_BIN_MAX_SIZE > encoded_len + 1); + mhd_assert (encoded_len >= decoded_size); + + ret = 0; + + /* check mhd_str_pct_decode_strict_n() with small out buffer */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf, + decoded_size); + if (res_size != 0) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong returned value:\n"); + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->\"%s\", %u) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) decoded_size, + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->(not defined), %u) -> 0\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_strict_n() with large out buffer */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_strict_n (encoded, encoded_len, buf, + encoded_len + 1); + if (res_size != 0) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_strict_n ()' FAILED: " + "Wrong returned value:\n"); + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->\"%s\", %u) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) (encoded_len + 1), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_strict_n (\"%s\", %u, " + "->(not defined), %u) -> 0\n", + n_prnt (encoded, encoded_len), (unsigned) (encoded_len + 1), + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_lenient_n() with small out buffer */ + if (1) + { + unsigned int check_res = 0; + bool is_broken = false; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf, + decoded_size + 1, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (fill_chr != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "A char written outside the buffer:\n"); + } + else + { + is_broken = false; + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf, + decoded_size, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong returned value:\n"); + } + } + if (! is_broken) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong 'broken_encoding' result:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->%s) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) decoded_size, + is_broken ? "true" : "false", + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->true) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (decoded, decoded_size), (unsigned) decoded_size, + (unsigned) decoded_size); + } + } + + /* check mhd_str_pct_decode_lenient_n() with large out buffer */ + if (1) + { + unsigned int check_res = 0; + bool is_broken = false; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + res_size = mhd_str_pct_decode_lenient_n (encoded, encoded_len, buf, + encoded_len + 1, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (fill_chr != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "A char written outside the buffer:\n"); + } + if (! is_broken) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong 'broken_encoding' result:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_lenient_n ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->%s) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (buf, res_size), (unsigned) (encoded_len + 1), + is_broken ? "true" : "false", + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_lenient_n (\"%s\", %u, " + "->\"%s\", %u, ->true) -> %u\n", + n_prnt (encoded, encoded_len), (unsigned) encoded_len, + n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1), + (unsigned) decoded_size); + } + } + + if (strlen (encoded) == encoded_len) + { + /* check mhd_str_pct_decode_in_place_strict() */ + if (1) + { + unsigned int check_res = 0; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + memcpy (buf, encoded, encoded_len); + buf[encoded_len] = 0; + res_size = mhd_str_pct_decode_in_place_strict (buf); + if (res_size != 0) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_strict ()' FAILED: " + "Wrong returned value:\n"); + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_in_place_strict (\"%s\" " + "-> \"%s\") -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (buf, res_size), + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_in_place_strict (\"%s\" " + "-> (not defined)) -> 0\n", + n_prnt (encoded, encoded_len)); + } + } + + /* check mhd_str_pct_decode_in_place_lenient() */ + if (1) + { + unsigned int check_res = 0; + bool is_broken = false; + + memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ + memcpy (buf, encoded, encoded_len); + buf[encoded_len] = 0; + res_size = mhd_str_pct_decode_in_place_lenient (buf, &is_broken); + if (res_size != decoded_size) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "Wrong returned value:\n"); + } + else + { + if (0 != buf[res_size]) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "The result is not zero-terminated:\n"); + } + if (((res_size + 1) < encoded_len) ? + (encoded[res_size + 1] != buf[res_size + 1]) : + (fill_chr != buf[res_size + 1])) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "A char written outside the buffer:\n"); + } + if (! is_broken) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "Wrong 'broken_encoding' result:\n"); + } + if ((res_size == decoded_size) && (0 != decoded_size) && + (0 != memcmp (buf, decoded, decoded_size))) + { + check_res = 1; + fprintf (stderr, + "'mhd_str_pct_decode_in_place_lenient ()' FAILED: " + "Wrong output string:\n"); + } + } + if (0 != check_res) + { + ret++; + fprintf (stderr, + "\tRESULT : mhd_str_pct_decode_in_place_lenient (\"%s\" " + "-> \"%s\", ->%s) -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (buf, res_size), + is_broken ? "true" : "false", + (unsigned) res_size); + fprintf (stderr, + "\tEXPECTED: mhd_str_pct_decode_in_place_lenient (\"%s\" " + "-> \"%s\", ->true) -> %u\n", + n_prnt (encoded, encoded_len), + n_prnt (decoded, decoded_size), + (unsigned) decoded_size); + } + } + } + + if (0 != ret) + { + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + return ret; +} + + +#define expect_decoded_bad(e,d) \ + expect_decoded_bad_n (e,MHD_STATICSTR_LEN_ (e), \ + d,MHD_STATICSTR_LEN_ (d), \ + __LINE__) + +static unsigned int +check_decode_bad_str (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_decoded_bad ("50%/50%", "50%/50%"); + r += expect_decoded_bad ("This is 100% incorrect.", + "This is 100% incorrect."); + r += expect_decoded_bad ("Some %%", "Some %%"); + r += expect_decoded_bad ("1 %", "1 %"); + r += expect_decoded_bad ("%", "%"); + r += expect_decoded_bad ("%a", "%a"); + r += expect_decoded_bad ("%0", "%0"); + r += expect_decoded_bad ("%0x", "%0x"); + r += expect_decoded_bad ("%FX", "%FX"); + r += expect_decoded_bad ("Valid%20and%2invalid", "Valid and%2invalid"); + + return r; +} + + +int +main (int argc, char *argv[]) +{ + unsigned int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_decode_str (); + errcount += check_decode_bin (); + errcount += check_decode_bad_str (); + if (0 == errcount) + printf ("All tests have been passed without errors.\n"); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/test_str_quote.c b/src/tests/unit/test_str_quote.c @@ -0,0 +1,798 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2022 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_quote.c + * @brief Unit tests for quoted strings processing + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_options.h" +#include <string.h> +#include <stdio.h> +#include "mhd_str.h" +#include "mhd_assert.h" + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +#define TEST_STR_MAX_LEN 1024 + +/* return zero if succeed, non-zero otherwise */ +static unsigned int +expect_result_unquote_n (const char *const quoted, const size_t quoted_len, + const char *const unquoted, const size_t unquoted_len, + const unsigned int line_num) +{ + static char buf[TEST_STR_MAX_LEN]; + size_t res_len; + unsigned int ret1; + unsigned int ret2; + unsigned int ret3; + unsigned int ret4; + + mhd_assert (NULL != quoted); + mhd_assert (NULL != unquoted); + mhd_assert (TEST_STR_MAX_LEN > quoted_len); + mhd_assert (quoted_len >= unquoted_len); + + /* First check: mhd_str_unquote () */ + ret1 = 0; + memset (buf, '#', sizeof(buf)); /* Fill buffer with character unused in the check */ + res_len = mhd_str_unquote (quoted, quoted_len, buf); + + if (res_len != unquoted_len) + { + ret1 = 1; + fprintf (stderr, + "'mhd_str_unquote ()' FAILED: Wrong result size:\n"); + } + else if ((0 != unquoted_len) && (0 != memcmp (buf, unquoted, unquoted_len))) + { + ret1 = 1; + fprintf (stderr, + "'mhd_str_unquote ()' FAILED: Wrong result string:\n"); + } + if (0 != ret1) + { + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_unquote('%.*s', %u, ->'%.*s') -> %u\n" + "\tEXPECTED: mhd_str_unquote('%.*s', %u, ->'%.*s') -> %u\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) res_len, buf, (unsigned) res_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + + /* Second check: mhd_str_equal_quoted_bin_n () */ + ret2 = 0; + if (! mhd_str_equal_quoted_bin_n (quoted, quoted_len, unquoted, unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_quoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret2 = 1; + } + + /* Third check: mhd_str_equal_caselessquoted_bin_n () */ + ret3 = 0; + if (! mhd_str_equal_caselessquoted_bin_n (quoted, quoted_len, unquoted, + unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_caselessquoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret3 = 1; + } + + /* Fourth check: mhd_str_unquote () */ + ret4 = 0; + memset (buf, '#', sizeof(buf)); /* Fill buffer with character unused in the check */ + res_len = mhd_str_quote (unquoted, unquoted_len, buf, quoted_len); + if (res_len != quoted_len) + { + ret4 = 1; + fprintf (stderr, + "'mhd_str_quote ()' FAILED: Wrong result size:\n"); + } + else if ((0 != quoted_len) && (0 != memcmp (buf, quoted, quoted_len))) + { + ret4 = 1; + fprintf (stderr, + "'mhd_str_quote ()' FAILED: Wrong result string:\n"); + } + if (0 != ret4) + { + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_quote('%.*s', %u, ->'%.*s', %u) -> %u\n" + "\tEXPECTED: mhd_str_quote('%.*s', %u, ->'%.*s', %u) -> %u\n", + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) res_len, buf, (unsigned) quoted_len, (unsigned) res_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + + return ret1 + ret2 + ret3 + ret4; +} + + +#define expect_result_unquote(q,u) \ + expect_result_unquote_n (q,MHD_STATICSTR_LEN_ (q), \ + u,MHD_STATICSTR_LEN_ (u),__LINE__) + + +static unsigned int +check_match (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_result_unquote ("", ""); + r += expect_result_unquote ("a", "a"); + r += expect_result_unquote ("abc", "abc"); + r += expect_result_unquote ("abcdef", "abcdef"); + r += expect_result_unquote ("a\0" "bc", "a\0" "bc"); + r += expect_result_unquote ("abc\\\"", "abc\""); + r += expect_result_unquote ("\\\"", "\""); + r += expect_result_unquote ("\\\"abc", "\"abc"); + r += expect_result_unquote ("abc\\\\", "abc\\"); + r += expect_result_unquote ("\\\\", "\\"); + r += expect_result_unquote ("\\\\abc", "\\abc"); + r += expect_result_unquote ("123\\\\\\\\\\\\\\\\", "123\\\\\\\\"); + r += expect_result_unquote ("\\\\\\\\\\\\\\\\", "\\\\\\\\"); + r += expect_result_unquote ("\\\\\\\\\\\\\\\\123", "\\\\\\\\123"); + r += expect_result_unquote ("\\\\\\\"\\\\\\\"\\\\\\\"\\\\\\\"\\\\\\\"" \ + "\\\\\\\"\\\\\\\"\\\\\\\"\\\\\\\"\\\\\\\"", \ + "\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\""); + + return r; +} + + +/* return zero if succeed, non-zero otherwise */ +static unsigned int +expect_result_quote_failed_n (const char *const unquoted, + const size_t unquoted_len, + const size_t buf_size, + const unsigned int line_num) +{ + static char buf[TEST_STR_MAX_LEN]; + size_t res_len; + unsigned int ret4; + + mhd_assert (TEST_STR_MAX_LEN > buf_size); + + /* The check: mhd_str_unquote () */ + ret4 = 0; + memset (buf, '#', sizeof(buf)); /* Fill buffer with character unused in the check */ + res_len = mhd_str_quote (unquoted, unquoted_len, buf, buf_size); + if (0 != res_len) + { + ret4 = 1; + fprintf (stderr, + "'mhd_str_quote ()' FAILED: Wrong result size:\n"); + } + if (0 != ret4) + { + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_quote('%.*s', %u, ->'%.*s', %u) -> %u\n" + "\tEXPECTED: mhd_str_quote('%.*s', %u, (not checked), %u) -> 0\n", + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) res_len, buf, + (unsigned) buf_size, (unsigned) res_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (unsigned) buf_size); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + + return ret4; +} + + +#define expect_result_quote_failed(q,s) \ + expect_result_quote_failed_n (q,MHD_STATICSTR_LEN_ (q), \ + s,__LINE__) + + +static unsigned int +check_quote_failed (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_result_quote_failed ("a", 0); + r += expect_result_quote_failed ("aa", 1); + r += expect_result_quote_failed ("abc\\", 4); + r += expect_result_quote_failed ("abc\"", 4); + r += expect_result_quote_failed ("abc\"\"\"\"", 6); + r += expect_result_quote_failed ("abc\"\"\"\"", 7); + r += expect_result_quote_failed ("abc\"\"\"\"", 8); + r += expect_result_quote_failed ("abc\"\"\"\"", 9); + r += expect_result_quote_failed ("abc\"\"\"\"", 10); + r += expect_result_quote_failed ("abc\\\\\\\\", 9); + r += expect_result_quote_failed ("abc\\\\\\\\", 10); + r += expect_result_quote_failed ("abc\"\"\"\"", 9); + r += expect_result_quote_failed ("abc\"\"\"\"", 10); + r += expect_result_quote_failed ("abc\"\\\"\\", 9); + r += expect_result_quote_failed ("abc\\\"\\\"", 10); + r += expect_result_quote_failed ("\"\"\"\"abc", 6); + r += expect_result_quote_failed ("\"\"\"\"abc", 7); + r += expect_result_quote_failed ("\"\"\"\"abc", 8); + r += expect_result_quote_failed ("\"\"\"\"abc", 9); + r += expect_result_quote_failed ("\"\"\"\"abc", 10); + r += expect_result_quote_failed ("\\\\\\\\abc", 9); + r += expect_result_quote_failed ("\\\\\\\\abc", 10); + r += expect_result_quote_failed ("\"\"\"\"abc", 9); + r += expect_result_quote_failed ("\"\"\"\"abc", 10); + r += expect_result_quote_failed ("\"\\\"\\abc", 9); + r += expect_result_quote_failed ("\\\"\\\"abc", 10); + + return r; +} + + +/* return zero if succeed, one otherwise */ +static unsigned int +expect_match_caseless_n (const char *const quoted, const size_t quoted_len, + const char *const unquoted, const size_t unquoted_len, + const unsigned int line_num) +{ + unsigned int ret3; + + mhd_assert (NULL != quoted); + mhd_assert (NULL != unquoted); + mhd_assert (TEST_STR_MAX_LEN > quoted_len); + + /* The check: mhd_str_equal_caselessquoted_bin_n () */ + ret3 = 0; + if (! mhd_str_equal_caselessquoted_bin_n (quoted, quoted_len, unquoted, + unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_caselessquoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret3 = 1; + } + + return ret3; +} + + +#define expect_match_caseless(q,u) \ + expect_match_caseless_n (q,MHD_STATICSTR_LEN_ (q), \ + u,MHD_STATICSTR_LEN_ (u),__LINE__) + +static unsigned int +check_match_caseless (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_match_caseless ("a", "A"); + r += expect_match_caseless ("abC", "aBc"); + r += expect_match_caseless ("AbCdeF", "aBCdEF"); + r += expect_match_caseless ("a\0" "Bc", "a\0" "bC"); + r += expect_match_caseless ("Abc\\\"", "abC\""); + r += expect_match_caseless ("\\\"", "\""); + r += expect_match_caseless ("\\\"aBc", "\"abc"); + r += expect_match_caseless ("abc\\\\", "ABC\\"); + r += expect_match_caseless ("\\\\", "\\"); + r += expect_match_caseless ("\\\\ABC", "\\abc"); + r += expect_match_caseless ("\\\\ZYX", "\\ZYX"); + r += expect_match_caseless ("abc", "ABC"); + r += expect_match_caseless ("ABCabc", "abcABC"); + r += expect_match_caseless ("abcXYZ", "ABCxyz"); + r += expect_match_caseless ("AbCdEfABCabc", "ABcdEFabcABC"); + r += expect_match_caseless ("a\\\\bc", "A\\BC"); + r += expect_match_caseless ("ABCa\\\\bc", "abcA\\BC"); + r += expect_match_caseless ("abcXYZ\\\\", "ABCxyz\\"); + r += expect_match_caseless ("\\\\AbCdEfABCabc", "\\ABcdEFabcABC"); + + return r; +} + + +/* return zero if succeed, one otherwise */ +static unsigned int +expect_result_invalid_n (const char *const quoted, const size_t quoted_len, + const unsigned int line_num) +{ + static char buf[TEST_STR_MAX_LEN]; + size_t res_len; + unsigned int ret1; + + mhd_assert (NULL != quoted); + mhd_assert (TEST_STR_MAX_LEN > quoted_len); + + /* The check: mhd_str_unquote () */ + ret1 = 0; + memset (buf, '#', sizeof(buf)); /* Fill buffer with character unused in the check */ + res_len = mhd_str_unquote (quoted, quoted_len, buf); + + if (res_len != 0) + { + ret1 = 1; + fprintf (stderr, + "'mhd_str_unquote ()' FAILED: Wrong result size:\n"); + } + if (0 != ret1) + { + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_unquote('%.*s', %u, (not checked)) -> %u\n" + "\tEXPECTED: mhd_str_unquote('%.*s', %u, (not checked)) -> 0\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (unsigned) res_len, + (int) quoted_len, quoted, (unsigned) quoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + } + + return ret1; +} + + +#define expect_result_invalid(q) \ + expect_result_invalid_n (q,MHD_STATICSTR_LEN_ (q),__LINE__) + + +static unsigned int +check_invalid (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_result_invalid ("\\"); + r += expect_result_invalid ("\\\\\\"); + r += expect_result_invalid ("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"); + r += expect_result_invalid ("xyz\\"); + r += expect_result_invalid ("\\\"\\"); + r += expect_result_invalid ("\\\"\\\"\\\"\\"); + + return r; +} + + +/* return zero if succeed, non-zero otherwise */ +static unsigned int +expect_result_unmatch_n (const char *const quoted, const size_t quoted_len, + const char *const unquoted, + const size_t unquoted_len, + const unsigned int line_num) +{ + unsigned int ret2; + unsigned int ret3; + + mhd_assert (NULL != quoted); + mhd_assert (NULL != unquoted); + + /* The check: mhd_str_equal_quoted_bin_n () */ + ret2 = 0; + if (mhd_str_equal_quoted_bin_n (quoted, quoted_len, unquoted, unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_quoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret2 = 1; + } + + /* The check: mhd_str_equal_quoted_bin_n () */ + ret3 = 0; + if (mhd_str_equal_caselessquoted_bin_n (quoted, quoted_len, unquoted, + unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_caselessquoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret3 = 1; + } + + return ret2 + ret3; +} + + +#define expect_result_unmatch(q,u) \ + expect_result_unmatch_n (q,MHD_STATICSTR_LEN_ (q), \ + u,MHD_STATICSTR_LEN_ (u),__LINE__) + + +static unsigned int +check_unmatch (void) +{ + unsigned int r = 0; /**< The number of errors */ + + /* Matched sequence except invalid backslash at the end */ + r += expect_result_unmatch ("\\", ""); + r += expect_result_unmatch ("a\\", "a"); + r += expect_result_unmatch ("abc\\", "abc"); + r += expect_result_unmatch ("a\0" "bc\\", "a\0" "bc"); + r += expect_result_unmatch ("abc\\\"\\", "abc\""); + r += expect_result_unmatch ("\\\"\\", "\""); + r += expect_result_unmatch ("\\\"abc\\", "\"abc"); + r += expect_result_unmatch ("abc\\\\\\", "abc\\"); + r += expect_result_unmatch ("\\\\\\", "\\"); + r += expect_result_unmatch ("\\\\abc\\", "\\abc"); + r += expect_result_unmatch ("123\\\\\\\\\\\\\\\\\\", "123\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\\\", "\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\123\\", "\\\\\\\\123"); + /* Invalid backslash at the end and empty string */ + r += expect_result_unmatch ("\\", ""); + r += expect_result_unmatch ("a\\", ""); + r += expect_result_unmatch ("abc\\", ""); + r += expect_result_unmatch ("a\0" "bc\\", ""); + r += expect_result_unmatch ("abc\\\"\\", ""); + r += expect_result_unmatch ("\\\"\\", ""); + r += expect_result_unmatch ("\\\"abc\\", ""); + r += expect_result_unmatch ("abc\\\\\\", ""); + r += expect_result_unmatch ("\\\\\\", ""); + r += expect_result_unmatch ("\\\\abc\\", ""); + r += expect_result_unmatch ("123\\\\\\\\\\\\\\\\\\", ""); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\\\", ""); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\123\\", ""); + /* Difference at binary zero */ + r += expect_result_unmatch ("\0", ""); + r += expect_result_unmatch ("", "\0"); + r += expect_result_unmatch ("a\0", "a"); + r += expect_result_unmatch ("a", "a\0"); + r += expect_result_unmatch ("abc\0", "abc"); + r += expect_result_unmatch ("abc", "abc\0"); + r += expect_result_unmatch ("a\0" "bc\0", "a\0" "bc"); + r += expect_result_unmatch ("a\0" "bc", "a\0" "bc\0"); + r += expect_result_unmatch ("abc\\\"\0", "abc\""); + r += expect_result_unmatch ("abc\\\"", "abc\"\0"); + r += expect_result_unmatch ("\\\"\0", "\""); + r += expect_result_unmatch ("\\\"", "\"\0"); + r += expect_result_unmatch ("\\\"abc\0", "\"abc"); + r += expect_result_unmatch ("\\\"abc", "\"abc\0"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\\0", "\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\", "\\\\\\\\\0"); + r += expect_result_unmatch ("\\\\\\\\\\\\\0" "\\\\", "\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\", "\\\\\\\0" "\\"); + r += expect_result_unmatch ("\0" "abc", "abc"); + r += expect_result_unmatch ("abc", "\0" "abc"); + r += expect_result_unmatch ("\0" "abc", "0abc"); + r += expect_result_unmatch ("0abc", "\0" "abc"); + r += expect_result_unmatch ("xyz", "xy" "\0" "z"); + r += expect_result_unmatch ("xy" "\0" "z", "xyz"); + /* Difference after binary zero */ + r += expect_result_unmatch ("abc\0" "1", "abc\0" "2"); + r += expect_result_unmatch ("a\0" "bcx", "a\0" "bcy"); + r += expect_result_unmatch ("\0" "abc\\\"2", "\0" "abc\"1"); + r += expect_result_unmatch ("\0" "abc1\\\"", "\0" "abc2\""); + r += expect_result_unmatch ("\0" "\\\"c", "\0" "\"d"); + r += expect_result_unmatch ("\\\"ab" "\0" "1c", "\"ab" "\0" "2c"); + r += expect_result_unmatch ("a\0" "bcdef2", "a\0" "bcdef1"); + r += expect_result_unmatch ("a\0" "bc2def", "a\0" "bc1def"); + r += expect_result_unmatch ("a\0" "1bcdef", "a\0" "2bcdef"); + r += expect_result_unmatch ("abcde\0" "f2", "abcde\0" "f1"); + r += expect_result_unmatch ("123\\\\\\\\\\\\\0" "\\\\1", "123\\\\\\\0" "\\2"); + r += expect_result_unmatch ("\\\\\\\\\\\\\0" "1\\\\", "\\\\\\" "2\\"); + /* One side is empty */ + r += expect_result_unmatch ("abc", ""); + r += expect_result_unmatch ("", "abc"); + r += expect_result_unmatch ("1234567890", ""); + r += expect_result_unmatch ("", "1234567890"); + r += expect_result_unmatch ("abc\\\"", ""); + r += expect_result_unmatch ("", "abc\""); + r += expect_result_unmatch ("\\\"", ""); + r += expect_result_unmatch ("", "\""); + r += expect_result_unmatch ("\\\"abc", ""); + r += expect_result_unmatch ("", "\"abc"); + r += expect_result_unmatch ("abc\\\\", ""); + r += expect_result_unmatch ("", "abc\\"); + r += expect_result_unmatch ("\\\\", ""); + r += expect_result_unmatch ("", "\\"); + r += expect_result_unmatch ("\\\\abc", ""); + r += expect_result_unmatch ("", "\\abc"); + r += expect_result_unmatch ("123\\\\\\\\\\\\\\\\", ""); + r += expect_result_unmatch ("", "123\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\", ""); + r += expect_result_unmatch ("", "\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\123", ""); + r += expect_result_unmatch ("", "\\\\\\\\123"); + /* Various unmatched strings */ + r += expect_result_unmatch ("a", "x"); + r += expect_result_unmatch ("abc", "abcabc"); + r += expect_result_unmatch ("abc", "abcabcabc"); + r += expect_result_unmatch ("abc", "abcabcabcabc"); + r += expect_result_unmatch ("ABCABC", "ABC"); + r += expect_result_unmatch ("ABCABCABC", "ABC"); + r += expect_result_unmatch ("ABCABCABCABC", "ABC"); + r += expect_result_unmatch ("123\\\\\\\\\\\\\\\\\\\\", "123\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\\\\\", "\\\\\\\\"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\123\\\\", "\\\\\\\\123"); + r += expect_result_unmatch ("\\\\\\\\\\\\\\\\", "\\\\\\\\\\"); + + return r; +} + + +/* return zero if succeed, one otherwise */ +static unsigned int +expect_result_case_unmatch_n (const char *const quoted, + const size_t quoted_len, + const char *const unquoted, + const size_t unquoted_len, + const unsigned int line_num) +{ + unsigned int ret2; + + mhd_assert (NULL != quoted); + mhd_assert (NULL != unquoted); + + /* THe check: mhd_str_equal_quoted_bin_n () */ + ret2 = 0; + if (mhd_str_equal_quoted_bin_n (quoted, quoted_len, unquoted, unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_quoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret2 = 1; + } + + return ret2; +} + + +#define expect_result_case_unmatch(q,u) \ + expect_result_case_unmatch_n (q,MHD_STATICSTR_LEN_ (q), \ + u,MHD_STATICSTR_LEN_ (u),__LINE__) + +static unsigned int +check_unmatch_case (void) +{ + unsigned int r = 0; /**< The number of errors */ + + r += expect_result_case_unmatch ("a", "A"); + r += expect_result_case_unmatch ("abC", "aBc"); + r += expect_result_case_unmatch ("AbCdeF", "aBCdEF"); + r += expect_result_case_unmatch ("a\0" "Bc", "a\0" "bC"); + r += expect_result_case_unmatch ("Abc\\\"", "abC\""); + r += expect_result_case_unmatch ("\\\"aBc", "\"abc"); + r += expect_result_case_unmatch ("abc\\\\", "ABC\\"); + r += expect_result_case_unmatch ("\\\\ABC", "\\abc"); + r += expect_result_case_unmatch ("\\\\ZYX", "\\ZYx"); + r += expect_result_case_unmatch ("abc", "ABC"); + r += expect_result_case_unmatch ("ABCabc", "abcABC"); + r += expect_result_case_unmatch ("abcXYZ", "ABCxyz"); + r += expect_result_case_unmatch ("AbCdEfABCabc", "ABcdEFabcABC"); + r += expect_result_case_unmatch ("a\\\\bc", "A\\BC"); + r += expect_result_case_unmatch ("ABCa\\\\bc", "abcA\\BC"); + r += expect_result_case_unmatch ("abcXYZ\\\\", "ABCxyz\\"); + r += expect_result_case_unmatch ("\\\\AbCdEfABCabc", "\\ABcdEFabcABC"); + + return r; +} + + +/* return zero if succeed, one otherwise */ +static unsigned int +expect_result_caseless_unmatch_n (const char *const quoted, + const size_t quoted_len, + const char *const unquoted, + const size_t unquoted_len, + const unsigned int line_num) +{ + unsigned int ret2; + unsigned int ret3; + + mhd_assert (NULL != quoted); + mhd_assert (NULL != unquoted); + + /* The check: mhd_str_equal_quoted_bin_n () */ + ret2 = 0; + if (mhd_str_equal_quoted_bin_n (quoted, quoted_len, unquoted, unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_quoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_quoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret2 = 1; + } + + /* The check: mhd_str_equal_quoted_bin_n () */ + ret3 = 0; + if (mhd_str_equal_caselessquoted_bin_n (quoted, quoted_len, unquoted, + unquoted_len)) + { + fprintf (stderr, + "'mhd_str_equal_caselessquoted_bin_n ()' FAILED: Wrong result:\n"); + /* This does NOT print part of the string after binary zero */ + fprintf (stderr, + "\tRESULT : mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> true\n" + "\tEXPECTED: mhd_str_equal_caselessquoted_bin_n('%.*s', %u, " + "'%.*s', %u) -> false\n", + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len, + (int) quoted_len, quoted, (unsigned) quoted_len, + (int) unquoted_len, unquoted, (unsigned) unquoted_len); + fprintf (stderr, + "The check is at line: %u\n\n", line_num); + ret3 = 1; + } + + return ret2 + ret3; +} + + +#define expect_result_caseless_unmatch(q,u) \ + expect_result_caseless_unmatch_n (q,MHD_STATICSTR_LEN_ (q), \ + u,MHD_STATICSTR_LEN_ (u),__LINE__) + + +static unsigned int +check_unmatch_caseless (void) +{ + unsigned int r = 0; /**< The number of errors */ + + /* Matched sequence except invalid backslash at the end */ + r += expect_result_caseless_unmatch ("a\\", "A"); + r += expect_result_caseless_unmatch ("abC\\", "abc"); + r += expect_result_caseless_unmatch ("a\0" "Bc\\", "a\0" "bc"); + r += expect_result_caseless_unmatch ("abc\\\"\\", "ABC\""); + r += expect_result_caseless_unmatch ("\\\"\\", "\""); + r += expect_result_caseless_unmatch ("\\\"ABC\\", "\"abc"); + r += expect_result_caseless_unmatch ("Abc\\\\\\", "abC\\"); + r += expect_result_caseless_unmatch ("\\\\\\", "\\"); + r += expect_result_caseless_unmatch ("\\\\aBc\\", "\\abC"); + /* Difference at binary zero */ + r += expect_result_caseless_unmatch ("a\0", "A"); + r += expect_result_caseless_unmatch ("A", "a\0"); + r += expect_result_caseless_unmatch ("abC\0", "abc"); + r += expect_result_caseless_unmatch ("abc", "ABc\0"); + r += expect_result_caseless_unmatch ("a\0" "bC\0", "a\0" "bc"); + r += expect_result_caseless_unmatch ("a\0" "bc", "A\0" "bc\0"); + r += expect_result_caseless_unmatch ("ABC\\\"\0", "abc\""); + r += expect_result_caseless_unmatch ("abc\\\"", "ABC\"\0"); + r += expect_result_caseless_unmatch ("\\\"aBc\0", "\"abc"); + r += expect_result_caseless_unmatch ("\\\"Abc", "\"abc\0"); + r += expect_result_caseless_unmatch ("\\\\\\\\\\\\\\\\\0", "\\\\\\\\"); + r += expect_result_caseless_unmatch ("\\\\\\\\\\\\\\\\", "\\\\\\\\\0"); + r += expect_result_caseless_unmatch ("\\\\\\\\\\\\\0" "\\\\", "\\\\\\\\"); + r += expect_result_caseless_unmatch ("\\\\\\\\\\\\\\\\", "\\\\\\\0" "\\"); + r += expect_result_caseless_unmatch ("\0" "aBc", "abc"); + r += expect_result_caseless_unmatch ("abc", "\0" "abC"); + r += expect_result_caseless_unmatch ("\0" "abc", "0abc"); + r += expect_result_caseless_unmatch ("0abc", "\0" "aBc"); + r += expect_result_caseless_unmatch ("xyZ", "xy" "\0" "z"); + r += expect_result_caseless_unmatch ("Xy" "\0" "z", "xyz"); + /* Difference after binary zero */ + r += expect_result_caseless_unmatch ("abc\0" "1", "aBC\0" "2"); + r += expect_result_caseless_unmatch ("a\0" "bcX", "a\0" "bcy"); + r += expect_result_caseless_unmatch ("\0" "abc\\\"2", "\0" "Abc\"1"); + r += expect_result_caseless_unmatch ("\0" "Abc1\\\"", "\0" "abc2\""); + r += expect_result_caseless_unmatch ("\0" "\\\"c", "\0" "\"d"); + r += expect_result_caseless_unmatch ("\\\"ab" "\0" "1C", "\"ab" "\0" "2C"); + r += expect_result_caseless_unmatch ("a\0" "BCDef2", "a\0" "bcdef1"); + r += expect_result_caseless_unmatch ("a\0" "bc2def", "a\0" "BC1def"); + r += expect_result_caseless_unmatch ("a\0" "1bcdeF", "a\0" "2bcdef"); + r += expect_result_caseless_unmatch ("abcde\0" "f2", "ABCDE\0" "f1"); + r += expect_result_caseless_unmatch ("\\\"ab" "\0" "XC", "\"ab" "\0" "yC"); + r += expect_result_caseless_unmatch ("a\0" "BCDefY", "a\0" "bcdefx"); + r += expect_result_caseless_unmatch ("a\0" "bczdef", "a\0" "BCXdef"); + r += expect_result_caseless_unmatch ("a\0" "YbcdeF", "a\0" "zbcdef"); + r += expect_result_caseless_unmatch ("abcde\0" "fy", "ABCDE\0" "fX"); + + return r; +} + + +int +main (int argc, char *argv[]) +{ + unsigned int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_match (); + errcount += check_quote_failed (); + errcount += check_match_caseless (); + errcount += check_invalid (); + errcount += check_unmatch (); + errcount += check_unmatch_case (); + errcount += check_unmatch_caseless (); + if (0 == errcount) + printf ("All tests were passed without errors.\n"); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/test_str_to_value.c b/src/tests/unit/test_str_to_value.c @@ -0,0 +1,2614 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2016 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/unit_str_test.h + * @brief Unit tests for mhd_str functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "../mhdt_checks.h" + +#include <stdio.h> +#include <locale.h> +#include <string.h> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else /* ! HAVE_INTTYPES_H */ +#define PRIu64 "llu" +#define PRIuPTR "u" +#define PRIX64 "llX" +#endif /* ! HAVE_INTTYPES_H */ +#include <stdint.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif /* HAVE_STDLIB_H */ +#include "mhd_limits.h" +#include "mhd_str.h" +#include "test_helpers.h" + + +static int verbose = 0; /* verbose level (0-3)*/ + +/* Locale names to test. + * Functions must not depend of current current locale, + * so result must be the same in any locale. + */ +static const char *const locale_names[] = { + "C", + "", /* System default locale */ +#if defined(_WIN32) && ! defined(__CYGWIN__) + ".OCP", /* W32 system default OEM code page */ + ".ACP", /* W32 system default ANSI code page */ + ".65001", /* UTF-8 */ + ".437", + ".850", + ".857", + ".866", + ".1250", + ".1251", + ".1252", + "en", + "english", + "French_France", + "Turkish_Turkey.1254", + "de", + "zh-Hans", + "ru-RU.1251" +#if 0 /* Disabled extra checks */ + , + ".1254", + ".20866", /* number for KOI8-R */ + ".28591", /* number for ISO-8859-1 */ + ".28595", /* number for ISO-8859-5 */ + ".28599", /* number for ISO-8859-9 */ + ".28605", /* number for ISO-8859-15 */ + "en-US", + "English-US", + "en-US.437", + "English_United States.437", + "en-US.1252", + "English_United States.1252", + "English_United States.28591", + "English_United States.65001", + "fra", + "french", + "fr-FR", + "fr-FR.850", + "french_france.850", + "fr-FR.1252", + "French_france.1252", + "French_france.28605", + "French_France.65001", + "de-DE", + "de-DE.850", + "German_Germany.850", + "German_Germany.1250", + "de-DE.1252", + "German_Germany.1252", + "German_Germany.28605", + "German_Germany.65001", + "tr", + "trk", + "turkish", + "tr-TR", + "tr-TR.1254", + "tr-TR.857", + "Turkish_Turkey.857", + "Turkish_Turkey.28599", + "Turkish_Turkey.65001", + "ru", + "ru-RU", + "Russian", + "ru-RU.866", + "Russian_Russia.866", + "Russian_Russia.1251", + "Russian_Russia.20866", + "Russian_Russia.28595", + "Russian_Russia.65001", + "zh-Hans.936", + "chinese-simplified" +#endif /* Disabled extra checks */ +#else /* ! _WIN32 || __CYGWIN__ */ + "C.UTF-8", + "POSIX", + "en", + "en_US", + "en_US.ISO-8859-1", + "en_US.ISO_8859-1", + "en_US.ISO8859-1", + "en_US.iso88591", + "en_US.ISO-8859-15", + "en_US.DIS_8859-15", + "en_US.ISO8859-15", + "en_US.iso885915", + "en_US.1252", + "en_US.CP1252", + "en_US.UTF-8", + "en_US.utf8", + "fr", + "fr_FR", + "fr_FR.850", + "fr_FR.IBM850", + "fr_FR.1252", + "fr_FR.CP1252", + "fr_FR.ISO-8859-1", + "fr_FR.ISO_8859-1", + "fr_FR.ISO8859-1", + "fr_FR.iso88591", + "fr_FR.ISO-8859-15", + "fr_FR.DIS_8859-15", + "fr_FR.ISO8859-15", + "fr_FR.iso8859-15", + "fr_FR.UTF-8", + "fr_FR.utf8", + "de", + "de_DE", + "de_DE.850", + "de_DE.IBM850", + "de_DE.1250", + "de_DE.CP1250", + "de_DE.1252", + "de_DE.CP1252", + "de_DE.ISO-8859-1", + "de_DE.ISO_8859-1", + "de_DE.ISO8859-1", + "de_DE.iso88591", + "de_DE.ISO-8859-15", + "de_DE.DIS_8859-15", + "de_DE.ISO8859-15", + "de_DE.iso885915", + "de_DE.UTF-8", + "de_DE.utf8", + "tr", + "tr_TR", + "tr_TR.1254", + "tr_TR.CP1254", + "tr_TR.857", + "tr_TR.IBM857", + "tr_TR.ISO-8859-9", + "tr_TR.ISO8859-9", + "tr_TR.iso88599", + "tr_TR.UTF-8", + "tr_TR.utf8", + "ru", + "ru_RU", + "ru_RU.1251", + "ru_RU.CP1251", + "ru_RU.866", + "ru_RU.IBM866", + "ru_RU.KOI8-R", + "ru_RU.koi8-r", + "ru_RU.KOI8-RU", + "ru_RU.ISO-8859-5", + "ru_RU.ISO_8859-5", + "ru_RU.ISO8859-5", + "ru_RU.iso88595", + "ru_RU.UTF-8", + "zh_CN", + "zh_CN.GB2312", + "zh_CN.UTF-8", +#endif /* ! _WIN32 || __CYGWIN__ */ +}; + +static const unsigned int locale_name_count = sizeof(locale_names) + / sizeof(locale_names[0]); + + +/* + * Helper functions + */ + +static int +set_test_locale (size_t num) +{ + if (num >= locale_name_count) + { + fprintf (stderr, "Unexpected number of locale.\n"); + exit (99); + } + if (verbose > 2) + printf ("Setting locale \"%s\":", locale_names[num]); + if (setlocale (LC_ALL, locale_names[num])) + { + if (verbose > 2) + printf (" succeed.\n"); + return 1; + } + if (verbose > 2) + printf (" failed.\n"); + return 0; +} + + +static const char * +get_current_locale_str (void) +{ + char const *loc_str = setlocale (LC_ALL, NULL); + return loc_str ? loc_str : "unknown"; +} + + +static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */ +static size_t buf_idx = 0; + +/* print non-printable chars as char codes */ +static char * +n_prnt (const char *str) +{ + static char *buf; /* should be enough for testing */ + static const size_t buf_size = sizeof(tmp_bufs[0]); + const unsigned char *p = (const unsigned char *) str; + size_t w_pos = 0; + if (++buf_idx > 3) + buf_idx = 0; + buf = tmp_bufs[buf_idx]; + + while (*p && w_pos + 1 < buf_size) + { + const unsigned char c = *p; + if ((c == '\\') || (c == '"') ) + { + if (w_pos + 2 >= buf_size) + break; + buf[w_pos++] = '\\'; + buf[w_pos++] = (char) c; + } + else if ((c >= 0x20) && (c <= 0x7E) ) + buf[w_pos++] = (char) c; + else + { + if (w_pos + 4 >= buf_size) + break; + if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned + int) c) != 4) + break; + w_pos += 4; + } + p++; + } + if (*p) + { /* not full string is printed */ + /* enough space for "..." ? */ + if (w_pos + 3 > buf_size) + w_pos = buf_size - 4; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + buf[w_pos++] = '.'; + } + buf[w_pos] = 0; + return buf; +} + + +struct str_with_len +{ + const char *const str; + const size_t len; +}; + +#define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} + +/* + * Digits in string -> value tests + */ + +struct str_with_value +{ + const struct str_with_len str; + const size_t num_of_digt; + const uint64_t val; +}; + +/* valid string for conversion to unsigned integer value */ +static const struct str_with_value dstrs_w_values[] = { + /* simplest strings */ + {D_STR_W_LEN ("1"), 1, 1}, + {D_STR_W_LEN ("0"), 1, 0}, + {D_STR_W_LEN ("10000"), 5, 10000}, + + /* all digits */ + {D_STR_W_LEN ("1234"), 4, 1234}, + {D_STR_W_LEN ("4567"), 4, 4567}, + {D_STR_W_LEN ("7890"), 4, 7890}, + {D_STR_W_LEN ("8021"), 4, 8021}, + {D_STR_W_LEN ("9754"), 4, 9754}, + {D_STR_W_LEN ("6392"), 4, 6392}, + + /* various prefixes */ + {D_STR_W_LEN ("00000000"), 8, 0}, + {D_STR_W_LEN ("0755"), 4, 755}, /* not to be interpreted as octal value! */ + {D_STR_W_LEN ("002"), 3, 2}, + {D_STR_W_LEN ("0001"), 4, 1}, + {D_STR_W_LEN ("00000000000000000000000031295483"), 32, 31295483}, + + /* numbers below and above limits */ + {D_STR_W_LEN ("127"), 3, 127}, /* 0x7F, SCHAR_MAX */ + {D_STR_W_LEN ("128"), 3, 128}, /* 0x80, SCHAR_MAX+1 */ + {D_STR_W_LEN ("255"), 3, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("256"), 3, 256}, /* 0x100, UCHAR_MAX+1 */ + {D_STR_W_LEN ("32767"), 5, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("32768"), 5, 32768}, /* 0x8000, INT16_MAX+1 */ + {D_STR_W_LEN ("65535"), 5, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("65536"), 5, 65536}, /* 0x10000, UINT16_MAX+1 */ + {D_STR_W_LEN ("2147483647"), 10, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("2147483648"), 10, UINT64_C (2147483648)}, /* 0x80000000, INT32_MAX+1 */ + {D_STR_W_LEN ("4294967295"), 10, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("4294967296"), 10, UINT64_C (4294967296)}, /* 0x100000000, UINT32_MAX+1 */ + {D_STR_W_LEN ("9223372036854775807"), 19, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("9223372036854775808"), 19, UINT64_C (9223372036854775808)}, /* 0x8000000000000000, INT64_MAX+1 */ + {D_STR_W_LEN ("18446744073709551615"), 20, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + + /* random numbers */ + {D_STR_W_LEN ("10186753"), 8, 10186753}, + {D_STR_W_LEN ("144402566"), 9, 144402566}, + {D_STR_W_LEN ("151903144"), 9, 151903144}, + {D_STR_W_LEN ("139264621"), 9, 139264621}, + {D_STR_W_LEN ("730348"), 6, 730348}, + {D_STR_W_LEN ("21584377"), 8, 21584377}, + {D_STR_W_LEN ("709"), 3, 709}, + {D_STR_W_LEN ("54"), 2, 54}, + {D_STR_W_LEN ("8452"), 4, 8452}, + {D_STR_W_LEN ("17745098750013624977"), 20, UINT64_C (17745098750013624977)}, + {D_STR_W_LEN ("06786878769931678000"), 20, UINT64_C (6786878769931678000)}, + + /* non-digit suffixes */ + {D_STR_W_LEN ("1234oa"), 4, 1234}, + {D_STR_W_LEN ("20h"), 2, 20}, /* not to be interpreted as hex value! */ + {D_STR_W_LEN ("0x1F"), 1, 0}, /* not to be interpreted as hex value! */ + {D_STR_W_LEN ("0564`~}"), 4, 564}, + {D_STR_W_LEN ("7240146.724"), 7, 7240146}, + {D_STR_W_LEN ("2,9"), 1, 2}, + {D_STR_W_LEN ("200+1"), 3, 200}, + {D_STR_W_LEN ("1a"), 1, 1}, + {D_STR_W_LEN ("2E"), 1, 2}, + {D_STR_W_LEN ("6c"), 1, 6}, + {D_STR_W_LEN ("8F"), 1, 8}, + {D_STR_W_LEN ("287416997! And the not too long string."), 9, 287416997} +}; + +/* strings that should overflow uint64_t */ +static const struct str_with_len str_ovflw[] = { + D_STR_W_LEN ("18446744073709551616"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("18446744073709551620"), + D_STR_W_LEN ("18446744083709551615"), + D_STR_W_LEN ("19234761020556472143"), + D_STR_W_LEN ("184467440737095516150"), + D_STR_W_LEN ("1844674407370955161500"), + D_STR_W_LEN ("000018446744073709551616"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("20000000000000000000"), + D_STR_W_LEN ("020000000000000000000"), + D_STR_W_LEN ("0020000000000000000000"), + D_STR_W_LEN ("100000000000000000000"), + D_STR_W_LEN ("434532891232591226417"), + D_STR_W_LEN ("99999999999999999999"), + D_STR_W_LEN ("18446744073709551616abcd"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("20000000000000000000 suffix"), + D_STR_W_LEN ("020000000000000000000x") +}; + +/* strings that should not be convertible to numeric value */ +static const struct str_with_len str_no_num[] = { + D_STR_W_LEN ("zero"), + D_STR_W_LEN ("one"), + D_STR_W_LEN ("\xb9\xb2\xb3"), /* superscript "123" in ISO-8859-1/CP1252 */ + D_STR_W_LEN ("\xc2\xb9\xc2\xb2\xc2\xb3"), /* superscript "123" in UTF-8 */ + D_STR_W_LEN ("\xd9\xa1\xd9\xa2\xd9\xa3"), /* Arabic-Indic "١٢٣" in UTF-8 */ + D_STR_W_LEN ("\xdb\xb1\xdb\xb2\xdb\xb3"), /* Ext Arabic-Indic "۱۲۳" in UTF-8 */ + D_STR_W_LEN ("\xe0\xa5\xa7\xe0\xa5\xa8\xe0\xa5\xa9"), /* Devanagari "१२३" in UTF-8 */ + D_STR_W_LEN ("\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89"), /* Chinese "一二三" in UTF-8 */ + D_STR_W_LEN ("\xd2\xbb\xb6\xfe\xc8\xfd"), /* Chinese "一二三" in GB2312/CP936 */ + D_STR_W_LEN ("\x1B\x24\x29\x41\x0E\x52\x3B\x36\x7E\x48\x7D\x0F") /* Chinese "一二三" in ISO-2022-CN */ +}; + +/* valid hex string for conversion to unsigned integer value */ +static const struct str_with_value xdstrs_w_values[] = { + /* simplest strings */ + {D_STR_W_LEN ("1"), 1, 0x1}, + {D_STR_W_LEN ("0"), 1, 0x0}, + {D_STR_W_LEN ("10000"), 5, 0x10000}, + + /* all digits */ + {D_STR_W_LEN ("1234"), 4, 0x1234}, + {D_STR_W_LEN ("4567"), 4, 0x4567}, + {D_STR_W_LEN ("7890"), 4, 0x7890}, + {D_STR_W_LEN ("8021"), 4, 0x8021}, + {D_STR_W_LEN ("9754"), 4, 0x9754}, + {D_STR_W_LEN ("6392"), 4, 0x6392}, + {D_STR_W_LEN ("abcd"), 4, 0xABCD}, + {D_STR_W_LEN ("cdef"), 4, 0xCDEF}, + {D_STR_W_LEN ("FEAB"), 4, 0xFEAB}, + {D_STR_W_LEN ("BCED"), 4, 0xBCED}, + {D_STR_W_LEN ("bCeD"), 4, 0xBCED}, + {D_STR_W_LEN ("1A5F"), 4, 0x1A5F}, + {D_STR_W_LEN ("12AB"), 4, 0x12AB}, + {D_STR_W_LEN ("CD34"), 4, 0xCD34}, + {D_STR_W_LEN ("56EF"), 4, 0x56EF}, + {D_STR_W_LEN ("7a9f"), 4, 0x7A9F}, + + /* various prefixes */ + {D_STR_W_LEN ("00000000"), 8, 0x0}, + {D_STR_W_LEN ("0755"), 4, 0x755}, /* not to be interpreted as octal value! */ + {D_STR_W_LEN ("002"), 3, 0x2}, + {D_STR_W_LEN ("0001"), 4, 0x1}, + {D_STR_W_LEN ("00a"), 3, 0xA}, + {D_STR_W_LEN ("0F"), 2, 0xF}, + {D_STR_W_LEN ("0000000000000000000000003A29e4C3"), 32, 0x3A29E4C3}, + + /* numbers below and above limits */ + {D_STR_W_LEN ("7F"), 2, 127}, /* 0x7F, SCHAR_MAX */ + {D_STR_W_LEN ("7f"), 2, 127}, /* 0x7F, SCHAR_MAX */ + {D_STR_W_LEN ("80"), 2, 128}, /* 0x80, SCHAR_MAX+1 */ + {D_STR_W_LEN ("fF"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("Ff"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("FF"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("ff"), 2, 255}, /* 0xFF, UCHAR_MAX */ + {D_STR_W_LEN ("100"), 3, 256}, /* 0x100, UCHAR_MAX+1 */ + {D_STR_W_LEN ("7fff"), 4, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("7FFF"), 4, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("7Fff"), 4, 32767}, /* 0x7FFF, INT16_MAX */ + {D_STR_W_LEN ("8000"), 4, 32768}, /* 0x8000, INT16_MAX+1 */ + {D_STR_W_LEN ("ffff"), 4, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("FFFF"), 4, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("FffF"), 4, 65535}, /* 0xFFFF, UINT16_MAX */ + {D_STR_W_LEN ("10000"), 5, 65536}, /* 0x10000, UINT16_MAX+1 */ + {D_STR_W_LEN ("7FFFFFFF"), 8, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("7fffffff"), 8, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("7FFffFff"), 8, 2147483647}, /* 0x7FFFFFFF, INT32_MAX */ + {D_STR_W_LEN ("80000000"), 8, UINT64_C (2147483648)}, /* 0x80000000, INT32_MAX+1 */ + {D_STR_W_LEN ("FFFFFFFF"), 8, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("ffffffff"), 8, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("FfFfFfFf"), 8, UINT64_C (4294967295)}, /* 0xFFFFFFFF, UINT32_MAX */ + {D_STR_W_LEN ("100000000"), 9, UINT64_C (4294967296)}, /* 0x100000000, UINT32_MAX+1 */ + {D_STR_W_LEN ("7fffffffffffffff"), 16, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("7FFFFFFFFFFFFFFF"), 16, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("7FfffFFFFffFFffF"), 16, UINT64_C (9223372036854775807)}, /* 0x7FFFFFFFFFFFFFFF, INT64_MAX */ + {D_STR_W_LEN ("8000000000000000"), 16, UINT64_C (9223372036854775808)}, /* 0x8000000000000000, INT64_MAX+1 */ + {D_STR_W_LEN ("ffffffffffffffff"), 16, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + {D_STR_W_LEN ("FFFFFFFFFFFFFFFF"), 16, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + {D_STR_W_LEN ("FffFffFFffFFfFFF"), 16, UINT64_C (18446744073709551615)}, /* 0xFFFFFFFFFFFFFFFF, UINT64_MAX */ + + /* random numbers */ + {D_STR_W_LEN ("10186753"), 8, 0x10186753}, + {D_STR_W_LEN ("144402566"), 9, 0x144402566}, + {D_STR_W_LEN ("151903144"), 9, 0x151903144}, + {D_STR_W_LEN ("139264621"), 9, 0x139264621}, + {D_STR_W_LEN ("730348"), 6, 0x730348}, + {D_STR_W_LEN ("21584377"), 8, 0x21584377}, + {D_STR_W_LEN ("709"), 3, 0x709}, + {D_STR_W_LEN ("54"), 2, 0x54}, + {D_STR_W_LEN ("8452"), 4, 0x8452}, + {D_STR_W_LEN ("22353EC6"), 8, 0x22353EC6}, + {D_STR_W_LEN ("307F1655"), 8, 0x307F1655}, + {D_STR_W_LEN ("1FCB7226"), 8, 0x1FCB7226}, + {D_STR_W_LEN ("82480560"), 8, 0x82480560}, + {D_STR_W_LEN ("7386D95"), 7, 0x7386D95}, + {D_STR_W_LEN ("EC3AB"), 5, 0xEC3AB}, + {D_STR_W_LEN ("6DD05"), 5, 0x6DD05}, + {D_STR_W_LEN ("C5DF"), 4, 0xC5DF}, + {D_STR_W_LEN ("6CE"), 3, 0x6CE}, + {D_STR_W_LEN ("CE6"), 3, 0xCE6}, + {D_STR_W_LEN ("ce6"), 3, 0xCE6}, + {D_STR_W_LEN ("F27"), 3, 0xF27}, + {D_STR_W_LEN ("8497D54277D7E1"), 14, UINT64_C (37321639124785121)}, + {D_STR_W_LEN ("8497d54277d7e1"), 14, UINT64_C (37321639124785121)}, + {D_STR_W_LEN ("8497d54277d7E1"), 14, UINT64_C (37321639124785121)}, + {D_STR_W_LEN ("8C8112D0A06"), 11, UINT64_C (9655374645766)}, + {D_STR_W_LEN ("8c8112d0a06"), 11, UINT64_C (9655374645766)}, + {D_STR_W_LEN ("8c8112d0A06"), 11, UINT64_C (9655374645766)}, + {D_STR_W_LEN ("1774509875001362"), 16, UINT64_C (1690064375898968930)}, + {D_STR_W_LEN ("0678687876998000"), 16, UINT64_C (466237428027981824)}, + + /* non-digit suffixes */ + {D_STR_W_LEN ("1234oa"), 4, 0x1234}, + {D_STR_W_LEN ("20h"), 2, 0x20}, + {D_STR_W_LEN ("2CH"), 2, 0x2C}, + {D_STR_W_LEN ("2ch"), 2, 0x2C}, + {D_STR_W_LEN ("0x1F"), 1, 0x0}, /* not to be interpreted as hex prefix! */ + {D_STR_W_LEN ("0564`~}"), 4, 0x564}, + {D_STR_W_LEN ("0A64`~}"), 4, 0xA64}, + {D_STR_W_LEN ("056c`~}"), 4, 0X56C}, + {D_STR_W_LEN ("7240146.724"), 7, 0x7240146}, + {D_STR_W_LEN ("7E4c1AB.724"), 7, 0X7E4C1AB}, + {D_STR_W_LEN ("F24B1B6.724"), 7, 0xF24B1B6}, + {D_STR_W_LEN ("2,9"), 1, 0x2}, + {D_STR_W_LEN ("a,9"), 1, 0xA}, + {D_STR_W_LEN ("200+1"), 3, 0x200}, + {D_STR_W_LEN ("2cc+1"), 3, 0x2CC}, + {D_STR_W_LEN ("2cC+1"), 3, 0x2CC}, + {D_STR_W_LEN ("27416997! And the not too long string."), 8, 0x27416997}, + {D_STR_W_LEN ("27555416997! And the not too long string."), 11, + 0x27555416997}, + {D_STR_W_LEN ("416997And the not too long string."), 7, 0x416997A}, + {D_STR_W_LEN ("0F4C3Dabstract addition to make string even longer"), 8, + 0xF4C3DAB} +}; + +/* hex strings that should overflow uint64_t */ +static const struct str_with_len strx_ovflw[] = { + D_STR_W_LEN ("10000000000000000"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("10000000000000001"), + D_STR_W_LEN ("10000000000000002"), + D_STR_W_LEN ("1000000000000000A"), + D_STR_W_LEN ("11000000000000000"), + D_STR_W_LEN ("010000000000000000"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("000010000000000000000"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("20000000000000000000"), + D_STR_W_LEN ("020000000000000000000"), + D_STR_W_LEN ("0020000000000000000000"), + D_STR_W_LEN ("20000000000000000"), + D_STR_W_LEN ("A0000000000000000"), + D_STR_W_LEN ("F0000000000000000"), + D_STR_W_LEN ("a0000000000000000"), + D_STR_W_LEN ("11111111111111111"), + D_STR_W_LEN ("CcCcCCccCCccCCccC"), + D_STR_W_LEN ("f0000000000000000"), + D_STR_W_LEN ("100000000000000000000"), + D_STR_W_LEN ("434532891232591226417"), + D_STR_W_LEN ("10000000000000000a"), + D_STR_W_LEN ("10000000000000000E"), + D_STR_W_LEN ("100000000000000000 and nothing"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("100000000000000000xx"), /* 0x10000000000000000, UINT64_MAX+1 */ + D_STR_W_LEN ("99999999999999999999"), + D_STR_W_LEN ("18446744073709551616abcd"), + D_STR_W_LEN ("20000000000000000000 suffix"), + D_STR_W_LEN ("020000000000000000000x") +}; + + +static size_t +check_str_to_uint64_valid (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(dstrs_w_values) + / sizeof(dstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + uint64_t rv; + size_t rs; + const struct str_with_value *const t = dstrs_w_values + i; + + if (c_failed[i]) + continue; /* skip already failed checks */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + rv = 9435223; /* some random value */ + rs = mhd_str_to_uint64 (t->str.str, &rv); + if (rs != t->num_of_digt) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", ->%" PRIu64 ") returned %" + PRIuPTR + ", while expecting %d." + " Locale: %s\n", n_prnt (t->str.str), rv, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + if (rv != t->val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", ->%" PRIu64 + ") converted string to value %" + PRIu64 "," + " while expecting result %" PRIu64 ". Locale: %s\n", + n_prnt (t->str.str), rv, rv, + t->val, get_current_locale_str ()); + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_to_uint64(\"%s\", ->%" PRIu64 ") == %" \ + PRIuPTR "\n", + n_prnt (t->str.str), rv, rs); + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_all_chars (void) +{ + int c_failed[256]; /* from 0 to 255 */ + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + size_t t_failed = 0; + size_t j; + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + unsigned int c; + uint64_t test_val; + + set_test_locale (j); /* setlocale() can be slow! */ + for (c = 0; c < n_checks; c++) + { + static const uint64_t rnd_val = 24941852; + size_t rs; + if ((c >= '0') && (c <= '9') ) + continue; /* skip digits */ + for (test_val = 0; test_val <= rnd_val && ! c_failed[c]; test_val += + rnd_val) + { + char test_str[] = "0123"; + uint64_t rv = test_val; + + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + rs = mhd_str_to_uint64 (test_str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", ->%" PRIu64 + ") returned %" PRIuPTR + ", while expecting zero." + " Locale: %s\n", n_prnt (test_str), rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", &ret_val) modified value of ret_val" + " (before call: %" PRIu64 ", after call %" PRIu64 + "). Locale: %s\n", + n_prnt (test_str), test_val, rv, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[c]) + { + char test_str[] = "0123"; + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + + printf ("PASSED: mhd_str_to_uint64(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (test_str)); + } + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_overflow (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_ovflw) / sizeof(str_ovflw[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_ovflw + i; + static const uint64_t rnd_val = 2; + uint64_t test_val; + + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_str_to_uint64 (t->str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", ->%" PRIu64 + ") returned %" PRIuPTR + ", while expecting zero." + " Locale: %s\n", n_prnt (t->str), rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", &ret_val) modified value of ret_val" + " (before call: %" PRIu64 ", after call %" PRIu64 + "). Locale: %s\n", + n_prnt (t->str), test_val, rv, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_to_uint64(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (t->str)); + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_no_val (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_no_num) / sizeof(str_no_num[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_no_num + i; + static const uint64_t rnd_val = 74218431; + uint64_t test_val; + + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_str_to_uint64 (t->str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", ->%" PRIu64 + ") returned %" PRIuPTR + ", while expecting zero." + " Locale: %s\n", n_prnt (t->str), rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64(\"%s\", &ret_val) modified value of ret_val" + " (before call: %" PRIu64 ", after call %" PRIu64 + "). Locale: %s\n", + n_prnt (t->str), test_val, rv, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_to_uint64(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (t->str)); + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_n_valid (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(dstrs_w_values) + / sizeof(dstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + uint64_t rv = 1235572; /* some random value */ + size_t rs = 0; + size_t len; + const struct str_with_value *const t = dstrs_w_values + i; + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + for (len = t->num_of_digt; len <= t->str.len + 1 && ! c_failed[i]; len++) + { + rs = mhd_str_to_uint64_n (t->str.str, len, &rv); + if (rs != t->num_of_digt) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR ", ->%" + PRIu64 ")" + " returned %" PRIuPTR ", while expecting %d. Locale: %s\n", + n_prnt (t->str.str), (uintptr_t) len, rv, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + if (rv != t->val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR ", ->%" + PRIu64 ")" + " converted string to value %" PRIu64 + ", while expecting result %" PRIu64 + ". Locale: %s\n", n_prnt (t->str.str), (uintptr_t) len, rv, + rv, + t->val, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR "..%" + PRIuPTR ", ->%" PRIu64 ")" " == %" PRIuPTR "\n", + n_prnt (t->str.str), + (uintptr_t) t->num_of_digt, + (uintptr_t) t->str.len + 1, rv, rs); + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_n_all_chars (void) +{ + int c_failed[256]; /* from 0 to 255 */ + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + size_t t_failed = 0; + size_t j; + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + unsigned int c; + uint64_t test_val; + + set_test_locale (j); /* setlocale() can be slow! */ + for (c = 0; c < n_checks; c++) + { + static const uint64_t rnd_val = 98372558; + size_t rs; + size_t len; + + if ((c >= '0') && (c <= '9') ) + continue; /* skip digits */ + + for (len = 0; len <= 5; len++) + { + for (test_val = 0; test_val <= rnd_val && ! c_failed[c]; test_val += + rnd_val) + { + char test_str[] = "0123"; + uint64_t rv = test_val; + + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + rs = mhd_str_to_uint64_n (test_str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR ", ->%" + PRIu64 ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (test_str), (uintptr_t) len, rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: %" PRIu64 + ", after call %" PRIu64 ")." + " Locale: %s\n", + n_prnt (test_str), (uintptr_t) len, test_val, rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[c]) + { + char test_str[] = "0123"; + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + + printf ("PASSED: mhd_str_to_uint64_n(\"%s\", 0..5, &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (test_str)); + } + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_n_overflow (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_ovflw) / sizeof(str_ovflw[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_ovflw + i; + static const uint64_t rnd_val = 3; + size_t len; + + for (len = t->len; len <= t->len + 1; len++) + { + uint64_t test_val; + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_str_to_uint64_n (t->str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR ", ->%" + PRIu64 ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (t->str), (uintptr_t) len, rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: %" PRIu64 + ", after call %" PRIu64 ")." + " Locale: %s\n", n_prnt (t->str), (uintptr_t) len, + test_val, rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR "..%" PRIuPTR + ", &ret_val) == 0," + " value of ret_val is unmodified\n", n_prnt (t->str), + (uintptr_t) t->len, + (uintptr_t) t->len + 1); + } + } + return t_failed; +} + + +static size_t +check_str_to_uint64_n_no_val (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_no_num) / sizeof(str_no_num[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_no_num + i; + static const uint64_t rnd_val = 43255654342; + size_t len; + + for (len = 0; len <= t->len + 1; len++) + { + uint64_t test_val; + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_str_to_uint64_n (t->str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR ", ->%" + PRIu64 ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (t->str), (uintptr_t) len, rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_str_to_uint64_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: %" PRIu64 + ", after call %" PRIu64 ")." + " Locale: %s\n", n_prnt (t->str), (uintptr_t) len, + test_val, rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_str_to_uint64_n(\"%s\", 0..%" PRIuPTR + ", &ret_val) == 0," + " value of ret_val is unmodified\n", n_prnt (t->str), + (uintptr_t) t->len + 1); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_valid (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(xdstrs_w_values) + / sizeof(xdstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + uint_fast32_t rv; + size_t rs; + const struct str_with_value *const t = xdstrs_w_values + i; + + if (t->val > UINT32_MAX) + continue; /* number is too high for this function */ + + if (c_failed[i]) + continue; /* skip already failed checks */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: xdstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + rv = 1458532; /* some random value */ + rs = mhd_strx_to_uint32 (t->str.str, &rv); + if (rs != t->num_of_digt) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting %d." + " Locale: %s\n", n_prnt (t->str.str), (uint64_t) rv, + (uintptr_t) rs, (int) t->num_of_digt, + get_current_locale_str ()); + } + if (rv != t->val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", ->0x%" PRIX64 + ") converted string to value 0x%" + PRIX64 "," + " while expecting result 0x%" PRIX64 ". Locale: %s\n", + n_prnt (t->str.str), (uint64_t) rv, (uint64_t) rv, + t->val, get_current_locale_str ()); + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint32(\"%s\", ->0x%" PRIX64 ") == %" + PRIuPTR "\n", + n_prnt (t->str.str), (uint64_t) rv, rs); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_all_chars (void) +{ + int c_failed[256]; /* from 0 to 255 */ + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + size_t t_failed = 0; + size_t j; + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + unsigned int c; + uint_fast32_t test_val; + + set_test_locale (j); /* setlocale() can be slow! */ + for (c = 0; c < n_checks; c++) + { + static const uint_fast32_t rnd_val = 234234; + size_t rs; + if (( (c >= '0') && (c <= '9') ) + || ( (c >= 'A') && (c <= 'F') ) + || ( (c >= 'a') && (c <= 'f') )) + continue; /* skip xdigits */ + for (test_val = 0; test_val <= rnd_val && ! c_failed[c]; test_val += + rnd_val) + { + char test_str[] = "0123"; + uint_fast32_t rv = test_val; + + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + rs = mhd_strx_to_uint32 (test_str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting zero." + " Locale: %s\n", n_prnt (test_str), (uint64_t) rv, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", &ret_val) modified value of ret_val" + " (before call: 0x%" PRIX64 ", after call 0x%" PRIX64 + "). Locale: %s\n", + n_prnt (test_str), (uint64_t) test_val, (uint64_t) rv, + get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[c]) + { + char test_str[] = "0123"; + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + + printf ("PASSED: mhd_strx_to_uint32(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (test_str)); + } + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_overflow (void) +{ + size_t t_failed = 0; + size_t i, j; + static const size_t n_checks1 = sizeof(strx_ovflw) / sizeof(strx_ovflw[0]); + int c_failed[(sizeof(strx_ovflw) / sizeof(strx_ovflw[0])) + + (sizeof(xdstrs_w_values) + / sizeof(xdstrs_w_values[0]))]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + static const uint_fast32_t rnd_val = 74218431; + uint_fast32_t test_val; + const char *str; + if (i < n_checks1) + { + const struct str_with_len *const t = strx_ovflw + i; + str = t->str; + } + else + { + const struct str_with_value *const t = xdstrs_w_values + (i + - n_checks1); + if (t->val <= UINT32_MAX) + continue; /* check only strings that should overflow uint32_t */ + str = t->str.str; + } + + + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint_fast32_t rv = test_val; + + rs = mhd_strx_to_uint32 (str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting zero." + " Locale: %s\n", n_prnt (str), (uint64_t) rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", &ret_val) modified value of ret_val" + " (before call: 0x%" PRIX64 ", after call 0x%" PRIX64 + "). Locale: %s\n", + n_prnt (str), (uint64_t) test_val, (uint64_t) rv, + get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint32(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (str)); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_no_val (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_no_num) / sizeof(str_no_num[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_no_num + i; + static const uint_fast32_t rnd_val = 74218431; + uint_fast32_t test_val; + + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint_fast32_t rv = test_val; + + rs = mhd_strx_to_uint32 (t->str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting zero." + " Locale: %s\n", n_prnt (t->str), (uint64_t) rv, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32(\"%s\", &ret_val) modified value of ret_val" + " (before call: 0x%" PRIX64 ", after call 0x%" PRIX64 + "). Locale: %s\n", + n_prnt (t->str), (uint64_t) test_val, (uint64_t) rv, + get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint32(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (t->str)); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_n_valid (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(xdstrs_w_values) + / sizeof(xdstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + uint_fast32_t rv = 2352932; /* some random value */ + size_t rs = 0; + size_t len; + const struct str_with_value *const t = xdstrs_w_values + i; + + if (t->val > UINT32_MAX) + continue; /* number is too high for this function */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: xdstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + for (len = t->num_of_digt; len <= t->str.len + 1 && ! c_failed[i]; len++) + { + rs = mhd_strx_to_uint32_n (t->str.str, len, &rv); + if (rs != t->num_of_digt) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 ")" + " returned %" PRIuPTR ", while expecting %d. Locale: %s\n", + n_prnt (t->str.str), (uintptr_t) len, (uint64_t) rv, + (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + if (rv != t->val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 ")" + " converted string to value 0x%" PRIX64 + ", while expecting result 0x%" PRIX64 + ". Locale: %s\n", n_prnt (t->str.str), (uintptr_t) len, + (uint64_t) rv, (uint64_t) rv, + t->val, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ( + "PASSED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR "..%" PRIuPTR + ", ->0x%" + PRIX64 ")" + " == %" PRIuPTR "\n", n_prnt (t->str.str), + (uintptr_t) t->num_of_digt, + (uintptr_t) t->str.len + 1, (uint64_t) rv, rs); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_n_all_chars (void) +{ + int c_failed[256]; /* from 0 to 255 */ + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + size_t t_failed = 0; + size_t j; + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + unsigned int c; + uint_fast32_t test_val; + + set_test_locale (j); /* setlocale() can be slow! */ + for (c = 0; c < n_checks; c++) + { + static const uint_fast32_t rnd_val = 98372558; + size_t rs; + size_t len; + + if (( (c >= '0') && (c <= '9') ) + || ( (c >= 'A') && (c <= 'F') ) + || ( (c >= 'a') && (c <= 'f') )) + continue; /* skip xdigits */ + + for (len = 0; len <= 5; len++) + { + for (test_val = 0; test_val <= rnd_val && ! c_failed[c]; test_val += + rnd_val) + { + char test_str[] = "0123"; + uint_fast32_t rv = test_val; + + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + rs = mhd_strx_to_uint32_n (test_str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 + ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (test_str), (uintptr_t) len, (uint64_t) rv, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: 0x%" PRIX64 + ", after call 0x%" PRIX64 ")." + " Locale: %s\n", + n_prnt (test_str), (uintptr_t) len, (uint64_t) test_val, + (uint64_t) rv, get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[c]) + { + char test_str[] = "0123"; + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + + printf ("PASSED: mhd_strx_to_uint32_n(\"%s\", 0..5, &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (test_str)); + } + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_n_overflow (void) +{ + size_t t_failed = 0; + size_t i, j; + static const size_t n_checks1 = sizeof(strx_ovflw) / sizeof(strx_ovflw[0]); + int c_failed[(sizeof(strx_ovflw) / sizeof(strx_ovflw[0])) + + (sizeof(xdstrs_w_values) + / sizeof(xdstrs_w_values[0]))]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + static const uint_fast32_t rnd_val = 4; + size_t len; + const char *str; + size_t min_len, max_len; + if (i < n_checks1) + { + const struct str_with_len *const t = strx_ovflw + i; + str = t->str; + min_len = t->len; + max_len = t->len + 1; + } + else + { + const struct str_with_value *const t = xdstrs_w_values + (i + - n_checks1); + if (t->val <= UINT32_MAX) + continue; /* check only strings that should overflow uint32_t */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: xdstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) (i - n_checks1), (unsigned + int) t->num_of_digt, + (unsigned int) t->str.len); + exit (99); + } + str = t->str.str; + min_len = t->num_of_digt; + max_len = t->str.len + 1; + } + + for (len = min_len; len <= max_len; len++) + { + uint_fast32_t test_val; + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint_fast32_t rv = test_val; + + rs = mhd_strx_to_uint32_n (str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 + ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (str), (uintptr_t) len, (uint64_t) rv, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: 0x%" PRIX64 + ", after call 0x%" PRIX64 ")." + " Locale: %s\n", n_prnt (str), (uintptr_t) len, + (uint64_t) test_val, (uint64_t) rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR "..%" PRIuPTR + ", &ret_val) == 0," + " value of ret_val is unmodified\n", n_prnt (str), + (uintptr_t) min_len, + (uintptr_t) max_len); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint32_n_no_val (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_no_num) / sizeof(str_no_num[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_no_num + i; + static const uint_fast32_t rnd_val = 3214314212UL; + size_t len; + + for (len = 0; len <= t->len + 1; len++) + { + uint_fast32_t test_val; + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint_fast32_t rv = test_val; + + rs = mhd_strx_to_uint32_n (t->str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 + ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (t->str), (uintptr_t) len, (uint64_t) rv, + (uintptr_t) rs, get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint32_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: 0x%" PRIX64 + ", after call 0x%" PRIX64 ")." + " Locale: %s\n", n_prnt (t->str), (uintptr_t) len, + (uint64_t) test_val, (uint64_t) rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint32_n(\"%s\", 0..%" PRIuPTR + ", &ret_val) == 0," + " value of ret_val is unmodified\n", n_prnt (t->str), + (uintptr_t) t->len + 1); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_valid (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(xdstrs_w_values) + / sizeof(xdstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + uint64_t rv; + size_t rs; + const struct str_with_value *const t = xdstrs_w_values + i; + + if (c_failed[i]) + continue; /* skip already failed checks */ + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: xdstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + rv = 1458532; /* some random value */ + rs = mhd_strx_to_uint64 (t->str.str, &rv); + if (rs != t->num_of_digt) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting %d." + " Locale: %s\n", n_prnt (t->str.str), rv, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + if (rv != t->val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", ->0x%" PRIX64 + ") converted string to value 0x%" + PRIX64 "," + " while expecting result 0x%" PRIX64 ". Locale: %s\n", + n_prnt (t->str.str), rv, rv, + t->val, get_current_locale_str ()); + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint64(\"%s\", ->0x%" PRIX64 ") == %" + PRIuPTR "\n", + n_prnt (t->str.str), rv, rs); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_all_chars (void) +{ + int c_failed[256]; /* from 0 to 255 */ + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + size_t t_failed = 0; + size_t j; + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + unsigned int c; + uint64_t test_val; + + set_test_locale (j); /* setlocale() can be slow! */ + for (c = 0; c < n_checks; c++) + { + static const uint64_t rnd_val = 234234; + size_t rs; + if (( (c >= '0') && (c <= '9') ) + || ( (c >= 'A') && (c <= 'F') ) + || ( (c >= 'a') && (c <= 'f') )) + continue; /* skip xdigits */ + for (test_val = 0; test_val <= rnd_val && ! c_failed[c]; test_val += + rnd_val) + { + char test_str[] = "0123"; + uint64_t rv = test_val; + + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + rs = mhd_strx_to_uint64 (test_str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting zero." + " Locale: %s\n", n_prnt (test_str), rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", &ret_val) modified value of ret_val" + " (before call: 0x%" PRIX64 ", after call 0x%" PRIX64 + "). Locale: %s\n", + n_prnt (test_str), test_val, rv, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[c]) + { + char test_str[] = "0123"; + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + + printf ("PASSED: mhd_strx_to_uint64(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (test_str)); + } + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_overflow (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(strx_ovflw) / sizeof(strx_ovflw[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = strx_ovflw + i; + static const uint64_t rnd_val = 74218431; + uint64_t test_val; + + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_strx_to_uint64 (t->str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting zero." + " Locale: %s\n", n_prnt (t->str), rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", &ret_val) modified value of ret_val" + " (before call: 0x%" PRIX64 ", after call 0x%" PRIX64 + "). Locale: %s\n", + n_prnt (t->str), test_val, rv, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint64(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (t->str)); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_no_val (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_no_num) / sizeof(str_no_num[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_no_num + i; + static const uint64_t rnd_val = 74218431; + uint64_t test_val; + + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_strx_to_uint64 (t->str, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", ->0x%" PRIX64 + ") returned %" + PRIuPTR ", while expecting zero." + " Locale: %s\n", n_prnt (t->str), rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64(\"%s\", &ret_val) modified value of ret_val" + " (before call: 0x%" PRIX64 ", after call 0x%" PRIX64 + "). Locale: %s\n", + n_prnt (t->str), test_val, rv, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint64(\"%s\", &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (t->str)); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_n_valid (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(xdstrs_w_values) / sizeof(xdstrs_w_values[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + uint64_t rv = 2352932; /* some random value */ + size_t rs = 0; + size_t len; + const struct str_with_value *const t = xdstrs_w_values + i; + + if (t->str.len < t->num_of_digt) + { + fprintf (stderr, + "ERROR: xdstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected" + " to be less or equal to str.len (%u).\n", + (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned + int) t->str. + len); + exit (99); + } + for (len = t->num_of_digt; len <= t->str.len + 1 && ! c_failed[i]; len++) + { + rs = mhd_strx_to_uint64_n (t->str.str, len, &rv); + if (rs != t->num_of_digt) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 ")" + " returned %" PRIuPTR ", while expecting %d. Locale: %s\n", + n_prnt (t->str.str), (uintptr_t) len, rv, (uintptr_t) rs, + (int) t->num_of_digt, get_current_locale_str ()); + } + if (rv != t->val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 ")" + " converted string to value 0x%" PRIX64 + ", while expecting result 0x%" PRIX64 + ". Locale: %s\n", n_prnt (t->str.str), (uintptr_t) len, rv, + rv, + t->val, get_current_locale_str ()); + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR "..%" PRIuPTR + ", ->0x%" + PRIX64 ")" + " == %" PRIuPTR "\n", n_prnt (t->str.str), + (uintptr_t) t->num_of_digt, + (uintptr_t) t->str.len + 1, rv, rs); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_n_all_chars (void) +{ + int c_failed[256]; /* from 0 to 255 */ + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + size_t t_failed = 0; + size_t j; + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + unsigned int c; + uint64_t test_val; + + set_test_locale (j); /* setlocale() can be slow! */ + for (c = 0; c < n_checks; c++) + { + static const uint64_t rnd_val = 98372558; + size_t rs; + size_t len; + + if (( (c >= '0') && (c <= '9') ) + || ( (c >= 'A') && (c <= 'F') ) + || ( (c >= 'a') && (c <= 'f') )) + continue; /* skip xdigits */ + + for (len = 0; len <= 5; len++) + { + for (test_val = 0; test_val <= rnd_val && ! c_failed[c]; test_val += + rnd_val) + { + char test_str[] = "0123"; + uint64_t rv = test_val; + + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + rs = mhd_strx_to_uint64_n (test_str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 + ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (test_str), (uintptr_t) len, rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[c] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: 0x%" PRIX64 + ", after call 0x%" PRIX64 ")." + " Locale: %s\n", + n_prnt (test_str), (uintptr_t) len, test_val, rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[c]) + { + char test_str[] = "0123"; + test_str[0] = (char) (unsigned char) c; /* replace first char with non-digit char */ + + printf ("PASSED: mhd_strx_to_uint64_n(\"%s\", 0..5, &ret_val) == 0, " + "value of ret_val is unmodified\n", + n_prnt (test_str)); + } + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_n_overflow (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(strx_ovflw) / sizeof(strx_ovflw[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = strx_ovflw + i; + static const uint64_t rnd_val = 4; + size_t len; + + for (len = t->len; len <= t->len + 1; len++) + { + uint64_t test_val; + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_strx_to_uint64_n (t->str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 + ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (t->str), (uintptr_t) len, rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: 0x%" PRIX64 + ", after call 0x%" PRIX64 ")." + " Locale: %s\n", n_prnt (t->str), (uintptr_t) len, + test_val, rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR "..%" PRIuPTR + ", &ret_val) == 0," + " value of ret_val is unmodified\n", n_prnt (t->str), + (uintptr_t) t->len, + (uintptr_t) t->len + 1); + } + } + return t_failed; +} + + +static size_t +check_strx_to_uint64_n_no_val (void) +{ + size_t t_failed = 0; + size_t i, j; + int c_failed[sizeof(str_no_num) / sizeof(str_no_num[0])]; + static const size_t n_checks = sizeof(c_failed) / sizeof(c_failed[0]); + + memset (c_failed, 0, sizeof(c_failed)); + + for (j = 0; j < locale_name_count; j++) + { + set_test_locale (j); /* setlocale() can be slow! */ + for (i = 0; i < n_checks; i++) + { + size_t rs; + const struct str_with_len *const t = str_no_num + i; + static const uint64_t rnd_val = 3214314212UL; + size_t len; + + for (len = 0; len <= t->len + 1; len++) + { + uint64_t test_val; + for (test_val = 0; test_val <= rnd_val && ! c_failed[i]; test_val += + rnd_val) + { + uint64_t rv = test_val; + + rs = mhd_strx_to_uint64_n (t->str, len, &rv); + if (rs != 0) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR ", ->0x%" + PRIX64 + ")" + " returned %" PRIuPTR + ", while expecting zero. Locale: %s\n", + n_prnt (t->str), (uintptr_t) len, rv, (uintptr_t) rs, + get_current_locale_str ()); + } + else if (rv != test_val) + { + t_failed++; + c_failed[i] = ! 0; + fprintf (stderr, + "FAILED: mhd_strx_to_uint64_n(\"%s\", %" PRIuPTR + ", &ret_val)" + " modified value of ret_val (before call: 0x%" PRIX64 + ", after call 0x%" PRIX64 ")." + " Locale: %s\n", n_prnt (t->str), (uintptr_t) len, + test_val, rv, + get_current_locale_str ()); + } + } + } + if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i]) + printf ("PASSED: mhd_strx_to_uint64_n(\"%s\", 0..%" PRIuPTR + ", &ret_val) == 0," + " value of ret_val is unmodified\n", n_prnt (t->str), + (uintptr_t) t->len + 1); + } + } + return t_failed; +} + + +static int +run_str_to_X_tests (void) +{ + size_t str_to_uint64_fails = 0; + size_t str_to_uint64_n_fails = 0; + size_t strx_to_uint32_fails = 0; + size_t strx_to_uint32_n_fails = 0; + size_t strx_to_uint64_fails = 0; + size_t strx_to_uint64_n_fails = 0; + size_t res; + + res = check_str_to_uint64_valid (); + if (res != 0) + { + str_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_valid() failed.\n\n"); + } + else if (verbose > 1) + printf ( + "PASSED: testcase check_str_to_uint64_valid() successfully passed.\n\n"); + + res = check_str_to_uint64_all_chars (); + if (res != 0) + { + str_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_all_chars() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_all_chars() " + "successfully passed.\n\n"); + + res = check_str_to_uint64_overflow (); + if (res != 0) + { + str_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_overflow() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_overflow() " + "successfully passed.\n\n"); + + res = check_str_to_uint64_no_val (); + if (res != 0) + { + str_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_no_val() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_no_val() " + "successfully passed.\n\n"); + + if (str_to_uint64_fails) + fprintf (stderr, + "FAILED: function mhd_str_to_uint64() failed %lu time%s.\n\n", + (unsigned long) str_to_uint64_fails, + str_to_uint64_fails == 1 ? "" : "s"); + else if (verbose > 0) + printf ("PASSED: function mhd_str_to_uint64() successfully " + "passed all checks.\n\n"); + + res = check_str_to_uint64_n_valid (); + if (res != 0) + { + str_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_n_valid() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_n_valid() " + "successfully passed.\n\n"); + + res = check_str_to_uint64_n_all_chars (); + if (res != 0) + { + str_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_n_all_chars() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_n_all_chars() " + "successfully passed.\n\n"); + + res = check_str_to_uint64_n_overflow (); + if (res != 0) + { + str_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_n_overflow() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_n_overflow() " + "successfully passed.\n\n"); + + res = check_str_to_uint64_n_no_val (); + if (res != 0) + { + str_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_str_to_uint64_n_no_val() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_str_to_uint64_n_no_val() " + "successfully passed.\n\n"); + + if (str_to_uint64_n_fails) + fprintf (stderr, + "FAILED: function mhd_str_to_uint64_n() failed %lu time%s.\n\n", + (unsigned long) str_to_uint64_n_fails, + str_to_uint64_n_fails == 1 ? "" : "s"); + else if (verbose > 0) + printf ("PASSED: function mhd_str_to_uint64_n() successfully " + "passed all checks.\n\n"); + + res = check_strx_to_uint32_valid (); + if (res != 0) + { + strx_to_uint32_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_valid() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_valid() " + "successfully passed.\n\n"); + + res = check_strx_to_uint32_all_chars (); + if (res != 0) + { + strx_to_uint32_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_all_chars() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_all_chars() " + "successfully passed.\n\n"); + + res = check_strx_to_uint32_overflow (); + if (res != 0) + { + strx_to_uint32_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_overflow() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_overflow() " + "successfully passed.\n\n"); + + res = check_strx_to_uint32_no_val (); + if (res != 0) + { + strx_to_uint32_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_no_val() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_no_val() " + "successfully passed.\n\n"); + + if (strx_to_uint32_fails) + fprintf (stderr, + "FAILED: function mhd_strx_to_uint32() failed %lu time%s.\n\n", + (unsigned long) strx_to_uint32_fails, + strx_to_uint32_fails == 1 ? "" : "s"); + else if (verbose > 0) + printf ("PASSED: function mhd_strx_to_uint32() successfully " + "passed all checks.\n\n"); + + res = check_strx_to_uint32_n_valid (); + if (res != 0) + { + strx_to_uint32_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_n_valid() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_n_valid() " + "successfully passed.\n\n"); + + res = check_strx_to_uint32_n_all_chars (); + if (res != 0) + { + strx_to_uint32_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_n_all_chars() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_n_all_chars() " + "successfully passed.\n\n"); + + res = check_strx_to_uint32_n_overflow (); + if (res != 0) + { + strx_to_uint32_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_n_overflow() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_n_overflow() " + "successfully passed.\n\n"); + + res = check_strx_to_uint32_n_no_val (); + if (res != 0) + { + strx_to_uint32_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint32_n_no_val() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint32_n_no_val() " + "successfully passed.\n\n"); + + if (strx_to_uint32_n_fails) + fprintf (stderr, + "FAILED: function mhd_strx_to_uint32_n() failed %lu time%s.\n\n", + (unsigned long) strx_to_uint32_n_fails, + strx_to_uint32_n_fails == 1 ? "" : "s"); + else if (verbose > 0) + printf ("PASSED: function mhd_strx_to_uint32_n() successfully " + "passed all checks.\n\n"); + + res = check_strx_to_uint64_valid (); + if (res != 0) + { + strx_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_valid() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_valid() " + "successfully passed.\n\n"); + + res = check_strx_to_uint64_all_chars (); + if (res != 0) + { + strx_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_all_chars() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_all_chars() " + "successfully passed.\n\n"); + + res = check_strx_to_uint64_overflow (); + if (res != 0) + { + strx_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_overflow() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_overflow() " + "successfully passed.\n\n"); + + res = check_strx_to_uint64_no_val (); + if (res != 0) + { + strx_to_uint64_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_no_val() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_no_val() " + "successfully passed.\n\n"); + + if (strx_to_uint64_fails) + fprintf (stderr, + "FAILED: function mhd_strx_to_uint64() failed %lu time%s.\n\n", + (unsigned long) strx_to_uint64_fails, + strx_to_uint64_fails == 1 ? "" : "s"); + else if (verbose > 0) + printf ("PASSED: function mhd_strx_to_uint64() successfully " + "passed all checks.\n\n"); + + res = check_strx_to_uint64_n_valid (); + if (res != 0) + { + strx_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_n_valid() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_n_valid() " + "successfully passed.\n\n"); + + res = check_strx_to_uint64_n_all_chars (); + if (res != 0) + { + strx_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_n_all_chars() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_n_all_chars() " + "successfully passed.\n\n"); + + res = check_strx_to_uint64_n_overflow (); + if (res != 0) + { + strx_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_n_overflow() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_n_overflow() " + "successfully passed.\n\n"); + + res = check_strx_to_uint64_n_no_val (); + if (res != 0) + { + strx_to_uint64_n_fails += res; + fprintf (stderr, + "FAILED: testcase check_strx_to_uint64_n_no_val() failed.\n\n"); + } + else if (verbose > 1) + printf ("PASSED: testcase check_strx_to_uint64_n_no_val() " + "successfully passed.\n\n"); + + if (strx_to_uint64_n_fails) + fprintf (stderr, + "FAILED: function mhd_strx_to_uint64_n() failed %lu time%s.\n\n", + (unsigned long) strx_to_uint64_n_fails, + strx_to_uint64_n_fails == 1 ? "" : "s"); + else if (verbose > 0) + printf ("PASSED: function mhd_strx_to_uint64_n() successfully " + "passed all checks.\n\n"); + + if (str_to_uint64_fails || str_to_uint64_n_fails || + strx_to_uint32_fails || strx_to_uint32_n_fails || + strx_to_uint64_fails || strx_to_uint64_n_fails) + { + if (verbose > 0) + printf ("At least one test failed.\n"); + + return 1; + } + + if (verbose > 0) + printf ("All tests passed successfully.\n"); + + return 0; +} + + +int +main (int argc, char *argv[]) +{ + if (has_param (argc, argv, "-v") || + has_param (argc, argv, "--verbose") || + has_param (argc, argv, "--verbose1")) + MHDT_set_verbosity (MHDT_VERB_LVL_BASIC); + if (has_param (argc, argv, "-vv") || + has_param (argc, argv, "--verbose2")) + MHDT_set_verbosity (MHDT_VERB_LVL_VERBOSE); + + return run_str_to_X_tests (); +} diff --git a/src/tests/unit/test_str_token.c b/src/tests/unit/test_str_token.c @@ -0,0 +1,137 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2017 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_token.c + * @brief Unit tests for some mhd_str functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include <stdio.h> +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" + + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +static int +expect_found_n (const char *str, const char *token, size_t token_len) +{ + if (! mhd_str_has_token_caseless (str, token, token_len)) + { + fprintf (stderr, + "mhd_str_has_token_caseless() FAILED:\n\tmhd_str_has_token_caseless(%s, %s, %lu) return false\n", + str, token, (unsigned long) token_len); + return 1; + } + return 0; +} + + +#define expect_found(s,t) expect_found_n ((s),(t),MHD_STATICSTR_LEN_ (t)) + +static int +expect_not_found_n (const char *str, const char *token, size_t token_len) +{ + if (mhd_str_has_token_caseless (str, token, token_len)) + { + fprintf (stderr, + "mhd_str_has_token_caseless() FAILED:\n\tmhd_str_has_token_caseless(%s, %s, %lu) return true\n", + str, token, (unsigned long) token_len); + return 1; + } + return 0; +} + + +#define expect_not_found(s,t) expect_not_found_n ((s),(t),MHD_STATICSTR_LEN_ ( \ + t)) + +static int +check_match (void) +{ + int errcount = 0; + errcount += expect_found ("string", "string"); + errcount += expect_found ("String", "string"); + errcount += expect_found ("string", "String"); + errcount += expect_found ("strinG", "String"); + errcount += expect_found ("\t strinG", "String"); + errcount += expect_found ("strinG\t ", "String"); + errcount += expect_found (" \t tOkEn ", "toKEN"); + errcount += expect_found ("not token\t, tOkEn ", "toKEN"); + errcount += expect_found ("not token,\t tOkEn, more token", "toKEN"); + errcount += expect_found ("not token,\t tOkEn\t, more token", "toKEN"); + errcount += expect_found (",,,,,,test,,,,", "TESt"); + errcount += expect_found (",,,,,\t,test,,,,", "TESt"); + errcount += expect_found (",,,,,,test, ,,,", "TESt"); + errcount += expect_found (",,,,,, test,,,,", "TESt"); + errcount += expect_found (",,,,,, test not,test,,", "TESt"); + errcount += expect_found (",,,,,, test not,,test,,", "TESt"); + errcount += expect_found (",,,,,, test not ,test,,", "TESt"); + errcount += expect_found (",,,,,, test", "TESt"); + errcount += expect_found (",,,,,, test ", "TESt"); + errcount += expect_found ("no test,,,,,, test ", "TESt"); + return errcount; +} + + +static int +check_not_match (void) +{ + int errcount = 0; + errcount += expect_not_found ("strin", "string"); + errcount += expect_not_found ("Stringer", "string"); + errcount += expect_not_found ("sstring", "String"); + errcount += expect_not_found ("string", "Strin"); + errcount += expect_not_found ("\t( strinG", "String"); + errcount += expect_not_found (")strinG\t ", "String"); + errcount += expect_not_found (" \t tOkEn t ", "toKEN"); + errcount += expect_not_found ("not token\t, tOkEner ", "toKEN"); + errcount += expect_not_found ("not token,\t tOkEns, more token", "toKEN"); + errcount += expect_not_found ("not token,\t tOkEns\t, more token", "toKEN"); + errcount += expect_not_found (",,,,,,testing,,,,", "TESt"); + errcount += expect_not_found (",,,,,\t,test,,,,", "TESting"); + errcount += expect_not_found ("tests,,,,,,quest, ,,,", "TESt"); + errcount += expect_not_found (",,,,,, testы,,,,", "TESt"); + errcount += expect_not_found (",,,,,, test not,хtest,,", "TESt"); + errcount += expect_not_found ("testing,,,,,, test not,,test2,,", "TESt"); + errcount += expect_not_found (",testi,,,,, test not ,test,,", "TESting"); + errcount += expect_not_found (",,,,,,2 test", "TESt"); + errcount += expect_not_found (",,,,,,test test ", "test"); + errcount += expect_not_found ("no test,,,,,, test test", "test"); + return errcount; +} + + +int +main (int argc, char *argv[]) +{ + int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_match (); + errcount += check_not_match (); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/test_str_token_remove.c b/src/tests/unit/test_str_token_remove.c @@ -0,0 +1,259 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2017-2021 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_token_remove.c + * @brief Unit tests for mhd_str_remove_token_caseless() function + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include <string.h> +#include <stdio.h> +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "mhd_assert.h" + + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +static int +expect_result_n (const char *str, size_t str_len, + const char *token, size_t token_len, + const char *expected, size_t expected_len, + const bool expected_removed) +{ + char buf_in[1024]; + char buf_token[256]; + char buf_out[1024]; + size_t buf_len; + + mhd_assert (sizeof(buf_in) > str_len + 2); + mhd_assert (sizeof(buf_token) > token_len + 2); + mhd_assert (sizeof(buf_out) > expected_len + 2); + + memset (buf_in, '#', sizeof(buf_in)); + memset (buf_token, '#', sizeof(buf_token)); + memcpy (buf_in, str, str_len); /* Copy without zero-termination */ + memcpy (buf_token, token, token_len); /* Copy without zero-termination */ + + for (buf_len = 0; buf_len <= expected_len + 3; ++buf_len) + { + bool res; + ssize_t result_len; + memset (buf_out, '$', sizeof(buf_out)); + + result_len = (ssize_t) buf_len; + mhd_assert (0 <= result_len); + + res = mhd_str_remove_token_caseless (buf_in, str_len, buf_token, token_len, + buf_out, &result_len); + if (buf_len < expected_len) + { /* The result should not fit into the buffer */ + if (res || (0 <= result_len)) + { + fprintf (stderr, + "mhd_str_remove_token_caseless() FAILED:\n" + "\tmhd_str_remove_token_caseless(\"%.*s\", %lu," + " \"%.*s\", %lu, buf, &(%ld->%ld)) returned %s\n", + (int) str_len + 2, buf_in, (unsigned long) str_len, + (int) token_len + 2, buf_token, (unsigned long) token_len, + (long) buf_len, (long) result_len, res ? "true" : "false"); + return 1; + } + } + else + { /* The result should fit into the buffer */ + if ( (expected_removed != res) || + (result_len < 0) || + (expected_len != (size_t) result_len) || + ((0 != result_len) && (0 != memcmp (expected, buf_out, + (size_t) result_len))) || + ('$' != buf_out[result_len])) + { + fprintf (stderr, + "mhd_str_remove_token_caseless() FAILED:\n" + "\tmhd_str_remove_token_caseless(\"%.*s\", %lu," + " \"%.*s\", %lu, \"%.*s\", &(%ld->%ld)) returned %s\n", + (int) str_len + 2, buf_in, (unsigned long) str_len, + (int) token_len + 2, buf_token, (unsigned long) token_len, + (int) expected_len + 2, buf_out, + (long) buf_len, (long) result_len, + res ? "true" : "false"); + return 1; + } + } + } + return 0; +} + + +#define expect_result(s,t,e,found) \ + expect_result_n ((s),MHD_STATICSTR_LEN_ (s), \ + (t),MHD_STATICSTR_LEN_ (t), \ + (e),MHD_STATICSTR_LEN_ (e), found) + +static int +check_result (void) +{ + int errcount = 0; + errcount += expect_result ("string", "string", "", true); + errcount += expect_result ("String", "string", "", true); + errcount += expect_result ("string", "String", "", true); + errcount += expect_result ("strinG", "String", "", true); + errcount += expect_result ("\t strinG", "String", "", true); + errcount += expect_result ("strinG\t ", "String", "", true); + errcount += expect_result (" \t tOkEn ", "toKEN", "", true); + errcount += expect_result ("not token\t, tOkEn ", "toKEN", "not token", + true); + errcount += expect_result ("not token,\t tOkEn, more token", "toKEN", + "not token, more token", true); + errcount += expect_result ("not token,\t tOkEn\t, more token", "toKEN", + "not token, more token", true); + errcount += expect_result (",,,,,,test,,,,", "TESt", "", true); + errcount += expect_result (",,,,,\t,test,,,,", "TESt", "", true); + errcount += expect_result (",,,,,,test, ,,,", "TESt", "", true); + errcount += expect_result (",,,,,, test,,,,", "TESt", "", true); + errcount += expect_result (",,,,,, test not,test,,", "TESt", "test not", + true); + errcount += expect_result (",,,,,, test not,,test,,", "TESt", "test not", + true); + errcount += expect_result (",,,,,, test not ,test,,", "TESt", "test not", + true); + errcount += expect_result (",,,,,, test", "TESt", "", true); + errcount += expect_result (",,,,,, test ", "TESt", "", true); + errcount += expect_result ("no test,,,,,, test ", "TESt", "no test", + true); + errcount += expect_result ("the-token,, the-token , the-token" \ + ",the-token ,the-token", "the-token", "", true); + errcount += expect_result (" the-token,, the-token , the-token," \ + "the-token ,the-token ", "the-token", "", true); + errcount += expect_result (" the-token ,, the-token , the-token," \ + "the-token , the-token ", "the-token", "", true); + errcount += expect_result ("the-token,a, the-token , the-token,b," \ + "the-token , c,the-token", "the-token", "a, b, c", + true); + errcount += expect_result (" the-token, a, the-token , the-token, b," \ + "the-token ,c ,the-token ", "the-token", + "a, b, c", true); + errcount += expect_result (" the-token , a , the-token , the-token, b ," \ + "the-token , c , the-token ", "the-token", + "a, b, c",true); + errcount += expect_result ("the-token,aa, the-token , the-token,bb," \ + "the-token , cc,the-token", "the-token", + "aa, bb, cc", true); + errcount += expect_result (" the-token, aa, the-token , the-token, bb," \ + "the-token ,cc ,the-token ", "the-token", + "aa, bb, cc", true); + errcount += expect_result (" the-token , aa , the-token , the-token, bb ," \ + "the-token , cc , the-token ", "the-token", + "aa, bb, cc", true); + + errcount += expect_result ("strin", "string", "strin", false); + errcount += expect_result ("Stringer", "string", "Stringer", false); + errcount += expect_result ("sstring", "String", "sstring", false); + errcount += expect_result ("string", "Strin", "string", false); + errcount += expect_result ("\t( strinG", "String", "( strinG", false); + errcount += expect_result (")strinG\t ", "String", ")strinG", false); + errcount += expect_result (" \t tOkEn t ", "toKEN", "tOkEn t", false); + errcount += expect_result ("not token\t, tOkEner ", "toKEN", + "not token, tOkEner", false); + errcount += expect_result ("not token,\t tOkEns, more token", "toKEN", + "not token, tOkEns, more token", false); + errcount += expect_result ("not token,\t tOkEns\t, more token", "toKEN", + "not token, tOkEns, more token", false); + errcount += expect_result (",,,,,,testing,,,,", "TESt", "testing", false); + errcount += expect_result (",,,,,\t,test,,,,", "TESting", "test", false); + errcount += expect_result ("tests,,,,,,quest, ,,,", "TESt", "tests, quest", + false); + errcount += expect_result (",,,,,, testы,,,,", "TESt", "testы", false); + errcount += expect_result (",,,,,, test not,хtest,,", "TESt", + "test not, хtest", false); + errcount += expect_result ("testing,,,,,, test not,,test2,,", "TESt", + "testing, test not, test2", false); + errcount += expect_result (",testi,,,,, test not ,test,,", "TESting", + "testi, test not, test", false); + errcount += expect_result (",,,,,,2 test", "TESt", "2 test", false); + errcount += expect_result (",,,,,,test test ", "test", "test test", + false); + errcount += expect_result ("no test,,,,,,test test", "test", + "no test, test test", false); + errcount += expect_result (",,,,,,,,,,,,,,,,,,,", "the-token", "", false); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,", "the-token", + "a, b, c, d, e, f, g", false); + errcount += expect_result (",,,,,,,,,,,,,,,,,,,", "", "", false); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,", "", + "a, b, c, d, e, f, g", false); + errcount += expect_result ("a,b,c,d,e,f,g", "", "a, b, c, d, e, f, g", + false); + errcount += expect_result ("a1,b1,c1,d1,e1,f1,g1", "", + "a1, b1, c1, d1, e1, f1, g1", false); + + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,the-token", + "the-token", "a, b, c, d, e, f, g", true); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,the-token,", + "the-token", "a, b, c, d, e, f, g", true); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,the-token,x", + "the-token", "a, b, c, d, e, f, g, x", true); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,the-token x", + "the-token", "a, b, c, d, e, f, g, the-token x", + false); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,the-token x,", + "the-token", "a, b, c, d, e, f, g, the-token x", + false); + errcount += expect_result (",a,b,c,d,e,f,g,,,,,,,,,,,,the-token x,x", + "the-token", "a, b, c, d, e, f, g," \ + " the-token x, x", false); + errcount += expect_result ("the-token,a,b,c,d,e,f,g,,,,,,,,,,,,the-token", + "the-token", "a, b, c, d, e, f, g", true); + errcount += expect_result ("the-token ,a,b,c,d,e,f,g,,,,,,,,,,,,the-token,", + "the-token", "a, b, c, d, e, f, g", true); + errcount += expect_result ("the-token,a,b,c,d,e,f,g,,,,,,,,,,,,the-token,x", + "the-token", "a, b, c, d, e, f, g, x", true); + errcount += expect_result ("the-token x,a,b,c,d,e,f,g,,,,,,,,,,,," \ + "the-token x", "the-token", + "the-token x, a, b, c, d, e, f, g, the-token x", + false); + errcount += expect_result ("the-token x,a,b,c,d,e,f,g,,,,,,,,,,,," \ + "the-token x,", "the-token", + "the-token x, a, b, c, d, e, f, g, the-token x", + false); + errcount += expect_result ("the-token x,a,b,c,d,e,f,g,,,,,,,,,,,," \ + "the-token x,x", "the-token", + "the-token x, a, b, c, d, e, f, g, " \ + "the-token x, x", false); + + return errcount; +} + + +int +main (int argc, char *argv[]) +{ + int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_result (); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/test_str_tokens_remove.c b/src/tests/unit/test_str_tokens_remove.c @@ -0,0 +1,291 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2017-2021 Karlson2k (Evgeny Grin) + + This test tool is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + This test tool is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * @file microhttpd/test_str_tokens_remove.c + * @brief Unit tests for mhd_str_remove_tokens_caseless() function + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" +#include <string.h> +#include <stdio.h> +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "mhd_assert.h" + + +#ifndef MHD_STATICSTR_LEN_ +/** + * Determine length of static string / macro strings at compile time. + */ +#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) +#endif /* ! MHD_STATICSTR_LEN_ */ + + +static int +expect_result_n (const char *str, size_t str_len, + const char *tokens, size_t tokens_len, + const char *expected, size_t expected_len, + const bool expected_removed) +{ + char buf_in[1024]; + char buf_tokens[256]; + bool res; + size_t result_len; + + mhd_assert (sizeof(buf_in) > str_len + 2); + mhd_assert (sizeof(buf_tokens) > tokens_len + 2); + + memset (buf_tokens, '#', sizeof(buf_tokens)); + memcpy (buf_tokens, tokens, tokens_len); /* Copy without zero-termination */ + memset (buf_in, '$', sizeof(buf_in)); + memcpy (buf_in, str, str_len); /* Copy without zero-termination */ + + result_len = str_len; + + res = mhd_str_remove_tokens_caseless (buf_in, &result_len, + buf_tokens, tokens_len); + + if ( (expected_removed != res) || + (expected_len != result_len) || + ((0 != result_len) && (0 != memcmp (expected, buf_in, result_len))) || + ('$' != buf_in[str_len])) + { + fprintf (stderr, + "mhd_str_remove_tokens_caseless() FAILED:\n" + "\tRESULT: " + "\tmhd_str_remove_token_caseless(\"%s\"->\"%.*s\", &(%lu->%lu)," + " \"%.*s\", %lu) returned %s\n", + str, + (int) result_len, buf_in, + (unsigned long) str_len, (unsigned long) result_len, + (int) tokens_len, buf_tokens, (unsigned long) tokens_len, + res ? "true" : "false"); + fprintf (stderr, + "\tEXPECTED: " + "\tmhd_str_remove_token_caseless(\"%s\"->\"%s\", &(%lu->%lu)," + " \"%.*s\", %lu) returned %s\n", + str, + expected, + (unsigned long) str_len, (unsigned long) expected_len, + (int) tokens_len, buf_tokens, (unsigned long) tokens_len, + expected_removed ? "true" : "false"); + return 1; + } + return 0; +} + + +#define expect_result(s,t,e,found) \ + expect_result_n ((s),MHD_STATICSTR_LEN_ (s), \ + (t),MHD_STATICSTR_LEN_ (t), \ + (e),MHD_STATICSTR_LEN_ (e), found) + +static int +check_result (void) +{ + int errcount = 0; + errcount += expect_result ("string", "string", "", true); + errcount += expect_result ("String", "string", "", true); + errcount += expect_result ("string", "String", "", true); + errcount += expect_result ("strinG", "String", "", true); + errcount += expect_result ("strinG", "String\t", "", true); + errcount += expect_result ("strinG", "\tString", "", true); + errcount += expect_result ("tOkEn", " \t toKEN ", "", true); + errcount += expect_result ("not-token, tOkEn", "token", "not-token", + true); + errcount += expect_result ("not-token1, tOkEn1, token", "token1", + "not-token1, token", + true); + errcount += expect_result ("token, tOkEn1", "token1", "token", + true); + errcount += expect_result ("not-token, tOkEn", " \t toKEN", "not-token", + true); + errcount += expect_result ("not-token, tOkEn, more-token", "toKEN\t", + "not-token, more-token", true); + errcount += expect_result ("not-token, tOkEn, more-token", "\t toKEN,,,,,", + "not-token, more-token", true); + errcount += expect_result ("a, b, c, d", ",,,,,a", "b, c, d", true); + errcount += expect_result ("a, b, c, d", "a,,,,,,", "b, c, d", true); + errcount += expect_result ("a, b, c, d", ",,,,a,,,,,,", "b, c, d", true); + errcount += expect_result ("a, b, c, d", "\t \t,,,,a,, , ,,,\t", + "b, c, d", true); + errcount += expect_result ("a, b, c, d", "b, c, d", "a", true); + errcount += expect_result ("a, b, c, d", "a, b, c, d", "", true); + errcount += expect_result ("a, b, c, d", "d, c, b, a", "", true); + errcount += expect_result ("a, b, c, d", "b, d, a, c", "", true); + errcount += expect_result ("a, b, c, d, e", "b, d, a, c", "e", true); + errcount += expect_result ("e, a, b, c, d", "b, d, a, c", "e", true); + errcount += expect_result ("e, a, b, c, d, e", "b, d, a, c", "e, e", true); + errcount += expect_result ("a, b, c, d", "b,c,d", "a", true); + errcount += expect_result ("a, b, c, d", "a,b,c,d", "", true); + errcount += expect_result ("a, b, c, d", "d,c,b,a", "", true); + errcount += expect_result ("a, b, c, d", "b,d,a,c", "", true); + errcount += expect_result ("a, b, c, d, e", "b,d,a,c", "e", true); + errcount += expect_result ("e, a, b, c, d", "b,d,a,c", "e", true); + errcount += expect_result ("e, a, b, c, d, e", "b,d,a,c", "e, e", true); + errcount += expect_result ("a, b, c, d", "d,,,,,,,,,c,b,a", "", true); + errcount += expect_result ("a, b, c, d", "b,d,a,c,,,,,,,,,,", "", true); + errcount += expect_result ("a, b, c, d, e", ",,,,\t,,,,b,d,a,c,\t", "e", + true); + errcount += expect_result ("e, a, b, c, d", "b,d,a,c", "e", true); + errcount += expect_result ("token, a, b, c, d", "token", "a, b, c, d", true); + errcount += expect_result ("token1, a, b, c, d", "token1", "a, b, c, d", + true); + errcount += expect_result ("token12, a, b, c, d", "token12", "a, b, c, d", + true); + errcount += expect_result ("token123, a, b, c, d", "token123", "a, b, c, d", + true); + errcount += expect_result ("token1234, a, b, c, d", "token1234", "a, b, c, d", + true); + errcount += expect_result ("token12345, a, b, c, d", "token12345", + "a, b, c, d", true); + errcount += expect_result ("token123456, a, b, c, d", "token123456", + "a, b, c, d", true); + errcount += expect_result ("token1234567, a, b, c, d", "token1234567", + "a, b, c, d", true); + errcount += expect_result ("token12345678, a, b, c, d", "token12345678", + "a, b, c, d", true); + + errcount += expect_result ("", "a", "", false); + errcount += expect_result ("", "", "", false); + errcount += expect_result ("a, b, c, d", "bb, dd, aa, cc", "a, b, c, d", + false); + errcount += expect_result ("a, b, c, d, e", "bb, dd, aa, cc", "a, b, c, d, e", + false); + errcount += expect_result ("e, a, b, c, d", "bb, dd, aa, cc", "e, a, b, c, d", + false); + errcount += expect_result ("e, a, b, c, d, e", "bb, dd, aa, cc", + "e, a, b, c, d, e", false); + errcount += expect_result ("aa, bb, cc, dd", "b, d, a, c", "aa, bb, cc, dd", + false); + errcount += expect_result ("aa, bb, cc, dd, ee", "b, d, a, c", + "aa, bb, cc, dd, ee", false); + errcount += expect_result ("ee, aa, bb, cc, dd", "b, d, a, c", + "ee, aa, bb, cc, dd", false); + errcount += expect_result ("ee, aa, bb, cc, dd, ee", "b, d, a, c", + "ee, aa, bb, cc, dd, ee", false); + + errcount += expect_result ("TESt", ",,,,,,test,,,,", "", true); + errcount += expect_result ("TESt", ",,,,,\t,test,,,,", "", true); + errcount += expect_result ("TESt", ",,,,,,test, ,,,", "", true); + errcount += expect_result ("TESt", ",,,,,, test,,,,", "", true); + errcount += expect_result ("TESt", ",,,,,, test-not,test,,", "", + true); + errcount += expect_result ("TESt", ",,,,,, test-not,,test,,", "", + true); + errcount += expect_result ("TESt", ",,,,,, test-not ,test,,", "", + true); + errcount += expect_result ("TESt", ",,,,,, test", "", true); + errcount += expect_result ("TESt", ",,,,,, test ", "", true); + errcount += expect_result ("TESt", "no-test,,,,,, test ", "", + true); + + errcount += expect_result ("the-token, a, the-token, b, the-token, " \ + "the-token, c, the-token", "the-token", "a, b, c", + true); + errcount += expect_result ("aa, the-token, bb, the-token, cc, the-token, " \ + "the-token, dd, the-token", "the-token", + "aa, bb, cc, dd", true); + errcount += expect_result ("the-token, a, the-token, b, the-token, " \ + "the-token, c, the-token, e", "the-token", + "a, b, c, e", true); + errcount += expect_result ("aa, the-token, bb, the-token, cc, the-token, " \ + "the-token, dd, the-token, ee", "the-token", + "aa, bb, cc, dd, ee", true); + errcount += expect_result ("the-token, the-token, the-token, " \ + "the-token, the-token", "the-token", "", true); + errcount += expect_result ("the-token, a, the-token, the-token, b, " \ + "the-token, c, the-token, a", "c,a,b", + "the-token, the-token, the-token, the-token, the-token", + true); + errcount += expect_result ("the-token, xx, the-token, the-token, zz, " \ + "the-token, yy, the-token, ww", "ww,zz,yy", + "the-token, xx, the-token, the-token, the-token, the-token", + true); + errcount += expect_result ("the-token, a, the-token, the-token, b, " \ + "the-token, c, the-token, a", " c,\t a,b,,,", + "the-token, the-token, the-token, the-token, the-token", + true); + errcount += expect_result ("the-token, xx, the-token, the-token, zz, " \ + "the-token, yy, the-token, ww", + ",,,,ww,\t zz, yy", + "the-token, xx, the-token, the-token, the-token, the-token", + true); + errcount += expect_result ("the-token, a, the-token, the-token, b, " \ + "the-token, c, the-token, a", ",,,,c,\t a,b", + "the-token, the-token, the-token, the-token, the-token", + true); + errcount += expect_result ("the-token, xx, the-token, the-token, zz, " \ + "the-token, yy, the-token, ww", " ww,\t zz,yy,,,,", + "the-token, xx, the-token, the-token, the-token, the-token", + true); + errcount += expect_result ("close, 2", "close", + "2", true); + errcount += expect_result ("close, 22", "close", + "22", true); + errcount += expect_result ("close, nothing", "close", + "nothing", true); + errcount += expect_result ("close, 2", "2", + "close", true); + errcount += expect_result ("close", "close", + "", true); + errcount += expect_result ("close, nothing", "close, token", + "nothing", true); + errcount += expect_result ("close, nothing", "nothing, token", + "close", true); + errcount += expect_result ("close, 2", "close, 10, 12, 22, nothing", + "2", true); + + errcount += expect_result ("strin", "string", "strin", false); + errcount += expect_result ("Stringer", "string", "Stringer", false); + errcount += expect_result ("sstring", "String", "sstring", false); + errcount += expect_result ("string", "Strin", "string", false); + errcount += expect_result ("String", "\t(-strinG", "String", false); + errcount += expect_result ("String", ")strinG\t ", "String", false); + errcount += expect_result ("not-token, tOkEner", "toKEN", + "not-token, tOkEner", false); + errcount += expect_result ("not-token, tOkEns, more-token", "toKEN", + "not-token, tOkEns, more-token", false); + errcount += expect_result ("tests, quest", "TESt", "tests, quest", + false); + errcount += expect_result ("testы", "TESt", "testы", false); + errcount += expect_result ("test-not, хtest", "TESt", + "test-not, хtest", false); + errcount += expect_result ("testing, test not, test2", "TESt", + "testing, test not, test2", false); + errcount += expect_result ("", ",,,,,,,,,,,,,,,,,,,the-token", "", false); + errcount += expect_result ("a1, b1, c1, d1, e1, f1, g1", "", + "a1, b1, c1, d1, e1, f1, g1", false); + + return errcount; +} + + +int +main (int argc, char *argv[]) +{ + int errcount = 0; + (void) argc; (void) argv; /* Unused. Silent compiler warning. */ + errcount += check_result (); + if (0 == errcount) + printf ("All tests were passed without errors.\n"); + return errcount == 0 ? 0 : 1; +} diff --git a/src/tests/unit/unit_md5.c b/src/tests/unit/unit_md5.c @@ -39,7 +39,7 @@ /** * @file src/test/unit/unit_md5.c * @brief Unit tests for md5 functions - * @author Karlson2k (Evgeny Grin) + * @author Karlson2k (Evgeny Grin) & Christian Grothoff */ #include <stdio.h> @@ -69,7 +69,6 @@ static int verbose; - /** * Check whether one of strings in array is equal to @a param. * String @a argv[0] is ignored. @@ -120,7 +119,6 @@ hex2bin (const char *hex, } - /* * Helper functions */ @@ -156,43 +154,43 @@ check_result (const char *test_name, const uint8_t expected[mhd_MD5_DIGEST_SIZE]) { int failed = memcmp (calculated, - expected, - mhd_MD5_DIGEST_SIZE); + expected, + mhd_MD5_DIGEST_SIZE); check_num++; /* Print 1-based numbers */ if (failed) { char calc_str[MD5_DIGEST_STRING_SIZE]; char expc_str[MD5_DIGEST_STRING_SIZE]; - + bin2hex (calculated, - mhd_MD5_DIGEST_SIZE, - calc_str); + mhd_MD5_DIGEST_SIZE, + calc_str); bin2hex (expected, - mhd_MD5_DIGEST_SIZE, - expc_str); + mhd_MD5_DIGEST_SIZE, + expc_str); fprintf (stderr, "FAILED: %s check %u: calculated digest %s, expected digest %s.\n", test_name, - check_num, - calc_str, - expc_str); + check_num, + calc_str, + expc_str); fflush (stderr); return 1; } if (verbose) { char calc_str[MD5_DIGEST_STRING_SIZE]; - + bin2hex (calculated, - mhd_MD5_DIGEST_SIZE, - calc_str); + mhd_MD5_DIGEST_SIZE, + calc_str); fprintf (stderr, - "PASSED: %s check %u: calculated digest %s " - "matches expected digest.\n", - test_name, - check_num, - calc_str); + "PASSED: %s check %u: calculated digest %s " + "matches expected digest.\n", + test_name, + check_num, + calc_str); fflush (stdout); } return 0; @@ -263,7 +261,7 @@ static const struct data_unit1 data_units1[] = { }; static const size_t units1_num = sizeof(data_units1) / sizeof(data_units1[0]); - + /* Calculated MD5 as one pass for whole data */ static int test1_str (void) @@ -279,19 +277,19 @@ test1_str (void) mhd_MD5_update (&ctx, data_units1[i].str_l.len, - (const uint8_t *) data_units1[i].str_l.str); + (const uint8_t *) data_units1[i].str_l.str); mhd_MD5_finish_reset (&ctx, - digest); + digest); if (mhd_MD5_has_err (&ctx)) { fprintf (stderr, - "External hashing error: %d.\n", - ctx.ext_error); + "External hashing error: %d.\n", + ctx.ext_error); exit (99); } num_failed += check_result (MHD_FUNC_, - i, - digest, + i, + digest, data_units1[i].digest); } mhd_MD5_deinit (&ctx); @@ -458,20 +456,20 @@ test1_bin (void) uint8_t digest[mhd_MD5_DIGEST_SIZE]; mhd_MD5_update (&ctx, - data_units2[i].bin_l.len, - data_units2[i].bin_l.bin); + data_units2[i].bin_l.len, + data_units2[i].bin_l.bin); mhd_MD5_finish_reset (&ctx, - digest); + digest); if (mhd_MD5_has_err (&ctx)) { fprintf (stderr, - "External hashing error: %d.\n", - ctx.ext_error); + "External hashing error: %d.\n", + ctx.ext_error); exit (99); } num_failed += check_result (MHD_FUNC_, - i, - digest, + i, + digest, data_units2[i].digest); } mhd_MD5_deinit (&ctx); @@ -494,32 +492,32 @@ test2_str (void) size_t part_s = data_units1[i].str_l.len / 4; mhd_MD5_update (&ctx, - 0, - (const uint8_t *) ""); + 0, + (const uint8_t *) ""); mhd_MD5_update (&ctx, - part_s, - (const uint8_t *) data_units1[i].str_l.str); + part_s, + (const uint8_t *) data_units1[i].str_l.str); mhd_MD5_update (&ctx, - 0, - (const uint8_t *) ""); + 0, + (const uint8_t *) ""); mhd_MD5_update (&ctx, - data_units1[i].str_l.len - part_s, - (const uint8_t *) data_units1[i].str_l.str + part_s); + data_units1[i].str_l.len - part_s, + (const uint8_t *) data_units1[i].str_l.str + part_s); mhd_MD5_update (&ctx, - 0, - (const uint8_t *) ""); + 0, + (const uint8_t *) ""); mhd_MD5_finish_reset (&ctx, - digest); + digest); if (mhd_MD5_has_err (&ctx)) { fprintf (stderr, - "External hashing error: %d.\n", - ctx.ext_error); + "External hashing error: %d.\n", + ctx.ext_error); exit (99); } num_failed += check_result (MHD_FUNC_, - i, - digest, + i, + digest, data_units1[i].digest); } mhd_MD5_deinit (&ctx); @@ -542,26 +540,26 @@ test2_bin (void) size_t part_s = data_units2[i].bin_l.len * 2 / 3; mhd_MD5_update (&ctx, - part_s, - data_units2[i].bin_l.bin); + part_s, + data_units2[i].bin_l.bin); mhd_MD5_update (&ctx, - 0, - (const uint8_t *) ""); + 0, + (const uint8_t *) ""); mhd_MD5_update (&ctx, data_units2[i].bin_l.len - part_s, - data_units2[i].bin_l.bin + part_s); + data_units2[i].bin_l.bin + part_s); mhd_MD5_finish_reset (&ctx, - digest); + digest); if (mhd_MD5_has_err (&ctx)) { fprintf (stderr, - "External hashing error: %d.\n", - ctx.ext_error); + "External hashing error: %d.\n", + ctx.ext_error); exit (99); } num_failed += check_result (MHD_FUNC_, - i, - digest, + i, + digest, data_units2[i].digest); } mhd_MD5_deinit (&ctx); @@ -598,28 +596,28 @@ test_unaligned (void) unaligned_buf = buf + offset; memcpy (unaligned_buf, - tdata->bin_l.bin, - tdata->bin_l.len); + tdata->bin_l.bin, + tdata->bin_l.len); unaligned_digest = digest_buf + MAX_OFFSET - offset; memset (unaligned_digest, - 0, - mhd_MD5_DIGEST_SIZE); + 0, + mhd_MD5_DIGEST_SIZE); mhd_MD5_update (&ctx, - tdata->bin_l.len, - unaligned_buf); + tdata->bin_l.len, + unaligned_buf); mhd_MD5_finish_reset (&ctx, - unaligned_digest); + unaligned_digest); if (mhd_MD5_has_err (&ctx)) { fprintf (stderr, - "External hashing error: %d.\n", - ctx.ext_error); + "External hashing error: %d.\n", + ctx.ext_error); exit (99); } num_failed += check_result (MHD_FUNC_, - MAX_OFFSET - offset, + MAX_OFFSET - offset, unaligned_digest, - tdata->digest); + tdata->digest); } mhd_MD5_deinit (&ctx); free (digest_buf); @@ -628,7 +626,6 @@ test_unaligned (void) } - /* Helper function to compare digest with expected hex string */ static int check_digest (const uint8_t *digest, @@ -773,18 +770,18 @@ main (int argc, { data[0] = 'a'; mhd_MD5_update (&ctx, - 1, - data); + 1, + data); data[0] = 'b'; mhd_MD5_update (&ctx, - 1, - data); + 1, + data); data[0] = 'c'; mhd_MD5_update (&ctx, - 1, - data); + 1, + data); mhd_MD5_finish_deinit (&ctx, - digest); + digest); if (! mhd_MD5_has_err (&ctx)) { if (check_digest (digest, @@ -830,7 +827,7 @@ main (int argc, num_failed += test2_str (); num_failed += test2_bin (); num_failed += test_unaligned (); - + printf ("Results: %u tests failed\n", num_failed); diff --git a/src/tests/unit/unit_str.c b/src/tests/unit/unit_str.c @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ +/* + This file is part of GNU libmicrohttpd. + Copyright (C) 2025 Christian Grothoff + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + Alternatively, you can redistribute GNU libmicrohttpd and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version, together + with the eCos exception, as follows: + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile this + file and link it with other works to produce a work based on this + file, this file does not by itself cause the resulting work to be + covered by the GNU General Public License. However the source code + for this file must still be made available in accordance with + section (3) of the GNU General Public License v2. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + + You should have received copies of the GNU Lesser General Public + License and the GNU General Public License along with this library; + if not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file src/test/unit/unit_str.c + * @brief Unit tests for string functions + * @author Christian Grothoff + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "mhd_sys_options.h" +#include "../mhd2/mhd_str.h" +#include "../mhd2/mhd_str.c" +#include "../mhdt_checks.h" + +#define CHECK_TRUE(cond) \ + if (0 == MHDT_EXPECT_TRUE (cond)) { failures++; } else {} + +#define CHECK_FALSE(cond) \ + if (0 == MHDT_EXPECT_FALSE (cond)) { failures++; } else {} + +int +main (void) +{ + unsigned int failures = 0; + + MHDT_set_verbosity (MHDT_VERB_LVL_VERBOSE); + CHECK_TRUE (mhd_str_equal_caseless ("ab", + "AB")); + CHECK_TRUE (mhd_str_equal_caseless ("ab", + "ab")); + CHECK_TRUE (mhd_str_equal_caseless ("", + "")); + CHECK_FALSE (mhd_str_equal_caseless ("ab", + "ABc")); + CHECK_FALSE (mhd_str_equal_caseless ("a b", + "ab")); + CHECK_FALSE (mhd_str_equal_caseless ("", + " ")); + /* Note: our caseless ONLY refers to US-ASCII */ + CHECK_FALSE (mhd_str_equal_caseless ("Ä", + "ä")); + + CHECK_TRUE (mhd_str_equal_caseless_n ("ab\0x", + "AB\0y", + 4)); + CHECK_TRUE (mhd_str_equal_caseless_n ("abc", + "abd", + 2)); + CHECK_TRUE (mhd_str_equal_caseless_n ("", + "", + 0)); + CHECK_FALSE (mhd_str_equal_caseless_n ("ab", + "ABc", + 3)); + CHECK_FALSE (mhd_str_equal_caseless_n ("a b", + "ab", + 2)); + CHECK_FALSE (mhd_str_equal_caseless_n ("", + " ", + 1)); + /* Note: our caseless ONLY refers to US-ASCII, + Need 3 here because Umlaut is equal in first + byte and diffes in 2nd byte. */ + CHECK_FALSE (mhd_str_equal_caseless_n ("xÄbb", + "xäbb", + 3)); + CHECK_TRUE (mhd_str_equal_caseless_n ("ab\0x", + "AB\0y", + 4)); + + CHECK_TRUE (mhd_str_equal_caseless_bin_n ("ab\0x", + "AB\0x", + 4)); + CHECK_FALSE (mhd_str_equal_caseless_bin_n ("ab\0x", + "AB\0y", + 4)); + CHECK_FALSE (mhd_str_equal_caseless_bin_n ("ab\0x", + "AB\0y", + 4)); + + CHECK_TRUE (mhd_str_equal_lowercase_bin_n ("AB", + "ab", + 2)); + CHECK_FALSE (mhd_str_equal_lowercase_bin_n ("ab", + "AB", + 2)); + CHECK_TRUE (mhd_str_is_lowercase_bin_n (0, + "")); + CHECK_TRUE (mhd_str_is_lowercase_bin_n (2, + "ab")); + CHECK_TRUE (mhd_str_is_lowercase_bin_n (2, + "abC")); + CHECK_TRUE (mhd_str_is_lowercase_bin_n (2, + "xä")); + CHECK_TRUE (mhd_str_is_lowercase_bin_n (2, + "xÄ")); + CHECK_FALSE (mhd_str_is_lowercase_bin_n (2, + "aB")); + + return (0 == failures) ? 0 : 1; +}