1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6236dae4SAndroid Build Coastguard Worker# -*- coding: utf-8 -*- 3*6236dae4SAndroid Build Coastguard Worker#*************************************************************************** 4*6236dae4SAndroid Build Coastguard Worker# _ _ ____ _ 5*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 6*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 7*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 8*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 9*6236dae4SAndroid Build Coastguard Worker# 10*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 11*6236dae4SAndroid Build Coastguard Worker# 12*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 13*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 14*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 15*6236dae4SAndroid Build Coastguard Worker# 16*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 17*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 18*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 19*6236dae4SAndroid Build Coastguard Worker# 20*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 22*6236dae4SAndroid Build Coastguard Worker# 23*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 24*6236dae4SAndroid Build Coastguard Worker# 25*6236dae4SAndroid Build Coastguard Worker########################################################################### 26*6236dae4SAndroid Build Coastguard Worker# 27*6236dae4SAndroid Build Coastguard Workerimport logging 28*6236dae4SAndroid Build Coastguard Workerimport pytest 29*6236dae4SAndroid Build Coastguard Worker 30*6236dae4SAndroid Build Coastguard Workerfrom testenv import Env, CurlClient 31*6236dae4SAndroid Build Coastguard Worker 32*6236dae4SAndroid Build Coastguard Worker 33*6236dae4SAndroid Build Coastguard Workerlog = logging.getLogger(__name__) 34*6236dae4SAndroid Build Coastguard Worker 35*6236dae4SAndroid Build Coastguard Worker 36*6236dae4SAndroid Build Coastguard Workerclass TestEyeballs: 37*6236dae4SAndroid Build Coastguard Worker 38*6236dae4SAndroid Build Coastguard Worker @pytest.fixture(autouse=True, scope='class') 39*6236dae4SAndroid Build Coastguard Worker def _class_scope(self, env, httpd, nghttpx): 40*6236dae4SAndroid Build Coastguard Worker if env.have_h3(): 41*6236dae4SAndroid Build Coastguard Worker nghttpx.start_if_needed() 42*6236dae4SAndroid Build Coastguard Worker httpd.clear_extra_configs() 43*6236dae4SAndroid Build Coastguard Worker httpd.reload() 44*6236dae4SAndroid Build Coastguard Worker 45*6236dae4SAndroid Build Coastguard Worker # download using only HTTP/3 on working server 46*6236dae4SAndroid Build Coastguard Worker @pytest.mark.skipif(condition=not Env.have_h3(), reason="missing HTTP/3 support") 47*6236dae4SAndroid Build Coastguard Worker def test_06_01_h3_only(self, env: Env, httpd, nghttpx, repeat): 48*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 49*6236dae4SAndroid Build Coastguard Worker urln = f'https://{env.authority_for(env.domain1, "h3")}/data.json' 50*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln], extra_args=['--http3-only']) 51*6236dae4SAndroid Build Coastguard Worker r.check_response(count=1, http_status=200) 52*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['http_version'] == '3' 53*6236dae4SAndroid Build Coastguard Worker 54*6236dae4SAndroid Build Coastguard Worker # download using only HTTP/3 on missing server 55*6236dae4SAndroid Build Coastguard Worker @pytest.mark.skipif(condition=not Env.have_h3(), reason="missing HTTP/3 support") 56*6236dae4SAndroid Build Coastguard Worker def test_06_02_h3_only(self, env: Env, httpd, nghttpx, repeat): 57*6236dae4SAndroid Build Coastguard Worker nghttpx.stop_if_running() 58*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 59*6236dae4SAndroid Build Coastguard Worker urln = f'https://{env.authority_for(env.domain1, "h3")}/data.json' 60*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln], extra_args=['--http3-only']) 61*6236dae4SAndroid Build Coastguard Worker r.check_response(exitcode=7, http_status=None) 62*6236dae4SAndroid Build Coastguard Worker 63*6236dae4SAndroid Build Coastguard Worker # download using HTTP/3 on missing server with fallback on h2 64*6236dae4SAndroid Build Coastguard Worker @pytest.mark.skipif(condition=not Env.have_h3(), reason="missing HTTP/3 support") 65*6236dae4SAndroid Build Coastguard Worker def test_06_03_h3_fallback_h2(self, env: Env, httpd, nghttpx, repeat): 66*6236dae4SAndroid Build Coastguard Worker nghttpx.stop_if_running() 67*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 68*6236dae4SAndroid Build Coastguard Worker urln = f'https://{env.authority_for(env.domain1, "h3")}/data.json' 69*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln], extra_args=['--http3']) 70*6236dae4SAndroid Build Coastguard Worker r.check_response(count=1, http_status=200) 71*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['http_version'] == '2' 72*6236dae4SAndroid Build Coastguard Worker 73*6236dae4SAndroid Build Coastguard Worker # download using HTTP/3 on missing server with fallback on http/1.1 74*6236dae4SAndroid Build Coastguard Worker @pytest.mark.skipif(condition=not Env.have_h3(), reason="missing HTTP/3 support") 75*6236dae4SAndroid Build Coastguard Worker def test_06_04_h3_fallback_h1(self, env: Env, httpd, nghttpx, repeat): 76*6236dae4SAndroid Build Coastguard Worker nghttpx.stop_if_running() 77*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 78*6236dae4SAndroid Build Coastguard Worker urln = f'https://{env.authority_for(env.domain2, "h3")}/data.json' 79*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln], extra_args=['--http3']) 80*6236dae4SAndroid Build Coastguard Worker r.check_response(count=1, http_status=200) 81*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['http_version'] == '1.1' 82*6236dae4SAndroid Build Coastguard Worker 83*6236dae4SAndroid Build Coastguard Worker # make a successful https: transfer and observer the timer stats 84*6236dae4SAndroid Build Coastguard Worker def test_06_10_stats_success(self, env: Env, httpd, nghttpx, repeat): 85*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 86*6236dae4SAndroid Build Coastguard Worker urln = f'https://{env.authority_for(env.domain1, "h2")}/data.json' 87*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln]) 88*6236dae4SAndroid Build Coastguard Worker r.check_response(count=1, http_status=200) 89*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['time_connect'] > 0.0 90*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['time_appconnect'] > 0.0 91*6236dae4SAndroid Build Coastguard Worker 92*6236dae4SAndroid Build Coastguard Worker # make https: to a hostname that tcp connects, but will not verify 93*6236dae4SAndroid Build Coastguard Worker def test_06_11_stats_fail_verify(self, env: Env, httpd, nghttpx, repeat): 94*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 95*6236dae4SAndroid Build Coastguard Worker urln = f'https://not-valid.com:{env.https_port}/data.json' 96*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln], extra_args=[ 97*6236dae4SAndroid Build Coastguard Worker '--resolve', f'not-valid.com:{env.https_port}:127.0.0.1' 98*6236dae4SAndroid Build Coastguard Worker ]) 99*6236dae4SAndroid Build Coastguard Worker r.check_response(count=1, http_status=0, exitcode=False) 100*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['time_connect'] > 0.0 # was tcp connected 101*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['time_appconnect'] == 0 # but not SSL verified 102*6236dae4SAndroid Build Coastguard Worker 103*6236dae4SAndroid Build Coastguard Worker # make https: to an invalid address 104*6236dae4SAndroid Build Coastguard Worker def test_06_12_stats_fail_tcp(self, env: Env, httpd, nghttpx, repeat): 105*6236dae4SAndroid Build Coastguard Worker curl = CurlClient(env=env) 106*6236dae4SAndroid Build Coastguard Worker urln = 'https://not-valid.com:1/data.json' 107*6236dae4SAndroid Build Coastguard Worker r = curl.http_download(urls=[urln], extra_args=[ 108*6236dae4SAndroid Build Coastguard Worker '--resolve', f'not-valid.com:{1}:127.0.0.1' 109*6236dae4SAndroid Build Coastguard Worker ]) 110*6236dae4SAndroid Build Coastguard Worker r.check_response(count=1, http_status=None, exitcode=False) 111*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['time_connect'] == 0 # no one should have listened 112*6236dae4SAndroid Build Coastguard Worker assert r.stats[0]['time_appconnect'] == 0 # did not happen either 113