Files
recordingtest/docs/contracts/engine-bridge-v2.md

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.dllHintPath로 참조 (Private=false, SUT의 정본 복사 금지)
    • Editor03.PluginInterface.dll실제 계약을 MetadataLoadContext로 분석해서 구현할 최소 interface/attribute를 확인 (Generator가 discovery 수행)
    • 플러그인 로드 시점에 HttpListenerhttp://localhost:{port}/ 시작 (기본 포트 38080, 환경변수 RECORDINGTEST_BRIDGE_PORT로 override)
    • 엔드포인트: /selection, /camera, /scene, /render, /health
    • 각 엔드포인트는 IEngineStateProvider 인터페이스로부터 JSON을 반환
    • 기본 ReflectionEngineStateProvider는 HmEG 내부 타입을 리플렉션으로 찾아 상태를 구성 (실패해도 예외 삼킴 — {error: "..."} 반환)
    • 플러그인 unload 시 HttpListener 정리
  • 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:
      1. Client_SelectionEndpoint_ReturnsIds
      2. Client_CameraEndpoint_ReturnsCameraState
      3. Client_SceneEndpoint_ReturnsSceneSummary
      4. Client_RenderEndpoint_ReturnsIsComplete
      5. Client_HealthEndpoint_ReturnsOk
      6. Client_Timeout_ThrowsOrReturnsError (2초 이내 미응답 시)
  • src/Recordingtest.EgPlugin 단위 테스트 ≥ 3 (플러그인 로직)
    • 테스트에서 실제 plugin dll을 SUT에 주입하지 않음. 순수 로직만.
    • StateRouter_SerializesSelection_ToJson
    • StateRouter_WithFaultyProvider_ReturnsErrorPayload
    • PortResolver_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

  1. dotnet build recordingtest.sln green
  2. dotnet test tests/Recordingtest.EngineBridge.IntegrationTests — 6 pass
  3. dotnet test tests/Recordingtest.EgPlugin.Tests — 3 pass
  4. Recordingtest.EgPlugin.dll 출력 확인, Editor03.PluginInterface에 대한 HintPath/Private=false 확인 (csproj 리뷰)
  5. Generator가 Editor03.PluginInterface.dll 메타데이터에서 발견한 실제 인터페이스 이름을 history에 기록했는지 확인
  6. docs/guides/engine-bridge-deploy.md 존재 + 배포 단계(복사·환경변수·검증) 기술
  7. SUT 폴더에 쓰기 흔적 없음 (grep)
  8. Plugin 코드가 HttpListener 예외 상황(port 충돌, stop) 처리

Risks

  • Editor03.PluginInterface가 WPF dependency를 가지면 net8.0-windows로 충분하지 않을 수 있음 — 필요 시 TFM 조정
  • 플러그인 dll이 SUT와 같은 디렉터리의 다른 dll 버전과 충돌 가능 — Private=false 필수
  • HmEG 리플렉션 실제 매핑은 SUT 런타임에서만 검증 가능 → v2는 error fallback 철저