gunicorn/tests/docker/uwsgi/conftest.py
Benoit Chesneau 95b7ffeeaa chore: prepare release 25.0.2
- Bump version to 25.0.2
- Update copyright year to 2026 in LICENSE and NOTICE
- Add license headers to all Python source files
- Add changelog entry for 25.0.2
2026-02-06 08:21:18 +01:00

126 lines
3.2 KiB
Python

#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
"""
pytest fixtures for uWSGI Docker integration tests.
"""
import os
import subprocess
import time
import pytest
import requests
COMPOSE_FILE = os.path.join(os.path.dirname(__file__), 'docker-compose.yml')
NGINX_URL = 'http://127.0.0.1:8080'
STARTUP_TIMEOUT = 60 # seconds
def is_docker_available():
"""Check if Docker is available."""
try:
result = subprocess.run(
['docker', 'info'],
capture_output=True,
timeout=10
)
return result.returncode == 0
except (subprocess.TimeoutExpired, FileNotFoundError):
return False
def is_compose_available():
"""Check if docker compose is available."""
try:
result = subprocess.run(
['docker', 'compose', 'version'],
capture_output=True,
timeout=10
)
return result.returncode == 0
except (subprocess.TimeoutExpired, FileNotFoundError):
return False
docker_available = pytest.mark.skipif(
not is_docker_available() or not is_compose_available(),
reason="Docker or docker compose not available"
)
@pytest.fixture(scope='session')
def docker_services():
"""
Start Docker Compose services for the test session.
This fixture builds and starts the gunicorn and nginx containers,
waits for them to be healthy, and tears them down after all tests.
"""
if not is_docker_available() or not is_compose_available():
pytest.skip("Docker or docker compose not available")
# Build and start services
subprocess.run(
['docker', 'compose', '-f', COMPOSE_FILE, 'build'],
check=True,
capture_output=True
)
subprocess.run(
['docker', 'compose', '-f', COMPOSE_FILE, 'up', '-d'],
check=True,
capture_output=True
)
# Wait for services to be healthy
start_time = time.time()
while time.time() - start_time < STARTUP_TIMEOUT:
try:
response = requests.get(f'{NGINX_URL}/', timeout=2)
if response.status_code == 200:
break
except requests.RequestException:
pass
time.sleep(1)
else:
# Get logs for debugging
logs = subprocess.run(
['docker', 'compose', '-f', COMPOSE_FILE, 'logs'],
capture_output=True,
text=True
)
subprocess.run(
['docker', 'compose', '-f', COMPOSE_FILE, 'down', '-v'],
capture_output=True
)
pytest.fail(
f"Services did not become healthy within {STARTUP_TIMEOUT}s.\n"
f"Logs:\n{logs.stdout}\n{logs.stderr}"
)
yield
# Teardown
subprocess.run(
['docker', 'compose', '-f', COMPOSE_FILE, 'down', '-v'],
capture_output=True
)
@pytest.fixture
def nginx_url(docker_services):
"""Return the nginx base URL."""
return NGINX_URL
@pytest.fixture
def session(docker_services):
"""Return a requests Session with keep-alive enabled."""
with requests.Session() as s:
# Enable keep-alive
s.headers['Connection'] = 'keep-alive'
yield s