From db2eb9412ddc4ff687eb4c9b862053f49f9aec7b Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 26 八月 2026 13:16:42 +0800
Subject: [PATCH] feat(device): 完善 BTS 只读协议与模拟器

---
 ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsTcpTransportTest.java |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 111 insertions(+), 1 deletions(-)

diff --git a/ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsTcpTransportTest.java b/ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsTcpTransportTest.java
index 595af12..511a6b8 100644
--- a/ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsTcpTransportTest.java
+++ b/ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsTcpTransportTest.java
@@ -1,6 +1,7 @@
 package com.ruoyi.device.bts;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.time.Duration;
 import java.util.Set;
@@ -23,7 +24,7 @@
             {
                 simulator.enqueue("<bts><cmd>first_resp</cmd></bts>");
                 simulator.enqueue("<bts><cmd>second_resp</cmd></bts>");
-                Callable<String> first = () -> transport.exchange("<bts><cmd>first</cmd></bts>");
+                Callable<String> first = () -> transport.exchange("<bts><cmd>first</cmd><note>检测</note></bts>");
                 Callable<String> second = () -> transport.exchange("<bts><cmd>second</cmd></bts>");
 
                 Future<String> firstResult = callers.submit(first);
@@ -33,6 +34,7 @@
                 assertEquals(Set.of("<bts><cmd>first_resp</cmd></bts>", "<bts><cmd>second_resp</cmd></bts>"), responses);
                 assertEquals(2, simulator.requests().size());
                 assertTrue(simulator.requests().stream().allMatch(request -> request.startsWith("<bts>")));
+                assertTrue(simulator.requests().stream().anyMatch(request -> request.contains("<note>检测</note>")));
             }
             finally
             {
@@ -40,4 +42,112 @@
             }
         }
     }
+
+    @Test
+    void reportsDelayedResponseAsTimeout() throws Exception
+    {
+        try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
+             BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
+                     Duration.ofSeconds(1), Duration.ofMillis(50)))
+        {
+            simulator.enqueueDelayed(Duration.ofMillis(200), "<bts><cmd>late_resp</cmd></bts>");
+
+            BtsTransportException exception = assertThrows(BtsTransportException.class,
+                    () -> transport.exchange("<bts><cmd>late</cmd></bts>"));
+
+            assertEquals(BtsTransportException.Reason.TIMEOUT, exception.reason());
+        }
+    }
+
+    @Test
+    void reportsActiveDisconnectAndReconnectsOnNextExchange() throws Exception
+    {
+        try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
+             BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
+                     Duration.ofSeconds(1), Duration.ofSeconds(1)))
+        {
+            simulator.enqueueDisconnect();
+
+            BtsTransportException exception = assertThrows(BtsTransportException.class,
+                    () -> transport.exchange("<bts><cmd>first</cmd></bts>"));
+
+            assertEquals(BtsTransportException.Reason.DISCONNECTED, exception.reason());
+
+            simulator.enqueue("<bts><cmd>second_resp</cmd></bts>");
+            assertEquals("<bts><cmd>second_resp</cmd></bts>",
+                    transport.exchange("<bts><cmd>second</cmd></bts>"));
+            assertEquals(2, simulator.requests().size());
+        }
+    }
+
+    @Test
+    void rejectsResponseLargerThanConfiguredLimit() throws Exception
+    {
+        try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
+             BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
+                     Duration.ofSeconds(1), Duration.ofSeconds(1), 32))
+        {
+            simulator.enqueue("x".repeat(33));
+
+            BtsTransportException exception = assertThrows(BtsTransportException.class,
+                    () -> transport.exchange("<bts><cmd>large</cmd></bts>"));
+
+            assertEquals(BtsTransportException.Reason.RESPONSE_TOO_LARGE, exception.reason());
+        }
+    }
+
+    @Test
+    void reportsRefusedConnection() throws Exception
+    {
+        try (ScriptedBtsTcpSimulator simulator = ScriptedBtsTcpSimulator.refusingConnections();
+             BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
+                     Duration.ofSeconds(1), Duration.ofSeconds(1)))
+        {
+            BtsTransportException exception = assertThrows(BtsTransportException.class,
+                    () -> transport.exchange("<bts><cmd>getdevinfo</cmd></bts>"));
+
+            assertEquals(BtsTransportException.Reason.CONNECTION_FAILED, exception.reason());
+            assertTrue(simulator.requests().isEmpty());
+        }
+    }
+
+    @Test
+    void rejectsResponseTimeoutAboveProtocolMaximum()
+    {
+        assertThrows(IllegalArgumentException.class,
+                () -> new BtsTcpTransport("127.0.0.1", 502,
+                        Duration.ofSeconds(1), Duration.ofSeconds(31)));
+    }
+
+    @Test
+    void rejectsResponseThatIsNotValidUtf8() throws Exception
+    {
+        try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
+             BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
+                     Duration.ofSeconds(1), Duration.ofSeconds(1)))
+        {
+            simulator.enqueueRaw(new byte[] {(byte) 0xC3, (byte) 0x28});
+
+            BtsTransportException exception = assertThrows(BtsTransportException.class,
+                    () -> transport.exchange("<bts><cmd>getdevinfo</cmd></bts>"));
+
+            assertEquals(BtsTransportException.Reason.INVALID_UTF8, exception.reason());
+        }
+    }
+
+    @Test
+    void acceptsResponseAtSizeLimitAndDelimiterPrefixInPayload() throws Exception
+    {
+        try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
+             BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
+                     Duration.ofSeconds(1), Duration.ofSeconds(1), 32))
+        {
+            String atLimit = "x".repeat(32);
+            simulator.enqueue(atLimit);
+            simulator.enqueue("#");
+
+            assertEquals(atLimit, transport.exchange("first"));
+            assertEquals("#", transport.exchange("second"));
+        }
+    }
 }

--
Gitblit v1.7.1