test_spoolman_slot_ddl.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. """T-Gap 4: PostgreSQL DDL dialect tests for spoolman_slot_assignments table."""
  2. import re
  3. import pytest
  4. def _extract_spoolman_slot_ddl(is_sqlite: bool) -> str:
  5. """Extract the spoolman_slot_assignments DDL from database.py."""
  6. import inspect
  7. from unittest.mock import patch
  8. import backend.app.core.database as db_module
  9. source = inspect.getsource(db_module)
  10. # Find the block that creates spoolman_slot_assignments
  11. start = source.find("CREATE TABLE IF NOT EXISTS spoolman_slot_assignments")
  12. assert start != -1, "spoolman_slot_assignments DDL not found"
  13. # Scan forward to find the matching end of the SQL string
  14. block = source[start : start + 2000]
  15. return block
  16. class TestSpoolmanSlotDdl:
  17. """Verify the DDL for spoolman_slot_assignments contains required constraints."""
  18. def test_sqlite_ddl_has_named_unique_constraint(self):
  19. ddl = _extract_spoolman_slot_ddl(is_sqlite=True)
  20. assert "uq_slot_assignment" in ddl, "Named UNIQUE constraint missing from SQLite DDL"
  21. def test_sqlite_ddl_has_ams_id_check(self):
  22. ddl = _extract_spoolman_slot_ddl(is_sqlite=True)
  23. # ams_id allows 0–7 for physical AMS units and 255 for external slot
  24. assert re.search(r"ams_id.*CHECK.*ams_id.*>=.*0.*AND.*ams_id.*<=.*7.*OR.*ams_id.*=.*255", ddl, re.DOTALL), (
  25. "ams_id CHECK constraint missing from SQLite DDL"
  26. )
  27. def test_sqlite_ddl_has_tray_id_check(self):
  28. ddl = _extract_spoolman_slot_ddl(is_sqlite=True)
  29. assert re.search(r"tray_id.*CHECK.*tray_id.*>=.*0.*AND.*tray_id.*<=.*3", ddl, re.DOTALL), (
  30. "tray_id CHECK constraint missing from SQLite DDL"
  31. )
  32. def test_postgres_ddl_has_named_unique_constraint(self):
  33. ddl = _extract_spoolman_slot_ddl(is_sqlite=False)
  34. # PostgreSQL DDL appears after the SQLite block
  35. pg_start = ddl.find("SERIAL PRIMARY KEY")
  36. assert pg_start != -1 or "uq_slot_assignment" in ddl, "uq_slot_assignment not found in DDL"
  37. def test_orm_model_has_named_unique_constraint(self):
  38. from sqlalchemy import inspect as sa_inspect
  39. from backend.app.models.spoolman_slot_assignment import SpoolmanSlotAssignment
  40. table = SpoolmanSlotAssignment.__table__
  41. constraint_names = {c.name for c in table.constraints}
  42. assert "uq_slot_assignment" in constraint_names, (
  43. f"uq_slot_assignment not in ORM constraints: {constraint_names}"
  44. )
  45. def test_orm_model_has_ams_id_check_constraint(self):
  46. from sqlalchemy import CheckConstraint
  47. from backend.app.models.spoolman_slot_assignment import SpoolmanSlotAssignment
  48. table = SpoolmanSlotAssignment.__table__
  49. check_names = {c.name for c in table.constraints if isinstance(c, CheckConstraint)}
  50. assert "ck_ams_id_range" in check_names, f"ck_ams_id_range not in ORM check constraints: {check_names}"
  51. def test_orm_model_has_tray_id_check_constraint(self):
  52. from sqlalchemy import CheckConstraint
  53. from backend.app.models.spoolman_slot_assignment import SpoolmanSlotAssignment
  54. table = SpoolmanSlotAssignment.__table__
  55. check_names = {c.name for c in table.constraints if isinstance(c, CheckConstraint)}
  56. assert "ck_tray_id_range" in check_names, f"ck_tray_id_range not in ORM check constraints: {check_names}"