package com.ruoyi.device.bts;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import java.time.Duration;
|
import java.util.Set;
|
import java.util.concurrent.Callable;
|
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.Executors;
|
import java.util.concurrent.Future;
|
import org.junit.jupiter.api.Test;
|
|
class BtsTcpTransportTest
|
{
|
@Test
|
void framesRequestsAndSerializesConcurrentExchanges() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(), Duration.ofSeconds(1), Duration.ofSeconds(2)))
|
{
|
ExecutorService callers = Executors.newFixedThreadPool(2);
|
try
|
{
|
simulator.enqueue("<bts><cmd>first_resp</cmd></bts>");
|
simulator.enqueue("<bts><cmd>second_resp</cmd></bts>");
|
Callable<String> first = () -> transport.exchange("<bts><cmd>first</cmd><note>检测</note></bts>");
|
Callable<String> second = () -> transport.exchange("<bts><cmd>second</cmd></bts>");
|
|
Future<String> firstResult = callers.submit(first);
|
Future<String> secondResult = callers.submit(second);
|
Set<String> responses = Set.of(firstResult.get(), secondResult.get());
|
|
assertEquals(Set.of("<bts><cmd>first_resp</cmd></bts>", "<bts><cmd>second_resp</cmd></bts>"), responses);
|
assertEquals(2, simulator.requests().size());
|
assertTrue(simulator.requests().stream().allMatch(request -> request.startsWith("<bts>")));
|
assertTrue(simulator.requests().stream().anyMatch(request -> request.contains("<note>检测</note>")));
|
}
|
finally
|
{
|
callers.shutdownNow();
|
}
|
}
|
}
|
|
@Test
|
void reportsDelayedResponseAsTimeout() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
|
Duration.ofSeconds(1), Duration.ofMillis(50)))
|
{
|
simulator.enqueueDelayed(Duration.ofMillis(200), "<bts><cmd>late_resp</cmd></bts>");
|
|
BtsTransportException exception = assertThrows(BtsTransportException.class,
|
() -> transport.exchange("<bts><cmd>late</cmd></bts>"));
|
|
assertEquals(BtsTransportException.Reason.TIMEOUT, exception.reason());
|
}
|
}
|
|
@Test
|
void reportsActiveDisconnectAndReconnectsOnNextExchange() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
|
Duration.ofSeconds(1), Duration.ofSeconds(1)))
|
{
|
simulator.enqueueDisconnect();
|
|
BtsTransportException exception = assertThrows(BtsTransportException.class,
|
() -> transport.exchange("<bts><cmd>first</cmd></bts>"));
|
|
assertEquals(BtsTransportException.Reason.DISCONNECTED, exception.reason());
|
|
simulator.enqueue("<bts><cmd>second_resp</cmd></bts>");
|
assertEquals("<bts><cmd>second_resp</cmd></bts>",
|
transport.exchange("<bts><cmd>second</cmd></bts>"));
|
assertEquals(2, simulator.requests().size());
|
}
|
}
|
|
@Test
|
void rejectsResponseLargerThanConfiguredLimit() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
|
Duration.ofSeconds(1), Duration.ofSeconds(1), 32))
|
{
|
simulator.enqueue("x".repeat(33));
|
|
BtsTransportException exception = assertThrows(BtsTransportException.class,
|
() -> transport.exchange("<bts><cmd>large</cmd></bts>"));
|
|
assertEquals(BtsTransportException.Reason.RESPONSE_TOO_LARGE, exception.reason());
|
}
|
}
|
|
@Test
|
void reportsRefusedConnection() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = ScriptedBtsTcpSimulator.refusingConnections();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
|
Duration.ofSeconds(1), Duration.ofSeconds(1)))
|
{
|
BtsTransportException exception = assertThrows(BtsTransportException.class,
|
() -> transport.exchange("<bts><cmd>getdevinfo</cmd></bts>"));
|
|
assertEquals(BtsTransportException.Reason.CONNECTION_FAILED, exception.reason());
|
assertTrue(simulator.requests().isEmpty());
|
}
|
}
|
|
@Test
|
void rejectsResponseTimeoutAboveProtocolMaximum()
|
{
|
assertThrows(IllegalArgumentException.class,
|
() -> new BtsTcpTransport("127.0.0.1", 502,
|
Duration.ofSeconds(1), Duration.ofSeconds(31)));
|
}
|
|
@Test
|
void rejectsResponseThatIsNotValidUtf8() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
|
Duration.ofSeconds(1), Duration.ofSeconds(1)))
|
{
|
simulator.enqueueRaw(new byte[] {(byte) 0xC3, (byte) 0x28});
|
|
BtsTransportException exception = assertThrows(BtsTransportException.class,
|
() -> transport.exchange("<bts><cmd>getdevinfo</cmd></bts>"));
|
|
assertEquals(BtsTransportException.Reason.INVALID_UTF8, exception.reason());
|
}
|
}
|
|
@Test
|
void acceptsResponseAtSizeLimitAndDelimiterPrefixInPayload() throws Exception
|
{
|
try (ScriptedBtsTcpSimulator simulator = new ScriptedBtsTcpSimulator();
|
BtsTcpTransport transport = new BtsTcpTransport("127.0.0.1", simulator.port(),
|
Duration.ofSeconds(1), Duration.ofSeconds(1), 32))
|
{
|
String atLimit = "x".repeat(32);
|
simulator.enqueue(atLimit);
|
simulator.enqueue("#");
|
|
assertEquals(atLimit, transport.exchange("first"));
|
assertEquals("#", transport.exchange("second"));
|
}
|
}
|
}
|