113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "curlcheck.h" 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 2713498266Sopenharmony_ci#include <netinet/in.h> 2813498266Sopenharmony_ci#endif 2913498266Sopenharmony_ci#ifdef HAVE_NETINET_IN6_H 3013498266Sopenharmony_ci#include <netinet/in6.h> 3113498266Sopenharmony_ci#endif 3213498266Sopenharmony_ci#ifdef HAVE_NETDB_H 3313498266Sopenharmony_ci#include <netdb.h> 3413498266Sopenharmony_ci#endif 3513498266Sopenharmony_ci#ifdef HAVE_ARPA_INET_H 3613498266Sopenharmony_ci#include <arpa/inet.h> 3713498266Sopenharmony_ci#endif 3813498266Sopenharmony_ci#ifdef __VMS 3913498266Sopenharmony_ci#include <in.h> 4013498266Sopenharmony_ci#include <inet.h> 4113498266Sopenharmony_ci#endif 4213498266Sopenharmony_ci 4313498266Sopenharmony_ci#include <setjmp.h> 4413498266Sopenharmony_ci#include <signal.h> 4513498266Sopenharmony_ci 4613498266Sopenharmony_ci#include "urldata.h" 4713498266Sopenharmony_ci#include "connect.h" 4813498266Sopenharmony_ci#include "cfilters.h" 4913498266Sopenharmony_ci#include "multiif.h" 5013498266Sopenharmony_ci#include "curl_trc.h" 5113498266Sopenharmony_ci 5213498266Sopenharmony_ci 5313498266Sopenharmony_cistatic CURL *easy; 5413498266Sopenharmony_ci 5513498266Sopenharmony_cistatic CURLcode unit_setup(void) 5613498266Sopenharmony_ci{ 5713498266Sopenharmony_ci CURLcode res = CURLE_OK; 5813498266Sopenharmony_ci 5913498266Sopenharmony_ci global_init(CURL_GLOBAL_ALL); 6013498266Sopenharmony_ci easy = curl_easy_init(); 6113498266Sopenharmony_ci if(!easy) { 6213498266Sopenharmony_ci curl_global_cleanup(); 6313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 6413498266Sopenharmony_ci } 6513498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L); 6613498266Sopenharmony_ci return res; 6713498266Sopenharmony_ci} 6813498266Sopenharmony_ci 6913498266Sopenharmony_cistatic void unit_stop(void) 7013498266Sopenharmony_ci{ 7113498266Sopenharmony_ci curl_easy_cleanup(easy); 7213498266Sopenharmony_ci curl_global_cleanup(); 7313498266Sopenharmony_ci} 7413498266Sopenharmony_ci 7513498266Sopenharmony_ci#ifdef DEBUGBUILD 7613498266Sopenharmony_ci 7713498266Sopenharmony_cistruct test_case { 7813498266Sopenharmony_ci int id; 7913498266Sopenharmony_ci const char *url; 8013498266Sopenharmony_ci const char *resolve_info; 8113498266Sopenharmony_ci unsigned char ip_version; 8213498266Sopenharmony_ci timediff_t connect_timeout_ms; 8313498266Sopenharmony_ci timediff_t he_timeout_ms; 8413498266Sopenharmony_ci timediff_t cf4_fail_delay_ms; 8513498266Sopenharmony_ci timediff_t cf6_fail_delay_ms; 8613498266Sopenharmony_ci 8713498266Sopenharmony_ci int exp_cf4_creations; 8813498266Sopenharmony_ci int exp_cf6_creations; 8913498266Sopenharmony_ci timediff_t min_duration_ms; 9013498266Sopenharmony_ci timediff_t max_duration_ms; 9113498266Sopenharmony_ci CURLcode exp_result; 9213498266Sopenharmony_ci const char *pref_family; 9313498266Sopenharmony_ci}; 9413498266Sopenharmony_ci 9513498266Sopenharmony_cistruct ai_family_stats { 9613498266Sopenharmony_ci const char *family; 9713498266Sopenharmony_ci int creations; 9813498266Sopenharmony_ci timediff_t first_created; 9913498266Sopenharmony_ci timediff_t last_created; 10013498266Sopenharmony_ci}; 10113498266Sopenharmony_ci 10213498266Sopenharmony_cistruct test_result { 10313498266Sopenharmony_ci CURLcode result; 10413498266Sopenharmony_ci struct curltime started; 10513498266Sopenharmony_ci struct curltime ended; 10613498266Sopenharmony_ci struct ai_family_stats cf4; 10713498266Sopenharmony_ci struct ai_family_stats cf6; 10813498266Sopenharmony_ci}; 10913498266Sopenharmony_ci 11013498266Sopenharmony_cistatic struct test_case *current_tc; 11113498266Sopenharmony_cistatic struct test_result *current_tr; 11213498266Sopenharmony_ci 11313498266Sopenharmony_cistruct cf_test_ctx { 11413498266Sopenharmony_ci int ai_family; 11513498266Sopenharmony_ci int transport; 11613498266Sopenharmony_ci char id[16]; 11713498266Sopenharmony_ci struct curltime started; 11813498266Sopenharmony_ci timediff_t fail_delay_ms; 11913498266Sopenharmony_ci struct ai_family_stats *stats; 12013498266Sopenharmony_ci}; 12113498266Sopenharmony_ci 12213498266Sopenharmony_cistatic void cf_test_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) 12313498266Sopenharmony_ci{ 12413498266Sopenharmony_ci struct cf_test_ctx *ctx = cf->ctx; 12513498266Sopenharmony_ci#ifndef CURL_DISABLE_VERBOSE_STRINGS 12613498266Sopenharmony_ci infof(data, "%04dms: cf[%s] destroyed", 12713498266Sopenharmony_ci (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id); 12813498266Sopenharmony_ci#else 12913498266Sopenharmony_ci (void)data; 13013498266Sopenharmony_ci#endif 13113498266Sopenharmony_ci free(ctx); 13213498266Sopenharmony_ci cf->ctx = NULL; 13313498266Sopenharmony_ci} 13413498266Sopenharmony_ci 13513498266Sopenharmony_cistatic CURLcode cf_test_connect(struct Curl_cfilter *cf, 13613498266Sopenharmony_ci struct Curl_easy *data, 13713498266Sopenharmony_ci bool blocking, bool *done) 13813498266Sopenharmony_ci{ 13913498266Sopenharmony_ci struct cf_test_ctx *ctx = cf->ctx; 14013498266Sopenharmony_ci timediff_t duration_ms; 14113498266Sopenharmony_ci 14213498266Sopenharmony_ci (void)data; 14313498266Sopenharmony_ci (void)blocking; 14413498266Sopenharmony_ci *done = FALSE; 14513498266Sopenharmony_ci duration_ms = Curl_timediff(Curl_now(), ctx->started); 14613498266Sopenharmony_ci if(duration_ms >= ctx->fail_delay_ms) { 14713498266Sopenharmony_ci infof(data, "%04dms: cf[%s] fail delay reached", 14813498266Sopenharmony_ci (int)duration_ms, ctx->id); 14913498266Sopenharmony_ci return CURLE_COULDNT_CONNECT; 15013498266Sopenharmony_ci } 15113498266Sopenharmony_ci if(duration_ms) 15213498266Sopenharmony_ci infof(data, "%04dms: cf[%s] continuing", (int)duration_ms, ctx->id); 15313498266Sopenharmony_ci Curl_expire(data, ctx->fail_delay_ms - duration_ms, EXPIRE_RUN_NOW); 15413498266Sopenharmony_ci return CURLE_OK; 15513498266Sopenharmony_ci} 15613498266Sopenharmony_ci 15713498266Sopenharmony_cistatic struct Curl_cftype cft_test = { 15813498266Sopenharmony_ci "TEST", 15913498266Sopenharmony_ci CF_TYPE_IP_CONNECT, 16013498266Sopenharmony_ci CURL_LOG_LVL_NONE, 16113498266Sopenharmony_ci cf_test_destroy, 16213498266Sopenharmony_ci cf_test_connect, 16313498266Sopenharmony_ci Curl_cf_def_close, 16413498266Sopenharmony_ci Curl_cf_def_get_host, 16513498266Sopenharmony_ci Curl_cf_def_adjust_pollset, 16613498266Sopenharmony_ci Curl_cf_def_data_pending, 16713498266Sopenharmony_ci Curl_cf_def_send, 16813498266Sopenharmony_ci Curl_cf_def_recv, 16913498266Sopenharmony_ci Curl_cf_def_cntrl, 17013498266Sopenharmony_ci Curl_cf_def_conn_is_alive, 17113498266Sopenharmony_ci Curl_cf_def_conn_keep_alive, 17213498266Sopenharmony_ci Curl_cf_def_query, 17313498266Sopenharmony_ci}; 17413498266Sopenharmony_ci 17513498266Sopenharmony_cistatic CURLcode cf_test_create(struct Curl_cfilter **pcf, 17613498266Sopenharmony_ci struct Curl_easy *data, 17713498266Sopenharmony_ci struct connectdata *conn, 17813498266Sopenharmony_ci const struct Curl_addrinfo *ai, 17913498266Sopenharmony_ci int transport) 18013498266Sopenharmony_ci{ 18113498266Sopenharmony_ci struct cf_test_ctx *ctx = NULL; 18213498266Sopenharmony_ci struct Curl_cfilter *cf = NULL; 18313498266Sopenharmony_ci timediff_t created_at; 18413498266Sopenharmony_ci CURLcode result; 18513498266Sopenharmony_ci 18613498266Sopenharmony_ci (void)data; 18713498266Sopenharmony_ci (void)conn; 18813498266Sopenharmony_ci ctx = calloc(1, sizeof(*ctx)); 18913498266Sopenharmony_ci if(!ctx) { 19013498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 19113498266Sopenharmony_ci goto out; 19213498266Sopenharmony_ci } 19313498266Sopenharmony_ci ctx->ai_family = ai->ai_family; 19413498266Sopenharmony_ci ctx->transport = transport; 19513498266Sopenharmony_ci ctx->started = Curl_now(); 19613498266Sopenharmony_ci#ifdef ENABLE_IPV6 19713498266Sopenharmony_ci if(ctx->ai_family == AF_INET6) { 19813498266Sopenharmony_ci ctx->stats = ¤t_tr->cf6; 19913498266Sopenharmony_ci ctx->fail_delay_ms = current_tc->cf6_fail_delay_ms; 20013498266Sopenharmony_ci curl_msprintf(ctx->id, "v6-%d", ctx->stats->creations); 20113498266Sopenharmony_ci ctx->stats->creations++; 20213498266Sopenharmony_ci } 20313498266Sopenharmony_ci else 20413498266Sopenharmony_ci#endif 20513498266Sopenharmony_ci { 20613498266Sopenharmony_ci ctx->stats = ¤t_tr->cf4; 20713498266Sopenharmony_ci ctx->fail_delay_ms = current_tc->cf4_fail_delay_ms; 20813498266Sopenharmony_ci curl_msprintf(ctx->id, "v4-%d", ctx->stats->creations); 20913498266Sopenharmony_ci ctx->stats->creations++; 21013498266Sopenharmony_ci } 21113498266Sopenharmony_ci 21213498266Sopenharmony_ci created_at = Curl_timediff(ctx->started, current_tr->started); 21313498266Sopenharmony_ci if(ctx->stats->creations == 1) 21413498266Sopenharmony_ci ctx->stats->first_created = created_at; 21513498266Sopenharmony_ci ctx->stats->last_created = created_at; 21613498266Sopenharmony_ci infof(data, "%04dms: cf[%s] created", (int)created_at, ctx->id); 21713498266Sopenharmony_ci 21813498266Sopenharmony_ci result = Curl_cf_create(&cf, &cft_test, ctx); 21913498266Sopenharmony_ci if(result) 22013498266Sopenharmony_ci goto out; 22113498266Sopenharmony_ci 22213498266Sopenharmony_ci Curl_expire(data, ctx->fail_delay_ms, EXPIRE_RUN_NOW); 22313498266Sopenharmony_ci 22413498266Sopenharmony_ciout: 22513498266Sopenharmony_ci *pcf = (!result)? cf : NULL; 22613498266Sopenharmony_ci if(result) { 22713498266Sopenharmony_ci free(cf); 22813498266Sopenharmony_ci free(ctx); 22913498266Sopenharmony_ci } 23013498266Sopenharmony_ci return result; 23113498266Sopenharmony_ci} 23213498266Sopenharmony_ci 23313498266Sopenharmony_cistatic void check_result(struct test_case *tc, 23413498266Sopenharmony_ci struct test_result *tr) 23513498266Sopenharmony_ci{ 23613498266Sopenharmony_ci char msg[256]; 23713498266Sopenharmony_ci timediff_t duration_ms; 23813498266Sopenharmony_ci 23913498266Sopenharmony_ci duration_ms = Curl_timediff(tr->ended, tr->started); 24013498266Sopenharmony_ci fprintf(stderr, "%d: test case took %dms\n", tc->id, (int)duration_ms); 24113498266Sopenharmony_ci 24213498266Sopenharmony_ci if(tr->result != tc->exp_result 24313498266Sopenharmony_ci && CURLE_OPERATION_TIMEDOUT != tr->result) { 24413498266Sopenharmony_ci /* on CI we encounter the TIMEOUT result, since images get less CPU 24513498266Sopenharmony_ci * and events are not as sharply timed. */ 24613498266Sopenharmony_ci curl_msprintf(msg, "%d: expected result %d but got %d", 24713498266Sopenharmony_ci tc->id, tc->exp_result, tr->result); 24813498266Sopenharmony_ci fail(msg); 24913498266Sopenharmony_ci } 25013498266Sopenharmony_ci if(tr->cf4.creations != tc->exp_cf4_creations) { 25113498266Sopenharmony_ci curl_msprintf(msg, "%d: expected %d ipv4 creations, but got %d", 25213498266Sopenharmony_ci tc->id, tc->exp_cf4_creations, tr->cf4.creations); 25313498266Sopenharmony_ci fail(msg); 25413498266Sopenharmony_ci } 25513498266Sopenharmony_ci if(tr->cf6.creations != tc->exp_cf6_creations) { 25613498266Sopenharmony_ci curl_msprintf(msg, "%d: expected %d ipv6 creations, but got %d", 25713498266Sopenharmony_ci tc->id, tc->exp_cf6_creations, tr->cf6.creations); 25813498266Sopenharmony_ci fail(msg); 25913498266Sopenharmony_ci } 26013498266Sopenharmony_ci 26113498266Sopenharmony_ci duration_ms = Curl_timediff(tr->ended, tr->started); 26213498266Sopenharmony_ci if(duration_ms < tc->min_duration_ms) { 26313498266Sopenharmony_ci curl_msprintf(msg, "%d: expected min duration of %dms, but took %dms", 26413498266Sopenharmony_ci tc->id, (int)tc->min_duration_ms, (int)duration_ms); 26513498266Sopenharmony_ci fail(msg); 26613498266Sopenharmony_ci } 26713498266Sopenharmony_ci if(duration_ms > tc->max_duration_ms) { 26813498266Sopenharmony_ci curl_msprintf(msg, "%d: expected max duration of %dms, but took %dms", 26913498266Sopenharmony_ci tc->id, (int)tc->max_duration_ms, (int)duration_ms); 27013498266Sopenharmony_ci fail(msg); 27113498266Sopenharmony_ci } 27213498266Sopenharmony_ci if(tr->cf6.creations && tr->cf4.creations && tc->pref_family) { 27313498266Sopenharmony_ci /* did ipv4 and ipv6 both, expect the preferred family to start right arway 27413498266Sopenharmony_ci * with the other being delayed by the happy_eyeball_timeout */ 27513498266Sopenharmony_ci struct ai_family_stats *stats1 = !strcmp(tc->pref_family, "v6")? 27613498266Sopenharmony_ci &tr->cf6 : &tr->cf4; 27713498266Sopenharmony_ci struct ai_family_stats *stats2 = !strcmp(tc->pref_family, "v6")? 27813498266Sopenharmony_ci &tr->cf4 : &tr->cf6; 27913498266Sopenharmony_ci 28013498266Sopenharmony_ci if(stats1->first_created > 100) { 28113498266Sopenharmony_ci curl_msprintf(msg, "%d: expected ip%s to start right away, instead " 28213498266Sopenharmony_ci "first attempt made after %dms", 28313498266Sopenharmony_ci tc->id, stats1->family, (int)stats1->first_created); 28413498266Sopenharmony_ci fail(msg); 28513498266Sopenharmony_ci } 28613498266Sopenharmony_ci if(stats2->first_created < tc->he_timeout_ms) { 28713498266Sopenharmony_ci curl_msprintf(msg, "%d: expected ip%s to start delayed after %dms, " 28813498266Sopenharmony_ci "instead first attempt made after %dms", 28913498266Sopenharmony_ci tc->id, stats2->family, (int)tc->he_timeout_ms, 29013498266Sopenharmony_ci (int)stats2->first_created); 29113498266Sopenharmony_ci fail(msg); 29213498266Sopenharmony_ci } 29313498266Sopenharmony_ci } 29413498266Sopenharmony_ci} 29513498266Sopenharmony_ci 29613498266Sopenharmony_cistatic void test_connect(struct test_case *tc) 29713498266Sopenharmony_ci{ 29813498266Sopenharmony_ci struct test_result tr; 29913498266Sopenharmony_ci struct curl_slist *list = NULL; 30013498266Sopenharmony_ci 30113498266Sopenharmony_ci Curl_debug_set_transport_provider(TRNSPRT_TCP, cf_test_create); 30213498266Sopenharmony_ci current_tc = tc; 30313498266Sopenharmony_ci current_tr = &tr; 30413498266Sopenharmony_ci 30513498266Sopenharmony_ci list = curl_slist_append(NULL, tc->resolve_info); 30613498266Sopenharmony_ci fail_unless(list, "error allocating resolve list entry"); 30713498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_RESOLVE, list); 30813498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_IPRESOLVE, (long)tc->ip_version); 30913498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_CONNECTTIMEOUT_MS, 31013498266Sopenharmony_ci (long)tc->connect_timeout_ms); 31113498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, 31213498266Sopenharmony_ci (long)tc->he_timeout_ms); 31313498266Sopenharmony_ci 31413498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_URL, tc->url); 31513498266Sopenharmony_ci memset(&tr, 0, sizeof(tr)); 31613498266Sopenharmony_ci tr.cf6.family = "v6"; 31713498266Sopenharmony_ci tr.cf4.family = "v4"; 31813498266Sopenharmony_ci 31913498266Sopenharmony_ci tr.started = Curl_now(); 32013498266Sopenharmony_ci tr.result = curl_easy_perform(easy); 32113498266Sopenharmony_ci tr.ended = Curl_now(); 32213498266Sopenharmony_ci 32313498266Sopenharmony_ci curl_easy_setopt(easy, CURLOPT_RESOLVE, NULL); 32413498266Sopenharmony_ci curl_slist_free_all(list); 32513498266Sopenharmony_ci list = NULL; 32613498266Sopenharmony_ci current_tc = NULL; 32713498266Sopenharmony_ci current_tr = NULL; 32813498266Sopenharmony_ci 32913498266Sopenharmony_ci check_result(tc, &tr); 33013498266Sopenharmony_ci} 33113498266Sopenharmony_ci 33213498266Sopenharmony_ci#endif /* DEBUGBUILD */ 33313498266Sopenharmony_ci 33413498266Sopenharmony_ci/* 33513498266Sopenharmony_ci * How these test cases work: 33613498266Sopenharmony_ci * - replace the creation of the TCP socket filter with our test filter 33713498266Sopenharmony_ci * - test filter does nothing and reports failure after configured delay 33813498266Sopenharmony_ci * - we feed addresses into the resolve cache to simulate different cases 33913498266Sopenharmony_ci * - we monitor how many instances of ipv4/v6 attempts are made and when 34013498266Sopenharmony_ci * - for mixed families, we expect HAPPY_EYEBALLS_TIMEOUT to trigger 34113498266Sopenharmony_ci * 34213498266Sopenharmony_ci * Max Duration checks needs to be conservative since CI jobs are not 34313498266Sopenharmony_ci * as sharp. 34413498266Sopenharmony_ci */ 34513498266Sopenharmony_ci#define TURL "http://test.com:123" 34613498266Sopenharmony_ci 34713498266Sopenharmony_ci#define R_FAIL CURLE_COULDNT_CONNECT 34813498266Sopenharmony_ci/* timeout values accounting for low cpu resources in CI */ 34913498266Sopenharmony_ci#define TC_TMOT 90000 /* 90 sec max test duration */ 35013498266Sopenharmony_ci#define CNCT_TMOT 60000 /* 60sec connect timeout */ 35113498266Sopenharmony_ci 35213498266Sopenharmony_cistatic struct test_case TEST_CASES[] = { 35313498266Sopenharmony_ci /* TIMEOUT_MS, FAIL_MS CREATED DURATION Result, HE_PREF */ 35413498266Sopenharmony_ci /* CNCT HE v4 v6 v4 v6 MIN MAX */ 35513498266Sopenharmony_ci { 1, TURL, "test.com:123:192.0.2.1", CURL_IPRESOLVE_WHATEVER, 35613498266Sopenharmony_ci CNCT_TMOT, 150, 200, 200, 1, 0, 200, TC_TMOT, R_FAIL, NULL }, 35713498266Sopenharmony_ci /* 1 ipv4, fails after ~200ms, reports COULDNT_CONNECT */ 35813498266Sopenharmony_ci { 2, TURL, "test.com:123:192.0.2.1,192.0.2.2", CURL_IPRESOLVE_WHATEVER, 35913498266Sopenharmony_ci CNCT_TMOT, 150, 200, 200, 2, 0, 400, TC_TMOT, R_FAIL, NULL }, 36013498266Sopenharmony_ci /* 2 ipv4, fails after ~400ms, reports COULDNT_CONNECT */ 36113498266Sopenharmony_ci#ifdef ENABLE_IPV6 36213498266Sopenharmony_ci { 3, TURL, "test.com:123:::1", CURL_IPRESOLVE_WHATEVER, 36313498266Sopenharmony_ci CNCT_TMOT, 150, 200, 200, 0, 1, 200, TC_TMOT, R_FAIL, NULL }, 36413498266Sopenharmony_ci /* 1 ipv6, fails after ~200ms, reports COULDNT_CONNECT */ 36513498266Sopenharmony_ci { 4, TURL, "test.com:123:::1,::2", CURL_IPRESOLVE_WHATEVER, 36613498266Sopenharmony_ci CNCT_TMOT, 150, 200, 200, 0, 2, 400, TC_TMOT, R_FAIL, NULL }, 36713498266Sopenharmony_ci /* 2 ipv6, fails after ~400ms, reports COULDNT_CONNECT */ 36813498266Sopenharmony_ci 36913498266Sopenharmony_ci { 5, TURL, "test.com:123:192.0.2.1,::1", CURL_IPRESOLVE_WHATEVER, 37013498266Sopenharmony_ci CNCT_TMOT, 150, 200, 200, 1, 1, 350, TC_TMOT, R_FAIL, "v4" }, 37113498266Sopenharmony_ci /* mixed ip4+6, v4 starts, v6 kicks in on HE, fails after ~350ms */ 37213498266Sopenharmony_ci { 6, TURL, "test.com:123:::1,192.0.2.1", CURL_IPRESOLVE_WHATEVER, 37313498266Sopenharmony_ci CNCT_TMOT, 150, 200, 200, 1, 1, 350, TC_TMOT, R_FAIL, "v6" }, 37413498266Sopenharmony_ci /* mixed ip6+4, v6 starts, v4 never starts due to high HE, TIMEOUT */ 37513498266Sopenharmony_ci { 7, TURL, "test.com:123:192.0.2.1,::1", CURL_IPRESOLVE_V4, 37613498266Sopenharmony_ci CNCT_TMOT, 150, 500, 500, 1, 0, 400, TC_TMOT, R_FAIL, NULL }, 37713498266Sopenharmony_ci /* mixed ip4+6, but only use v4, check it uses full connect timeout, 37813498266Sopenharmony_ci although another address of the 'wrong' family is available */ 37913498266Sopenharmony_ci { 8, TURL, "test.com:123:::1,192.0.2.1", CURL_IPRESOLVE_V6, 38013498266Sopenharmony_ci CNCT_TMOT, 150, 500, 500, 0, 1, 400, TC_TMOT, R_FAIL, NULL }, 38113498266Sopenharmony_ci /* mixed ip4+6, but only use v6, check it uses full connect timeout, 38213498266Sopenharmony_ci although another address of the 'wrong' family is available */ 38313498266Sopenharmony_ci#endif 38413498266Sopenharmony_ci}; 38513498266Sopenharmony_ci 38613498266Sopenharmony_ciUNITTEST_START 38713498266Sopenharmony_ci 38813498266Sopenharmony_ci#if defined(DEBUGBUILD) 38913498266Sopenharmony_ci size_t i; 39013498266Sopenharmony_ci 39113498266Sopenharmony_ci for(i = 0; i < sizeof(TEST_CASES)/sizeof(TEST_CASES[0]); ++i) { 39213498266Sopenharmony_ci test_connect(&TEST_CASES[i]); 39313498266Sopenharmony_ci } 39413498266Sopenharmony_ci#else 39513498266Sopenharmony_ci (void)TEST_CASES; 39613498266Sopenharmony_ci (void)test_connect; 39713498266Sopenharmony_ci#endif 39813498266Sopenharmony_ci 39913498266Sopenharmony_ciUNITTEST_STOP 400