aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2020-10-25 00:43:23 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2020-10-25 17:19:01 +0300
commitfa330be735a39d30f4e025c3afdba192e6c2b1bb (patch)
tree9981832d8c225465b8b75dfc0453e8f8bb0bf7be /src/testcurl
parent19b038f68272a423ae74c89427c8b5dcfc7ce1ae (diff)
downloadlibmicrohttpd-fa330be735a39d30f4e025c3afdba192e6c2b1bb.tar.gz
libmicrohttpd-fa330be735a39d30f4e025c3afdba192e6c2b1bb.zip
Added tests for cleanup of unprocessed externally added connections
Diffstat (limited to 'src/testcurl')
-rw-r--r--src/testcurl/.gitignore2
-rw-r--r--src/testcurl/Makefile.am22
-rw-r--r--src/testcurl/test_add_conn.c211
3 files changed, 190 insertions, 45 deletions
diff --git a/src/testcurl/.gitignore b/src/testcurl/.gitignore
index 4c1c7f03..0ca3ac3c 100644
--- a/src/testcurl/.gitignore
+++ b/src/testcurl/.gitignore
@@ -113,4 +113,6 @@ test_patch
113test_patch11 113test_patch11
114/test_add_conn 114/test_add_conn
115/test_add_conn_nolisten 115/test_add_conn_nolisten
116/test_add_conn_cleanup
117/test_add_conn_cleanup_nolisten
116core 118core
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index f45f13d3..6587c79a 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -23,6 +23,8 @@ THREAD_ONLY_TESTS = \
23 test_long_header11 \ 23 test_long_header11 \
24 test_iplimit11 \ 24 test_iplimit11 \
25 test_termination \ 25 test_termination \
26 test_add_conn_cleanup \
27 test_add_conn_cleanup_nolisten \
26 test_timeout 28 test_timeout
27 29
28if HAVE_POSIX_THREADS 30if HAVE_POSIX_THREADS
@@ -276,16 +278,36 @@ test_put_chunked_LDADD = \
276 278
277test_add_conn_SOURCES = \ 279test_add_conn_SOURCES = \
278 test_add_conn.c $(top_srcdir)/src/microhttpd/test_helpers.h 280 test_add_conn.c $(top_srcdir)/src/microhttpd/test_helpers.h
281test_add_conn_CFLAGS = \
282 $(PTHREAD_CFLAGS) $(AM_CFLAGS)
279test_add_conn_LDADD = \ 283test_add_conn_LDADD = \
280 $(top_builddir)/src/microhttpd/libmicrohttpd.la \ 284 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
281 @LIBCURL@ 285 @LIBCURL@
282 286
283test_add_conn_nolisten_SOURCES = \ 287test_add_conn_nolisten_SOURCES = \
284 test_add_conn.c $(top_srcdir)/src/microhttpd/test_helpers.h 288 test_add_conn.c $(top_srcdir)/src/microhttpd/test_helpers.h
289test_add_conn_nolisten_CFLAGS = \
290 $(PTHREAD_CFLAGS) $(AM_CFLAGS)
285test_add_conn_nolisten_LDADD = \ 291test_add_conn_nolisten_LDADD = \
286 $(top_builddir)/src/microhttpd/libmicrohttpd.la \ 292 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
287 @LIBCURL@ 293 @LIBCURL@
288 294
295test_add_conn_cleanup_SOURCES = \
296 test_add_conn.c $(top_srcdir)/src/microhttpd/test_helpers.h
297test_add_conn_cleanup_CFLAGS = \
298 $(PTHREAD_CFLAGS) $(AM_CFLAGS)
299test_add_conn_cleanup_LDADD = \
300 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
301 @LIBCURL@
302
303test_add_conn_cleanup_nolisten_SOURCES = \
304 test_add_conn.c $(top_srcdir)/src/microhttpd/test_helpers.h
305test_add_conn_cleanup_nolisten_CFLAGS = \
306 $(PTHREAD_CFLAGS) $(AM_CFLAGS)
307test_add_conn_cleanup_nolisten_LDADD = \
308 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
309 @LIBCURL@
310
289test_get11_SOURCES = \ 311test_get11_SOURCES = \
290 test_get.c 312 test_get.c
291test_get11_LDADD = \ 313test_get11_LDADD = \
diff --git a/src/testcurl/test_add_conn.c b/src/testcurl/test_add_conn.c
index 52aa2831..c7e49b91 100644
--- a/src/testcurl/test_add_conn.c
+++ b/src/testcurl/test_add_conn.c
@@ -57,6 +57,11 @@
57#if ! defined(CPU_COUNT) 57#if ! defined(CPU_COUNT)
58#define CPU_COUNT 2 58#define CPU_COUNT 2
59#endif 59#endif
60#if CPU_COUNT > 32
61#undef CPU_COUNT
62/* Limit to reasonable value */
63#define CPU_COUNT 32
64#endif /* CPU_COUNT > 32 */
60 65
61/* Could be increased to facilitate debugging */ 66/* Could be increased to facilitate debugging */
62#define TIMEOUTS_VAL 5 67#define TIMEOUTS_VAL 5
@@ -65,9 +70,16 @@
65#define EXPECTED_URI_QUERY "a=%26&b=c" 70#define EXPECTED_URI_QUERY "a=%26&b=c"
66#define EXPECTED_URI_FULL_PATH EXPECTED_URI_BASE_PATH "?" EXPECTED_URI_QUERY 71#define EXPECTED_URI_FULL_PATH EXPECTED_URI_BASE_PATH "?" EXPECTED_URI_QUERY
67 72
68static int oneone; 73/* Global parameters */
69static int no_listen; 74static int oneone; /**< Use HTTP/1.1 instead of HTTP/1.0 */
70static int global_port; 75static int no_listen; /**< Start MHD daemons without listen socket */
76static int global_port; /**< MHD deamons listen port number */
77static int cleanup_test; /**< Test for final cleanup */
78static int slow_reply = 0; /**< Slowdown MHD replies */
79static int ignore_response_errors = 0; /**< Do not fail test if CURL
80 returns error */
81static int response_timeout_val = TIMEOUTS_VAL;
82
71 83
72struct CBC 84struct CBC
73{ 85{
@@ -165,6 +177,9 @@ ahc_echo (void *cls,
165 NULL == v ? "NULL" : v); 177 NULL == v ? "NULL" : v);
166 _exit (19); 178 _exit (19);
167 } 179 }
180 if (slow_reply)
181 usleep (200000);
182
168 response = MHD_create_response_from_buffer (strlen (url), 183 response = MHD_create_response_from_buffer (strlen (url),
169 (void *) url, 184 (void *) url,
170 MHD_RESPMEM_MUST_COPY); 185 MHD_RESPMEM_MUST_COPY);
@@ -401,8 +416,8 @@ curlEasyInitForTest (const char *queryPath, int port, struct CBC *pcbc)
401 curl_easy_setopt (c, CURLOPT_PORT, (long) port); 416 curl_easy_setopt (c, CURLOPT_PORT, (long) port);
402 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer); 417 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
403 curl_easy_setopt (c, CURLOPT_WRITEDATA, pcbc); 418 curl_easy_setopt (c, CURLOPT_WRITEDATA, pcbc);
404 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, (long) TIMEOUTS_VAL); 419 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, (long) response_timeout_val);
405 curl_easy_setopt (c, CURLOPT_TIMEOUT, (long) TIMEOUTS_VAL); 420 curl_easy_setopt (c, CURLOPT_TIMEOUT, (long) response_timeout_val);
406 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 421 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
407 if (oneone) 422 if (oneone)
408 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 423 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
@@ -434,6 +449,11 @@ doCurlQueryInThread (struct curlQueryParams *p)
434 c = curlEasyInitForTest (p->queryPath, p->queryPort, &cbc); 449 c = curlEasyInitForTest (p->queryPath, p->queryPort, &cbc);
435 450
436 errornum = curl_easy_perform (c); 451 errornum = curl_easy_perform (c);
452 if (ignore_response_errors)
453 {
454 p->queryError = 0;
455 return p->queryError;
456 }
437 if (CURLE_OK != errornum) 457 if (CURLE_OK != errornum)
438 { 458 {
439 fprintf (stderr, 459 fprintf (stderr,
@@ -511,11 +531,11 @@ performTestQueries (struct MHD_Daemon *d, int d_port)
511{ 531{
512 struct curlQueryParams qParam; 532 struct curlQueryParams qParam;
513 struct addConnParam aParam; 533 struct addConnParam aParam;
514 int a_port = 0; /* Additional listening socket port */ 534 int a_port; /* Additional listening socket port */
515 int ret = 0; /* Return value */ 535 int ret = 0; /* Return value */
516 536
517 qParam.queryPath = "http://127.0.0.1" EXPECTED_URI_FULL_PATH; 537 qParam.queryPath = "http://127.0.0.1" EXPECTED_URI_FULL_PATH;
518 qParam.queryPort = 0; /* autoassign */ 538 a_port = 0; /* auto-assign */
519 539
520 aParam.d = d; 540 aParam.d = d;
521 aParam.lstn_sk = createListeningSocket (&a_port); /* Sets a_port */ 541 aParam.lstn_sk = createListeningSocket (&a_port); /* Sets a_port */
@@ -550,6 +570,59 @@ performTestQueries (struct MHD_Daemon *d, int d_port)
550} 570}
551 571
552 572
573/* Perform test for cleanup and shutdown MHD daemon */
574static int
575performTestCleanup (struct MHD_Daemon *d, int num_queries)
576{
577 struct curlQueryParams *qParamList;
578 struct addConnParam aParam;
579 MHD_socket lstn_sk; /* Additional listening socket */
580 int a_port; /* Additional listening socket port */
581 int i;
582 int ret = 0; /* Return value */
583
584 a_port = 0; /* auto-assign */
585
586 if (0 >= num_queries)
587 abort (); /* Test's API violation */
588
589 lstn_sk = createListeningSocket (&a_port); /* Sets a_port */
590
591 qParamList = malloc (sizeof(struct curlQueryParams) * num_queries);
592 if (NULL == qParamList)
593 externalErrorExitDesc ("malloc failed");
594
595 /* Start CURL queries */
596 for (i = 0; i < num_queries; i++)
597 {
598 qParamList[i].queryPath = "http://127.0.0.1" EXPECTED_URI_FULL_PATH;
599 qParamList[i].queryError = 0;
600 qParamList[i].queryPort = a_port;
601
602 startThreadCurlQuery (qParamList + i);
603 }
604
605 /* Accept and add required number of client sockets */
606 aParam.d = d;
607 aParam.lstn_sk = lstn_sk;
608 for (i = 0; i < num_queries; i++)
609 ret |= doAcceptAndAddConnInThread (&aParam);
610
611 /* Stop daemon while some of new connection are not yet
612 * processed because of slow response to the first queries. */
613 MHD_stop_daemon (d);
614 (void) MHD_socket_close_ (aParam.lstn_sk);
615
616 /* Wait for CURL threads to complete. */
617 /* Ignore soft CURL errors as many connection shouldn't get any response.
618 * Hard failures are detected in processing function. */
619 for (i = 0; i < num_queries; i++)
620 (void) finishThreadCurlQuery (qParamList + i);
621
622 return ret;
623}
624
625
553#endif /* HAVE_PTHREAD_H */ 626#endif /* HAVE_PTHREAD_H */
554 627
555enum testMhdThreadsType 628enum testMhdThreadsType
@@ -578,7 +651,15 @@ startTestMhdDaemon (enum testMhdThreadsType thrType,
578 651
579 if ( (0 == *pport) && 652 if ( (0 == *pport) &&
580 (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) 653 (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) )
581 *pport = oneone ? 1550 : 1570; 654 {
655 *pport = 1550;
656 if (oneone)
657 *pport += 1;
658 if (no_listen)
659 *pport += 2;
660 if (cleanup_test)
661 *pport += 4;
662 }
582 663
583 if (testMhdThreadInternalPool != thrType) 664 if (testMhdThreadInternalPool != thrType)
584 d = MHD_start_daemon (((int) thrType) | ((int) pollType) 665 d = MHD_start_daemon (((int) thrType) | ((int) pollType)
@@ -656,6 +737,10 @@ testExternalGet (void)
656 cbc_a.size = sizeof(buf_a); 737 cbc_a.size = sizeof(buf_a);
657 cbc_a.pos = 0; 738 cbc_a.pos = 0;
658 739
740 if (cleanup_test)
741 abort (); /* Not possible with "external poll" as connections are directly
742 added to the daemon processing in the mode. */
743
659 if (! no_listen) 744 if (! no_listen)
660 c_d = curlEasyInitForTest ("http://127.0.0.1" EXPECTED_URI_FULL_PATH, 745 c_d = curlEasyInitForTest ("http://127.0.0.1" EXPECTED_URI_FULL_PATH,
661 d_port, &cbc_d); 746 d_port, &cbc_d);
@@ -828,6 +913,8 @@ testInternalGet (enum testMhdPollType pollType)
828 913
829 d = startTestMhdDaemon (testMhdThreadInternal, pollType, 914 d = startTestMhdDaemon (testMhdThreadInternal, pollType,
830 &d_port); 915 &d_port);
916 if (cleanup_test)
917 return performTestCleanup (d, 10);
831 918
832 return performTestQueries (d, d_port); 919 return performTestQueries (d, d_port);
833} 920}
@@ -841,6 +928,10 @@ testMultithreadedGet (enum testMhdPollType pollType)
841 928
842 d = startTestMhdDaemon (testMhdThreadInternalPerConnection, pollType, 929 d = startTestMhdDaemon (testMhdThreadInternalPerConnection, pollType,
843 &d_port); 930 &d_port);
931 if (cleanup_test)
932 abort (); /* Cannot be tested as main daemon thread cannot be slowed down
933 by slow responses, so it processes all new connections before
934 daemon could be stopped. */
844 935
845 return performTestQueries (d, d_port); 936 return performTestQueries (d, d_port);
846} 937}
@@ -855,6 +946,9 @@ testMultithreadedPoolGet (enum testMhdPollType pollType)
855 d = startTestMhdDaemon (testMhdThreadInternalPool, pollType, 946 d = startTestMhdDaemon (testMhdThreadInternalPool, pollType,
856 &d_port); 947 &d_port);
857 948
949 if (cleanup_test)
950 return performTestCleanup (d, 10 * CPU_COUNT);
951
858 return performTestQueries (d, d_port); 952 return performTestQueries (d, d_port);
859} 953}
860 954
@@ -930,19 +1024,40 @@ main (int argc, char *const *argv)
930 if ((NULL == argv) || (0 == argv[0])) 1024 if ((NULL == argv) || (0 == argv[0]))
931 return 99; 1025 return 99;
932 oneone = has_in_name (argv[0], "11"); 1026 oneone = has_in_name (argv[0], "11");
1027 /* Whether to test MHD daemons without listening socket. */
933 no_listen = has_in_name (argv[0], "_nolisten"); 1028 no_listen = has_in_name (argv[0], "_nolisten");
1029 /* Whether to test for correct final cleanup instead of
1030 * of test of normal processing. */
1031 cleanup_test = has_in_name (argv[0], "_cleanup");
1032 /* There are almost nothing that could be tested externally
1033 * for final cleanup. Cleanup test actually just tests that
1034 * nothing fails or crashes when final cleanup is performed.
1035 * Mostly useful when configured with '--enable-asserts. */
1036 slow_reply = cleanup_test;
1037 ignore_response_errors = cleanup_test;
1038 if (cleanup_test)
1039 response_timeout_val /= 5;
1040 if (0 == response_timeout_val)
1041 response_timeout_val = 1;
1042#ifndef HAVE_PTHREAD_H
1043 if (cleanup_test)
1044 return 77; /* Cannot run without threads */
1045#endif /* HAVE_PTHREAD_H */
934 verbose = ! has_param (argc, argv, "-q") || has_param (argc, argv, "--quiet"); 1046 verbose = ! has_param (argc, argv, "-q") || has_param (argc, argv, "--quiet");
935 if (0 != curl_global_init (CURL_GLOBAL_WIN32)) 1047 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
936 return 2; 1048 return 2;
937 /* Could be set to non-zero value to enforce using specific port 1049 /* Could be set to non-zero value to enforce using specific port
938 * in the test */ 1050 * in the test */
939 global_port = 0; 1051 global_port = 0;
940 test_result = testExternalGet (); 1052 if (! cleanup_test)
941 if (test_result) 1053 {
942 fprintf (stderr, "FAILED: testExternalGet () - %u.\n", test_result); 1054 test_result = testExternalGet ();
943 else if (verbose) 1055 if (test_result)
944 printf ("PASSED: testExternalGet ().\n"); 1056 fprintf (stderr, "FAILED: testExternalGet () - %u.\n", test_result);
945 errorCount += test_result; 1057 else if (verbose)
1058 printf ("PASSED: testExternalGet ().\n");
1059 errorCount += test_result;
1060 }
946#ifdef HAVE_PTHREAD_H 1061#ifdef HAVE_PTHREAD_H
947 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS)) 1062 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
948 { 1063 {
@@ -953,14 +1068,6 @@ main (int argc, char *const *argv)
953 else if (verbose) 1068 else if (verbose)
954 printf ("PASSED: testInternalGet (testMhdPollBySelect).\n"); 1069 printf ("PASSED: testInternalGet (testMhdPollBySelect).\n");
955 errorCount += test_result; 1070 errorCount += test_result;
956 test_result = testMultithreadedGet (testMhdPollBySelect);
957 if (test_result)
958 fprintf (stderr,
959 "FAILED: testMultithreadedGet (testMhdPollBySelect) - %u.\n",
960 test_result);
961 else if (verbose)
962 printf ("PASSED: testMultithreadedGet (testMhdPollBySelect).\n");
963 errorCount += test_result;
964 test_result = testMultithreadedPoolGet (testMhdPollBySelect); 1071 test_result = testMultithreadedPoolGet (testMhdPollBySelect);
965 if (test_result) 1072 if (test_result)
966 fprintf (stderr, 1073 fprintf (stderr,
@@ -969,45 +1076,59 @@ main (int argc, char *const *argv)
969 else if (verbose) 1076 else if (verbose)
970 printf ("PASSED: testMultithreadedPoolGet (testMhdPollBySelect).\n"); 1077 printf ("PASSED: testMultithreadedPoolGet (testMhdPollBySelect).\n");
971 errorCount += test_result; 1078 errorCount += test_result;
972 test_result = testStopRace (testMhdPollBySelect); 1079 if (! cleanup_test)
973 if (test_result)
974 fprintf (stderr, "FAILED: testStopRace (testMhdPollBySelect) - %u.\n",
975 test_result);
976 else if (verbose)
977 printf ("PASSED: testStopRace (testMhdPollBySelect).\n");
978 errorCount += test_result;
979 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_POLL))
980 { 1080 {
981 test_result = testInternalGet (testMhdPollByPoll); 1081 test_result = testMultithreadedGet (testMhdPollBySelect);
982 if (test_result) 1082 if (test_result)
983 fprintf (stderr, "FAILED: testInternalGet (testMhdPollByPoll) - %u.\n", 1083 fprintf (stderr,
1084 "FAILED: testMultithreadedGet (testMhdPollBySelect) - %u.\n",
984 test_result); 1085 test_result);
985 else if (verbose) 1086 else if (verbose)
986 printf ("PASSED: testInternalGet (testMhdPollByPoll).\n"); 1087 printf ("PASSED: testMultithreadedGet (testMhdPollBySelect).\n");
987 errorCount += test_result; 1088 errorCount += test_result;
988 test_result = testMultithreadedGet (testMhdPollByPoll); 1089 test_result = testStopRace (testMhdPollBySelect);
989 if (test_result) 1090 if (test_result)
990 fprintf (stderr, 1091 fprintf (stderr, "FAILED: testStopRace (testMhdPollBySelect) - %u.\n",
991 "FAILED: testMultithreadedGet (testMhdPollByPoll) - %u.\n",
992 test_result); 1092 test_result);
993 else if (verbose) 1093 else if (verbose)
994 printf ("PASSED: testMultithreadedGet (testMhdPollByPoll).\n"); 1094 printf ("PASSED: testStopRace (testMhdPollBySelect).\n");
995 errorCount += test_result; 1095 errorCount += test_result;
996 test_result = testMultithreadedPoolGet (testMhdPollByPoll); 1096 }
1097 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_POLL))
1098 {
1099 test_result = testInternalGet (testMhdPollByPoll);
997 if (test_result) 1100 if (test_result)
998 fprintf (stderr, 1101 fprintf (stderr, "FAILED: testInternalGet (testMhdPollByPoll) - %u.\n",
999 "FAILED: testMultithreadedPoolGet (testMhdPollByPoll) - %u.\n",
1000 test_result); 1102 test_result);
1001 else if (verbose) 1103 else if (verbose)
1002 printf ("PASSED: testMultithreadedPoolGet (testMhdPollByPoll).\n"); 1104 printf ("PASSED: testInternalGet (testMhdPollByPoll).\n");
1003 errorCount += test_result; 1105 errorCount += test_result;
1004 test_result = testStopRace (testMhdPollByPoll); 1106 test_result = testMultithreadedPoolGet (testMhdPollByPoll);
1005 if (test_result) 1107 if (test_result)
1006 fprintf (stderr, "FAILED: testStopRace (testMhdPollByPoll) - %u.\n", 1108 fprintf (stderr,
1109 "FAILED: testMultithreadedPoolGet (testMhdPollByPoll) - %u.\n",
1007 test_result); 1110 test_result);
1008 else if (verbose) 1111 else if (verbose)
1009 printf ("PASSED: testStopRace (testMhdPollByPoll).\n"); 1112 printf ("PASSED: testMultithreadedPoolGet (testMhdPollByPoll).\n");
1010 errorCount += test_result; 1113 errorCount += test_result;
1114 if (! cleanup_test)
1115 {
1116 test_result = testMultithreadedGet (testMhdPollByPoll);
1117 if (test_result)
1118 fprintf (stderr,
1119 "FAILED: testMultithreadedGet (testMhdPollByPoll) - %u.\n",
1120 test_result);
1121 else if (verbose)
1122 printf ("PASSED: testMultithreadedGet (testMhdPollByPoll).\n");
1123 errorCount += test_result;
1124 test_result = testStopRace (testMhdPollByPoll);
1125 if (test_result)
1126 fprintf (stderr, "FAILED: testStopRace (testMhdPollByPoll) - %u.\n",
1127 test_result);
1128 else if (verbose)
1129 printf ("PASSED: testStopRace (testMhdPollByPoll).\n");
1130 errorCount += test_result;
1131 }
1011 } 1132 }
1012 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_EPOLL)) 1133 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_EPOLL))
1013 { 1134 {