test.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import importlib
  2. import io
  3. import json
  4. import os
  5. import pytest
  6. from fastapi.testclient import TestClient
  7. @pytest.fixture()
  8. def client(tmp_path, monkeypatch):
  9. app_mod = importlib.import_module("app")
  10. app_mod.STORE_DIR = str(tmp_path)
  11. os.makedirs(app_mod.STORE_DIR, exist_ok=True)
  12. class DummyRecoApp:
  13. def __init__(self, name, digit, shift):
  14. self.name = name
  15. self.digit = digit
  16. self.shift = shift
  17. def start_reconstruction(self, path_raw_data, path_np_data_json, path_order_json):
  18. import matplotlib.pyplot as plt
  19. plt.figure()
  20. plt.plot([0, 1], [0, 1])
  21. plt.title(f"{self.name}-{self.digit}")
  22. plt.savefig("data/test.png")
  23. plt.close()
  24. monkeypatch.setattr(app_mod, "ReconstructionApp", DummyRecoApp, raising=True)
  25. return TestClient(app_mod.app)
  26. def _upload(client: TestClient, name: str, content: bytes, mime: str = "application/octet-stream"):
  27. files = {"file": (name, io.BytesIO(content), mime)}
  28. r = client.post("/upload", files=files)
  29. assert r.status_code == 200, r.text
  30. obj = r.json()
  31. assert "file_id" in obj
  32. return obj["file_id"]
  33. def test_upload_json(client: TestClient):
  34. params = {
  35. "Np": 8, "Nf": 8, "sl_nb": 1,
  36. "contrasts": 1, "RF_spoil": 0,
  37. "ETL": 0, "N_TE": 0, "phi_wing": 0, "N_wings": 0,
  38. "D_scans": 1
  39. }
  40. fid = _upload(client, "params.json", json.dumps(params).encode("utf-8"), "application/json")
  41. assert isinstance(fid, str) and len(fid) > 0
  42. def test_upload_h5(client: TestClient):
  43. fake = b"\x89HDF\r\n\x1a\n" + b"\x00" * 64
  44. fid = _upload(client, "raw.h5", fake, "application/octet-stream")
  45. assert isinstance(fid, str) and len(fid) > 0
  46. def test_full_reconstruction_flow(client: TestClient, tmp_path):
  47. raw_bytes = b"\x89HDF\r\n\x1a\n" + b"\x00" * 64
  48. raw_id = _upload(client, "raw.h5", raw_bytes)
  49. params = {
  50. "Np": 8, "Nf": 8, "sl_nb": 1,
  51. "contrasts": 1, "RF_spoil": 0,
  52. "ETL": 0, "N_TE": 0, "phi_wing": 0, "N_wings": 0,
  53. "D_scans": 1
  54. }
  55. json_id = _upload(client, "params.json", json.dumps(params).encode("utf-8"), "application/json")
  56. payload = {
  57. "file_raw_id": raw_id,
  58. "file_json_id": json_id,
  59. "file_order_id": None,
  60. "sequence_name": "linear_decart",
  61. "digit": "2d",
  62. "phase_shift": True
  63. }
  64. r = client.post("/reconstruct", json=payload)
  65. assert r.status_code == 200, r.text
  66. job = r.json()
  67. job_id = job["job_id"]
  68. for _ in range(50):
  69. s = client.get(f"/jobs/{job_id}")
  70. assert s.status_code == 200
  71. st = s.json()
  72. if st["status"] in ("done", "error"):
  73. break
  74. assert st["status"] == "done", f"job failed: {st.get('error_traceback')}"
  75. lf = client.get(f"/jobs/{job_id}/files")
  76. assert lf.status_code == 200
  77. files = lf.json()["files"]
  78. assert any(name.endswith(".png") for name in files), f"no png files in {files}"
  79. dz = client.get(f"/jobs/{job_id}/archive.zip")
  80. assert dz.status_code == 200
  81. assert dz.headers.get("content-type") == "application/zip"
  82. def test_reconstruct_bad_ids(client: TestClient):
  83. payload = {
  84. "file_raw_id": "nope",
  85. "file_json_id": "nope",
  86. "file_order_id": None,
  87. "sequence_name": "linear_decart",
  88. "digit": "2d",
  89. "phase_shift": False
  90. }
  91. r = client.post("/reconstruct", json=payload)
  92. assert r.status_code == 400