From 31458271981e5658bd7b52daeb7625a0b5c3daa9 Mon Sep 17 00:00:00 2001 From: Jair Henrique Date: Wed, 19 Nov 2025 11:39:11 -0300 Subject: [PATCH] Fixes some tornado tests --- .github/workflows/main.yml | 1 - tests/integration/test_tornado.py | 116 +++++++++++++++++------------- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4133226..abb5f27 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,6 @@ jobs: - "3.11" - "3.12" - "3.13" - - "pypy-3.10" - "pypy-3.11" steps: diff --git a/tests/integration/test_tornado.py b/tests/integration/test_tornado.py index d20ca33..d216b94 100644 --- a/tests/integration/test_tornado.py +++ b/tests/integration/test_tornado.py @@ -4,6 +4,8 @@ import asyncio import functools import inspect import json +import os +import ssl import pytest @@ -36,24 +38,23 @@ def gen_test(func): return wrapper -@pytest.fixture(params=["https", "http"]) -def scheme(request): - """Fixture that returns both http and https.""" - return request.param - - @pytest.fixture(params=["simple", "curl", "default"]) def get_client(request): + ca_bundle_path = os.environ.get("REQUESTS_CA_BUNDLE") + ssl_ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) + ssl_ctx.load_verify_locations(cafile=ca_bundle_path) + ssl_ctx.verify_mode = ssl.CERT_REQUIRED + if request.param == "simple": from tornado import simple_httpclient as simple - return lambda: simple.SimpleAsyncHTTPClient() + return lambda: simple.SimpleAsyncHTTPClient(defaults={"ssl_options": ssl_ctx}) if request.param == "curl": curl = pytest.importorskip("tornado.curl_httpclient") - return lambda: curl.CurlAsyncHTTPClient() + return lambda: curl.CurlAsyncHTTPClient(defaults={"ca_certs": ca_bundle_path}) - return lambda: http.AsyncHTTPClient() + return lambda: http.AsyncHTTPClient(defaults={"ssl_options": ssl_ctx}) def get(client, url, **kwargs): @@ -72,9 +73,9 @@ def post(client, url, data=None, **kwargs): @pytest.mark.online @gen_test -def test_status_code(get_client, scheme, tmpdir): +def test_status_code(get_client, tmpdir, httpbin_both): """Ensure that we can read the status code""" - url = scheme + "://httpbin.org/" + url = httpbin_both.url with vcr.use_cassette(str(tmpdir.join("atts.yaml"))): status_code = (yield get(get_client(), url)).code @@ -85,9 +86,9 @@ def test_status_code(get_client, scheme, tmpdir): @pytest.mark.online @gen_test -def test_headers(get_client, scheme, tmpdir): +def test_headers(get_client, httpbin_both, tmpdir): """Ensure that we can read the headers back""" - url = scheme + "://httpbin.org/" + url = httpbin_both.url with vcr.use_cassette(str(tmpdir.join("headers.yaml"))): headers = (yield get(get_client(), url)).headers @@ -98,10 +99,10 @@ def test_headers(get_client, scheme, tmpdir): @pytest.mark.online @gen_test -def test_body(get_client, tmpdir, scheme): +def test_body(get_client, tmpdir, httpbin_both): """Ensure the responses are all identical enough""" - url = scheme + "://httpbin.org/bytes/1024" + url = httpbin_both.url + "/bytes/1024" with vcr.use_cassette(str(tmpdir.join("body.yaml"))): content = (yield get(get_client(), url)).body @@ -125,10 +126,10 @@ def test_effective_url(get_client, tmpdir, httpbin): @pytest.mark.online @gen_test -def test_auth(get_client, tmpdir, scheme): +def test_auth(get_client, tmpdir, httpbin_both): """Ensure that we can handle basic auth""" auth = ("user", "passwd") - url = scheme + "://httpbin.org/basic-auth/user/passwd" + url = httpbin_both.url + "/basic-auth/user/passwd" with vcr.use_cassette(str(tmpdir.join("auth.yaml"))): one = yield get(get_client(), url, auth_username=auth[0], auth_password=auth[1]) @@ -141,10 +142,10 @@ def test_auth(get_client, tmpdir, scheme): @pytest.mark.online @gen_test -def test_auth_failed(get_client, tmpdir, scheme): +def test_auth_failed(get_client, tmpdir, httpbin_both): """Ensure that we can save failed auth statuses""" auth = ("user", "wrongwrongwrong") - url = scheme + "://httpbin.org/basic-auth/user/passwd" + url = httpbin_both.url + "/basic-auth/user/passwd" with vcr.use_cassette(str(tmpdir.join("auth-failed.yaml"))) as cass: # Ensure that this is empty to begin with assert_cassette_empty(cass) @@ -165,10 +166,10 @@ def test_auth_failed(get_client, tmpdir, scheme): @pytest.mark.online @gen_test -def test_post(get_client, tmpdir, scheme): +def test_post(get_client, tmpdir, httpbin_both): """Ensure that we can post and cache the results""" data = {"key1": "value1", "key2": "value2"} - url = scheme + "://httpbin.org/post" + url = httpbin_both.url + "/post" with vcr.use_cassette(str(tmpdir.join("requests.yaml"))): req1 = (yield post(get_client(), url, data)).body @@ -193,32 +194,36 @@ def test_redirects(get_client, tmpdir, httpbin): @pytest.mark.online @gen_test -def test_cross_scheme(get_client, tmpdir): +def test_cross_scheme(get_client, tmpdir, httpbin, httpbin_secure): """Ensure that requests between schemes are treated separately""" # First fetch a url under http, and then again under https and then # ensure that we haven't served anything out of cache, and we have two # requests / response pairs in the cassette + + url = httpbin.url + url_secure = httpbin_secure.url + with vcr.use_cassette(str(tmpdir.join("cross_scheme.yaml"))) as cass: - yield get(get_client(), "https://httpbin.org/") - yield get(get_client(), "http://httpbin.org/") + yield get(get_client(), url) + yield get(get_client(), url_secure) assert cass.play_count == 0 assert len(cass) == 2 # Then repeat the same requests and ensure both were replayed. with vcr.use_cassette(str(tmpdir.join("cross_scheme.yaml"))) as cass: - yield get(get_client(), "https://httpbin.org/") - yield get(get_client(), "http://httpbin.org/") + yield get(get_client(), url) + yield get(get_client(), url_secure) assert cass.play_count == 2 @pytest.mark.online @gen_test -def test_gzip(get_client, tmpdir, scheme): +def test_gzip(get_client, tmpdir, httpbin_both): """ Ensure that httpclient is able to automatically decompress the response body """ - url = scheme + "://httpbin.org/gzip" + url = httpbin_both + "/gzip" # use_gzip was renamed to decompress_response in 4.0 kwargs = {} @@ -239,19 +244,21 @@ def test_gzip(get_client, tmpdir, scheme): @pytest.mark.online @gen_test -def test_https_with_cert_validation_disabled(get_client, tmpdir): +def test_https_with_cert_validation_disabled(get_client, tmpdir, httpbin_secure): cass_path = str(tmpdir.join("cert_validation_disabled.yaml")) + url = httpbin_secure.url + with vcr.use_cassette(cass_path): - yield get(get_client(), "https://httpbin.org", validate_cert=False) + yield get(get_client(), url, validate_cert=False) with vcr.use_cassette(cass_path) as cass: - yield get(get_client(), "https://httpbin.org", validate_cert=False) + yield get(get_client(), url, validate_cert=False) assert cass.play_count == 1 @gen_test -def test_unsupported_features_raises_in_future(get_client, tmpdir): +def test_unsupported_features_raises_in_future(get_client, tmpdir, httpbin): """Ensure that the exception for an AsyncHTTPClient feature not being supported is raised inside the future.""" @@ -259,7 +266,7 @@ def test_unsupported_features_raises_in_future(get_client, tmpdir): raise AssertionError("Did not expect to be called.") with vcr.use_cassette(str(tmpdir.join("invalid.yaml"))): - future = get(get_client(), "http://httpbin.org", streaming_callback=callback) + future = get(get_client(), httpbin.url, streaming_callback=callback) with pytest.raises(Exception) as excinfo: yield future @@ -293,15 +300,17 @@ def test_unsupported_features_raise_error_disabled(get_client, tmpdir): @pytest.mark.online @gen_test -def test_cannot_overwrite_cassette_raises_in_future(get_client, tmpdir): +def test_cannot_overwrite_cassette_raises_in_future(get_client, tmpdir, httpbin): """Ensure that CannotOverwriteExistingCassetteException is raised inside the future.""" - with vcr.use_cassette(str(tmpdir.join("overwrite.yaml"))): - yield get(get_client(), "http://httpbin.org/get") + url = httpbin.url with vcr.use_cassette(str(tmpdir.join("overwrite.yaml"))): - future = get(get_client(), "http://httpbin.org/headers") + yield get(get_client(), url + "/get") + + with vcr.use_cassette(str(tmpdir.join("overwrite.yaml"))): + future = get(get_client(), url + "/headers") with pytest.raises(CannotOverwriteExistingCassetteException): yield future @@ -313,15 +322,17 @@ def test_cannot_overwrite_cassette_raises_in_future(get_client, tmpdir): reason="raise_error only ignores HTTPErrors due to response code", ) @gen_test -def test_cannot_overwrite_cassette_raise_error_disabled(get_client, tmpdir): +def test_cannot_overwrite_cassette_raise_error_disabled(get_client, tmpdir, httpbin): """Ensure that CannotOverwriteExistingCassetteException is not raised if raise_error=False in the fetch() call.""" - with vcr.use_cassette(str(tmpdir.join("overwrite.yaml"))): - yield get(get_client(), "http://httpbin.org/get", raise_error=False) + url = httpbin.url with vcr.use_cassette(str(tmpdir.join("overwrite.yaml"))): - response = yield get(get_client(), "http://httpbin.org/headers", raise_error=False) + yield get(get_client(), url + "/get", raise_error=False) + + with vcr.use_cassette(str(tmpdir.join("overwrite.yaml"))): + response = yield get(get_client(), url + "/headers", raise_error=False) assert isinstance(response.error, CannotOverwriteExistingCassetteException) @@ -349,46 +360,51 @@ def test_tornado_exception_can_be_caught(get_client): @pytest.mark.online @gen_test -def test_existing_references_get_patched(tmpdir): +def test_existing_references_get_patched(tmpdir, httpbin): from tornado.httpclient import AsyncHTTPClient + url = httpbin.url + "/get" + with vcr.use_cassette(str(tmpdir.join("data.yaml"))): client = AsyncHTTPClient() - yield get(client, "http://httpbin.org/get") + yield get(client, url) with vcr.use_cassette(str(tmpdir.join("data.yaml"))) as cass: - yield get(client, "http://httpbin.org/get") + yield get(client, url) assert cass.play_count == 1 @pytest.mark.online @gen_test -def test_existing_instances_get_patched(get_client, tmpdir): +def test_existing_instances_get_patched(get_client, tmpdir, httpbin): """Ensure that existing instances of AsyncHTTPClient get patched upon entering VCR context.""" + url = httpbin.url + "/get" client = get_client() with vcr.use_cassette(str(tmpdir.join("data.yaml"))): - yield get(client, "http://httpbin.org/get") + yield get(client, url) with vcr.use_cassette(str(tmpdir.join("data.yaml"))) as cass: - yield get(client, "http://httpbin.org/get") + yield get(client, url) assert cass.play_count == 1 @pytest.mark.online @gen_test -def test_request_time_is_set(get_client, tmpdir): +def test_request_time_is_set(get_client, tmpdir, httpbin): """Ensures that the request_time on HTTPResponses is set.""" + url = httpbin.url + "/get" + with vcr.use_cassette(str(tmpdir.join("data.yaml"))): client = get_client() - response = yield get(client, "http://httpbin.org/get") + response = yield get(client, url) assert response.request_time is not None with vcr.use_cassette(str(tmpdir.join("data.yaml"))) as cass: client = get_client() - response = yield get(client, "http://httpbin.org/get") + response = yield get(client, url) assert response.request_time is not None assert cass.play_count == 1