Spaces:
Sleeping
Sleeping
| """End-to-end smoke test for the mock pipeline (no network, no GPU). | |
| Creates synthetic room images, drives every endpoint via FastAPI's TestClient, | |
| and asserts the generated output file actually lands on disk. | |
| Run: python scripts/smoke_test.py | |
| """ | |
| from __future__ import annotations | |
| import io | |
| import sys | |
| from pathlib import Path | |
| from PIL import Image, ImageDraw | |
| BACKEND_DIR = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(BACKEND_DIR)) | |
| from fastapi.testclient import TestClient # noqa: E402 | |
| from app.config import settings # noqa: E402 | |
| from app.main import app # noqa: E402 | |
| def make_room(floor_rgb, wall_rgb) -> bytes: | |
| """A trivial 'room': wall on the upper half, floor on the lower half.""" | |
| w, h = 1024, 768 | |
| img = Image.new("RGB", (w, h), wall_rgb) | |
| ImageDraw.Draw(img).rectangle([0, int(h * 0.5), w, h], fill=floor_rgb) | |
| buf = io.BytesIO() | |
| img.save(buf, format="JPEG") | |
| return buf.getvalue() | |
| def main() -> int: | |
| with TestClient(app) as client: # `with` runs the lifespan (init_db) | |
| r = client.get("/") | |
| assert r.status_code == 200, r.text | |
| print("health:", r.json()) | |
| r = client.get("/get-catalog") | |
| assert r.status_code == 200, r.text | |
| catalog = r.json() | |
| print("catalog items:", len(catalog)) | |
| assert 30 <= len(catalog) <= 40, "catalog must have 30-40 items" | |
| r = client.get("/get-catalog", params={"styles": "modern,minimal", "category": "sofa"}) | |
| recs = r.json() | |
| print("top sofa for modern,minimal:", recs[0]["name"], "score=", recs[0]["score"]) | |
| assert recs[0]["score"] >= recs[-1]["score"], "recommendations must be ranked" | |
| files = [ | |
| ("files", ("room1.jpg", make_room((150, 140, 130), (210, 205, 200)), "image/jpeg")), | |
| ("files", ("room2.jpg", make_room((120, 130, 140), (200, 205, 210)), "image/jpeg")), | |
| ("files", ("room3.jpg", make_room((140, 120, 110), (205, 200, 195)), "image/jpeg")), | |
| ] | |
| r = client.post("/upload-room", files=files) | |
| assert r.status_code == 200, r.text | |
| up = r.json() | |
| sid, img_id = up["session_id"], up["images"][0]["id"] | |
| print("uploaded:", len(up["images"]), "images; session", sid[:8]) | |
| assert len(up["images"]) == 3 | |
| # too-few-images guard | |
| r = client.post("/upload-room", files=files[:1]) | |
| assert r.status_code == 400, "should reject < 3 images" | |
| r = client.post("/analyze-room", json={"session_id": sid, "image_id": img_id}) | |
| assert r.status_code == 200, r.text | |
| an = r.json() | |
| print( | |
| "analyze: objects=", len(an["detected_objects"]), | |
| "floor_pts=", len(an["floor_polygon"]), | |
| "free=", an["free_space_ratio"], | |
| "ml_used=", an["ml_used"], | |
| ) | |
| assert len(an["floor_polygon"]) >= 3, "need a usable-floor polygon" | |
| item_ids = [catalog[0]["id"], catalog[7]["id"]] | |
| r = client.post( | |
| "/generate-room", | |
| json={"session_id": sid, "image_id": img_id, "item_ids": item_ids}, | |
| ) | |
| assert r.status_code == 200, r.text | |
| gen = r.json() | |
| print("generated:", gen["image_url"], "via", gen["provider"]) | |
| assert gen["provider"] == "mock" | |
| rel = gen["image_url"].split("/static/")[-1] | |
| out = settings.STATIC_DIR / rel | |
| assert out.exists(), f"missing output file {out}" | |
| print("output exists:", out.name, out.stat().st_size, "bytes") | |
| for p in gen["placements"]: | |
| print(" placement", p["item_id"], "->", p["scale_note"]) | |
| # confirm /remove-object does NOT exist | |
| r = client.post("/remove-object", json={}) | |
| assert r.status_code == 404, "/remove-object must not exist" | |
| print("confirmed: /remove-object returns 404 (removal is OUT)") | |
| print("\nSMOKE TEST PASSED") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |