| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertNull; |
| | | import static org.junit.jupiter.api.Assertions.assertTrue; |
| | | import static org.mockito.ArgumentMatchers.any; |
| | | import static org.mockito.ArgumentMatchers.anyString; |
| | | import static org.mockito.ArgumentMatchers.anyInt; |
| | | import static org.mockito.ArgumentMatchers.eq; |
| | | import static org.mockito.ArgumentMatchers.isNull; |
| | | import static org.mockito.Mockito.mock; |
| | | import static org.mockito.Mockito.never; |
| | | import static org.mockito.Mockito.times; |
| | | import static org.mockito.Mockito.verify; |
| | | import static org.mockito.Mockito.when; |
| | | |
| | | import java.time.Instant; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.math.BigDecimal; |
| | | import java.time.Clock; |
| | | import java.time.Instant; |
| | | import java.time.ZoneOffset; |
| | | import java.util.Date; |
| | | import java.util.HexFormat; |
| | | import java.util.List; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.junit.jupiter.api.extension.ExtendWith; |
| | | import org.mockito.ArgumentCaptor; |
| | | import org.springframework.boot.test.system.CapturedOutput; |
| | | import org.springframework.boot.test.system.OutputCaptureExtension; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.BtsCycleRecord; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.BtsStepRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.ruoyi.system.domain.TTestCollectorChannel; |
| | | import com.ruoyi.system.domain.TTest; |
| | | import com.ruoyi.system.domain.TTestBattery; |
| | | import com.ruoyi.system.domain.TTestChannelBinding; |
| | | import com.ruoyi.system.domain.TTestCollectorChannel; |
| | | import com.ruoyi.system.domain.TTestCycleRecord; |
| | | import com.ruoyi.system.domain.TTestRealtimeRecord; |
| | | import com.ruoyi.system.domain.TTestStepRecord; |
| | | import com.ruoyi.system.mapper.TTestMapper; |
| | | import com.ruoyi.system.service.ITTestService; |
| | | |
| | | /** 接收服务只应把本次测试开始后的模拟器事实归入测试。 */ |
| | | /** Ticket08 通过接收入口验证三类持久化事实。 */ |
| | | @ExtendWith(OutputCaptureExtension.class) |
| | | class TestDataReceptionServiceImplTest |
| | | { |
| | | private static final Instant CAPTURED_AT = Instant.parse("2026-09-02T04:01:00Z"); |
| | | private static final Clock CLOCK = Clock.fixed(CAPTURED_AT, ZoneOffset.UTC); |
| | | |
| | | @Test |
| | | void ignoresRecordsBeforeReceptionStart() |
| | | void savesOneCombinedRealtimeRowForOneBatteryPollingSlot() |
| | | { |
| | | Fixture fixture = fixture(); |
| | | when(fixture.simulator.btsRecords(1, 1)).thenReturn(List.of(cabinetRecord())); |
| | | when(fixture.simulator.collectorRealtime(9)).thenReturn(collectorSnapshot(true, List.of( |
| | | collector("S-01", 10L, "TEMPERATURE", "25.100", "℃"), |
| | | collector("S-02", 10L, "POSITIVE_POTENTIAL", "1.620", "V"), |
| | | collector("S-03", 10L, "NEGATIVE_POTENTIAL", "1.610", "V"), |
| | | collector("S-04", 10L, "AMBIENT_TEMPERATURE", "23.400", "℃")))); |
| | | when(fixture.mapper.insertRealtimeRecord(any())).thenReturn(1); |
| | | |
| | | fixture.service().captureDevelopmentRealtimeSnapshots(); |
| | | |
| | | ArgumentCaptor<TTestRealtimeRecord> saved = ArgumentCaptor.forClass(TTestRealtimeRecord.class); |
| | | verify(fixture.mapper).insertRealtimeRecord(saved.capture()); |
| | | TTestRealtimeRecord row = saved.getValue(); |
| | | assertEquals(1L, row.getTestId()); |
| | | assertEquals(4L, row.getTestBatteryId()); |
| | | assertEquals(2L, row.getBindingId()); |
| | | assertEquals("dev-sim:22:1:1:1", row.getSourceIdentity()); |
| | | assertEquals("cabinet:7:collector:10", row.getSourceRecordId()); |
| | | assertEquals(Date.from(Instant.parse("2026-09-02T04:00:30Z")), row.getCabinetDeviceTimeUtc()); |
| | | assertEquals(Date.from(Instant.parse("2026-09-02T04:00:40Z")), row.getCollectorDeviceTimeUtc()); |
| | | assertEquals(new BigDecimal("25.100"), row.getTemperature()); |
| | | assertEquals(new BigDecimal("1.620"), row.getPositivePotential()); |
| | | assertEquals(new BigDecimal("1.610"), row.getNegativePotential()); |
| | | assertTrue(row.getExtensionMeasurementsJson().contains("AMBIENT_TEMPERATURE")); |
| | | assertTrue(!row.getExtensionMeasurementsJson().contains("POSITIVE_POTENTIAL")); |
| | | } |
| | | |
| | | @Test |
| | | void savesCollectorFieldsWhenCabinetSourceFails() |
| | | { |
| | | Fixture fixture = fixture(); |
| | | when(fixture.simulator.btsRecords(1, 1)).thenThrow(new IllegalArgumentException("offline")); |
| | | when(fixture.simulator.collectorRealtime(9)).thenReturn(collectorSnapshot(true, |
| | | List.of(collector("S-01", 11L, "TEMPERATURE", "26.2", "℃")))); |
| | | when(fixture.mapper.insertRealtimeRecord(any())).thenReturn(1); |
| | | |
| | | fixture.service().captureDevelopmentRealtimeSnapshots(); |
| | | |
| | | ArgumentCaptor<TTestRealtimeRecord> saved = ArgumentCaptor.forClass(TTestRealtimeRecord.class); |
| | | verify(fixture.mapper).insertRealtimeRecord(saved.capture()); |
| | | assertNull(saved.getValue().getCabinetSequenceId()); |
| | | assertNull(saved.getValue().getCabinetDevtype()); |
| | | assertNull(saved.getValue().getCabinetAdapterTimezoneId()); |
| | | assertNull(saved.getValue().getVoltageV()); |
| | | assertEquals(11L, saved.getValue().getCollectorSequenceId()); |
| | | assertEquals("collector:11", saved.getValue().getSourceRecordId()); |
| | | assertEquals(new BigDecimal("26.2"), saved.getValue().getTemperature()); |
| | | assertNull(saved.getValue().getPositivePotential()); |
| | | } |
| | | |
| | | @Test |
| | | void savesOnlyDeviceReturnedStepAndCycleRecords() |
| | | { |
| | | Fixture fixture = fixture(); |
| | | Instant started = Instant.parse("2026-09-02T04:00:10Z"); |
| | | Instant ended = Instant.parse("2026-09-02T04:00:50Z"); |
| | | when(fixture.simulator.btsSteps(1, 1)).thenReturn(List.of(new BtsStepRecord( |
| | | 1, 2, 2, "恒流充电", "cc", 41, started, ended, 40, |
| | | 2.5, 8.4, 3.1, 3.4, 3.4, 0))); |
| | | when(fixture.simulator.btsCycles(1, 1)).thenReturn(List.of(new BtsCycleRecord( |
| | | "CYCLE-1-1-1", 1, 80, started, ended, 2.5, 2.4, 8.4, 8.0, 96))); |
| | | when(fixture.mapper.insertStepRecord(any())).thenReturn(1); |
| | | when(fixture.mapper.insertCycleRecord(any())).thenReturn(1); |
| | | |
| | | fixture.service().captureDevelopmentCabinetRecords(); |
| | | |
| | | ArgumentCaptor<TTestStepRecord> step = ArgumentCaptor.forClass(TTestStepRecord.class); |
| | | ArgumentCaptor<TTestCycleRecord> cycle = ArgumentCaptor.forClass(TTestCycleRecord.class); |
| | | verify(fixture.mapper).insertStepRecord(step.capture()); |
| | | verify(fixture.mapper).insertCycleRecord(cycle.capture()); |
| | | assertEquals("fallback:2026-09-02T04:00:50Z:1:2", step.getValue().getDedupeKey()); |
| | | assertEquals("CYCLE-1-1-1", cycle.getValue().getSourceRecordId()); |
| | | assertEquals("record:CYCLE-1-1-1", cycle.getValue().getDedupeKey()); |
| | | assertEquals(Date.from(CAPTURED_AT), step.getValue().getServerReceivedAtUtc()); |
| | | assertEquals(Date.from(CAPTURED_AT), cycle.getValue().getServerReceivedAtUtc()); |
| | | } |
| | | |
| | | @Test |
| | | void ignoresSameRealtimeContentOnRepeatedReception() |
| | | { |
| | | Fixture fixture = fixture(); |
| | | when(fixture.simulator.btsRecords(1, 1)).thenReturn(List.of(cabinetRecord())); |
| | | when(fixture.simulator.collectorRealtime(9)).thenReturn(collectorSnapshot(false, List.of())); |
| | | when(fixture.mapper.insertRealtimeRecord(any())).thenReturn(1); |
| | | |
| | | fixture.service().captureDevelopmentRealtimeSnapshots(); |
| | | ArgumentCaptor<TTestRealtimeRecord> saved = ArgumentCaptor.forClass(TTestRealtimeRecord.class); |
| | | verify(fixture.mapper).insertRealtimeRecord(saved.capture()); |
| | | when(fixture.mapper.selectRealtimeRecordContentHash(eq(1L), eq(4L), any(Date.class))) |
| | | .thenReturn(HexFormat.of().formatHex(saved.getValue().getContentSha256())); |
| | | |
| | | fixture.service().captureDevelopmentRealtimeSnapshots(); |
| | | |
| | | verify(fixture.mapper, times(1)).insertRealtimeRecord(any()); |
| | | } |
| | | |
| | | @Test |
| | | void rejectsConflictingRealtimeContentAndWritesApplicationLog(CapturedOutput output) |
| | | { |
| | | Fixture fixture = fixture(); |
| | | when(fixture.simulator.btsRecords(1, 1)).thenReturn(List.of(cabinetRecord())); |
| | | when(fixture.simulator.collectorRealtime(9)).thenReturn(collectorSnapshot(false, List.of())); |
| | | when(fixture.mapper.selectRealtimeRecordContentHash(eq(1L), eq(4L), any(Date.class))) |
| | | .thenReturn("different-content"); |
| | | |
| | | fixture.service().captureDevelopmentRealtimeSnapshots(); |
| | | |
| | | verify(fixture.mapper, never()).insertRealtimeRecord(any()); |
| | | assertTrue(output.getOut().contains("实时采样内容冲突")); |
| | | } |
| | | |
| | | private static Fixture fixture() |
| | | { |
| | | TTestMapper mapper = mock(TTestMapper.class); |
| | | ITTestService tests = mock(ITTestService.class); |
| | | BtsDevelopmentSimulator simulator = mock(BtsDevelopmentSimulator.class); |
| | | TTest test = test(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | TTest test = receivingTest(); |
| | | when(mapper.selectReceivingTestIds()).thenReturn(List.of(1L)); |
| | | when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test); |
| | | when(tests.selectTestById(1L)).thenReturn(test); |
| | | when(simulator.btsRecords(1, 1)).thenReturn(List.of( |
| | | record(1L, "2026-09-02T03:59:59Z"), record(2L, "2026-09-02T04:00:01Z"))); |
| | | when(mapper.selectBtsSampleContentHash(any(), anyString(), any())).thenReturn(null); |
| | | when(mapper.insertBtsSample(any(), any(), any(), anyString(), any(), any(Date.class), anyString(), |
| | | any(Date.class), anyInt(), anyInt(), anyString(), anyString(), isNull(), any(BigDecimal.class), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(byte[].class))).thenReturn(1); |
| | | |
| | | new TestDataReceptionServiceImpl(mapper, tests, simulator).captureDevelopmentCabinetRecords(); |
| | | |
| | | verify(mapper, times(1)).insertBtsSample(eq(1L), eq(2L), eq(3L), anyString(), eq(2L), any(Date.class), |
| | | anyString(), any(Date.class), anyInt(), anyInt(), anyString(), anyString(), isNull(), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), |
| | | any(byte[].class)); |
| | | when(simulator.persistenceIntervalMillis(1, 1)).thenReturn(60000L); |
| | | return new Fixture(mapper, tests, simulator); |
| | | } |
| | | |
| | | @Test |
| | | void doesNotWriteSamplesWhenNoSuccessfulRecordsAreAvailable() |
| | | { |
| | | TTestMapper mapper = mock(TTestMapper.class); |
| | | ITTestService tests = mock(ITTestService.class); |
| | | BtsDevelopmentSimulator simulator = mock(BtsDevelopmentSimulator.class); |
| | | TTest test = test(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | when(mapper.selectReceivingTestIds()).thenReturn(List.of(1L)); |
| | | when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test); |
| | | when(tests.selectTestById(1L)).thenReturn(test); |
| | | when(simulator.btsRecords(1, 1)).thenReturn(List.of()); |
| | | |
| | | new TestDataReceptionServiceImpl(mapper, tests, simulator).captureDevelopmentCabinetRecords(); |
| | | |
| | | verify(mapper, never()).insertBtsSample(any(), any(), any(), anyString(), any(), any(Date.class), anyString(), |
| | | any(Date.class), anyInt(), anyInt(), anyString(), anyString(), isNull(), any(BigDecimal.class), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(byte[].class)); |
| | | } |
| | | |
| | | @Test |
| | | void ordinaryEditsDoNotMoveReceptionBoundary() |
| | | { |
| | | TTestMapper mapper = mock(TTestMapper.class); |
| | | ITTestService tests = mock(ITTestService.class); |
| | | BtsDevelopmentSimulator simulator = mock(BtsDevelopmentSimulator.class); |
| | | TTest test = test(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | test.setUpdateTime(Date.from(Instant.parse("2026-09-02T04:00:10Z"))); |
| | | when(mapper.selectReceivingTestIds()).thenReturn(List.of(1L)); |
| | | when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test); |
| | | when(tests.selectTestById(1L)).thenReturn(test); |
| | | when(simulator.btsRecords(1, 1)).thenReturn(List.of( |
| | | record(1L, "2026-09-02T04:00:05Z"), record(2L, "2026-09-02T04:00:11Z"))); |
| | | when(mapper.selectBtsSampleContentHash(any(), anyString(), any())).thenReturn(null); |
| | | when(mapper.insertBtsSample(any(), any(), any(), anyString(), any(), any(Date.class), anyString(), |
| | | any(Date.class), anyInt(), anyInt(), anyString(), anyString(), isNull(), any(BigDecimal.class), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(byte[].class))).thenReturn(1); |
| | | |
| | | new TestDataReceptionServiceImpl(mapper, tests, simulator).captureDevelopmentCabinetRecords(); |
| | | |
| | | verify(mapper, times(2)).insertBtsSample(eq(1L), eq(2L), eq(3L), anyString(), any(), any(Date.class), |
| | | anyString(), any(Date.class), anyInt(), anyInt(), anyString(), anyString(), isNull(), |
| | | any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), |
| | | any(byte[].class)); |
| | | } |
| | | |
| | | @Test |
| | | void capturesOnlyMappedCollectorRealtimeMeasurementsAfterReceptionStart() |
| | | { |
| | | TTestMapper mapper = mock(TTestMapper.class); |
| | | ITTestService tests = mock(ITTestService.class); |
| | | BtsDevelopmentSimulator simulator = mock(BtsDevelopmentSimulator.class); |
| | | TTest test = test(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | test.setReceptionBoundaryAtUtc(Date.from(Instant.parse("2026-09-02T04:00:01.500Z"))); |
| | | test.getBatteries().get(0).setCollectorId(9L); |
| | | TTestCollectorChannel mapping = new TTestCollectorChannel(); |
| | | mapping.setMeasurementCode("temperature"); mapping.setChannelCode("S-01"); |
| | | test.getBatteries().get(0).setCollectorChannels(List.of(mapping)); |
| | | when(mapper.selectReceivingTestIds()).thenReturn(List.of(1L)); |
| | | when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test); |
| | | when(tests.selectTestById(1L)).thenReturn(test); |
| | | CollectorRealtimeMeasurement matched = new CollectorRealtimeMeasurement("dev-sim", "collector-9", "S-01", |
| | | 3L, Instant.parse("2026-09-02T04:00:01Z"), "2026-09-02 12:00:01.000", |
| | | Instant.parse("2026-09-02T04:00:02Z"), "temperature", new BigDecimal("25.1"), "℃"); |
| | | CollectorRealtimeMeasurement ignored = new CollectorRealtimeMeasurement("dev-sim", "collector-9", "S-02", |
| | | 3L, matched.deviceTime(), matched.deviceTimeRaw(), matched.serverReceivedAt(), "temperature", |
| | | new BigDecimal("25.2"), "℃"); |
| | | CollectorRealtimeMeasurement beforeBoundary = new CollectorRealtimeMeasurement("dev-sim", "collector-9", "S-01", |
| | | 2L, Instant.parse("2026-09-02T04:00:00Z"), "2026-09-02 12:00:00.000", |
| | | Instant.parse("2026-09-02T04:00:01Z"), "temperature", new BigDecimal("24.9"), "℃"); |
| | | when(simulator.collectorRealtime(9)).thenReturn(new CollectorRealtimeSnapshot("collector-9", true, 1000, |
| | | List.of(matched, ignored, beforeBoundary))); |
| | | when(mapper.selectCollectorSampleContentHash(any(), anyString(), any(), anyString())).thenReturn(null); |
| | | when(mapper.insertCollectorSample(any(), any(), any(), anyString(), anyString(), any(), any(Date.class), anyString(), |
| | | any(Date.class), anyString(), any(BigDecimal.class), anyString(), any(byte[].class))).thenReturn(1); |
| | | |
| | | new TestDataReceptionServiceImpl(mapper, tests, simulator).captureDevelopmentCollectorMeasurements(); |
| | | |
| | | verify(mapper).insertCollectorSample(eq(1L), eq(2L), eq(9L), eq("dev-sim"), eq("S-01"), eq(3L), any(Date.class), |
| | | eq("2026-09-02 12:00:01.000"), any(Date.class), eq("temperature"), eq(new BigDecimal("25.1")), |
| | | eq("℃"), any(byte[].class)); |
| | | verify(mapper, never()).insertCollectorSample(eq(1L), eq(2L), eq(9L), anyString(), eq("S-02"), any(), any(Date.class), |
| | | anyString(), any(Date.class), anyString(), any(BigDecimal.class), anyString(), any(byte[].class)); |
| | | } |
| | | |
| | | @Test |
| | | void recordsCollectorContentConflictWithoutOverwritingOriginal() |
| | | { |
| | | TTestMapper mapper = mock(TTestMapper.class); |
| | | ITTestService tests = mock(ITTestService.class); |
| | | BtsDevelopmentSimulator simulator = mock(BtsDevelopmentSimulator.class); |
| | | TTest test = test(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | test.getBatteries().get(0).setCollectorId(9L); |
| | | TTestCollectorChannel mapping = new TTestCollectorChannel(); mapping.setMeasurementCode("temperature"); mapping.setChannelCode("S-01"); |
| | | test.getBatteries().get(0).setCollectorChannels(List.of(mapping)); |
| | | CollectorRealtimeMeasurement measurement = new CollectorRealtimeMeasurement("dev-sim", "collector-9", "S-01", 3L, |
| | | Instant.parse("2026-09-02T04:00:01Z"), "2026-09-02 12:00:01.000", Instant.now(), "temperature", new BigDecimal("25.1"), "℃"); |
| | | when(mapper.selectReceivingTestIds()).thenReturn(List.of(1L)); when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test); |
| | | when(tests.selectTestById(1L)).thenReturn(test); when(simulator.collectorRealtime(9)).thenReturn(new CollectorRealtimeSnapshot("collector-9", true, 1000, List.of(measurement))); |
| | | when(mapper.selectCollectorSampleContentHash(9L, "S-01", 3L, "temperature")).thenReturn("different"); |
| | | |
| | | new TestDataReceptionServiceImpl(mapper, tests, simulator).captureDevelopmentCollectorMeasurements(); |
| | | |
| | | verify(mapper).insertSampleConflict(eq(1L), eq(3L), org.mockito.ArgumentMatchers.contains("采集器实时接收内容冲突")); |
| | | verify(mapper, never()).insertCollectorSample(any(), any(), any(), anyString(), anyString(), any(), any(Date.class), anyString(), any(Date.class), anyString(), any(BigDecimal.class), anyString(), any(byte[].class)); |
| | | } |
| | | |
| | | private static TTest test(Date startedAt) |
| | | private static TTest receivingTest() |
| | | { |
| | | TTestChannelBinding binding = new TTestChannelBinding(); |
| | | binding.setBindingId(2L); |
| | | binding.setChannelId(3L); |
| | | binding.setAdapterCode("dev-sim"); |
| | | binding.setAdapterTimezoneId("Asia/Hong_Kong"); |
| | | binding.setDevtype(22); |
| | | binding.setDevid(1); |
| | | binding.setSubdevid(1); |
| | | binding.setChlid(1); |
| | | TTestBattery battery = new TTestBattery(); |
| | | battery.setTestBatteryId(4L); |
| | | battery.setCollectorId(9L); |
| | | battery.setBinding(binding); |
| | | battery.setCollectorChannels(List.of( |
| | | mapping("TEMPERATURE", "S-01"), mapping("POSITIVE_POTENTIAL", "S-02"), |
| | | mapping("NEGATIVE_POTENTIAL", "S-03"), mapping("AMBIENT_TEMPERATURE", "S-04"))); |
| | | TTest test = new TTest(); |
| | | test.setTestId(1L); |
| | | test.setTestStatus("RUNNING"); |
| | | test.setReceptionStatus("RECEIVING"); |
| | | test.setStartedAtUtc(startedAt); |
| | | test.setStartedAtUtc(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | test.setReceptionBoundaryAtUtc(Date.from(Instant.parse("2026-09-02T04:00:00Z"))); |
| | | test.setBatteries(List.of(battery)); |
| | | return test; |
| | | } |
| | | |
| | | private static BtsHistoryRecord record(long sequenceId, String deviceTime) |
| | | private static TTestCollectorChannel mapping(String metric, String channel) |
| | | { |
| | | Instant parsed = Instant.parse(deviceTime); |
| | | return new BtsHistoryRecord(sequenceId, parsed, 1d, 2d, 3d, 4d, |
| | | 1, 1, "恒流充电", "cc", parsed); |
| | | TTestCollectorChannel mapping = new TTestCollectorChannel(); |
| | | mapping.setMeasurementCode(metric); |
| | | mapping.setChannelCode(channel); |
| | | return mapping; |
| | | } |
| | | |
| | | private static BtsHistoryRecord cabinetRecord() |
| | | { |
| | | Instant deviceTime = Instant.parse("2026-09-02T04:00:30Z"); |
| | | return new BtsHistoryRecord(7L, deviceTime, 1, 3.2, 2.5, 8.4, |
| | | 1, 2, "恒流充电", "cc", Instant.parse("2026-09-02T04:00:35Z")); |
| | | } |
| | | |
| | | private static CollectorRealtimeMeasurement collector(String channel, long sequenceId, String metric, |
| | | String value, String unit) |
| | | { |
| | | return new CollectorRealtimeMeasurement("dev-sim", "collector-9", channel, sequenceId, |
| | | Instant.parse("2026-09-02T04:00:40Z"), "2026-09-02 12:00:40.000", |
| | | Instant.parse("2026-09-02T04:00:50Z"), metric, new BigDecimal(value), unit); |
| | | } |
| | | |
| | | private static CollectorRealtimeSnapshot collectorSnapshot(boolean online, |
| | | List<CollectorRealtimeMeasurement> measurements) |
| | | { |
| | | return new CollectorRealtimeSnapshot("collector-9", online, 1000, measurements); |
| | | } |
| | | |
| | | private record Fixture(TTestMapper mapper, ITTestService tests, BtsDevelopmentSimulator simulator) |
| | | { |
| | | TestDataReceptionServiceImpl service() |
| | | { |
| | | return new TestDataReceptionServiceImpl(mapper, tests, simulator, CLOCK); |
| | | } |
| | | } |
| | | } |