Sfoglia il codice sorgente

test(上传输入): 覆盖 input 与 runtime 双库路由

使用两个独立 SQLite 数据库模拟生产分库。断言 execution_id=0 只从 runtime 读取上传 topic,并完整还原 point-item 关系,防止再次出现写入成功但冻结输入不可见。
SamLee 15 ore fa
parent
commit
e77266237f
1 ha cambiato i file con 83 aggiunte e 1 eliminazioni
  1. 83 1
      script_build_host/tests/test_legacy_input_and_adapters.py

+ 83 - 1
script_build_host/tests/test_legacy_input_and_adapters.py

@@ -5,7 +5,12 @@ from pathlib import Path
 
 import pytest
 from sqlalchemy import insert
-from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
+from sqlalchemy.ext.asyncio import (
+    AsyncEngine,
+    AsyncSession,
+    async_sessionmaker,
+    create_async_engine,
+)
 
 from script_build_host.adapters.persona import FilePersonaSource
 from script_build_host.adapters.prompts import DatabaseFirstPromptSource
@@ -24,6 +29,7 @@ from script_build_host.infrastructure.legacy_tables import (
     topic_build_record,
     topic_build_topic,
     topic_pattern_execution,
+    legacy_metadata,
 )
 from script_build_host.repositories.legacy_input import LegacySqlAlchemyInputReader
 
@@ -170,6 +176,82 @@ async def test_legacy_reader_fails_closed_on_relation_mismatch(
         await reader.read_topic_graph(execution_id=10, topic_build_id=20, topic_id=30)
 
 
+@pytest.mark.asyncio
+async def test_legacy_reader_routes_uploaded_topics_to_runtime_database(
+    database: tuple[AsyncEngine, async_sessionmaker[AsyncSession]],
+    tmp_path: Path,
+) -> None:
+    _, input_sessions = database
+    runtime_engine = create_async_engine(f"sqlite+aiosqlite:///{tmp_path / 'runtime.db'}")
+    async with runtime_engine.begin() as connection:
+        await connection.run_sync(legacy_metadata.create_all)
+    runtime_sessions = async_sessionmaker(runtime_engine, expire_on_commit=False)
+    try:
+        async with runtime_sessions() as session, session.begin():
+            await session.execute(
+                insert(topic_build_record).values(
+                    id=21,
+                    execution_id=0,
+                    agent_type="UploadedTopic",
+                    status="success",
+                    is_deleted=False,
+                    personal_config={"account_name": "uploaded-account"},
+                    origin="upload",
+                )
+            )
+            await session.execute(
+                insert(topic_build_topic).values(
+                    id=31,
+                    build_id=21,
+                    execution_id=0,
+                    sort_order=0,
+                    result="uploaded topic",
+                    status="mature",
+                )
+            )
+            await session.execute(
+                insert(topic_build_point).values(
+                    id=41,
+                    topic_id=31,
+                    build_id=21,
+                    point_type="关键点",
+                    point_result="uploaded point",
+                    is_active=True,
+                )
+            )
+            await session.execute(
+                insert(topic_build_composition_item).values(
+                    id=51,
+                    topic_id=31,
+                    build_id=21,
+                    item_level="element",
+                    dimension="实质",
+                    point_type="关键点",
+                    element_name="uploaded element",
+                    step=0,
+                    sort_order=0,
+                    is_active=True,
+                )
+            )
+            await session.execute(
+                insert(topic_build_point_item_relation).values(
+                    id=61,
+                    point_id=41,
+                    item_id=51,
+                )
+            )
+
+        graph = await LegacySqlAlchemyInputReader(
+            input_sessions,
+            uploaded_sessions=runtime_sessions,
+        ).read_topic_graph(execution_id=0, topic_build_id=21, topic_id=31)
+        assert graph["build_record"]["origin"] == "upload"
+        assert graph["topic"]["result"] == "uploaded topic"
+        assert graph["points"][0]["item_ids"] == [51]
+    finally:
+        await runtime_engine.dispose()
+
+
 @pytest.mark.asyncio
 async def test_persona_adapter_applies_alias_filters_and_versions(tmp_path: Path) -> None:
     persona_root = tmp_path / "persona"