From f522c9ffa487e3710d691e8b98df8c4f0cfafd43 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 05 九月 2026 20:07:26 +0800
Subject: [PATCH] 支持模拟器逐通道参数与工步方案配置

---
 battery-device-simulator/src/test/java/com/battery/device/simulator/SimulatorObservationAdapterContractTest.java |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/battery-device-simulator/src/test/java/com/battery/device/simulator/SimulatorObservationAdapterContractTest.java b/battery-device-simulator/src/test/java/com/battery/device/simulator/SimulatorObservationAdapterContractTest.java
index 86e331a..9407dfd 100644
--- a/battery-device-simulator/src/test/java/com/battery/device/simulator/SimulatorObservationAdapterContractTest.java
+++ b/battery-device-simulator/src/test/java/com/battery/device/simulator/SimulatorObservationAdapterContractTest.java
@@ -1,13 +1,110 @@
 package com.battery.device.simulator;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.*;
 import org.junit.jupiter.api.Test;
-import com.battery.device.model.ChannelIdentity;
-import com.battery.device.model.DeviceConnectionStatus;
-import com.battery.device.model.DeviceWorkStatus;
+import com.battery.device.api.model.ChannelIdentity;
+import com.battery.device.api.model.DeviceConnectionStatus;
+import com.battery.device.api.model.DeviceWorkStatus;
 
 class SimulatorObservationAdapterContractTest
 {
+    @Test void configuredChannelFactsSurviveSoftwareFailureAndRestart() throws Exception
+    {
+        var store = new InMemoryBtsSimulatorStateStore();
+        long firstSequence;
+        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
+        {
+            simulator.updateChannel(1, 1, true, DeviceWorkStatus.PROTECTED);
+            simulator.updateCollectorChannelStatus(1, "S-01", DeviceWorkStatus.UNOBSERVABLE);
+            var collector = simulator.latestCollector("dev-sim-collector-1");
+            assertTrue(collector.measurements().stream().noneMatch(item -> item.channelCode().equals("S-01")));
+            firstSequence = collector.measurements().get(0).sequenceId();
+            simulator.setSoftwareAccessible(false);
+            simulator.updateDevice(1, "127.0.0.8", 4, false);
+            assertFalse(simulator.snapshot().softwareAccessible());
+        }
+        try (BtsDevelopmentSimulator restored = new BtsDevelopmentSimulator(0, store))
+        {
+            assertFalse(restored.snapshot().softwareAccessible());
+            assertEquals("127.0.0.8", restored.snapshot().devices().get(0).ip());
+            assertEquals(DeviceWorkStatus.PROTECTED, restored.snapshot().devices().get(0).channels().get(0).workStatus());
+            assertTrue(restored.snapshot().collectors().get(0).latestMeasurements().isEmpty());
+            restored.setSoftwareAccessible(true);
+            assertTrue(restored.latestCollector("dev-sim-collector-1").measurements().get(0).sequenceId() > firstSequence);
+            assertEquals(DeviceWorkStatus.UNOBSERVABLE, restored.snapshot().collectors().get(0).channels().get(0).workStatus());
+        }
+    }
+
+    @Test void offlineCollectorDoesNotReturnLastSuccessAndStateReadsDoNotSample() throws Exception
+    {
+        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
+        {
+            assertTrue(simulator.snapshot().collectors().get(0).latestMeasurements().isEmpty());
+            var first = simulator.collectorRealtime(1);
+            var recent = simulator.snapshot().recentRequests();
+            assertEquals(recent, simulator.snapshot().recentRequests());
+            simulator.updateCollector(1, "127.0.1.2", 4, false);
+            assertFalse(simulator.collectorRealtime(1).online());
+            assertTrue(simulator.collectorRealtime(1).measurements().isEmpty());
+            simulator.updateCollector(1, "127.0.1.2", 4, true);
+            assertTrue(simulator.collectorRealtime(1).measurements().get(0).sequenceId() > first.measurements().get(0).sequenceId());
+            var channel = simulator.discoverChannels().get(0).identity();
+            simulator.updateChannel(1, 1, true, DeviceWorkStatus.UNOBSERVABLE);
+            assertNull(simulator.latestCabinet(channel));
+            assertEquals(DeviceWorkStatus.UNOBSERVABLE, simulator.observe(java.util.Set.of(channel)).get(channel).workStatus());
+        }
+    }
+
+    @Test void softwareFailurePreservesIdentityAndDoesNotReplayMeasurements() throws Exception
+    {
+        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
+        {
+            var channel = simulator.discoverChannels().get(0).identity();
+            simulator.updateChannel(1, 1, true, DeviceWorkStatus.WORKING);
+            var first = simulator.latestCabinet(channel);
+            assertNotNull(first);
+            assertFalse(simulator.latestCollector("dev-sim-collector-1").measurements().isEmpty());
+            simulator.setSoftwareAccessible(false);
+            assertEquals(channel, simulator.discoverChannels().get(0).identity());
+            assertTrue(simulator.snapshot().devices().get(0).online());
+            assertEquals(DeviceWorkStatus.UNOBSERVABLE,
+                    simulator.observe(java.util.Set.of(channel)).get(channel).workStatus());
+            assertNull(simulator.latestCabinet(channel));
+            assertTrue(simulator.latestCollector("dev-sim-collector-1").measurements().isEmpty());
+            simulator.setSoftwareAccessible(true);
+            var next = simulator.latestCabinet(channel);
+            assertTrue(next.sequenceId() > first.sequenceId());
+            assertFalse(next.deviceTime().isBefore(first.deviceTime()));
+            assertTrue(simulator.stepRecords(channel).isEmpty());
+            assertTrue(simulator.cycleRecords(channel).isEmpty());
+            assertEquals(60000L, simulator.persistenceIntervalMillis(channel));
+        }
+    }
+
+    @Test void persistenceRejectsForeignIdentitiesAndOfflineCachedFacts() throws Exception
+    {
+        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
+        {
+            ChannelIdentity channel = simulator.discoverChannels().get(0).identity();
+            simulator.updateChannel(channel.devid(), channel.chlid(), true, DeviceWorkStatus.WORKING);
+            assertNotNull(simulator.latestCabinet(channel));
+            for (ChannelIdentity foreign : java.util.List.of(
+                    new ChannelIdentity("another-adapter", channel.devtype(), channel.devid(), channel.subdevid(), channel.chlid()),
+                    new ChannelIdentity(channel.adapterCode(), 999, channel.devid(), channel.subdevid(), channel.chlid()),
+                    new ChannelIdentity(channel.adapterCode(), channel.devtype(), channel.devid(), 999, channel.chlid())))
+            {
+                assertNull(simulator.latestCabinet(foreign));
+                assertNull(simulator.testPlan(foreign));
+                assertTrue(simulator.stepRecords(foreign).isEmpty());
+                assertTrue(simulator.cycleRecords(foreign).isEmpty());
+            }
+            simulator.updateChannel(channel.devid(), channel.chlid(), false, DeviceWorkStatus.WORKING);
+            assertNull(simulator.latestCabinet(channel));
+            assertTrue(simulator.stepRecords(channel).isEmpty());
+            assertTrue(simulator.cycleRecords(channel).isEmpty());
+        }
+    }
+
     @Test
     void simulatorCanBeUsedDirectlyThroughTheVendorNeutralContract() throws Exception
     {

--
Gitblit v1.7.1