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