mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-01 18:21:30 +08:00
- 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
126 lines
3.2 KiB
Python
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
|