From 7259e265b9237286996b09da03038ea5a133e1e0 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 05 九月 2026 17:45:07 +0800
Subject: [PATCH] 收敛模拟器为设备事实与实时观测

---
 battery-device-simulator/src/test/java/com/battery/device/contract/SimulatorPublicContractTest.java |  315 ---------------------------------------------------
 1 files changed, 4 insertions(+), 311 deletions(-)

diff --git a/battery-device-simulator/src/test/java/com/battery/device/contract/SimulatorPublicContractTest.java b/battery-device-simulator/src/test/java/com/battery/device/contract/SimulatorPublicContractTest.java
index 3349459..49d5be2 100644
--- a/battery-device-simulator/src/test/java/com/battery/device/contract/SimulatorPublicContractTest.java
+++ b/battery-device-simulator/src/test/java/com/battery/device/contract/SimulatorPublicContractTest.java
@@ -24,10 +24,6 @@
 import com.battery.device.simulator.BtsSimulatorStateStore;
 import com.battery.device.simulator.BtsSimulatorStateStore.ChannelState;
 import com.battery.device.simulator.BtsSimulatorStateStore.CollectorChannelState;
-import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend;
-import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryBatch;
-import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults;
-import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord;
 import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMetricState;
 import com.battery.device.simulator.BtsSimulatorStateStore.CollectorState;
 import com.battery.device.simulator.BtsSimulatorStateStore.DeviceState;
