From b544d5cccd76735e034c8055918a50927b437474 Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期二, 10 十一月 2026 08:29:04 +0800
Subject: [PATCH] fix: 维护模式重复进入失败与按钮灰死 + Broker 并发验证用例
---
tests/Aging.MvpTests/CanDeviceDriverTests.cs | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 120 insertions(+), 0 deletions(-)
diff --git a/tests/Aging.MvpTests/CanDeviceDriverTests.cs b/tests/Aging.MvpTests/CanDeviceDriverTests.cs
new file mode 100644
index 0000000..e136499
--- /dev/null
+++ b/tests/Aging.MvpTests/CanDeviceDriverTests.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Aging.Infrastructure.Drivers;
+using CanSimulatorServer;
+using Xunit;
+
+namespace Aging.MvpTests
+{
+ /// <summary>
+ /// 缁熶竴 CAN 椹卞姩锛圕anDeviceDriver, TCP NodeChannel 鍚庣锛夎涓烘祴璇曪細
+ /// 鍦ㄦ祴璇曡繘绋嬪唴鎵樼妯℃嫙鍣ㄦ湇鍔★紝楠岃瘉杩炴帴/鍙戦��/鎺ㄩ�佷簨浠�/鏈湴缂撳啿鏌ヨ/閿欒璇箟
+ /// 涓庤皟璇曢潰鏉跨幇鏈夎В鏋愭牸寮忥紙RECV_ALL:n:鈥︺�丱K:TX鈥︼級淇濇寔鍏煎銆�
+ /// </summary>
+ public class CanDeviceDriverTests : IDisposable
+ {
+ private readonly TcpSimulatorHost _host;
+
+ public CanDeviceDriverTests()
+ {
+ _host = new TcpSimulatorHost();
+ _host.StartAsync().GetAwaiter().GetResult();
+ }
+
+ public void Dispose() => _host.Dispose();
+
+ private CanDeviceDriver NewDriver(string deviceId, string bus, int node) =>
+ new CanDeviceDriver(deviceId, $"{bus}:{node}", hostOverride: "127.0.0.1", portOverride: _host.Port);
+
+ [Fact]
+ public void ConnectAsync_OnRunningServer_Succeeds()
+ {
+ using var drv = NewDriver("CAN-T1", "CAN_BUS_1", 0);
+ drv.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+ Assert.True(drv.IsConnected);
+ }
+
+ [Fact]
+ public void ConnectAsync_NoServer_ThrowsWithStartupHint()
+ {
+ // 鎸囧悜蹇呯劧绌洪棽鐨勭鍙o細閿欒鏂囨搴斿紩瀵肩敤鎴峰惎鍔ㄦā鎷熷櫒鏈嶅姟
+ using var drv = new CanDeviceDriver("CAN-T2", "CAN_BUS_1:0", hostOverride: "127.0.0.1", portOverride: 1);
+ var ex = Assert.ThrowsAny<Exception>(() =>
+ drv.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult());
+ Assert.Contains("妯℃嫙鍣�", ex.Message);
+ }
+
+ [Fact]
+ public void SendCommandAsync_ReturnsOkTx_ReadableByPanel()
+ {
+ using var drv = NewDriver("CAN-T3", "CAN_BUS_1", 1);
+ drv.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+
+ string resp = drv.SendCommandAsync("SEND:0x100:AA BB", CancellationToken.None)
+ .GetAwaiter().GetResult();
+ Assert.StartsWith("OK:TX", resp);
+ }
+
+ [Fact]
+ public void Push_FromPeer_TriggersEvent_AndLocalRecvAll()
+ {
+ using var a = NewDriver("CAN-T4A", "CAN_BUS_1", 2);
+ using var b = NewDriver("CAN-T4B", "CAN_BUS_1", 3);
+ a.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+ b.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+
+ CanSimulator.CanFrame received = null;
+ a.DriverFrameReceived += (s, f) => received = f;
+
+ b.SendCommandAsync("SEND:0x222:11 22 33", CancellationToken.None).GetAwaiter().GetResult();
+
+ // 绛夊緟鎺ㄩ�佷簨浠跺埌杈撅紙璇诲惊鐜嚎绋嬭Е鍙戯級
+ SpinWait.SpinUntil(() => received != null, 3000);
+ Assert.NotNull(received);
+ Assert.Equal("0x222", received.FrameIdHex);
+
+ // RECV_ALL 鐢遍┍鍔ㄦ湰鍦扮紦鍐插簲绛旓紙涓嶄緷璧栨湇鍔$閭锛�
+ string all = a.QueryAsync("RECV_ALL", CancellationToken.None).GetAwaiter().GetResult();
+ Assert.StartsWith("RECV_ALL:1:", all);
+ Assert.Contains("0x222:11 22 33", all);
+ }
+
+ [Fact]
+ public void Query_AutoResponse_ProxiedToServer_ReturnsOk()
+ {
+ using var drv = NewDriver("CAN-T5", "CAN_BUS_1", 4);
+ drv.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+
+ string resp = drv.QueryAsync("AUTO_RESPONSE:ON", CancellationToken.None).GetAwaiter().GetResult();
+ Assert.StartsWith("OK:", resp);
+ string back = drv.QueryAsync("AUTO_RESPONSE", CancellationToken.None).GetAwaiter().GetResult();
+ Assert.Contains("ON", back);
+ }
+
+ [Fact]
+ public void Query_Status_HasLegacyCompatibleFormat()
+ {
+ using var drv = NewDriver("CAN-T6", "CAN_BUS_1", 5);
+ drv.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+
+ // 闈㈡澘 GetStatValue 瑙f瀽 "STATUS:Node=鈥�, 鈥�, Rx=0, Tx=0, 鈥�"锛堥�楀彿绛夊彿鍒嗛殧锛�
+ string resp = drv.QueryAsync("STATUS", CancellationToken.None).GetAwaiter().GetResult();
+ Assert.StartsWith("STATUS:Node=", resp);
+ Assert.Contains("Tx=", resp);
+ Assert.Contains("Rx=", resp);
+ }
+
+ [Fact]
+ public void Connect_NodeBusy_ThrowsWithNodeIndexHint()
+ {
+ using var first = NewDriver("CAN-T7A", "CAN_BUS_1", 6);
+ first.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult();
+
+ using var second = NewDriver("CAN-T7B", "CAN_BUS_1", 6);
+ var ex = Assert.ThrowsAny<Exception>(() =>
+ second.ConnectAsync(CancellationToken.None).GetAwaiter().GetResult());
+ Assert.Contains("鑺傜偣缂栧彿", ex.Message);
+ }
+ }
+}
--
Gitblit v1.9.1