forked from retoor/devplacepy
chore: reorganize test files into domain-specific subdirectories under tests/
Split the monolithic test directory into three tiers (unit, api, e2e) with a path-mirroring directory structure. Added corresponding Makefile targets (test-unit, test-api, test-e2e) and updated all documentation references (CLAUDE.md, README.md, testing-cicd.html, testing-framework.html, testing-make.html) to reflect the new layout and naming conventions.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from datetime import timedelta
|
||||
import pytest
|
||||
import requests
|
||||
from tests.conftest import BASE_URL, run_async
|
||||
from devplacepy.database import db, get_table, init_db, refresh_snapshot
|
||||
from devplacepy import config, project_files
|
||||
from devplacepy.services.containers import api, store, runtime
|
||||
from devplacepy.services.containers.backend.base import Mount, PortMapping, RunSpec
|
||||
from devplacepy.services.containers.backend.docker_cli import build_run_argv, parse_size
|
||||
from devplacepy.services.containers.backend.fake import FakeBackend
|
||||
from devplacepy.services.containers.service import ContainerService
|
||||
from devplacepy.services.containers.api import INSTANCE_LABEL
|
||||
from devplacepy.services.devii.tasks.schedule import Schedule, now_utc
|
||||
_CONTAINER_TABLES = (
|
||||
"instances",
|
||||
"instance_events",
|
||||
"instance_metrics",
|
||||
"instance_schedules",
|
||||
)
|
||||
@pytest.fixture(autouse=True)
|
||||
def _init_db_containers():
|
||||
init_db()
|
||||
yield
|
||||
@pytest.fixture
|
||||
def env(tmp_path, monkeypatch):
|
||||
fake = FakeBackend()
|
||||
runtime.set_backend(fake)
|
||||
monkeypatch.setattr("devplacepy.config.CONTAINER_WORKSPACES_DIR", tmp_path / "ws")
|
||||
pid = "ctest-p1"
|
||||
project = {"uid": pid, "slug": "ctest", "title": "C", "user_uid": "ctest-u1"}
|
||||
user = {"uid": "ctest-u1", "username": "ctestadmin"}
|
||||
project_files.write_text_file(pid, user, "app.py", "print(1)\n")
|
||||
yield {"fake": fake, "project": project, "user": user}
|
||||
runtime.set_backend(None)
|
||||
for table in _CONTAINER_TABLES:
|
||||
if table in db.tables:
|
||||
for row in [r for r in get_table(table).find()]:
|
||||
if str(row.get("project_uid", "")).startswith("ctest"):
|
||||
get_table(table).delete(uid=row["uid"])
|
||||
for row in list(get_table("project_files").find()):
|
||||
if str(row.get("project_uid", "")).startswith("ctest"):
|
||||
get_table("project_files").delete(uid=row["uid"])
|
||||
def _ready_instance(env, **kwargs):
|
||||
return run_async(
|
||||
api.create_instance(env["project"], name=kwargs.pop("name", "inst"), **kwargs)
|
||||
)
|
||||
def _promote_admin(username: str) -> None:
|
||||
users = get_table("users")
|
||||
user = users.find_one(username=username)
|
||||
if user:
|
||||
users.update({"uid": user["uid"], "role": "Admin"}, ["uid"])
|
||||
def _api_key(username: str) -> str:
|
||||
refresh_snapshot()
|
||||
return get_table("users").find_one(username=username)["api_key"]
|
||||
|
||||
|
||||
def test_http_ingress_proxy(app_server):
|
||||
import http.server
|
||||
import socket
|
||||
import socketserver
|
||||
import threading
|
||||
|
||||
sock = socket.socket()
|
||||
sock.bind(("127.0.0.1", 0))
|
||||
port = sock.getsockname()[1]
|
||||
sock.close()
|
||||
|
||||
class Handler(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/plain")
|
||||
self.end_headers()
|
||||
self.wfile.write(b"hello from upstream " + self.path.encode())
|
||||
|
||||
def log_message(self, *args):
|
||||
pass
|
||||
|
||||
httpd = socketserver.TCPServer(("127.0.0.1", port), Handler)
|
||||
thread = threading.Thread(target=httpd.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
slug = f"ing{port}"
|
||||
uid = f"ingtest-{port}"
|
||||
get_table("instances").insert(
|
||||
{
|
||||
"uid": uid,
|
||||
"name": "ingress",
|
||||
"project_uid": "ingtest",
|
||||
"status": "running",
|
||||
"ingress_slug": slug,
|
||||
"ingress_port": 8000,
|
||||
"ports_json": f'[{{"host": {port}, "container": 8000, "proto": "tcp"}}]',
|
||||
}
|
||||
)
|
||||
try:
|
||||
r = requests.get(f"{BASE_URL}/p/{slug}/foo")
|
||||
assert r.status_code == 200, r.text
|
||||
assert "hello from upstream" in r.text and "/foo" in r.text
|
||||
assert requests.get(f"{BASE_URL}/p/does-not-exist-slug").status_code == 404
|
||||
finally:
|
||||
httpd.shutdown()
|
||||
get_table("instances").delete(uid=uid)
|
||||
Reference in New Issue
Block a user