yeg
2026-08-29 370ef4f5e663fdfc1d19d2774dfc4ec1ed0af60e
ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java
@@ -11,6 +11,7 @@
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.device.api.DeviceAdapter;
import com.ruoyi.device.bts.BtsDevelopmentSimulator;
import com.ruoyi.device.bts.BtsDeviceAdapter;
@@ -22,6 +23,7 @@
import com.ruoyi.device.simulator.BtsSimulatorStateStore;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorChannelState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState;
@@ -132,6 +134,20 @@
    }
    @Test
    void collectorRawHistoryIsNotEmbeddedInMainSimulatorState() throws Exception
    {
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
        {
            simulator.advanceCollectors(Instant.parse("2026-08-29T03:30:00Z"));
            String mainState = JSON.toJSONString(store.loadOrInitialize(null));
            assertFalse(mainState.contains("\"history\":[{"));
            assertEquals(12, simulator.collectorHistory(1, 0, 100).total());
        }
    }
    @Test
    void collectorRealtimeDropsMeasurementsRemovedFromCurrentConfiguration() throws Exception
    {
        Instant startedAt = Instant.parse("2026-08-29T04:00:00Z");
@@ -159,6 +175,18 @@
        {
            assertEquals(4, restored.snapshot().collectors().get(0).latestMeasurements().size());
            assertEquals(12, restored.collectorHistory(1, 0, 100).total());
        }
    }
    @Test
    void collectorRejectsMetricWhitespaceThatWouldBreakRestore() throws Exception
    {
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
        {
            assertThrows(IllegalArgumentException.class, () -> simulator.configureCollectorChannel(1, "S-01",
                    List.of(new CollectorMetricState("temperature ", new BigDecimal("25.0"), "℃"))));
            assertThrows(IllegalArgumentException.class, () -> simulator.configureCollectorChannel(1, "S-01",
                    List.of(new CollectorMetricState("temperature", new BigDecimal("25.0"), " ℃"))));
        }
    }
@@ -347,6 +375,31 @@
    }
    @Test
    void collectorDeletionDoesNotReplaceMemoryWhenAtomicPersistenceFails() throws Exception
    {
        InMemoryBtsSimulatorStateStore delegate = new InMemoryBtsSimulatorStateStore();
        BtsSimulatorStateStore failing = new BtsSimulatorStateStore()
        {
            @Override public SimulatorState loadOrInitialize(SimulatorState value)
            { return delegate.loadOrInitialize(value); }
            @Override public void save(SimulatorState value) { delegate.save(value); }
            @Override public void saveAndDeleteCollectorHistory(SimulatorState value, String collectorCode)
            { throw new IllegalStateException("redis unavailable"); }
            @Override public java.util.List<RecentRequest> loadRecentRequests()
            { return delegate.loadRecentRequests(); }
            @Override public void saveRecentRequests(java.util.List<RecentRequest> requests)
            { delegate.saveRecentRequests(requests); }
            @Override public void reset(SimulatorState value) { delegate.reset(value); }
        };
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, failing))
        {
            assertThrows(IllegalStateException.class, () -> simulator.deleteCollector(1));
            assertEquals(1, simulator.snapshot().collectors().size());
        }
    }
    @Test
    void developmentSimulatorRestoresUnfinishedTombstones() throws Exception
    {
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
@@ -390,17 +443,20 @@
        Instant observedAt = Instant.parse("2026-08-29T05:00:00Z");
        List<CollectorChannelState> channels = List.of(new CollectorChannelState("S-01", List.of(
                new CollectorMetricState("temperature", new BigDecimal("25.0"), "℃"))));
        CollectorMeasurementRecord record = new CollectorMeasurementRecord(
                "dev-sim", "wrong-collector", "S-01", 1L, observedAt,
                "2026-08-29 13:00:00.000", observedAt, "temperature",
                new BigDecimal("25.0"), "℃");
        CollectorState collector = new CollectorState(1, "dev-sim-collector-1", "127.0.1.2",
                "02:43:00:00:00:01", "模拟采集器", "开发模拟器", "Virtual Collector", 1, true,
                1000, 2L, observedAt, channels, List.of(), List.of(new CollectorMeasurementRecord(
                        "dev-sim", "wrong-collector", "S-01", 1L, observedAt,
                        "2026-08-29 13:00:00.000", observedAt, "temperature",
                        new BigDecimal("25.0"), "℃")), CollectorHistoryFaults.none());
                1000, 2L, observedAt, channels, List.of(), 1L, CollectorHistoryFaults.none());
        SimulatorState damaged = new SimulatorState(BtsSimulatorStateStore.CURRENT_VERSION,
                List.of(), List.of(collector), 1, 2, List.of());
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore(damaged);
        store.save(damaged, List.of(new CollectorHistoryAppend(collector.deviceCode(), List.of(record))));
        assertThrows(IllegalStateException.class,
                () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
                () -> new BtsDevelopmentSimulator(0, store));
    }
    @Test
@@ -409,16 +465,19 @@
        Instant observedAt = Instant.parse("2026-08-29T06:00:00Z");
        List<CollectorChannelState> channels = List.of(new CollectorChannelState("S-01", List.of(
                new CollectorMetricState("temperature", new BigDecimal("25.0"), "℃"))));
        CollectorMeasurementRecord record = new CollectorMeasurementRecord(
                "dev-sim", "dev-sim-collector-1", "S-01", 1L, observedAt,
                "2026-08-29 14:00:00.000", observedAt, "temperature",
                new BigDecimal("25.0"), "℃");
        CollectorState collector = new CollectorState(1, "dev-sim-collector-1", "127.0.1.2",
                "02:43:00:00:00:01", "模拟采集器", "开发模拟器", "Virtual Collector", 1, true,
                1000, 1L, observedAt, channels, List.of(), List.of(new CollectorMeasurementRecord(
                        "dev-sim", "dev-sim-collector-1", "S-01", 1L, observedAt,
                        "2026-08-29 14:00:00.000", observedAt, "temperature",
                        new BigDecimal("25.0"), "℃")), CollectorHistoryFaults.none());
                1000, 1L, observedAt, channels, List.of(), 1L, CollectorHistoryFaults.none());
        SimulatorState damaged = new SimulatorState(BtsSimulatorStateStore.CURRENT_VERSION,
                List.of(), List.of(collector), 1, 2, List.of());
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore(damaged);
        store.save(damaged, List.of(new CollectorHistoryAppend(collector.deviceCode(), List.of(record))));
        assertThrows(IllegalStateException.class,
                () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
                () -> new BtsDevelopmentSimulator(0, store));
    }
}