test_pattern_pg.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. from __future__ import annotations
  2. import sys
  3. import types
  4. import pytest
  5. from content_agent.errors import ContentAgentError, ErrorCode
  6. from content_agent.integrations.pattern_pg import PatternPgClient
  7. class FakeCursor:
  8. def __init__(self, *, fail_on_execute: bool = False) -> None:
  9. self.fail_on_execute = fail_on_execute
  10. self.executed: list[tuple[str, object | None]] = []
  11. def execute(self, sql, params=None):
  12. self.executed.append((sql, params))
  13. if self.fail_on_execute:
  14. raise RuntimeError('syntax error at or near "$1"')
  15. def fetchone(self):
  16. return (1,)
  17. class FakeConnection:
  18. def __init__(self, cursor: FakeCursor) -> None:
  19. self._cursor = cursor
  20. self.closed = False
  21. def cursor(self):
  22. return self._cursor
  23. def close(self):
  24. self.closed = True
  25. def _install_fake_pg8000(monkeypatch, connect_fn):
  26. fake_pkg = types.ModuleType("pg8000")
  27. fake_pkg.__path__ = []
  28. fake_dbapi = types.ModuleType("pg8000.dbapi")
  29. fake_dbapi.connect = connect_fn
  30. fake_pkg.dbapi = fake_dbapi
  31. monkeypatch.setitem(sys.modules, "pg8000", fake_pkg)
  32. monkeypatch.setitem(sys.modules, "pg8000.dbapi", fake_dbapi)
  33. def _client() -> PatternPgClient:
  34. return PatternPgClient(
  35. host="127.0.0.1",
  36. port=5432,
  37. user="u",
  38. password="p",
  39. database="open_aigc",
  40. timeout_seconds=30,
  41. )
  42. def test_pattern_pg_sets_statement_timeout_without_parameter_placeholder(monkeypatch):
  43. cursor = FakeCursor()
  44. connection = FakeConnection(cursor)
  45. _install_fake_pg8000(monkeypatch, lambda **kwargs: connection)
  46. assert _client().has_terminal_element(581, [101, 102]) is True
  47. timeout_sql, timeout_params = cursor.executed[0]
  48. assert timeout_sql == "SET statement_timeout = 30000"
  49. assert timeout_params is None
  50. assert "$1" not in timeout_sql
  51. assert connection.closed is True
  52. def test_pattern_pg_query_failure_keeps_original_error_message(monkeypatch):
  53. cursor = FakeCursor(fail_on_execute=True)
  54. connection = FakeConnection(cursor)
  55. _install_fake_pg8000(monkeypatch, lambda **kwargs: connection)
  56. with pytest.raises(ContentAgentError) as exc:
  57. _client().has_terminal_element(581, [101])
  58. assert exc.value.error_code == ErrorCode.DB_SCHEMA_NOT_READY
  59. assert exc.value.detail["exception_type"] == "RuntimeError"
  60. assert 'syntax error at or near "$1"' in exc.value.detail["error_message"]
  61. assert exc.value.detail["execution_id"] == 581
  62. assert exc.value.detail["category_id_count"] == 1
  63. assert connection.closed is True