yeg
2026-08-29 0162f3730ca2e9644322a90450728b63243d40d0
ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java
@@ -21,8 +21,11 @@
import com.ruoyi.device.model.DeviceWorkStatus;
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.CollectorHistoryFaults;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.DeviceState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.SimulatorState;
import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore;
@@ -109,6 +112,53 @@
            assertEquals(List.of("S-01", "S-02", "S-03", "S-04"),
                    restored.snapshot().collectors().get(0).channels().stream()
                            .map(channel -> channel.channelCode()).toList());
        }
    }
    @Test
    void collectorKeepsAppendOnlyHistoryBeyondPreviousDisplayLimit() throws Exception
    {
        Instant startedAt = Instant.parse("2026-08-29T03:00:00Z");
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
        {
            simulator.configureCollectorSampling(1, 100, CollectorHistoryFaults.none());
            simulator.advanceCollectors(startedAt);
            for (int batch = 1; batch <= 5; batch++)
                simulator.advanceCollectors(startedAt.plusMillis(batch * 100_000L));
            assertEquals(60_012, simulator.collectorHistory(1, 0, 1).total());
            assertEquals(1, simulator.collectorHistory(1, 0, 1).records().get(0).sequenceId());
        }
    }
    @Test
    void collectorRealtimeDropsMeasurementsRemovedFromCurrentConfiguration() throws Exception
    {
        Instant startedAt = Instant.parse("2026-08-29T04:00:00Z");
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
        {
            simulator.advanceCollectors(startedAt);
            assertEquals(12, simulator.snapshot().collectors().get(0).latestMeasurements().size());
            simulator.configureCollectorChannel(1, "S-01", List.of(
                    new CollectorMetricState("temperature", new BigDecimal("27.0"), "℃")));
            simulator.updateCollector(1, "127.0.1.2", 2, true);
            var snapshot = simulator.snapshot().collectors().get(0);
            assertEquals(4, snapshot.latestMeasurements().size());
            assertTrue(snapshot.latestMeasurements().stream()
                    .noneMatch(item -> item.channelCode().equals("S-03")
                            || item.channelCode().equals("S-04")
                            || item.channelCode().equals("S-01")
                                    && item.metricCode().equals("positive_potential")));
            assertEquals(12, simulator.collectorHistory(1, 0, 100).total());
        }
        try (BtsDevelopmentSimulator restored = new BtsDevelopmentSimulator(0, store))
        {
            assertEquals(4, restored.snapshot().collectors().get(0).latestMeasurements().size());
            assertEquals(12, restored.collectorHistory(1, 0, 100).total());
        }
    }
@@ -333,4 +383,42 @@
        assertThrows(IllegalStateException.class,
                () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
    }
    @Test
    void developmentSimulatorRejectsDamagedCollectorHistoryIdentity()
    {
        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"), "℃"))));
        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());
        SimulatorState damaged = new SimulatorState(BtsSimulatorStateStore.CURRENT_VERSION,
                List.of(), List.of(collector), 1, 2, List.of());
        assertThrows(IllegalStateException.class,
                () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
    }
    @Test
    void developmentSimulatorRejectsCollectorSequenceBehindPersistedHistory()
    {
        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"), "℃"))));
        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());
        SimulatorState damaged = new SimulatorState(BtsSimulatorStateStore.CURRENT_VERSION,
                List.of(), List.of(collector), 1, 2, List.of());
        assertThrows(IllegalStateException.class,
                () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
    }
}