test_repository_rules.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import inspect
  2. from types import SimpleNamespace
  3. from app.repositories import ScriptBuildRepository
  4. class Row:
  5. def __init__(self, **values):
  6. self.__dict__.update(values)
  7. self.__table__ = SimpleNamespace(
  8. columns=[SimpleNamespace(name=name) for name in values]
  9. )
  10. def test_final_snapshot_filters_branch_zero_and_overlay_replaces_base_rows():
  11. repository = ScriptBuildRepository()
  12. paragraphs = [
  13. Row(id=1, branch_id=0, is_active=True, base_ref_id=None, content="base"),
  14. Row(id=2, branch_id=7, is_active=True, base_ref_id=1, content="overlay"),
  15. Row(id=3, branch_id=9, is_active=True, base_ref_id=None, content="other"),
  16. ]
  17. elements = [
  18. Row(id=10, branch_id=0, is_active=True, base_ref_id=None, content="base-element"),
  19. Row(id=11, branch_id=7, is_active=True, base_ref_id=10, content="overlay-element"),
  20. ]
  21. links = [
  22. Row(id=20, branch_id=0, paragraph_id=1, element_id=10),
  23. Row(id=21, branch_id=7, paragraph_id=2, element_id=11),
  24. ]
  25. final_snapshot = repository._snapshot_for_branch(0, paragraphs, elements, links)
  26. assert {row["branch_id"] for row in final_snapshot["paragraphs"]} == {0}
  27. assert {row["branch_id"] for row in final_snapshot["elements"]} == {0}
  28. assert {row["branch_id"] for row in final_snapshot["paragraphElements"]} == {0}
  29. overlay = repository._snapshot_for_branch(7, paragraphs, elements, links)
  30. assert [row["content"] for row in overlay["paragraphs"]] == ["overlay"]
  31. assert [row["content"] for row in overlay["elements"]] == ["overlay-element"]
  32. def test_candidate_snapshot_uses_saved_content_for_terminal_branch_and_overlay_for_park():
  33. repository = ScriptBuildRepository()
  34. merged = Row(status="merged", branch_id=1, content_snapshot={"paragraphs": [{"id": "saved"}]})
  35. parked = Row(status="parked", branch_id=2, content_snapshot=None)
  36. saved = repository._candidate_snapshot(merged, paragraphs=[], elements=[], links=[])
  37. assert saved["snapshot"]["paragraphs"][0]["id"] == "saved"
  38. assert saved["historicalAccuracy"] == "exact"
  39. assert saved["snapshotKind"] == "saved-at-disposition"
  40. overlay = repository._candidate_snapshot(parked, paragraphs=[], elements=[], links=[])
  41. assert overlay["sourceOrigin"] == "database"
  42. assert overlay["historicalAccuracy"] == "unknown"
  43. assert overlay["currentProjectionAccuracy"] == "exact"
  44. assert "不是暂存时的历史快照" in overlay["note"]
  45. def test_terminal_branch_without_snapshot_is_not_reconstructed_from_current_base():
  46. repository = ScriptBuildRepository()
  47. merged = Row(status="merged", branch_id=7, content_snapshot=None)
  48. result = repository._candidate_snapshot(merged, paragraphs=[], elements=[], links=[])
  49. assert result["snapshot"] is None
  50. assert result["historicalAccuracy"] == "missing"
  51. assert result["currentProjectionAccuracy"] == "not-applicable"
  52. assert result["snapshotKind"] == "missing-disposition-snapshot"
  53. def test_base_links_require_both_active_endpoints_and_override_has_effective_id():
  54. repository = ScriptBuildRepository()
  55. paragraphs = [
  56. Row(id=1, branch_id=0, is_active=True, base_ref_id=None),
  57. Row(id=2, branch_id=0, is_active=False, base_ref_id=None),
  58. Row(id=3, branch_id=7, is_active=True, base_ref_id=1),
  59. ]
  60. elements = [Row(id=10, branch_id=0, is_active=True, base_ref_id=None)]
  61. links = [
  62. Row(id=20, branch_id=0, paragraph_id=1, element_id=10),
  63. Row(id=21, branch_id=0, paragraph_id=2, element_id=10),
  64. ]
  65. base = repository._snapshot_for_branch(0, paragraphs, elements, links)
  66. assert [row["id"] for row in base["paragraphElements"]] == [20]
  67. overlay = repository._snapshot_for_branch(7, paragraphs, elements, links)
  68. assert overlay["paragraphs"][0]["rowId"] == 3
  69. assert overlay["paragraphs"][0]["effectiveId"] == 1
  70. def test_repository_implementation_contains_no_write_or_commit_calls():
  71. source = inspect.getsource(ScriptBuildRepository)
  72. for forbidden in (".commit(", ".flush(", ".add(", ".delete(", ".execute("):
  73. assert forbidden not in source
  74. def test_latest_split_event_body_fields_are_parsed_without_old_schema():
  75. repository = ScriptBuildRepository()
  76. body = Row(
  77. id=1,
  78. event_id=9,
  79. input_content_type="json",
  80. input_content='{"task": "查找案例"}',
  81. output_content_type="json",
  82. output_content='{"summary": "初筛完成"}',
  83. )
  84. parsed = repository._event_body(body)
  85. assert parsed["input"]["content"] == {"task": "查找案例"}
  86. assert parsed["output"]["content"] == {"summary": "初筛完成"}
  87. source = inspect.getsource(ScriptBuildRepository._event_body)
  88. assert "input_body_id" not in source
  89. assert "output_body_id" not in source
  90. def test_oversized_event_body_is_safely_bounded_and_reports_omitted_characters():
  91. raw = '{"content":"' + ("x" * 250_000) + '"}'
  92. parsed = ScriptBuildRepository._body_side("json", raw)
  93. assert parsed["truncated"] is True
  94. assert parsed["omittedCharacters"] == len(raw) - 240_000
  95. assert "[truncated" in parsed["content"]
  96. assert len(parsed["content"]) < len(raw)
  97. def test_main_view_reads_bodies_only_for_retrieval_evaluation_and_creative_agents():
  98. repository = ScriptBuildRepository()
  99. assert repository._needs_light_agent_body({"event_type": "agent_invoke", "event_name": "retrieve_data_knowledge"})
  100. assert repository._needs_light_agent_body({"event_type": "agent_invoke", "event_name": "script_multipath_evaluator"})
  101. assert repository._needs_light_agent_body({"event_type": "agent_invoke", "event_name": "script_implementer"})
  102. assert not repository._needs_light_agent_body({"event_type": "tool_call", "event_name": "retrieve_data_knowledge"})