103 lines
2.9 KiB
Python
103 lines
2.9 KiB
Python
"""Pytest fixture for managing the pipeline-runner server lifecycle during tests."""
|
|
|
|
import json
|
|
import os
|
|
import shutil
|
|
import socket
|
|
import subprocess
|
|
import tempfile
|
|
import time
|
|
|
|
import pytest
|
|
|
|
|
|
def get_free_port():
|
|
"""Get a free port for the test server."""
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
s.bind(("", 0))
|
|
port = s.getsockname()[1]
|
|
s.close()
|
|
return port
|
|
|
|
|
|
class PipelineServer:
|
|
"""Manages a pipeline-runner server instance for tests."""
|
|
|
|
def __init__(self, port, work_dir, verbose=False):
|
|
self.port = port
|
|
self.work_dir = work_dir
|
|
self.verbose = verbose
|
|
|
|
test_dir = os.path.dirname(os.path.abspath(__file__))
|
|
project_root = os.path.dirname(test_dir)
|
|
self.bin_path = os.path.join(project_root, "build", "pipeline-runner")
|
|
|
|
config = {
|
|
"port": port,
|
|
"pipelines_dir": os.path.join(work_dir, "pipelines") + "/",
|
|
"logs_dir": os.path.join(work_dir, "logs") + "/",
|
|
}
|
|
self.config_path = os.path.join(work_dir, "pipeline-runner.conf")
|
|
with open(self.config_path, "w") as f:
|
|
json.dump(config, f)
|
|
|
|
self.process = None
|
|
|
|
@property
|
|
def base_url(self):
|
|
return f"http://localhost:{self.port}"
|
|
|
|
def start(self, timeout=30):
|
|
"""Start the server and wait until it responds."""
|
|
self.process = subprocess.Popen(
|
|
[self.bin_path, self.config_path],
|
|
cwd=self.work_dir,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
|
|
deadline = time.time() + timeout
|
|
while time.time() < deadline:
|
|
try:
|
|
resp = __import__("requests").get(
|
|
f"{self.base_url}/api/pipelines", timeout=1
|
|
)
|
|
if resp.status_code == 200:
|
|
return True
|
|
except Exception:
|
|
pass
|
|
time.sleep(0.3)
|
|
|
|
return False
|
|
|
|
def stop(self):
|
|
"""Stop the server."""
|
|
if self.process:
|
|
self.process.terminate()
|
|
try:
|
|
self.process.wait(timeout=10)
|
|
except subprocess.TimeoutExpired:
|
|
self.process.kill()
|
|
self.process.wait(timeout=5)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def pipeline_server():
|
|
"""Session-scoped fixture that builds, starts, and stops the pipeline-runner server."""
|
|
project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
build_script = os.path.join(project_dir, "build.sh")
|
|
|
|
subprocess.check_call([build_script, "--fake"], cwd=project_dir)
|
|
|
|
work_dir = tempfile.mkdtemp(prefix="pipeline-test-")
|
|
port = get_free_port()
|
|
|
|
server = PipelineServer(port, work_dir)
|
|
if not server.start():
|
|
pytest.fail("Could not start pipeline-runner server")
|
|
|
|
yield server
|
|
|
|
server.stop()
|
|
shutil.rmtree(work_dir, ignore_errors=True)
|