pytest: add test for use of CURLMOPT_MAX_HOST_CONNECTIONS
Add test_02_33 to run with various values for the multi option CURLMOPT_MAX_HOST_CONNECTIONS and CURLOPT_FRESH_CONNECT to trigger connection pool limit handling code. Closes #15494
This commit is contained in:
parent
fcb59534e3
commit
55968fd14b
@ -229,7 +229,7 @@ static int my_progress_cb(void *userdata,
|
|||||||
|
|
||||||
static int setup(CURL *hnd, const char *url, struct transfer *t,
|
static int setup(CURL *hnd, const char *url, struct transfer *t,
|
||||||
int http_version, struct curl_slist *host,
|
int http_version, struct curl_slist *host,
|
||||||
CURLSH *share, int use_earlydata)
|
CURLSH *share, int use_earlydata, int fresh_connect)
|
||||||
{
|
{
|
||||||
curl_easy_setopt(hnd, CURLOPT_SHARE, share);
|
curl_easy_setopt(hnd, CURLOPT_SHARE, share);
|
||||||
curl_easy_setopt(hnd, CURLOPT_URL, url);
|
curl_easy_setopt(hnd, CURLOPT_URL, url);
|
||||||
@ -248,6 +248,8 @@ static int setup(CURL *hnd, const char *url, struct transfer *t,
|
|||||||
curl_easy_setopt(hnd, CURLOPT_FORBID_REUSE, 1L);
|
curl_easy_setopt(hnd, CURLOPT_FORBID_REUSE, 1L);
|
||||||
if(host)
|
if(host)
|
||||||
curl_easy_setopt(hnd, CURLOPT_RESOLVE, host);
|
curl_easy_setopt(hnd, CURLOPT_RESOLVE, host);
|
||||||
|
if(fresh_connect)
|
||||||
|
curl_easy_setopt(hnd, CURLOPT_FRESH_CONNECT, 1L);
|
||||||
|
|
||||||
/* please be verbose */
|
/* please be verbose */
|
||||||
if(verbose) {
|
if(verbose) {
|
||||||
@ -304,9 +306,11 @@ int main(int argc, char *argv[])
|
|||||||
int http_version = CURL_HTTP_VERSION_2_0;
|
int http_version = CURL_HTTP_VERSION_2_0;
|
||||||
int ch;
|
int ch;
|
||||||
struct curl_slist *host = NULL;
|
struct curl_slist *host = NULL;
|
||||||
const char *resolve = NULL;
|
char *resolve = NULL;
|
||||||
|
size_t max_host_conns = 0;
|
||||||
|
int fresh_connect = 0;
|
||||||
|
|
||||||
while((ch = getopt(argc, argv, "aefhm:n:A:F:P:r:V:")) != -1) {
|
while((ch = getopt(argc, argv, "aefhm:n:xA:F:M:P:r:V:")) != -1) {
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(NULL);
|
usage(NULL);
|
||||||
@ -326,17 +330,23 @@ int main(int argc, char *argv[])
|
|||||||
case 'n':
|
case 'n':
|
||||||
transfer_count = (size_t)strtol(optarg, NULL, 10);
|
transfer_count = (size_t)strtol(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
fresh_connect = 1;
|
||||||
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
abort_offset = (size_t)strtol(optarg, NULL, 10);
|
abort_offset = (size_t)strtol(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
fail_offset = (size_t)strtol(optarg, NULL, 10);
|
fail_offset = (size_t)strtol(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
max_host_conns = (size_t)strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
pause_offset = (size_t)strtol(optarg, NULL, 10);
|
pause_offset = (size_t)strtol(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
resolve = optarg;
|
resolve = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 'V': {
|
case 'V': {
|
||||||
if(!strcmp("http/1.1", optarg))
|
if(!strcmp("http/1.1", optarg))
|
||||||
@ -379,7 +389,7 @@ int main(int argc, char *argv[])
|
|||||||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
|
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
|
||||||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
|
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
|
||||||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
||||||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
|
/* curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); */
|
||||||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
|
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
|
||||||
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
|
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
|
||||||
|
|
||||||
@ -391,6 +401,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
multi_handle = curl_multi_init();
|
multi_handle = curl_multi_init();
|
||||||
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||||
|
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS,
|
||||||
|
(long)max_host_conns);
|
||||||
|
|
||||||
active_transfers = 0;
|
active_transfers = 0;
|
||||||
for(i = 0; i < transfer_count; ++i) {
|
for(i = 0; i < transfer_count; ++i) {
|
||||||
@ -406,7 +418,8 @@ int main(int argc, char *argv[])
|
|||||||
t = &transfers[i];
|
t = &transfers[i];
|
||||||
t->easy = curl_easy_init();
|
t->easy = curl_easy_init();
|
||||||
if(!t->easy ||
|
if(!t->easy ||
|
||||||
setup(t->easy, url, t, http_version, host, share, use_earlydata)) {
|
setup(t->easy, url, t, http_version, host, share, use_earlydata,
|
||||||
|
fresh_connect)) {
|
||||||
fprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
|
fprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -486,7 +499,7 @@ int main(int argc, char *argv[])
|
|||||||
t->easy = curl_easy_init();
|
t->easy = curl_easy_init();
|
||||||
if(!t->easy ||
|
if(!t->easy ||
|
||||||
setup(t->easy, url, t, http_version, host, share,
|
setup(t->easy, url, t, http_version, host, share,
|
||||||
use_earlydata)) {
|
use_earlydata, fresh_connect)) {
|
||||||
fprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
|
fprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -521,6 +534,8 @@ int main(int argc, char *argv[])
|
|||||||
free(transfers);
|
free(transfers);
|
||||||
|
|
||||||
curl_share_cleanup(share);
|
curl_share_cleanup(share);
|
||||||
|
curl_slist_free_all(host);
|
||||||
|
free(resolve);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -633,3 +633,28 @@ class TestDownload:
|
|||||||
elif proto == 'h3':
|
elif proto == 'h3':
|
||||||
# not implemented
|
# not implemented
|
||||||
assert earlydata[1] == 0, f'{earlydata}'
|
assert earlydata[1] == 0, f'{earlydata}'
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
|
||||||
|
@pytest.mark.parametrize("max_host_conns", [0, 1, 5])
|
||||||
|
def test_02_33_max_host_conns(self, env: Env, httpd, nghttpx, proto, max_host_conns):
|
||||||
|
if proto == 'h3' and not env.have_h3():
|
||||||
|
pytest.skip("h3 not supported")
|
||||||
|
count = 100
|
||||||
|
max_parallel = 100
|
||||||
|
docname = 'data-10k'
|
||||||
|
port = env.port_for(proto)
|
||||||
|
url = f'https://{env.domain1}:{port}/{docname}'
|
||||||
|
client = LocalClient(name='hx-download', env=env)
|
||||||
|
if not client.exists():
|
||||||
|
pytest.skip(f'example client not built: {client.name}')
|
||||||
|
r = client.run(args=[
|
||||||
|
'-n', f'{count}',
|
||||||
|
'-m', f'{max_parallel}',
|
||||||
|
'-x', # always use a fresh connection
|
||||||
|
'-M', str(max_host_conns), # limit conns per host
|
||||||
|
'-r', f'{env.domain1}:{port}:127.0.0.1',
|
||||||
|
'-V', proto, url
|
||||||
|
])
|
||||||
|
r.check_exit_code(0)
|
||||||
|
srcfile = os.path.join(httpd.docs_dir, docname)
|
||||||
|
self.check_downloads(client, srcfile, count)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user