diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am index cc685d3b..010ec2ef 100644 --- a/src/testcurl/Makefile.am +++ b/src/testcurl/Makefile.am @@ -145,7 +145,7 @@ check_PROGRAMS = \ if ENABLE_COOKIE check_PROGRAMS += \ test_parse_cookies \ - test_parse_cookies_invalid + test_parse_cookies_nonstrict endif if HEAVY_TESTS @@ -468,10 +468,10 @@ test_process_headers_SOURCES = \ test_process_headers.c mhd_has_in_name.h test_parse_cookies_SOURCES = \ - test_parse_cookies.c mhd_has_in_name.h + test_parse_cookies.c mhd_has_in_name.h mhd_has_param.h -test_parse_cookies_invalid_SOURCES = \ - test_parse_cookies.c mhd_has_in_name.h +test_parse_cookies_nonstrict_SOURCES = \ + $(test_parse_cookies_SOURCES) test_process_arguments_SOURCES = \ test_process_arguments.c mhd_has_in_name.h diff --git a/src/testcurl/test_parse_cookies.c b/src/testcurl/test_parse_cookies.c index d02a2b76..987ddbf4 100644 --- a/src/testcurl/test_parse_cookies.c +++ b/src/testcurl/test_parse_cookies.c @@ -1,14 +1,14 @@ /* - This file is part of libmicrohttpd + This file is part of GNU libmicrohttpd Copyright (C) 2007 Christian Grothoff - Copyright (C) 2014-2022 Evgeny Grin (Karlson2k) + Copyright (C) 2016-2022 Evgeny Grin (Karlson2k) - libmicrohttpd is free software; you can redistribute it and/or modify + GNU libmicrohttpd 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 3, or (at your + by the Free Software Foundation; either version 2, or (at your option) any later version. - libmicrohttpd is distributed in the hope that it will be useful, but + 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 General Public License for more details. @@ -22,25 +22,638 @@ /** * @file test_parse_cookies.c * @brief Testcase for HTTP cookie parsing - * @author Christian Grothoff * @author Karlson2k (Evgeny Grin) + * @author Christian Grothoff */ -#include "MHD_config.h" +#include "mhd_options.h" #include "platform.h" #include #include #include -#include #include #include -#include "mhd_has_in_name.h" -#ifndef WINDOWS +#ifndef _WIN32 +#include #include #endif -static int use_invalid; +#include "mhd_has_param.h" +#include "mhd_has_in_name.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_ */ + +#ifndef CURL_VERSION_BITS +#define CURL_VERSION_BITS(x,y,z) ((x) << 16 | (y) << 8 | (z)) +#endif /* ! CURL_VERSION_BITS */ +#ifndef CURL_AT_LEAST_VERSION +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS (x, y, z)) +#endif /* ! CURL_AT_LEAST_VERSION */ + +#ifndef _MHD_INSTRMACRO +/* Quoted macro parameter */ +#define _MHD_INSTRMACRO(a) #a +#endif /* ! _MHD_INSTRMACRO */ +#ifndef _MHD_STRMACRO +/* Quoted expanded macro parameter */ +#define _MHD_STRMACRO(a) _MHD_INSTRMACRO (a) +#endif /* ! _MHD_STRMACRO */ + +#if defined(HAVE___FUNC__) +#define externalErrorExit(ignore) \ + _externalErrorExit_func (NULL, __func__, __LINE__) +#define externalErrorExitDesc(errDesc) \ + _externalErrorExit_func (errDesc, __func__, __LINE__) +#define libcurlErrorExit(ignore) \ + _libcurlErrorExit_func (NULL, __func__, __LINE__) +#define libcurlErrorExitDesc(errDesc) \ + _libcurlErrorExit_func (errDesc, __func__, __LINE__) +#define mhdErrorExit(ignore) \ + _mhdErrorExit_func (NULL, __func__, __LINE__) +#define mhdErrorExitDesc(errDesc) \ + _mhdErrorExit_func (errDesc, __func__, __LINE__) +#define checkCURLE_OK(libcurlcall) \ + _checkCURLE_OK_func ((libcurlcall), _MHD_STRMACRO (libcurlcall), \ + __func__, __LINE__) +#elif defined(HAVE___FUNCTION__) +#define externalErrorExit(ignore) \ + _externalErrorExit_func (NULL, __FUNCTION__, __LINE__) +#define externalErrorExitDesc(errDesc) \ + _externalErrorExit_func (errDesc, __FUNCTION__, __LINE__) +#define libcurlErrorExit(ignore) \ + _libcurlErrorExit_func (NULL, __FUNCTION__, __LINE__) +#define libcurlErrorExitDesc(errDesc) \ + _libcurlErrorExit_func (errDesc, __FUNCTION__, __LINE__) +#define mhdErrorExit(ignore) \ + _mhdErrorExit_func (NULL, __FUNCTION__, __LINE__) +#define mhdErrorExitDesc(errDesc) \ + _mhdErrorExit_func (errDesc, __FUNCTION__, __LINE__) +#define checkCURLE_OK(libcurlcall) \ + _checkCURLE_OK_func ((libcurlcall), _MHD_STRMACRO (libcurlcall), \ + __FUNCTION__, __LINE__) +#else +#define externalErrorExit(ignore) _externalErrorExit_func (NULL, NULL, __LINE__) +#define externalErrorExitDesc(errDesc) \ + _externalErrorExit_func (errDesc, NULL, __LINE__) +#define libcurlErrorExit(ignore) _libcurlErrorExit_func (NULL, NULL, __LINE__) +#define libcurlErrorExitDesc(errDesc) \ + _libcurlErrorExit_func (errDesc, NULL, __LINE__) +#define mhdErrorExit(ignore) _mhdErrorExit_func (NULL, NULL, __LINE__) +#define mhdErrorExitDesc(errDesc) _mhdErrorExit_func (errDesc, NULL, __LINE__) +#define checkCURLE_OK(libcurlcall) \ + _checkCURLE_OK_func ((libcurlcall), _MHD_STRMACRO (libcurlcall), NULL, \ + __LINE__) +#endif + + +_MHD_NORETURN static void +_externalErrorExit_func (const char *errDesc, const char *funcName, int lineNum) +{ + fflush (stdout); + if ((NULL != errDesc) && (0 != errDesc[0])) + fprintf (stderr, "%s", errDesc); + else + fprintf (stderr, "System or external library call failed"); + if ((NULL != funcName) && (0 != funcName[0])) + fprintf (stderr, " in %s", funcName); + if (0 < lineNum) + fprintf (stderr, " at line %d", lineNum); + + fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, + strerror (errno)); +#ifdef MHD_WINSOCK_SOCKETS + fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); +#endif /* MHD_WINSOCK_SOCKETS */ + fflush (stderr); + exit (99); +} + + +static char libcurl_errbuf[CURL_ERROR_SIZE] = ""; + +_MHD_NORETURN static void +_libcurlErrorExit_func (const char *errDesc, const char *funcName, int lineNum) +{ + fflush (stdout); + if ((NULL != errDesc) && (0 != errDesc[0])) + fprintf (stderr, "%s", errDesc); + else + fprintf (stderr, "CURL library call failed"); + if ((NULL != funcName) && (0 != funcName[0])) + fprintf (stderr, " in %s", funcName); + if (0 < lineNum) + fprintf (stderr, " at line %d", lineNum); + + fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, + strerror (errno)); +#ifdef MHD_WINSOCK_SOCKETS + fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); +#endif /* MHD_WINSOCK_SOCKETS */ + if (0 != libcurl_errbuf[0]) + fprintf (stderr, "Last libcurl error description: %s\n", libcurl_errbuf); + + fflush (stderr); + exit (99); +} + + +_MHD_NORETURN static void +_mhdErrorExit_func (const char *errDesc, const char *funcName, int lineNum) +{ + fflush (stdout); + if ((NULL != errDesc) && (0 != errDesc[0])) + fprintf (stderr, "%s", errDesc); + else + fprintf (stderr, "MHD unexpected error"); + if ((NULL != funcName) && (0 != funcName[0])) + fprintf (stderr, " in %s", funcName); + if (0 < lineNum) + fprintf (stderr, " at line %d", lineNum); + + fprintf (stderr, ".\nLast errno value: %d (%s)\n", (int) errno, + strerror (errno)); +#ifdef MHD_WINSOCK_SOCKETS + fprintf (stderr, "WSAGetLastError() value: %d\n", (int) WSAGetLastError ()); +#endif /* MHD_WINSOCK_SOCKETS */ + + fflush (stderr); + exit (8); +} + + +/* Could be increased to facilitate debugging */ +#define TIMEOUTS_VAL 5 + +#define EXPECTED_URI_BASE_PATH "/" + +#define URL_SCHEME "http:/" "/" + +#define URL_HOST "127.0.0.1" + +#define URL_SCHEME_HOST URL_SCHEME URL_HOST + +#define PAGE \ + "libmicrohttpd test page" \ + "Success!" + + +#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_ */ + + +struct strct_str_len +{ + const char *str; + const size_t len; +}; + +#define STR_LEN_(str) {str, MHD_STATICSTR_LEN_(str)} +#define STR_NULL_ {NULL, 0} + +struct strct_cookie +{ + struct strct_str_len name; + struct strct_str_len value; +}; + +#define COOKIE_(name,value) {STR_LEN_(name), STR_LEN_(value)} +#define COOKIE_NULL {STR_NULL_, STR_NULL_} + +struct strct_test_data +{ + unsigned int line_num; + const char *header_str; + unsigned int num_cookies_non_strict; + unsigned int num_cookies_strict; + struct strct_cookie cookies[5]; +}; + +static const struct strct_test_data test_data[] = { + { + __LINE__, + "name1=var1; name2=var2; name3=; " \ + "name4=\"var4 with spaces\"; " \ + "name5=var_with_=_char", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name1=var1;name2=var2;name3=;" \ + "name4=\"var4 with spaces\";" \ + "name5=var_with_=_char", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name1=var1; name2=var2; name3=; " \ + "name4=\"var4 with spaces\"; " \ + "name5=var_with_=_char\t \t", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name1=var1;;name2=var2;;name3=;;" \ + "name4=\"var4 with spaces\";;" \ + "name5=var_with_=_char;\t \t", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name3=; name1=var1; name2=var2; " \ + "name5=var_with_=_char;" \ + "name4=\"var4 with spaces\"", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name2=var2; name1=var1; " \ + "name5=var_with_=_char; name3=; " \ + "name4=\"var4 with spaces\";", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name2=var2; name1=var1; " \ + "name5=var_with_=_char; " \ + "name4=\"var4 with spaces\"; name3=", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name2=var2; name1=var1; " \ + "name4=\"var4 with spaces\"; " \ + "name5=var_with_=_char; name3=;", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + ";;;;;;;;name1=var1; name2=var2; name3=; " \ + "name4=\"var4 with spaces\"; " \ + "name5=var_with_=_char", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name1=var1; name2=var2; name3=; " \ + "name4=\"var4 with spaces\"; ; ; ; ; " \ + "name5=var_with_=_char", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name1=var1; name2=var2; name3=; " \ + "name4=\"var4 with spaces\"; " \ + "name5=var_with_=_char;;;;;;;;", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name1=var1; name2=var2; " \ + "name4=\"var4 with spaces\"" \ + "name5=var_with_=_char; ; ; ; ; name3=", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name5=var_with_=_char ;" \ + "name1=var1; name2=var2; name3=; " \ + "name4=\"var4 with spaces\" ", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "name5=var_with_=_char; name4=\"var4 with spaces\";" \ + "name1=var1; name2=var2; name3=", + 5, + 0, + { + COOKIE_ ("name1", "var1"), + COOKIE_ ("name2", "var2"), + COOKIE_ ("name3", ""), + COOKIE_ ("name4", "var4 with spaces"), + COOKIE_ ("name5", "var_with_=_char") + } + }, + { + __LINE__, + "", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + " ", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "\t", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "var=,", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "var=\"\\ \"", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "var=value space", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "var=value\ttab", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "=", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "====", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + ";=", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "var", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "=;", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + "= ;", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + }, + { + __LINE__, + ";= ;", + 0, + 0, + { + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL, + COOKIE_NULL + } + } +}; + +/* Global parameters */ +static int verbose; +static int oneone; /**< If false use HTTP/1.0 for requests*/ +static int use_non_strict; + +static void +test_global_init (void) +{ + libcurl_errbuf[0] = 0; + + if (0 != curl_global_init (CURL_GLOBAL_WIN32)) + externalErrorExit (); +} + + +static void +test_global_cleanup (void) +{ + curl_global_cleanup (); +} + struct CBC { @@ -49,8 +662,12 @@ struct CBC size_t size; }; + static size_t -copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) +copyBuffer (void *ptr, + size_t size, + size_t nmemb, + void *ctx) { struct CBC *cbc = ctx; @@ -62,8 +679,16 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) } +struct ahc_cls_type +{ + const char *rq_method; + const char *rq_url; + const struct strct_test_data *check; +}; + + static enum MHD_Result -ahc_echo (void *cls, +ahcCheck (void *cls, struct MHD_Connection *connection, const char *url, const char *method, @@ -71,437 +696,496 @@ ahc_echo (void *cls, const char *upload_data, size_t *upload_data_size, void **req_cls) { - static int ptr; - const int *puse_invalid = cls; + static int marker; struct MHD_Response *response; enum MHD_Result ret; - const char *hdr; - (void) version; (void) upload_data; (void) upload_data_size; /* Unused. Silent compiler warning. */ + struct ahc_cls_type *const param = (struct ahc_cls_type *) cls; + const unsigned int expected_num_cookies = + use_non_strict ? param->check->num_cookies_non_strict : + param->check->num_cookies_strict; + unsigned int i; + int cookie_failed; - if (0 != strcmp (MHD_HTTP_METHOD_GET, method)) - return MHD_NO; /* unexpected method */ - if (&ptr != *req_cls) + if (NULL == param) + mhdErrorExitDesc ("cls parameter is NULL"); + + if (oneone) { - *req_cls = &ptr; + if (0 != strcmp (version, MHD_HTTP_VERSION_1_1)) + mhdErrorExitDesc ("Unexpected HTTP version"); + } + else + { + if (0 != strcmp (version, MHD_HTTP_VERSION_1_0)) + mhdErrorExitDesc ("Unexpected HTTP version"); + } + + if (0 != strcmp (url, param->rq_url)) + mhdErrorExitDesc ("Unexpected URI"); + + if (NULL != upload_data) + mhdErrorExitDesc ("'upload_data' is not NULL"); + + if (NULL == upload_data_size) + mhdErrorExitDesc ("'upload_data_size' pointer is NULL"); + + if (0 != *upload_data_size) + mhdErrorExitDesc ("'*upload_data_size' value is not zero"); + + if (0 != strcmp (param->rq_method, method)) + mhdErrorExitDesc ("Unexpected request method"); + + cookie_failed = 0; + for (i = 0; i < expected_num_cookies; ++i) + { + const char *cookie_val; + size_t cookie_val_len; + const struct strct_cookie *const cookie_data = param->check->cookies + i; + if (NULL == cookie_data->name.str) + externalErrorExitDesc ("Broken test data"); + if (NULL == cookie_data->value.str) + externalErrorExitDesc ("Broken test data"); + + cookie_val = + MHD_lookup_connection_value (connection, + MHD_COOKIE_KIND, + cookie_data->name.str); + if (cookie_val == NULL) + { + fprintf (stderr, "'%s' cookie not found.\n", + cookie_data->name.str); + cookie_failed = 1; + } + else if (0 != strcmp (cookie_val, + cookie_data->value.str)) + { + fprintf (stderr, "'%s' cookie decoded incorrectly.\n" + "Expected: %s\nGot: %s\n", + cookie_data->name.str, + cookie_data->value.str, + cookie_val); + cookie_failed = 1; + } + else if (MHD_YES != + MHD_lookup_connection_value_n (connection, + MHD_COOKIE_KIND, + cookie_data->name.str, + cookie_data->name.len, + &cookie_val, &cookie_val_len)) + { + fprintf (stderr, "'%s' (length %lu) cookie not found.\n", + cookie_data->name.str, + (unsigned long) cookie_data->name.len); + cookie_failed = 1; + } + else + { + if (cookie_data->value.len != cookie_val_len) + { + fprintf (stderr, "'%s' (length %lu) cookie has wrong value length.\n" + "Expected: %lu\nGot: %lu\n", + cookie_data->name.str, + (unsigned long) cookie_data->name.len, + (unsigned long) cookie_data->value.len, + (unsigned long) cookie_val_len); + cookie_failed = 1; + } + else if (0 != memcmp (cookie_val, cookie_data->value.str, cookie_val_len)) + { + fprintf (stderr, "'%s' (length %lu) cookie has wrong value.\n" + "Expected: %.*s\nGot: %.*s\n", + cookie_data->name.str, + (unsigned long) cookie_data->name.len, + (int) cookie_data->value.len, cookie_data->value.str, + (int) cookie_val_len, cookie_val); + cookie_failed = 1; + } + } + } + if (((int) expected_num_cookies) != + MHD_get_connection_values_n (connection, MHD_COOKIE_KIND, NULL, NULL)) + { + fprintf (stderr, "Wrong total number of cookies.\n" + "Expected: %u\nGot: %d\n", + expected_num_cookies, + MHD_get_connection_values_n (connection, MHD_COOKIE_KIND, NULL, + NULL)); + cookie_failed = 1; + } + if (cookie_failed) + return MHD_NO; /* Break connection */ + + if (&marker != *req_cls) + { + *req_cls = ▮ return MHD_YES; } *req_cls = NULL; - if (! *puse_invalid) - { - hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name1"); - if ((hdr == NULL) || (0 != strcmp (hdr, "var1"))) - { - fprintf (stderr, "'name1' cookie decoded incorrectly.\n"); - exit (11); - } - hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name2"); - if ((hdr == NULL) || (0 != strcmp (hdr, "var2"))) - { - fprintf (stderr, "'name2' cookie decoded incorrectly.\n"); - exit (11); - } - hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name3"); - if ((hdr == NULL) || (0 != strcmp (hdr, ""))) - { - fprintf (stderr, "'name3' cookie decoded incorrectly.\n"); - exit (11); - } - hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name4"); - if ((hdr == NULL) || (0 != strcmp (hdr, "var4 with spaces"))) - { - fprintf (stderr, "'name4' cookie decoded incorrectly.\n"); - exit (11); - } - hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name5"); - if ((hdr == NULL) || (0 != strcmp (hdr, "var_with_=_char"))) - { - fprintf (stderr, "'name5' cookie decoded incorrectly.\n"); - exit (11); - } - if (5 != MHD_get_connection_values_n (connection, MHD_COOKIE_KIND, - NULL, NULL)) - { - fprintf (stderr, "The total number of cookie is not five.\n"); - exit (12); - } - } - else - { - if (0 != MHD_get_connection_values_n (connection, MHD_COOKIE_KIND, - NULL, NULL)) - { - fprintf (stderr, "The total number of cookie is not zero.\n"); - exit (12); - } - } - response = MHD_create_response_from_buffer_copy (strlen (url), - url); - ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + response = + MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ (PAGE), + PAGE); + if (NULL == response) + mhdErrorExitDesc ("Failed to create response"); + + ret = MHD_queue_response (connection, + MHD_HTTP_OK, + response); MHD_destroy_response (response); - if (ret == MHD_NO) - abort (); + if (MHD_YES != ret) + mhdErrorExitDesc ("Failed to queue response"); + return ret; } -/* Re-use the same port for all checks */ -static uint16_t port; +static int +libcurl_debug_cb (CURL *handle, + curl_infotype type, + char *data, + size_t size, + void *userptr) +{ + static const char excess_mark[] = "Excess found"; + static const size_t excess_mark_len = MHD_STATICSTR_LEN_ (excess_mark); -static unsigned int -testExternalGet (int test_number) + (void) handle; + (void) userptr; + +#ifdef _DEBUG + switch (type) + { + case CURLINFO_TEXT: + fprintf (stderr, "* %.*s", (int) size, data); + break; + case CURLINFO_HEADER_IN: + fprintf (stderr, "< %.*s", (int) size, data); + break; + case CURLINFO_HEADER_OUT: + fprintf (stderr, "> %.*s", (int) size, data); + break; + case CURLINFO_DATA_IN: +#if 0 + fprintf (stderr, "<| %.*s\n", (int) size, data); +#endif + break; + case CURLINFO_DATA_OUT: + case CURLINFO_SSL_DATA_IN: + case CURLINFO_SSL_DATA_OUT: + case CURLINFO_END: + default: + break; + } +#endif /* _DEBUG */ + if (CURLINFO_TEXT == type) + { + if ((size >= excess_mark_len) && + (0 == memcmp (data, excess_mark, excess_mark_len))) + mhdErrorExitDesc ("Extra data has been detected in MHD reply"); + } + return 0; +} + + +static CURL * +setupCURL (void *cbc, uint16_t port) { - struct MHD_Daemon *d; CURL *c; - char buf[2048]; - struct CBC cbc; + + c = curl_easy_init (); + if (NULL == c) + libcurlErrorExitDesc ("curl_easy_init() failed"); + + if ((CURLE_OK != curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L)) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, + ©Buffer)) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_WRITEDATA, cbc)) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, + ((long) TIMEOUTS_VAL))) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_HTTP_VERSION, + (oneone) ? + CURL_HTTP_VERSION_1_1 : + CURL_HTTP_VERSION_1_0)) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_TIMEOUT, + ((long) TIMEOUTS_VAL))) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_ERRORBUFFER, + libcurl_errbuf)) || + (CURLE_OK != curl_easy_setopt (c, CURLOPT_FAILONERROR, 0L)) || +#ifdef _DEBUG + (CURLE_OK != curl_easy_setopt (c, CURLOPT_VERBOSE, 1L)) || +#endif /* _DEBUG */ + (CURLE_OK != curl_easy_setopt (c, CURLOPT_DEBUGFUNCTION, + &libcurl_debug_cb)) || +#if CURL_AT_LEAST_VERSION (7, 19, 4) + (CURLE_OK != curl_easy_setopt (c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP)) || +#endif /* CURL_AT_LEAST_VERSION (7, 19, 4) */ +#if CURL_AT_LEAST_VERSION (7, 45, 0) + (CURLE_OK != curl_easy_setopt (c, CURLOPT_DEFAULT_PROTOCOL, "http")) || +#endif /* CURL_AT_LEAST_VERSION (7, 45, 0) */ + (CURLE_OK != curl_easy_setopt (c, CURLOPT_PORT, ((long) port)))) + libcurlErrorExitDesc ("curl_easy_setopt() failed"); + + if (CURLE_OK != + curl_easy_setopt (c, CURLOPT_URL, + URL_SCHEME_HOST EXPECTED_URI_BASE_PATH)) + libcurlErrorExitDesc ("Cannot set request URL"); + + return c; +} + + +static CURLcode +performQueryExternal (struct MHD_Daemon *d, CURL *c, CURLM **multi_reuse) +{ CURLM *multi; - CURLMcode mret; - fd_set rs; - fd_set ws; - fd_set es; - MHD_socket maxsock; -#ifdef MHD_WINSOCK_SOCKETS - int maxposixs; /* Max socket number unused on W32 */ -#else /* MHD_POSIX_SOCKETS */ -#define maxposixs maxsock -#endif /* MHD_POSIX_SOCKETS */ - int running; - struct CURLMsg *msg; time_t start; struct timeval tv; + CURLcode ret; - multi = NULL; - cbc.buf = buf; - cbc.size = 2048; - cbc.pos = 0; - d = MHD_start_daemon (MHD_USE_ERROR_LOG, - port, NULL, NULL, &ahc_echo, &use_invalid, - MHD_OPTION_END); - if (d == NULL) - return 256; - if (0 == port) - { - const union MHD_DaemonInfo *dinfo; - dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); - if ((NULL == dinfo) || (0 == dinfo->port) ) - { - MHD_stop_daemon (d); return 32; - } - port = dinfo->port; - } - c = curl_easy_init (); - curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); - curl_easy_setopt (c, CURLOPT_PORT, (long) port); - curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); - curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); - curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); - if (! use_invalid) - { - if (0 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1; name2=var2; name3=; " \ - "name4=\"var4 with spaces\"; " \ - "name5=var_with_=_char"); - } - else if (1 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1;name2=var2;name3=;" \ - "name4=\"var4 with spaces\";" \ - "name5=var_with_=_char"); - } - else if (2 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1; name2=var2; name3=; " \ - "name4=\"var4 with spaces\"; " \ - "name5=var_with_=_char\t \t"); - } - else if (3 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1;;name2=var2;;name3=;;" \ - "name4=\"var4 with spaces\";;" \ - "name5=var_with_=_char;\t \t"); - } - else if (4 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1 ;name2=var2 ;name3= ;" \ - "name4=\"var4 with spaces\" ;" \ - "name5=var_with_=_char ;"); - } - else if (5 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name3=; name1=var1; name2=var2; " \ - "name5=var_with_=_char;" \ - "name4=\"var4 with spaces\""); - } - else if (6 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name2=var2; name1=var1; " \ - "name5=var_with_=_char; name3=; " \ - "name4=\"var4 with spaces\";"); - } - else if (7 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name2=var2; name1=var1; " \ - "name5=var_with_=_char; " \ - "name4=\"var4 with spaces\"; name3="); - } - else if (8 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name2=var2; name1=var1; " \ - "name4=\"var4 with spaces\"; " \ - "name5=var_with_=_char; name3=;"); - } - else if (9 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - ";;;;;;;;name1=var1; name2=var2; name3=; " \ - "name4=\"var4 with spaces\"; " \ - "name5=var_with_=_char"); - } - else if (10 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1; name2=var2; name3=; " \ - "name4=\"var4 with spaces\"; ; ; ; ; " \ - "name5=var_with_=_char"); - } - else if (11 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1; name2=var2; name3=; " \ - "name4=\"var4 with spaces\"; " \ - "name5=var_with_=_char;;;;;;;;"); - } - else if (12 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name1=var1; name2=var2; " \ - "name4=\"var4 with spaces\"" \ - "name5=var_with_=_char; ; ; ; ; name3="); - } - else if (13 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name5=var_with_=_char ;" \ - "name1=var1; name2=var2; name3=; " \ - "name4=\"var4 with spaces\" "); - } - else if (14 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "name5=var_with_=_char; name4=\"var4 with spaces\";" \ - "name1=var1; name2=var2; name3="); - } - } + ret = CURLE_FAILED_INIT; /* will be replaced with real result */ + if (NULL != *multi_reuse) + multi = *multi_reuse; else { - if (0 == test_number) - { - (void) 0; /* No cookie */ - } - else if (1 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - ""); - } - else if (2 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - " "); - } - else if (3 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "\t"); - } - else if (4 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "var=,"); - } - else if (5 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "var=\"\\ \""); - } - else if (6 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "var=value space"); - } - else if (7 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "var=value\ttab"); - } - else if (8 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "="); - } - else if (9 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "===="); - } - else if (10 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - ";="); - } - else if (11 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "var"); - } - else if (12 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "=;"); - } - else if (13 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - "= ;"); - } - else if (14 == test_number) - { - curl_easy_setopt (c, CURLOPT_COOKIE, - ";= ;"); - } + multi = curl_multi_init (); + if (multi == NULL) + libcurlErrorExitDesc ("curl_multi_init() failed"); + *multi_reuse = multi; } + if (CURLM_OK != curl_multi_add_handle (multi, c)) + libcurlErrorExitDesc ("curl_multi_add_handle() failed"); - curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); - curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); - /* NOTE: use of CONNECTTIMEOUT without also - setting NOSIGNAL results in really weird - crashes on my system! */ - curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); - - - multi = curl_multi_init (); - if (multi == NULL) - { - curl_easy_cleanup (c); - MHD_stop_daemon (d); - return 512; - } - mret = curl_multi_add_handle (multi, c); - if (mret != CURLM_OK) - { - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - MHD_stop_daemon (d); - return 1024; - } start = time (NULL); - while ((time (NULL) - start < 5) && (multi != NULL)) + while (time (NULL) - start <= TIMEOUTS_VAL) { - maxsock = MHD_INVALID_SOCKET; - maxposixs = -1; + fd_set rs; + fd_set ws; + fd_set es; + MHD_socket maxMhdSk; + int maxCurlSk; + int running; + + maxMhdSk = MHD_INVALID_SOCKET; + maxCurlSk = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); - curl_multi_perform (multi, &running); - mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); - if (mret != CURLM_OK) + if (NULL != multi) { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - MHD_stop_daemon (d); - return 2048; + curl_multi_perform (multi, &running); + if (0 == running) + { + struct CURLMsg *msg; + int msgLeft; + int totalMsgs = 0; + do + { + msg = curl_multi_info_read (multi, &msgLeft); + if (NULL == msg) + libcurlErrorExitDesc ("curl_multi_info_read() failed"); + totalMsgs++; + if (CURLMSG_DONE == msg->msg) + ret = msg->data.result; + } while (msgLeft > 0); + if (1 != totalMsgs) + { + fprintf (stderr, + "curl_multi_info_read returned wrong " + "number of results (%d).\n", + totalMsgs); + externalErrorExit (); + } + curl_multi_remove_handle (multi, c); + multi = NULL; + } + else + { + if (CURLM_OK != curl_multi_fdset (multi, &rs, &ws, &es, &maxCurlSk)) + libcurlErrorExitDesc ("curl_multi_fdset() failed"); + } } - if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) - { - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - MHD_stop_daemon (d); - return 4096; + if (NULL == multi) + { /* libcurl has finished, check whether MHD still needs to perform cleanup */ + if (0 != MHD_get_timeout64s (d)) + break; /* MHD finished as well */ } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxMhdSk)) + mhdErrorExitDesc ("MHD_get_fdset() failed"); tv.tv_sec = 0; - tv.tv_usec = 1000; - if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) + tv.tv_usec = 200000; + if (0 == MHD_get_timeout64s (d)) + tv.tv_usec = 0; + else + { + long curl_to = -1; + curl_multi_timeout (multi, &curl_to); + if (0 == curl_to) + tv.tv_usec = 0; + } +#ifdef MHD_POSIX_SOCKETS + if (maxMhdSk > maxCurlSk) + maxCurlSk = maxMhdSk; +#endif /* MHD_POSIX_SOCKETS */ + if (-1 == select (maxCurlSk + 1, &rs, &ws, &es, &tv)) { #ifdef MHD_POSIX_SOCKETS if (EINTR != errno) - { - fprintf (stderr, "Unexpected select() error: %d. Line: %d\n", - (int) errno, __LINE__); - fflush (stderr); - exit (99); - } + externalErrorExitDesc ("Unexpected select() error"); #else if ((WSAEINVAL != WSAGetLastError ()) || (0 != rs.fd_count) || (0 != ws.fd_count) || (0 != es.fd_count) ) - { - fprintf (stderr, "Unexpected select() error: %d. Line: %d\n", - (int) WSAGetLastError (), __LINE__); - fflush (stderr); - exit (99); - } - Sleep (1); + externalErrorExitDesc ("Unexpected select() error"); + Sleep ((unsigned long) tv.tv_usec / 1000); #endif } - curl_multi_perform (multi, &running); - if (0 == running) - { - int pending; - int curl_fine = 0; - while (NULL != (msg = curl_multi_info_read (multi, &pending))) - { - if (msg->msg == CURLMSG_DONE) - { - if (msg->data.result == CURLE_OK) - curl_fine = 1; - else - { - fprintf (stderr, - "%s failed at %s:%d: `%s'\n", - "curl_multi_perform", - __FILE__, - __LINE__, curl_easy_strerror (msg->data.result)); - abort (); - } - } - } - if (! curl_fine) - { - fprintf (stderr, "libcurl haven't returned OK code\n"); - abort (); - } - curl_multi_remove_handle (multi, c); - curl_multi_cleanup (multi); - curl_easy_cleanup (c); - c = NULL; - multi = NULL; - } - MHD_run (d); + if (MHD_YES != MHD_run_from_select (d, &rs, &ws, &es)) + mhdErrorExitDesc ("MHD_run_from_select() failed"); } - if (multi != NULL) + + return ret; +} + + +/** + * Check request result + * @param curl_code the CURL easy return code + * @param pcbc the pointer struct CBC + * @return non-zero if success, zero if failed + */ +static unsigned int +check_result (CURLcode curl_code, CURL *c, long expected_code, + struct CBC *pcbc) +{ + long code; + unsigned int ret; + + if (CURLE_OK != curl_code) { - curl_multi_remove_handle (multi, c); - curl_easy_cleanup (c); - curl_multi_cleanup (multi); + fflush (stdout); + if (0 != libcurl_errbuf[0]) + fprintf (stderr, "Request failed. " + "libcurl error: '%s'.\n" + "libcurl error description: '%s'.\n", + curl_easy_strerror (curl_code), + libcurl_errbuf); + else + fprintf (stderr, "Request failed. " + "libcurl error: '%s'.\n", + curl_easy_strerror (curl_code)); + fflush (stderr); + return 0; } + + if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code)) + libcurlErrorExit (); + + ret = 1; + if (expected_code != code) + { + fprintf (stderr, "The response has wrong HTTP code: %ld\tExpected: %ld.\n", + code, expected_code); + ret = 0; + } + else if (verbose) + printf ("The response has expected HTTP code: %ld\n", expected_code); + + if (pcbc->pos != MHD_STATICSTR_LEN_ (PAGE)) + { + fprintf (stderr, "Got %u bytes ('%.*s'), expected %u bytes. ", + (unsigned) pcbc->pos, (int) pcbc->pos, pcbc->buf, + (unsigned) MHD_STATICSTR_LEN_ (PAGE)); + mhdErrorExitDesc ("Wrong returned data length"); + } + if (0 != memcmp (PAGE, pcbc->buf, pcbc->pos)) + { + fprintf (stderr, "Got invalid response '%.*s'. ", + (int) pcbc->pos, pcbc->buf); + mhdErrorExitDesc ("Wrong returned data"); + } + fflush (stderr); + fflush (stdout); + + return ret; +} + + +static unsigned int +testExternalPolling (void) +{ + struct MHD_Daemon *d; + uint16_t port; + struct CBC cbc; + struct ahc_cls_type ahc_param; + char buf[2048]; + CURL *c; + CURLM *multi_reuse; + size_t i; + int failed = 0; + + if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) + port = 0; + else + port = 1340 + oneone ? 0 : 1 + use_non_strict ? 0 : 2; + + d = MHD_start_daemon (MHD_USE_ERROR_LOG, + port, NULL, NULL, + &ahcCheck, &ahc_param, + MHD_OPTION_STRICT_FOR_CLIENT, + (int) (use_non_strict ? 0 : 1), + MHD_OPTION_END); + if (d == NULL) + return 1; + if (0 == port) + { + const union MHD_DaemonInfo *dinfo; + + dinfo = MHD_get_daemon_info (d, + MHD_DAEMON_INFO_BIND_PORT); + if ( (NULL == dinfo) || + (0 == dinfo->port) ) + mhdErrorExitDesc ("MHD_get_daemon_info() failed"); + port = dinfo->port; + } + + ahc_param.rq_method = MHD_HTTP_METHOD_GET; + ahc_param.rq_url = EXPECTED_URI_BASE_PATH; + cbc.buf = buf; + cbc.size = sizeof (buf); + memset (cbc.buf, 0, cbc.size); + c = setupCURL (&cbc, port); + multi_reuse = NULL; + for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i) + { + cbc.pos = 0; + ahc_param.check = test_data + i; + if (CURLE_OK != + curl_easy_setopt (c, CURLOPT_COOKIE, + ahc_param.check->header_str)) + libcurlErrorExitDesc ("Cannot set request cookies"); + + if (check_result (performQueryExternal (d, c, &multi_reuse), c, + MHD_HTTP_OK, &cbc)) + { + if (verbose) + printf ("Got expected response for the check at line %u.\n", + test_data[i].line_num); + fflush (stdout); + } + else + { + fprintf (stderr, "FAILED request for the check at line %u.\n", + test_data[i].line_num); + fflush (stderr); + failed = 1; + } + } + + curl_easy_cleanup (c); + if (NULL != multi_reuse) + curl_multi_cleanup (multi_reuse); + MHD_stop_daemon (d); - if (cbc.pos != strlen ("/hello_world")) - return 8192; - if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) - return 16384; - return 0; + return failed ? 1 : 0; } @@ -509,35 +1193,22 @@ int main (int argc, char *const *argv) { unsigned int errorCount = 0; - (void) argc; /* Unused. Silent compiler warning. */ - if ((NULL == argv) || (0 == argv[0])) - return 99; - use_invalid = has_in_name (argv[0], "_invalid"); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return 2; - if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) - port = 0; - else - { - port = 1340; - if (use_invalid) - port += 5; - } - errorCount += testExternalGet (0); - errorCount += testExternalGet (1); - errorCount += testExternalGet (2); - errorCount += testExternalGet (3); - errorCount += testExternalGet (4); - errorCount += testExternalGet (5); - errorCount += testExternalGet (6); - errorCount += testExternalGet (7); - errorCount += testExternalGet (8); - errorCount += testExternalGet (9); - errorCount += testExternalGet (10); - errorCount += testExternalGet (11); + /* Test type and test parameters */ + verbose = ! (has_param (argc, argv, "-q") || + has_param (argc, argv, "--quiet") || + has_param (argc, argv, "-s") || + has_param (argc, argv, "--silent")); + oneone = ! has_in_name (argv[0], "10"); + use_non_strict = has_in_name (argv[0], "_nonstrict"); + + test_global_init (); + + errorCount += testExternalPolling (); if (errorCount != 0) fprintf (stderr, "Error (code: %u)\n", errorCount); - curl_global_cleanup (); + + test_global_cleanup (); + return (0 == errorCount) ? 0 : 1; /* 0 == pass */ }