4.6 KiB
4.6 KiB
Sprint Contract — engine-bridge v2 (MEF plugin masquerade)
Owner: Generator Depends on: engine-bridge v1 (완료) Issue: #10
Goal
engine-bridge v1 probe design 문서가 권고한 MEF plugin masquerade 경로를 구현한다. recordingtest 전용 플러그인을 빌드해 EG-BIM Modeler/Plugins/에 drop-in하면, SUT가 로드할 때 플러그인이 로컬 HTTP 서버를 띄워 HmEG 상태(선택/카메라/씬/렌더)를 JSON으로 노출한다. recordingtest-side 클라이언트는 HTTP로 상태를 조회한다.
PoC 범위: 플러그인 + 클라이언트 빌드 + 엔드투엔드 HTTP 테스트 (가짜 엔진 상태 주입). SUT 실제 실행은 수동 smoke test 단계에서.
Definition of Done
src/Recordingtest.EgPlugin/— MEF plugin dll- Target:
net8.0-windows Editor03.PluginInterface.dll을HintPath로 참조 (Private=false, SUT의 정본 복사 금지)Editor03.PluginInterface.dll의 실제 계약을 MetadataLoadContext로 분석해서 구현할 최소 interface/attribute를 확인 (Generator가 discovery 수행)- 플러그인 로드 시점에
HttpListener로http://localhost:{port}/시작 (기본 포트38080, 환경변수RECORDINGTEST_BRIDGE_PORT로 override) - 엔드포인트:
/selection,/camera,/scene,/render,/health - 각 엔드포인트는
IEngineStateProvider인터페이스로부터 JSON을 반환 - 기본
ReflectionEngineStateProvider는 HmEG 내부 타입을 리플렉션으로 찾아 상태를 구성 (실패해도 예외 삼킴 —{error: "..."}반환) - 플러그인 unload 시 HttpListener 정리
- Target:
src/Recordingtest.EngineBridge.Client/— HTTP 클라이언트 라이브러리HmEgHttpSnapshot : IEngineSnapshot구현 (v1 인터페이스 재사용)HttpClient로 엔드포인트 호출, 타임아웃 기본 2초- 각 속성은 on-demand HTTP GET (caching 없음 v2)
IsRenderComplete는/render응답의complete필드
tests/Recordingtest.EngineBridge.IntegrationTests/— xUnit- fake HTTP 서버:
HttpListener를 테스트 안에서 띄우고 고정 JSON 응답 - 테스트 ≥ 6:
Client_SelectionEndpoint_ReturnsIdsClient_CameraEndpoint_ReturnsCameraStateClient_SceneEndpoint_ReturnsSceneSummaryClient_RenderEndpoint_ReturnsIsCompleteClient_HealthEndpoint_ReturnsOkClient_Timeout_ThrowsOrReturnsError(2초 이내 미응답 시)
- fake HTTP 서버:
src/Recordingtest.EgPlugin단위 테스트 ≥ 3 (플러그인 로직)- 테스트에서 실제 plugin dll을 SUT에 주입하지 않음. 순수 로직만.
StateRouter_SerializesSelection_ToJsonStateRouter_WithFaultyProvider_ReturnsErrorPayloadPortResolver_PrefersEnvVar(RECORDINGTEST_BRIDGE_PORT)
docs/guides/engine-bridge-deploy.md— 수동 배포 가이드 (SUT Plugins/ 폴더에 dll 복사, 환경변수 설정, 검증 절차)dotnet build+dotnet test전부 green- 플러그인이 SUT 자체 파일을 건드리지 않음 (guard hook 준수)
Out of scope
- SUT 실제 실행 (수동 smoke test)
- 인증/암호화 (PoC는 localhost only)
- 멀티클라이언트 / 동시성 (단일 HttpListener)
- HmEG 리플렉션 매핑 완성도 — v2는 skeleton + error fallback 중심, 진짜 매핑은 smoke test 후 조정
Interfaces
- Inputs: SUT가 plugin을 로드할 때의 MEF 계약
- Outputs:
http://localhost:<port>/{selection|camera|scene|render|health}JSON - Side effects: HttpListener 포트 점유 (플러그인 생명주기 내)
Evaluation plan
dotnet build recordingtest.slngreendotnet test tests/Recordingtest.EngineBridge.IntegrationTests— 6 passdotnet test tests/Recordingtest.EgPlugin.Tests— 3 passRecordingtest.EgPlugin.dll출력 확인,Editor03.PluginInterface에 대한 HintPath/Private=false 확인 (csproj 리뷰)- Generator가 Editor03.PluginInterface.dll 메타데이터에서 발견한 실제 인터페이스 이름을 history에 기록했는지 확인
docs/guides/engine-bridge-deploy.md존재 + 배포 단계(복사·환경변수·검증) 기술- SUT 폴더에 쓰기 흔적 없음 (grep)
- Plugin 코드가
HttpListener예외 상황(port 충돌, stop) 처리
Risks
Editor03.PluginInterface가 WPF dependency를 가지면 net8.0-windows로 충분하지 않을 수 있음 — 필요 시 TFM 조정- 플러그인 dll이 SUT와 같은 디렉터리의 다른 dll 버전과 충돌 가능 — Private=false 필수
- HmEG 리플렉션 실제 매핑은 SUT 런타임에서만 검증 가능 → v2는 error fallback 철저