Skip to content

Invalid modality input causes 500 and DSCProcessor returns hardcoded string #35

@Devguru-codes

Description

@Devguru-codes

Locations

  • apps/backend/app/routers/reports.py:32,82 (Input validation)
  • package/src/pyaslreport/modalities/testdsc/processor.py:17-30 (DSC Placeholder)

Description

Two sub-issues: (1) Passing an invalid modality string (e.g., "xyz") to either BIDS or DICOM endpoint causes ModalityTypeValues("xyz") to raise an uncaught ValueError, returning an unhelpful 500 error. (2) The DSCProcessor returns a hardcoded string "dsc data" instead of a dict, breaking the endpoint's response_model=dict contract.

Reproduction (on main branch)

Automated Results on main branch

# Test Status Detail
T1 Valid modality 'ASL' accepted (no 500) PASS
T2 Invalid modality 'xyz' on /bids → 422 FAIL Status=500
T3 Invalid modality 'INVALID' on /dicom → 422 FAIL Status=400
T4 No modality → defaults to ASL PASS
T5 DSCProcessor returns dict FAIL Got string 'dsc data'

Summary: PASSED=2 FAILED=3

API Responses on main

POST /api/report/process/bids modality=xyz → Status: 500
POST /api/report/process/dicom modality=INVALID → Status: 400 (file check ran first)
DSCProcessor.process() → type=str, value='dsc data'

Code to reproduce this -

"""Bug 4 reproduction: Modality Processing Flaws (Input Validation & DSC Placeholder)"""
import sys, os, json
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'apps', 'backend'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'package', 'src'))

from unittest.mock import MagicMock
sys.modules['weasyprint'] = MagicMock()

from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app, raise_server_exceptions=False)

results = []

# ========== Sub-issue 1: Invalid modality input validation ==========

# T1: Valid modality "ASL" should work (returns 400 for no files, not 500 for bad modality)
r1 = client.post("/api/report/process/bids", data={"modality": "ASL"})
ok1 = r1.status_code in (200, 400)
results.append({"test": "T1: Valid modality 'ASL' accepted (no 500)",
                "pass": ok1,
                "detail": "" if ok1 else f"Status={r1.status_code}"})

# T2: Invalid modality "xyz" on BIDS endpoint should return 422 (not 500)
r2 = client.post("/api/report/process/bids", data={"modality": "xyz"})
ok2 = r2.status_code == 422
results.append({"test": "T2: Invalid modality 'xyz' on /bids returns 422 (not 500)",
                "pass": ok2,
                "detail": "" if ok2 else f"Status={r2.status_code}"})

# T3: Invalid modality on DICOM endpoint should also return 422 (not 400 for missing files first)
r3 = client.post("/api/report/process/dicom", data={"modality": "INVALID"})
ok3 = r3.status_code == 422
results.append({"test": "T3: Invalid modality 'INVALID' on /dicom returns 422 (not 400/500)",
                "pass": ok3,
                "detail": "" if ok3 else f"Status={r3.status_code}"})

# T4: Empty modality defaults to ASL (should not crash)
r4 = client.post("/api/report/process/bids")
ok4 = r4.status_code in (200, 400)
results.append({"test": "T4: No modality provided defaults to ASL (no crash)",
                "pass": ok4,
                "detail": "" if ok4 else f"Status={r4.status_code}"})

# ========== Sub-issue 2: DSC Processor placeholder ==========

# T5: DSC modality should return a proper dict, not a hardcoded string
from pyaslreport.modalities.testdsc.processor import DSCProcessor
proc = DSCProcessor({"modality": "DSC", "files": [], "nifti_file": None, "dcm_files": []})
result = proc.process()
ok5 = isinstance(result, dict)
results.append({"test": "T5: DSCProcessor.process() returns dict (not hardcoded string)",
                "pass": ok5,
                "detail": "" if ok5 else f"Got type={type(result).__name__}, value={repr(result)}"})

# ========== Print results ==========
passed = sum(1 for r in results if r["pass"])
failed = sum(1 for r in results if not r["pass"])
print(f"PASSED={passed} FAILED={failed}")
for r in results:
    status = "PASS" if r["pass"] else "FAIL"
    detail = f" -- {r['detail']}" if r["detail"] else ""
    print(f"  [{status}] {r['test']}{detail}")

with open(os.path.join(os.path.dirname(__file__), 'results.json'), 'w') as f:
    json.dump({"passed": passed, "failed": failed, "results": results}, f, indent=2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions