package com.ruoyi.web.controller.device;
|
|
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 static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import java.lang.reflect.Method;
|
import java.math.BigDecimal;
|
import java.net.InetAddress;
|
import java.time.Instant;
|
import java.util.List;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.web.bind.annotation.GetMapping;
|
import com.ruoyi.common.annotation.Anonymous;
|
import com.ruoyi.device.bts.BtsDevelopmentSimulator;
|
import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate;
|
import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate;
|
import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore;
|
import com.ruoyi.device.model.ChannelIdentity;
|
import com.ruoyi.device.model.DeviceWorkStatus;
|
import com.ruoyi.web.config.BtsDevelopmentSimulatorWebConfig;
|
|
class BtsDevelopmentSimulatorControllerTest
|
{
|
@Test
|
void controllerUpdatesDeviceAndChannelState() throws Exception
|
{
|
try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
|
{
|
BtsDevelopmentSimulatorController controller = controller(simulator);
|
|
controller.updateDevice(1,
|
new BtsDevelopmentSimulatorController.DeviceStateCommand("127.0.0.2", 4, false));
|
controller.updateChannel(1, 3,
|
new BtsDevelopmentSimulatorController.ChannelStateCommand(true, DeviceWorkStatus.PAUSED));
|
|
assertFalse(controller.state().devices().get(0).online());
|
assertEquals(DeviceWorkStatus.PAUSED,
|
controller.state().devices().get(0).channels().get(2).workStatus());
|
}
|
}
|
|
@Test
|
void controllerAddsUpdatesAndDeletesVirtualDevices() throws Exception
|
{
|
try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
|
{
|
BtsDevelopmentSimulatorController controller = controller(simulator);
|
|
var created = controller.createDevice(
|
new BtsDevelopmentSimulatorController.CreateDeviceCommand("127.0.0.8", 6));
|
int deviceId = created.devices().stream()
|
.filter(device -> device.ip().equals("127.0.0.8"))
|
.findFirst().orElseThrow().deviceId();
|
controller.updateDevice(deviceId,
|
new BtsDevelopmentSimulatorController.DeviceStateCommand("127.0.0.9", 3, false));
|
|
assertEquals(2, controller.state().devices().size());
|
assertEquals(3, controller.state().devices().stream()
|
.filter(device -> device.deviceId() == deviceId)
|
.findFirst().orElseThrow().channels().size());
|
|
controller.deleteDevice(deviceId);
|
assertEquals(1, controller.state().devices().size());
|
}
|
}
|
|
@Test
|
void controllerConfiguresCollectorsSeparatelyFromCabinets() throws Exception
|
{
|
try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
|
{
|
BtsDevelopmentSimulatorController controller = controller(simulator);
|
var created = controller.createCollector(
|
new BtsDevelopmentSimulatorController.CreateCollectorCommand("127.0.1.8", 6));
|
int collectorId = created.collectors().stream()
|
.filter(collector -> collector.ip().equals("127.0.1.8"))
|
.findFirst().orElseThrow().collectorId();
|
|
controller.updateCollector(collectorId,
|
new BtsDevelopmentSimulatorController.CollectorStateCommand("127.0.1.9", 3, false));
|
|
assertEquals(1, controller.state().devices().size());
|
assertEquals(2, controller.state().collectors().size());
|
assertFalse(controller.state().collectors().stream()
|
.filter(collector -> collector.collectorId() == collectorId)
|
.findFirst().orElseThrow().online());
|
|
controller.deleteCollector(collectorId);
|
assertEquals(1, controller.state().collectors().size());
|
assertEquals(1, controller.state().devices().size());
|
}
|
}
|
|
@Test
|
void controllerExposesCollectorRealtimeAndPagedHistory() throws Exception
|
{
|
try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
|
{
|
BtsDevelopmentSimulatorController controller = controller(simulator);
|
controller.configureCollectorSampling(1,
|
new BtsDevelopmentSimulatorController.CollectorSamplingCommand(
|
100, List.of(), null, null, false));
|
controller.configureCollectorChannel(1, "S-01",
|
new BtsDevelopmentSimulatorController.CollectorChannelCommand(List.of(
|
new BtsDevelopmentSimulatorController.CollectorMetricCommand(
|
"temperature", new BigDecimal("27.2"), "℃"),
|
new BtsDevelopmentSimulatorController.CollectorMetricCommand(
|
"custom_voltage", new BigDecimal("1.234"), "V"))));
|
simulator.advanceCollectors(Instant.parse("2026-08-29T01:00:00Z"));
|
|
var realtime = controller.collectorRealtime(1);
|
var firstPage = controller.collectorHistory(1, 0, 2);
|
|
assertTrue(realtime.online());
|
assertTrue(realtime.measurements().stream().anyMatch(item -> item.metricCode().equals("custom_voltage")));
|
assertEquals(2, firstPage.records().size());
|
assertTrue(firstPage.hasMore());
|
assertEquals(2, firstPage.nextOffset());
|
}
|
}
|
|
@Test
|
void virtualIpMustBeUniqueAcrossCabinetsAndCollectors() throws Exception
|
{
|
try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
|
{
|
BtsDevelopmentSimulatorController controller = controller(simulator);
|
|
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
() -> controller.createCollector(
|
new BtsDevelopmentSimulatorController.CreateCollectorCommand("127.0.0.2", 4)));
|
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
() -> controller.createDevice(
|
new BtsDevelopmentSimulatorController.CreateDeviceCommand("127.0.1.2", 4)));
|
}
|
}
|
|
@Test
|
void developmentControlBoundaryOnlyAllowsLoopbackClients() throws Exception
|
{
|
var interceptor = new BtsDevelopmentSimulatorWebConfig.LocalOnlyInterceptor();
|
MockHttpServletResponse localResponse = new MockHttpServletResponse();
|
MockHttpServletRequest localRequest = requestFrom(InetAddress.getLoopbackAddress().getHostAddress());
|
MockHttpServletResponse remoteResponse = new MockHttpServletResponse();
|
MockHttpServletRequest remoteRequest = requestFrom("192.168.1.20");
|
|
assertTrue(interceptor.preHandle(localRequest, localResponse, new Object()));
|
assertFalse(interceptor.preHandle(remoteRequest, remoteResponse, new Object()));
|
assertEquals(403, remoteResponse.getStatus());
|
assertTrue(BtsDevelopmentSimulatorController.class.isAnnotationPresent(Anonymous.class));
|
}
|
|
@Test
|
void exposesStaticControlPageThroughAnonymousHandler() throws Exception
|
{
|
Method page = BtsDevelopmentSimulatorController.class.getMethod("page");
|
|
assertArrayEquals(new String[] { "/dev/bts-simulator.html" },
|
page.getAnnotation(GetMapping.class).value());
|
assertTrue(BtsDevelopmentSimulatorController.class.isAnnotationPresent(Anonymous.class));
|
}
|
|
@Test
|
void resettingSimulatorRemovesExistingDevelopmentCandidates() throws Exception
|
{
|
Instant now = Instant.parse("2026-08-27T00:00:00Z");
|
InMemoryDeviceDiscoveryCandidateStore candidateStore = new InMemoryDeviceDiscoveryCandidateStore();
|
candidateStore.recordCabinets(List.of(new CabinetCandidate("dev-sim", null, "dev-sim-22-8", 22, 8,
|
"127.0.0.8", null, "旧模拟柜", null, null,
|
List.of(new ChannelCandidate(new ChannelIdentity("dev-sim", 22, 8, 1, 1), true,
|
DeviceWorkStatus.STOPPED, now)), now, now.plusSeconds(30))));
|
try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
|
{
|
BtsDevelopmentSimulatorController controller =
|
new BtsDevelopmentSimulatorController(simulator, candidateStore);
|
|
controller.reset();
|
|
assertEquals(List.of(), candidateStore.snapshot(now).cabinets());
|
}
|
}
|
|
private BtsDevelopmentSimulatorController controller(BtsDevelopmentSimulator simulator)
|
{
|
return new BtsDevelopmentSimulatorController(simulator, new InMemoryDeviceDiscoveryCandidateStore());
|
}
|
|
private MockHttpServletRequest requestFrom(String remoteAddress)
|
{
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/dev/bts-simulator/state");
|
request.setRemoteAddr(remoteAddress);
|
return request;
|
}
|
}
|