test_runtime_bridge.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. from types import SimpleNamespace
  2. import pytest
  3. from sqlalchemy import create_engine
  4. from app import runtime_bridge
  5. def test_database_host_override_is_host_only(monkeypatch):
  6. monkeypatch.setenv("PATTERN_DB_HOST_OVERRIDE", "192.168.202.204")
  7. assert runtime_bridge.database_host_override() == "192.168.202.204"
  8. for invalid in ("mysql://host", "host:3306", "user@host", "host name"):
  9. monkeypatch.setenv("PATTERN_DB_HOST_OVERRIDE", invalid)
  10. with pytest.raises(ValueError):
  11. runtime_bridge.database_host_override()
  12. def test_override_factory_replaces_only_host_and_keeps_parent_database(monkeypatch):
  13. class FakeDatabaseManager:
  14. def __init__(self):
  15. self.engine = create_engine("mysql+pymysql://reader:secret@old-host:3306/open_aigc_pattern")
  16. monkeypatch.setattr(
  17. runtime_bridge,
  18. "load_runtime_modules",
  19. lambda: (SimpleNamespace(DatabaseManager=FakeDatabaseManager), SimpleNamespace()),
  20. )
  21. runtime_bridge._read_only_session_factory.cache_clear()
  22. factory = runtime_bridge._read_only_session_factory("/runtime", "192.168.202.204")
  23. engine = factory.kw["bind"]
  24. try:
  25. assert engine.url.host == "192.168.202.204"
  26. assert engine.url.port == 3306
  27. assert engine.url.database == "open_aigc_pattern"
  28. assert engine.url.username == "reader"
  29. assert engine.url.password == "secret"
  30. finally:
  31. engine.dispose()
  32. runtime_bridge._read_only_session_factory.cache_clear()
  33. def test_read_only_factory_keeps_original_host_without_override(monkeypatch):
  34. class FakeDatabaseManager:
  35. def __init__(self):
  36. self.engine = create_engine("mysql+pymysql://reader:secret@db-host:3306/open_aigc_pattern")
  37. monkeypatch.setattr(
  38. runtime_bridge,
  39. "load_runtime_modules",
  40. lambda: (SimpleNamespace(DatabaseManager=FakeDatabaseManager), SimpleNamespace()),
  41. )
  42. runtime_bridge._read_only_session_factory.cache_clear()
  43. factory = runtime_bridge._read_only_session_factory("/runtime", "")
  44. engine = factory.kw["bind"]
  45. try:
  46. assert engine.url.host == "db-host"
  47. assert engine.url.database == "open_aigc_pattern"
  48. finally:
  49. engine.dispose()
  50. runtime_bridge._read_only_session_factory.cache_clear()
  51. def test_read_only_hook_executes_only_session_guard():
  52. statements = []
  53. class Cursor:
  54. def execute(self, statement):
  55. statements.append(statement)
  56. def close(self):
  57. statements.append("closed")
  58. runtime_bridge._set_mysql_session_read_only(SimpleNamespace(cursor=lambda: Cursor()), None)
  59. assert statements == ["SET SESSION TRANSACTION READ ONLY", "closed"]