image_server/tests/conftest.py

176 lines
5.0 KiB
Python

"""Shared fixtures for the test suite."""
import argparse
import shutil
import zipfile
from collections.abc import Generator
from pathlib import Path
import pytest
from httpx import ASGITransport, AsyncClient
import main
def _reset_state() -> None:
"""Reset all global state to defaults."""
main.file_mapping.clear()
main.indexers.clear()
main.sorted_hashes.clear()
@pytest.fixture(autouse=True)
def reset_globals() -> Generator[None]:
"""Reset global state before and after each test."""
_reset_state()
yield
_reset_state()
@pytest.fixture
def sample_files(tmp_path: Path) -> dict[str, Path]:
"""Create a directory with sample files for testing.
Returns:
Dict mapping logical names to file paths.
"""
subdir = tmp_path / "subdir"
subdir.mkdir()
files: dict[str, Path] = {}
files["root_file"] = tmp_path / "root.txt"
files["root_file"].write_text("root content")
files["sub_file"] = subdir / "nested.txt"
files["sub_file"].write_text("nested content")
files["binary_file"] = tmp_path / "data.bin"
files["binary_file"].write_bytes(b"\x00\x01\x02\x03")
files["image_file"] = tmp_path / "photo.jpg"
files["image_file"].write_bytes(b"\xff\xd8\xff\xe0fake_jpeg_data")
return files
@pytest.fixture
def sample_zip(tmp_path: Path) -> dict[str, Path]:
"""Create a ZIP file with sample files for testing.
Returns:
Dict mapping logical names to file paths inside the zip.
"""
zip_path = tmp_path / "test_archive.zip"
inner_files: dict[str, Path] = {}
with zipfile.ZipFile(zip_path, "w") as zf:
zf.writestr("top.txt", "top level content")
inner_files["top"] = Path("top.txt")
zf.writestr("folder/deep.txt", "deep content")
inner_files["deep"] = Path("folder/deep.txt")
zf.writestr("folder/image.png", b"\x89PNG fake png")
inner_files["image"] = Path("folder/image.png")
return inner_files
@pytest.fixture
def args_directory(sample_files: dict[str, Path], tmp_path: Path) -> argparse.Namespace:
"""Argparse namespace pointing at the sample directory."""
return argparse.Namespace(
source=str(tmp_path),
host="127.0.0.1",
port=0,
salt="test-salt",
)
@pytest.fixture
def args_zip(sample_zip: dict[str, Path], tmp_path: Path) -> argparse.Namespace:
"""Argparse namespace pointing at the sample zip."""
return argparse.Namespace(
source=str(tmp_path / "test_archive.zip"),
host="127.0.0.1",
port=0,
salt="test-salt",
)
@pytest.fixture
def initialized_dir(args_directory: argparse.Namespace) -> None:
"""Initialize the server with sample directory files."""
main.initialize_server(args_directory)
@pytest.fixture
def initialized_zip(args_zip: argparse.Namespace) -> None:
"""Initialize the server with sample zip files."""
main.initialize_server(args_zip)
@pytest.fixture
async def client_dir(initialized_dir: None) -> Generator[AsyncClient]:
"""Async HTTP client against the app initialized with directory files."""
transport = ASGITransport(app=main.app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac
@pytest.fixture
async def client_zip(initialized_zip: None) -> Generator[AsyncClient]:
"""Async HTTP client against the app initialized with zip files."""
transport = ASGITransport(app=main.app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac
@pytest.fixture
def sample_encrypted_zip(tmp_path: Path) -> tuple[Path, dict[str, str], str]:
"""Copy the pre-existing testfile.zip to a temp location.
Returns:
Tuple of (zip_path, inner_files dict, password).
inner_files maps logical names to internal paths.
"""
src = Path(__file__).parent / "testfile.zip"
zip_path = tmp_path / "testfile.zip"
shutil.copy2(src, zip_path)
password = "password"
inner_files: dict[str, str] = {
"encrypted": "encrypted.txt",
"unencrypted": "unencrypted.txt",
}
return zip_path, inner_files, password
@pytest.fixture
def args_encrypted_zip(
sample_encrypted_zip: tuple[Path, dict[str, str], str], tmp_path: Path
) -> argparse.Namespace:
"""Argparse namespace pointing at the encrypted sample zip."""
zip_path, _, _ = sample_encrypted_zip
return argparse.Namespace(
source=str(zip_path),
host="127.0.0.1",
port=0,
salt="test-salt",
)
@pytest.fixture
def initialized_encrypted_zip(args_encrypted_zip: argparse.Namespace) -> None:
"""Initialize the server with encrypted zip files."""
main.initialize_server(args_encrypted_zip)
@pytest.fixture
async def client_encrypted_zip(
initialized_encrypted_zip: None,
) -> Generator[AsyncClient]:
"""Async HTTP client against the app initialized with encrypted zip files."""
transport = ASGITransport(app=main.app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac