From 67303920fe57355093042b85897cbf48857fb2df Mon Sep 17 00:00:00 2001
From: James Addison <55152140+jayaddison@users.noreply.github.com>
Date: Fri, 12 Apr 2024 23:32:12 +0100
Subject: [PATCH] Make the test suite connectivity-agnostic (#12095)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
---
sphinx/testing/fixtures.py | 48 +-------------------
tests/roots/test-images/index.rst | 4 +-
tests/roots/test-root/images.txt | 3 --
tests/test_builders/test_build_html_image.py | 8 ++--
tests/test_builders/test_build_latex.py | 40 +++++++++++++---
5 files changed, 39 insertions(+), 64 deletions(-)
diff --git a/sphinx/testing/fixtures.py b/sphinx/testing/fixtures.py
index 95cf177c4af..6e1a1222a5f 100644
--- a/sphinx/testing/fixtures.py
+++ b/sphinx/testing/fixtures.py
@@ -7,7 +7,7 @@
import sys
from collections import namedtuple
from io import StringIO
-from typing import TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING
import pytest
@@ -236,52 +236,6 @@ def if_graphviz_found(app: SphinxTestApp) -> None: # NoQA: PT004
pytest.skip('graphviz "dot" is not available')
-_HOST_ONLINE_ERROR = pytest.StashKey[Optional[str]]()
-
-
-def _query(address: tuple[str, int]) -> str | None:
- import socket
-
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
- try:
- sock.settimeout(5)
- sock.connect(address)
- except OSError as exc:
- # other type of errors are propagated
- return str(exc)
- return None
-
-
-@pytest.fixture(scope='session')
-def sphinx_remote_query_address() -> tuple[str, int]:
- """Address to which a query is made to check that the host is online.
-
- By default, onlineness is tested by querying the DNS server ``1.1.1.1``
- but users concerned about privacy might change it in ``conftest.py``.
- """
- return ('1.1.1.1', 80)
-
-
-@pytest.fixture(scope='session')
-def if_online( # NoQA: PT004
- request: pytest.FixtureRequest,
- sphinx_remote_query_address: tuple[str, int],
-) -> None:
- """Skip the test if the host has no connection.
-
- Usage::
-
- @pytest.mark.usefixtures('if_online')
- def test_if_host_is_online(): ...
- """
- if _HOST_ONLINE_ERROR not in request.session.stash:
- # do not use setdefault() to avoid creating a socket connection
- lookup_error = _query(sphinx_remote_query_address)
- request.session.stash[_HOST_ONLINE_ERROR] = lookup_error
- if (error := request.session.stash[_HOST_ONLINE_ERROR]) is not None:
- pytest.skip('host appears to be offline (%s)' % error)
-
-
@pytest.fixture(scope='session')
def sphinx_test_tempdir(tmp_path_factory: Any) -> Path:
"""Temporary directory."""
diff --git a/tests/roots/test-images/index.rst b/tests/roots/test-images/index.rst
index 14a2987a0dd..9b9aac1e595 100644
--- a/tests/roots/test-images/index.rst
+++ b/tests/roots/test-images/index.rst
@@ -23,7 +23,7 @@ test-image
:target: https://www.python.org/
.. a remote image
-.. image:: https://www.python.org/static/img/python-logo.png
+.. image:: http://localhost:7777/sphinx.png
.. non-exist remote image
-.. image:: https://www.google.com/NOT_EXIST.PNG
+.. image:: http://localhost:7777/NOT_EXIST.PNG
diff --git a/tests/roots/test-root/images.txt b/tests/roots/test-root/images.txt
index 1dc591a0262..5a096dc5b4d 100644
--- a/tests/roots/test-root/images.txt
+++ b/tests/roots/test-root/images.txt
@@ -12,9 +12,6 @@ Sphinx image handling
.. an image with unspecified extension
.. image:: img.*
-.. a non-local image URI
-.. image:: https://www.python.org/static/img/python-logo.png
-
.. an image with subdir and unspecified extension
.. image:: subdir/simg.*
diff --git a/tests/test_builders/test_build_html_image.py b/tests/test_builders/test_build_html_image.py
index 66ba58df09c..08ed6187c81 100644
--- a/tests/test_builders/test_build_html_image.py
+++ b/tests/test_builders/test_build_html_image.py
@@ -5,15 +5,14 @@
import pytest
-@pytest.mark.usefixtures('if_online')
@pytest.mark.sphinx('html', testroot='images')
def test_html_remote_images(app, status, warning):
app.build(force_all=True)
result = (app.outdir / 'index.html').read_text(encoding='utf8')
- assert ('' in result)
- assert not (app.outdir / 'python-logo.png').exists()
+ assert ('' in result)
+ assert not (app.outdir / 'sphinx.png').exists()
@pytest.mark.sphinx('html', testroot='image-escape')
@@ -25,7 +24,6 @@ def test_html_encoded_image(app, status, warning):
assert (app.outdir / '_images/img_#1.png').exists()
-@pytest.mark.usefixtures('if_online')
@pytest.mark.sphinx('html', testroot='remote-logo')
def test_html_remote_logo(app, status, warning):
app.build(force_all=True)
diff --git a/tests/test_builders/test_build_latex.py b/tests/test_builders/test_build_latex.py
index e9114b5c4de..0776c747a17 100644
--- a/tests/test_builders/test_build_latex.py
+++ b/tests/test_builders/test_build_latex.py
@@ -1,5 +1,6 @@
"""Test the build process with LaTeX builder with the test root."""
+import http.server
import os
import re
import subprocess
@@ -17,6 +18,8 @@
from sphinx.util.osutil import ensuredir
from sphinx.writers.latex import LaTeXTranslator
+from tests.utils import http_server
+
try:
from contextlib import chdir
except ImportError:
@@ -79,6 +82,28 @@ def skip_if_stylefiles_notfound(testfunc):
return testfunc
+class RemoteImageHandler(http.server.BaseHTTPRequestHandler):
+ protocol_version = "HTTP/1.1"
+
+ def do_GET(self):
+ content, content_type = None, None
+ if self.path == "/sphinx.png":
+ with open("tests/roots/test-local-logo/images/img.png", "rb") as f:
+ content = f.read()
+ content_type = "image/png"
+
+ if content:
+ self.send_response(200, "OK")
+ self.send_header("Content-Length", str(len(content)))
+ self.send_header("Content-Type", content_type)
+ self.end_headers()
+ self.wfile.write(content)
+ else:
+ self.send_response(404, "Not Found")
+ self.send_header("Content-Length", "0")
+ self.end_headers()
+
+
@skip_if_requested
@skip_if_stylefiles_notfound
@pytest.mark.parametrize(
@@ -112,7 +137,8 @@ def test_build_latex_doc(app, engine, docclass, python_maximum_signature_line_le
load_mappings(app)
app.builder.init()
LaTeXTranslator.ignore_missing_images = True
- app.build(force_all=True)
+ with http_server(RemoteImageHandler):
+ app.build(force_all=True)
# file from latex_additional_files
assert (app.outdir / 'svgimg.svg').is_file()
@@ -1398,21 +1424,21 @@ def test_latex_raw_directive(app, status, warning):
assert 'LaTeX: abc def ghi' in result
-@pytest.mark.usefixtures('if_online')
@pytest.mark.sphinx('latex', testroot='images')
def test_latex_images(app, status, warning):
- app.build(force_all=True)
+ with http_server(RemoteImageHandler, port=7777):
+ app.build(force_all=True)
result = (app.outdir / 'python.tex').read_text(encoding='utf8')
# images are copied
- assert '\\sphinxincludegraphics{{python-logo}.png}' in result
- assert (app.outdir / 'python-logo.png').exists()
+ assert '\\sphinxincludegraphics{{sphinx}.png}' in result
+ assert (app.outdir / 'sphinx.png').exists()
# not found images
assert '\\sphinxincludegraphics{{NOT_EXIST}.PNG}' not in result
assert ('WARNING: Could not fetch remote image: '
- 'https://www.google.com/NOT_EXIST.PNG [404]' in warning.getvalue())
+ 'http://localhost:7777/NOT_EXIST.PNG [404]' in warning.getvalue())
# an image having target
assert ('\\sphinxhref{https://www.sphinx-doc.org/}'
@@ -1682,7 +1708,7 @@ def test_copy_images(app, status, warning):
image.name for image in test_dir.rglob('*')
if image.suffix in {'.gif', '.pdf', '.png', '.svg'}
}
- images.discard('python-logo.png')
+ images.discard('sphinx.png')
assert images == {
'img.pdf',
'rimg.png',