@@ -38,182 +34,20 @@
 class SimulatorPublicContractTest
 {
     @Test
-    void collectorGeneratesIndependentRealtimeAndHistoricalMeasurements() throws Exception
-    {
-        Instant startedAt = Instant.parse("2026-08-29T01:00:00Z");
-        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
-        {
-            simulator.configureCollectorSampling(1, 200, CollectorHistoryFaults.none());
-            simulator.configureCollectorChannel(1, "S-01", List.of(
-                    new CollectorMetricState("temperature", new BigDecimal("26.5"), "℃"),
-                    new CollectorMetricState("positive_potential", new BigDecimal("3.801"), "V"),
-                    new CollectorMetricState("negative_potential", new BigDecimal("-0.120"), "V"),
-                    new CollectorMetricState("pressure", new BigDecimal("101.2"), "kPa")));
-
-            simulator.advanceCollectors(startedAt);
-            simulator.advanceCollectors(startedAt.plusMillis(400));
-
-            var realtime = simulator.snapshot().collectors().get(0).latestMeasurements();
-            var history = simulator.collectorHistory(1, 0, 1000);
-            assertEquals(13, realtime.size());
-            assertTrue(realtime.stream().allMatch(item -> item.sequenceId() == 3));
-            assertTrue(realtime.stream().anyMatch(item -> item.channelCode().equals("S-01")
-                    && item.metricCode().equals("pressure") && item.unit().equals("kPa")));
-            assertEquals(39, history.total());
-            assertEquals("dev-sim", history.records().get(0).adapterCode());
-            assertEquals("dev-sim-collector-1", history.records().get(0).collectorCode());
-            assertEquals(startedAt, history.records().get(0).deviceTime());
-            assertTrue(history.records().get(0).deviceTimeRaw().startsWith("2026-08-29 09:00:00"));
-            assertEquals(startedAt, history.records().get(0).serverReceivedAt());
-        }
-    }
-
-    @Test
-    void collectorHistorySupportsPagingAndRepeatableFaultScenarios() throws Exception
-    {
-        Instant startedAt = Instant.parse("2026-08-29T02:00:00Z");
-        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
-        {
-            simulator.configureCollectorSampling(1, 100,
-                    new CollectorHistoryFaults(List.of(2L), 1L, 3L, true));
-            simulator.advanceCollectors(startedAt);
-            simulator.advanceCollectors(startedAt.plusMillis(200));
-
-            var first = simulator.collectorHistory(1, 0, 17);
-            var second = simulator.collectorHistory(1, first.nextOffset(), 1000);
-            List<com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord> records =
-                    new java.util.ArrayList<>(first.records());
-            records.addAll(second.records());
-
-            assertEquals(48, first.total());
-            assertTrue(first.hasMore());
-            assertFalse(second.hasMore());
-            assertTrue(records.stream().noneMatch(item -> item.sequenceId() == 2));
-            assertEquals(24, records.stream().filter(item -> item.sequenceId() == 1).count());
-            assertEquals(2, records.stream().filter(item -> item.sequenceId() == 3
-                    && item.channelCode().equals("S-01") && item.metricCode().equals("temperature")).count());
-            assertTrue(records.get(0).sequenceId() >= records.get(records.size() - 1).sequenceId());
-        }
-    }
-
-    @Test
-    void collectorStopsWhileOfflineAndResumesFromPersistedSequence() throws Exception
-    {
-        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
-        Instant now = Instant.now();
-        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
-        {
-            simulator.advanceCollectors(now);
-            simulator.updateCollector(1, "127.0.1.2", 4, false);
-            simulator.advanceCollectors(now.plusSeconds(10));
-            assertEquals(1, simulator.snapshot().collectors().get(0).latestMeasurements().get(0).sequenceId());
-        }
-
-        try (BtsDevelopmentSimulator restored = new BtsDevelopmentSimulator(0, store))
-        {
-            restored.updateCollector(1, "127.0.1.2", 4, true);
-            restored.advanceCollectors(Instant.now().plusSeconds(2));
-            assertTrue(restored.snapshot().collectors().get(0).latestMeasurements().get(0).sequenceId() >= 2);
-            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 simulatorPowerSwitchStopsSamplingAndRestoresWithoutDeletingHistory() throws Exception
-    {
-        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
-        long historyCount;
-        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
-        {
-            simulator.advanceCollectors(Instant.now());
-            historyCount = simulator.snapshot().collectors().get(0).historyRecordCount();
-
-            simulator.setAllDevicesPoweredOn(false);
-            simulator.advanceCollectors(Instant.now().plusSeconds(10));
-
-            var poweredOff = simulator.snapshot();
-            assertTrue(poweredOff.devices().stream().noneMatch(device -> device.online()
-                    || device.channels().stream().anyMatch(channel -> channel.online()
-                            || channel.workStatus() != DeviceWorkStatus.STOPPED)));
-            assertTrue(poweredOff.collectors().stream().noneMatch(collector -> collector.online()));
-            assertEquals(historyCount, poweredOff.collectors().get(0).historyRecordCount());
-        }
-
-        try (BtsDevelopmentSimulator restored = new BtsDevelopmentSimulator(0, store))
-        {
-            assertFalse(restored.snapshot().collectors().get(0).online());
-            assertEquals(historyCount, restored.collectorHistory(1, 0, 1000).total());
-
-            restored.setAllDevicesPoweredOn(true);
-            var poweredOn = restored.snapshot();
-            assertTrue(poweredOn.devices().stream().allMatch(device -> device.online()
-                    && device.channels().stream().allMatch(channel -> channel.online()
-                            && channel.workStatus() == DeviceWorkStatus.STOPPED)));
-            assertTrue(poweredOn.collectors().stream().allMatch(collector -> collector.online()));
-            restored.advanceCollectors(Instant.now().plusSeconds(2));
-            assertTrue(restored.snapshot().collectors().get(0).historyRecordCount() > historyCount);
-        }
-    }
-
-    @Test
-    void collectorKeepsOnlyBoundedDemoHistory() throws Exception
-    {
-        Instant startedAt = Instant.parse("2026-08-29T03:00:00Z");
-        TrackingHistoryStore store = new TrackingHistoryStore();
-        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
-        {
-            simulator.configureCollectorSampling(1, 100, CollectorHistoryFaults.none());
-            simulator.advanceCollectors(startedAt);
-            for (int batch = 1; batch <= 5; batch++)
-                simulator.advanceCollectors(startedAt.plusMillis(batch * 100_000L));
-
-            store.resetReadStats();
-            var page = simulator.collectorHistory(1, 0, 1);
-            assertEquals(BtsSimulatorStateStore.MAX_HISTORY_RECORDS, page.total());
-            assertTrue(page.records().get(0).sequenceId() > 1);
-            assertEquals(1, store.historyReads);
-            assertEquals(1, store.recordsRead);
-        }
-
-        store.resetReadStats();
-        try (BtsDevelopmentSimulator ignored = new BtsDevelopmentSimulator(0, store))
-        {
-            assertTrue(store.historyReads > 1);
-            assertEquals(1000, store.maximumRequestedLimit);
-            assertEquals(BtsSimulatorStateStore.MAX_HISTORY_RECORDS, store.recordsRead);
-        }
-    }
-
-    @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");
         InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
         try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
         {
-            simulator.advanceCollectors(startedAt);
+            simulator.collectorRealtime(1);
             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);
 
+            simulator.collectorRealtime(1);
             var snapshot = simulator.snapshot().collectors().get(0);
             assertEquals(4, snapshot.latestMeasurements().size());
             assertTrue(snapshot.latestMeasurements().stream()
@@ -221,13 +55,11 @@
                             || 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());
+            assertEquals(4, restored.collectorRealtime(1).measurements().size());
         }
     }
 
@@ -496,9 +328,7 @@
         {
             @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 void save(SimulatorState value) { throw new IllegalStateException("redis unavailable"); }
             @Override public java.util.List<RecentRequest> loadRecentRequests()
             { return delegate.loadRecentRequests(); }
             @Override public void saveRecentRequests(java.util.List<RecentRequest> requests)
@@ -551,141 +381,4 @@
                 () -> 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"), "℃"))));
-        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(), 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, store));
-    }
-
-    @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"), "℃"))));
-        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(), 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, store));
-    }
-
-    @Test
-    void developmentSimulatorRejectsHistorySequenceRegressionAcrossPages()
-    {
-        Instant observedAt = Instant.parse("2026-08-29T06:30:00Z");
-        List<CollectorChannelState> channels = List.of(new CollectorChannelState("S-01", List.of(
-                new CollectorMetricState("temperature", new BigDecimal("25.0"), "℃"))));
-        List<CollectorMeasurementRecord> records = new java.util.ArrayList<>();
-        for (long sequence = 1; sequence <= 1000; sequence++)
-            records.add(new CollectorMeasurementRecord("dev-sim", "dev-sim-collector-1", "S-01", sequence,
-                    observedAt, "2026-08-29 14:30:00.000", observedAt, "temperature",
-                    new BigDecimal("25.0"), "℃"));
-        records.add(new CollectorMeasurementRecord("dev-sim", "dev-sim-collector-1", "S-01", 999,
-                observedAt, "2026-08-29 14:30: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, 1001L, observedAt, channels, List.of(), records.size(), 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(), records)));
-
-        assertThrows(IllegalStateException.class,
-                () -> new BtsDevelopmentSimulator(0, store));
-    }
-
-    private static final class TrackingHistoryStore implements BtsSimulatorStateStore
-    {
-        private final InMemoryBtsSimulatorStateStore delegate = new InMemoryBtsSimulatorStateStore();
-        private int historyReads;
-        private int maximumRequestedLimit;
-        private long recordsRead;
-
-        @Override
-        public SimulatorState loadOrInitialize(SimulatorState defaultState)
-        {
-            return delegate.loadOrInitialize(defaultState);
-        }
-
-        @Override
-        public void save(SimulatorState state)
-        {
-            delegate.save(state);
-        }
-
-        @Override
-        public void save(SimulatorState state, List<CollectorHistoryAppend> historyAppends)
-        {
-            delegate.save(state, historyAppends);
-        }
-
-        @Override
-        public CollectorHistoryBatch loadCollectorHistoryPage(String collectorCode, long offset, int limit,
-                boolean reverse)
-        {
-            CollectorHistoryBatch batch = delegate.loadCollectorHistoryPage(collectorCode, offset, limit, reverse);
-            historyReads++;
-            maximumRequestedLimit = Math.max(maximumRequestedLimit, limit);
-            recordsRead += batch.records().size();
-            return batch;
-        }
-
-        @Override
-        public void saveAndDeleteCollectorHistory(SimulatorState state, String collectorCode)
-        {
-            delegate.saveAndDeleteCollectorHistory(state, collectorCode);
-        }
-
-        @Override
-        public List<RecentRequest> loadRecentRequests()
-        {
-            return delegate.loadRecentRequests();
-        }
-
-        @Override
-        public void saveRecentRequests(List<RecentRequest> requests)
-        {
-            delegate.saveRecentRequests(requests);
-        }
-
-        @Override
-        public void reset(SimulatorState defaultState)
-        {
-            delegate.reset(defaultState);
-        }
-
-        private void resetReadStats()
-        {
-            historyReads = 0;
-            maximumRequestedLimit = 0;
-            recordsRead = 0;
-        }
-    }
 }

--
Gitblit v1.7.1