| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- using System;
- using System.Collections.Generic;
- using System.Net;
- using System.Net.Http;
- using System.Threading;
- using System.Threading.Tasks;
- using ivf_tl_Operate.Debug;
- using Newtonsoft.Json.Linq;
- using Xunit;
- namespace IvfTl.ControlHost.Tests
- {
- /// <summary>
- /// operate 端 CalibrationClient 纯逻辑单测:用 fake HttpMessageHandler 注入 control 端
- /// /debug/calibrate/* 的响应,验证四个端点的路径/请求体/解析。
- /// 进度响应是 control 端 JsonConvert.SerializeObject(DebugCommandResult)——result 内嵌
- /// CalibProgress(PascalCase 字段,WellCalibState 枚举默认序列化为数字)。
- /// </summary>
- public class CalibrationClientTests
- {
- private sealed class FakeHandler : HttpMessageHandler
- {
- public Func<HttpRequestMessage, string, (HttpStatusCode, string)> Responder;
- public string LastPath;
- public string LastBody;
- protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken ct)
- {
- LastPath = req.RequestUri.AbsolutePath;
- LastBody = req.Content != null ? await req.Content.ReadAsStringAsync() : "";
- var (code, body) = Responder(req, LastBody);
- return new HttpResponseMessage(code) { Content = new StringContent(body) };
- }
- }
- private const string Sid = "sid123";
- [Fact]
- public async Task StartAsync_PostsToStart_WithSessionIdAndWells_ParsesOk()
- {
- var h = new FakeHandler { Responder = (_, __) => (HttpStatusCode.OK, "{\"ok\":true}") };
- var c = new CalibrationClient("http://127.0.0.1:9/", Sid, new HttpClient(h));
- var r = await c.StartAsync(new[] { 1, 2, 3 });
- Assert.True(r.Ok);
- Assert.Equal("/debug/calibrate/start", h.LastPath);
- var jo = JObject.Parse(h.LastBody);
- Assert.Equal(Sid, jo["sessionId"]?.ToString());
- Assert.Equal(new[] { 1, 2, 3 }, ((JArray)jo["wells"]).ToObject<int[]>());
- }
- [Fact]
- public async Task PollProgressAsync_ParsesCalibProgress_TotalCompletedIsRunning_AndWells()
- {
- // control 端真实形态:DebugCommandResult{ok, result=CalibProgress}(PascalCase,枚举=数字)。
- string body =
- "{\"ok\":true,\"result\":{" +
- "\"Total\":16,\"Completed\":2,\"CurrentWell\":3,\"IsRunning\":true,\"Wells\":[" +
- "{\"WellSn\":1,\"State\":2,\"FocusZ\":90000,\"Exposure\":120,\"PeakRatio\":1.8,\"CenterOffsetPct\":0.5,\"CircleFound\":true,\"Note\":\"\"}," +
- "{\"WellSn\":2,\"State\":3,\"FocusZ\":0,\"Exposure\":0,\"PeakRatio\":1.0,\"CenterOffsetPct\":0.0,\"CircleFound\":false,\"Note\":\"伪峰\"}" +
- "]}}";
- var h = new FakeHandler { Responder = (_, __) => (HttpStatusCode.OK, body) };
- var c = new CalibrationClient("http://127.0.0.1:9/", Sid, new HttpClient(h));
- var p = await c.PollProgressAsync();
- Assert.Equal("/debug/calibrate/progress", h.LastPath);
- Assert.Equal(Sid, JObject.Parse(h.LastBody)["sessionId"]?.ToString());
- Assert.NotNull(p);
- Assert.Equal(16, p.Total);
- Assert.Equal(2, p.Completed);
- Assert.Equal(3, p.CurrentWell);
- Assert.True(p.IsRunning);
- Assert.Equal(2, p.Wells.Count);
- Assert.Equal(1, p.Wells[0].WellSn);
- Assert.Equal(2, p.Wells[0].State); // Qualified=2
- Assert.Equal(90000, p.Wells[0].FocusZ);
- Assert.True(p.Wells[0].CircleFound);
- Assert.Equal(1.8, p.Wells[0].PeakRatio, 3);
- Assert.Equal(3, p.Wells[1].State); // FakePeak=3
- Assert.Equal("伪峰", p.Wells[1].Note);
- }
- [Fact]
- public async Task RecalibrateAsync_PostsToRecalibrate_WithWellSn()
- {
- var h = new FakeHandler { Responder = (_, __) => (HttpStatusCode.OK, "{\"ok\":true,\"result\":true}") };
- var c = new CalibrationClient("http://127.0.0.1:9/", Sid, new HttpClient(h));
- var r = await c.RecalibrateAsync(7);
- Assert.True(r.Ok);
- Assert.Equal("/debug/calibrate/recalibrate", h.LastPath);
- var jo = JObject.Parse(h.LastBody);
- Assert.Equal(Sid, jo["sessionId"]?.ToString());
- Assert.Equal(7, (int)jo["wellSn"]);
- }
- [Fact]
- public async Task StopAsync_PostsToStop_WithSessionId()
- {
- var h = new FakeHandler { Responder = (_, __) => (HttpStatusCode.OK, "{\"ok\":true}") };
- var c = new CalibrationClient("http://127.0.0.1:9/", Sid, new HttpClient(h));
- var r = await c.StopAsync();
- Assert.True(r.Ok);
- Assert.Equal("/debug/calibrate/stop", h.LastPath);
- Assert.Equal(Sid, JObject.Parse(h.LastBody)["sessionId"]?.ToString());
- }
- [Fact]
- public async Task SessionExpired_CodeIsReadable()
- {
- var h = new FakeHandler { Responder = (_, __) => (HttpStatusCode.Gone, "{\"ok\":false,\"code\":\"SESSION_EXPIRED\",\"error\":\"会话不存在或已过期\"}") };
- var c = new CalibrationClient("http://127.0.0.1:9/", Sid, new HttpClient(h));
- var r = await c.StartAsync();
- Assert.False(r.Ok);
- Assert.Equal("SESSION_EXPIRED", r.Code);
- }
- }
- }
|