| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- using System;
- using IvfTl.ControlHost.Debug;
- using IvfTl.ControlHost.Tests.Fakes;
- using Xunit;
- namespace IvfTl.ControlHost.Tests
- {
- /// <summary>
- /// D2-02 Task3.2a:CalibrationManager 的 sid 校验路径(不触真实硬件标定)。
- /// 真实标定要硬件,这里只断言会话校验/字典管理的纯逻辑分支:
- /// · 不存在的 sid → StartCalibrate / GetProgress / Recalibrate 返回 SESSION_EXPIRED;
- /// · Stop 未知 sid 幂等返回 Okay;
- /// · houseBinOf 委托在 SESSION_EXPIRED 路径上绝不被调用(closure 未进入)。
- /// </summary>
- public class CalibrationManagerTests
- {
- private DateTime _now = new DateTime(2026, 6, 25, 0, 0, 0);
- private (CalibrationManager calib, DebugSessionManager debug, bool[] houseBinTouched) New()
- {
- var serial = new FakeSerial();
- var gate = new FakeGate(7, serial) { CanAcquire = true };
- var debug = new DebugSessionManager(sn => gate, () => _now, ttlMs: 10000, log: _ => { });
- var touched = new bool[1];
- // houseBinOf:SESSION_EXPIRED 路径下绝不应被调用;被调用则置标志,便于断言。
- var calib = new CalibrationManager(debug, sn => { touched[0] = true; return null; }, log: _ => { });
- return (calib, debug, touched);
- }
- [Fact]
- public void StartCalibrate_Unknown_Sid_Returns_SESSION_EXPIRED_Without_Touching_HouseBin()
- {
- var (calib, _, touched) = New();
- var r = calib.StartCalibrate("not-a-session", null);
- Assert.False(r.Ok);
- Assert.Equal("SESSION_EXPIRED", r.Code);
- Assert.False(touched[0]); // 会话校验先于取 HouseBin,委托不被触发
- }
- [Fact]
- public void GetProgress_Unknown_Sid_Returns_SESSION_EXPIRED()
- {
- var (calib, _, _) = New();
- var r = calib.GetProgress("nope");
- Assert.False(r.Ok);
- Assert.Equal("SESSION_EXPIRED", r.Code);
- }
- [Fact]
- public void Recalibrate_Unknown_Sid_Returns_SESSION_EXPIRED()
- {
- var (calib, _, _) = New();
- var r = calib.Recalibrate("nope", 3);
- Assert.False(r.Ok);
- Assert.Equal("SESSION_EXPIRED", r.Code);
- }
- [Fact]
- public void Stop_Unknown_Sid_Is_Idempotent_Ok()
- {
- var (calib, _, _) = New();
- Assert.True(calib.Stop("nope").Ok);
- Assert.True(calib.Stop(null).Ok);
- }
- // Critical 并发修复:StopAndWait 对未起标定的 sid 是 no-op 且返回 true,
- // 让 DebugSessionManager 的"会话即将关闭"回调即便该会话没在标定也能畅通(不阻塞 Dispose)。
- [Fact]
- public void StopAndWait_Unknown_Sid_Is_NoOp_ReturnsTrue()
- {
- var (calib, _, _) = New();
- Assert.True(calib.StopAndWait("nope", 1000));
- Assert.True(calib.StopAndWait(null, 1000));
- }
- // ── Task3.2b:标定预览帧缓冲的「非标定/无帧」安全分支(推流线程据此决定走 GrabStable) ──
- [Fact]
- public void IsCalibrating_NoSession_Returns_False()
- {
- // 无活跃协作器(未起标定)→ IsCalibrating=false → 推流线程走原 GrabStable 分支(行为零变化)。
- var (calib, _, _) = New();
- Assert.False(calib.IsCalibrating("nope"));
- Assert.False(calib.IsCalibrating(null));
- }
- [Fact]
- public void TryGetLatestFrame_NoFrame_Returns_False_And_Empty_Out()
- {
- // 未标定/无缓冲帧 → TryGetLatestFrame=false 且 out 全空;
- // 推流线程标定中遇此会跳过等下一帧、绝不 GrabStable(不争相机锁)。
- var (calib, _, _) = New();
- Assert.False(calib.TryGetLatestFrame("nope", out var bgr, out var w, out var h));
- Assert.Null(bgr);
- Assert.Equal(0, w);
- Assert.Equal(0, h);
- Assert.False(calib.TryGetLatestFrame(null, out _, out _, out _));
- }
- }
- }
|