test_database_source_registration.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. from __future__ import annotations
  2. from types import SimpleNamespace
  3. import pytest
  4. class MemorySourceRepository:
  5. def __init__(self):
  6. self.records = {}
  7. def get(self, uid):
  8. return self.records.get(str(uid))
  9. def save(self, record):
  10. self.records[str(record.uid)] = record
  11. return record
  12. def definition(**overrides):
  13. values = {
  14. "uid": "00000000-0000-0000-0000-000000000001",
  15. "name_en": "equipment_registry",
  16. "name_zh": "设备台账库",
  17. "database_type": "postgresql",
  18. "database": "equipment",
  19. "schema": "asset",
  20. "status": True,
  21. "host": "db.internal.example",
  22. "credential_ref": "vault://must-not-copy",
  23. }
  24. values.update(overrides)
  25. return SimpleNamespace(**values)
  26. def test_database_source_registration_is_idempotent_and_secret_free():
  27. from app.core.data_research.sources import DatabaseSourceRegistrationService
  28. repository = MemorySourceRepository()
  29. current = definition()
  30. commits = []
  31. service = DatabaseSourceRegistrationService(
  32. repository,
  33. definition_resolver=lambda _uid: current,
  34. commit=lambda: commits.append("commit"),
  35. )
  36. first, first_created = service.ensure(current.uid, actor_uid="editor-1")
  37. second, second_created = service.ensure(current.uid, actor_uid="editor-2")
  38. assert first_created is True
  39. assert second_created is False
  40. assert second.uid == current.uid
  41. assert second.name == "设备台账库"
  42. assert second.config == {
  43. "database_type": "postgresql",
  44. "database": "equipment",
  45. "schema": "asset",
  46. }
  47. assert "host" not in second.config
  48. assert "credential" not in str(second.config).lower()
  49. assert commits == ["commit", "commit"]
  50. @pytest.mark.parametrize(
  51. ("candidate", "message"),
  52. [
  53. (None, "not found"),
  54. (definition(status=False), "disabled"),
  55. (definition(database_type="oracle"), "not supported"),
  56. ],
  57. )
  58. def test_database_source_registration_rejects_unusable_definitions(
  59. candidate,
  60. message,
  61. ):
  62. from app.core.data_research.errors import IngestionSourceInvalid
  63. from app.core.data_research.sources import DatabaseSourceRegistrationService
  64. repository = MemorySourceRepository()
  65. service = DatabaseSourceRegistrationService(
  66. repository,
  67. definition_resolver=lambda _uid: candidate,
  68. )
  69. with pytest.raises(IngestionSourceInvalid, match=message):
  70. service.ensure(
  71. "00000000-0000-0000-0000-000000000001",
  72. actor_uid="editor-1",
  73. )
  74. assert repository.records == {}