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 = &current_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 = &current_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