yeg
2026-08-31 6c38637d89f346a660618558451f2dd7286dc7a5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package com.ruoyi.device.bts;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Instant;
import org.junit.jupiter.api.Test;
import com.ruoyi.device.model.DeviceWorkStatus;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsPlaybackState;
import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore;
 
/** Ticket21:检测柜 record、step、cycle 生命周期和播放控制合同。 */
class BtsDevelopmentSimulatorRecordStepCycleTest
{
    @Test
    void recordsUseMinuteDeviceTimeAndActualStepCycleIdentity() throws Exception
    {
        Instant start = Instant.parse("2026-08-31T00:00:00Z");
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0,
                new InMemoryBtsSimulatorStateStore()))
        {
            simulator.updateChannel(1, 1, true, DeviceWorkStatus.WORKING);
            simulator.advanceBts(start);
            simulator.advanceBts(start.plusSeconds(5 * 60L));
 
            var records = simulator.btsRecords(1, 1);
            assertTrue(records.size() >= 6);
            assertEquals(1L, records.get(0).sequenceId());
            assertEquals(60L, records.get(1).deviceTime().getEpochSecond() - records.get(0).deviceTime().getEpochSecond());
            assertEquals(1, records.get(0).cycleNo());
            assertTrue(simulator.btsSteps(1, 1).stream().anyMatch(step -> step.stepNo() == 1));
            assertTrue(simulator.btsCycles(1, 1).stream().anyMatch(cycle -> cycle.cycleNo() == 1));
        }
    }
 
    @Test
    void playbackSpeedPauseResumeAndRestartAreIndependentOfDeviceStatus() throws Exception
    {
        Instant start = Instant.parse("2026-08-31T00:00:00Z");
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
        {
            simulator.updateChannel(1, 1, true, DeviceWorkStatus.WORKING);
            simulator.setBtsSpeed(1, 1, 600);
            simulator.advanceBts(start);
            simulator.pauseBts(1, 1);
            int pausedCount = simulator.btsRecords(1, 1).size();
            simulator.advanceBts(start.plusSeconds(600));
            assertEquals(pausedCount, simulator.btsRecords(1, 1).size());
            assertFalse(simulator.btsPlayback(1, 1).playback().playing());
        }
        try (BtsDevelopmentSimulator restored = new BtsDevelopmentSimulator(0, store))
        {
            BtsPlaybackState playback = restored.btsPlayback(1, 1).playback();
            assertEquals(600, playback.speedMultiplier());
            assertFalse(playback.playing());
            restored.resumeBts(1, 1);
            assertTrue(restored.btsPlayback(1, 1).playback().playing());
        }
    }
 
    @Test
    void nextCycleAndResetDoNotSendDeviceControlAndNaturalFinishStopsPlayback() throws Exception
    {
        InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
        {
            simulator.updateChannel(1, 1, true, DeviceWorkStatus.WORKING);
            simulator.nextBtsCycle(1, 1);
            assertEquals(2, simulator.btsPlayback(1, 1).playback().cycleNo());
            long firstCycleTwoRecord = BtsExcelFixture.records().stream()
                    .filter(record -> record.cycleNo() == 2).findFirst().orElseThrow().sequenceId();
            assertEquals(firstCycleTwoRecord, simulator.btsPlayback(1, 1).playback().nextSequence());
            Instant jumpedAt = simulator.btsPlayback(1, 1).playback().wallClockAt();
            simulator.advanceBts(jumpedAt.plusSeconds(60));
            assertEquals(2, simulator.btsRecords(1, 1).get(0).cycleNo());
            simulator.setBtsSpeed(1, 1, 600);
            Instant wallClock = simulator.btsPlayback(1, 1).playback().wallClockAt();
            long durationMillis = BtsExcelFixture.record(BtsExcelFixture.recordCount()).offsetSeconds() * 1000L;
            simulator.advanceBts(wallClock.plusMillis(durationMillis / 600L + 1000L));
            assertTrue(simulator.btsPlayback(1, 1).playback().naturallyFinished());
            simulator.resetBts(1, 1);
            assertEquals(0, simulator.btsRecords(1, 1).size());
            assertEquals(1, simulator.btsPlayback(1, 1).playback().cycleNo());
        }
        try (BtsDevelopmentSimulator restored = new BtsDevelopmentSimulator(0, store))
        {
            assertEquals(0, restored.btsRecords(1, 1).size());
            assertEquals(1, restored.btsPlayback(1, 1).playback().cycleNo());
        }
    }
 
    @Test
    void playbackFollowsExcelFixtureThroughAllCyclesAndRecords() throws Exception
    {
        Instant start = Instant.parse("2026-08-31T00:00:00Z");
        try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0,
                new InMemoryBtsSimulatorStateStore()))
        {
            simulator.updateChannel(1, 1, true, DeviceWorkStatus.WORKING);
            simulator.advanceBts(start);
            simulator.setBtsSpeed(1, 1, 600);
            Instant wallClock = simulator.btsPlayback(1, 1).playback().wallClockAt();
            long durationMillis = BtsExcelFixture.record(BtsExcelFixture.recordCount()).offsetSeconds() * 1000L;
            simulator.advanceBts(wallClock.plusMillis(durationMillis / 600L + 1000L));
 
            var records = simulator.btsRecords(1, 1);
            assertEquals(7605, records.size());
            assertEquals(7605L, records.get(records.size() - 1).sequenceId());
            assertEquals(33, records.get(records.size() - 1).cycleNo());
            assertEquals(33, simulator.btsCycles(1, 1).size());
            assertEquals(129, simulator.btsSteps(1, 1).size());
            assertTrue(simulator.btsPlayback(1, 1).playback().naturallyFinished());
        }
    }
}