package com.ruoyi.Dzp; import com.ruoyi.Dzp.domain.basLed; import com.ruoyi.Dzp.mapper.BasLedMapper; import org.junit.jupiter.api.Test; import org.springframework.test.util.ReflectionTestUtils; import java.io.IOException; import java.util.List; import java.util.concurrent.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import static org.mockito.ArgumentMatchers.*; class DzpSendTest { @Test void failedExchangeClosesItsSocketAndDoesNotAcknowledgeTheDisplay() throws Exception { var socket = mock(MyUdpSocket.class); var sender = new DzpSend() { @Override MyUdpSocket openSocket() { return socket; } }; var mapper = mock(BasLedMapper.class); ReflectionTestUtils.setField(sender, "mapper", mapper); var record = new basLed(); record.setModel("3"); record.setSendFlag("0"); record.setIpAddress("127.0.0.1"); record.setErrorMsg("alarm"); when(mapper.selectBasLedList(any())).thenAnswer(call -> call.getArgument(0, basLed.class).getId() == 1 ? List.of(record) : List.of()); try (var protocol = mockStatic(ProtocolDemo.class)) { protocol.when(() -> ProtocolDemo.demo_play_chapterschedule2(socket, "127.0.0.1", "报警信息", "alarm")) .thenThrow(new IllegalStateException("test send failure")).thenReturn(true); assertThatThrownBy(sender::ErrorLed).hasMessage("test send failure"); verify(socket).close(); verify(mapper, never()).updateBasLed(any()); assertThat(record.getSendFlag()).isEqualTo("0"); sender.ErrorLed(); verify(socket, times(2)).close(); verify(mapper).updateBasLed(record); } } @Test void busyLocalPortDefersOtherTimerWithoutBlockingOrChangingRows() throws Exception { var entered = new CountDownLatch(1); var release = new CountDownLatch(1); var sender = new DzpSend() { @Override MyUdpSocket openSocket() throws IOException { entered.countDown(); try { if (!release.await(3, TimeUnit.SECONDS)) throw new IOException("test timeout"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException(e); } throw new IOException("fixture port failure"); } }; var mapper = mock(BasLedMapper.class); ReflectionTestUtils.setField(sender, "mapper", mapper); var record = new basLed(); record.setModel("1"); record.setSendFlag("0"); when(mapper.selectBasLedList(any())).thenReturn(List.of(record)); var executor = Executors.newFixedThreadPool(2); try { var first = executor.submit(() -> { assertThatThrownBy(sender::InLed).isInstanceOf(IOException.class); }); assertThat(entered.await(2, TimeUnit.SECONDS)).isTrue(); executor.submit(() -> { sender.ErrorLed(); return null; }).get(1, TimeUnit.SECONDS); verify(mapper, times(1)).selectBasLedList(any()); verify(mapper, never()).updateBasLed(any()); release.countDown(); first.get(2, TimeUnit.SECONDS); } finally { release.countDown(); executor.shutdownNow(); } } @Test void eachScheduledMessageBuildsItsOwnPayload() throws Exception { try (var payloads = mockConstruction(LEDSender2010.class, (sender, context) -> when(sender.GetDataSize()).thenReturn((1 << 21) + 1))) { var socket = mock(MyUdpSocket.class); assertThat(ProtocolDemo.demo_play_chapterschedule2(socket, "127.0.0.1", "title1", "one")).isFalse(); assertThat(ProtocolDemo.demo_play_chapterschedule2(socket, "127.0.0.1", "title2", "two")).isFalse(); assertThat(payloads.constructed()).hasSize(2); verify(payloads.constructed().get(0)).GetDataSize(); verify(payloads.constructed().get(1)).GetDataSize(); verifyNoInteractions(socket); } } @Test void transientSocketErrorsStayInsideTheBoundedProtocolRetry() throws Exception { var socket = mock(MyUdpSocket.class); var payload = mock(LEDSender2010.class); doThrow(new IOException("transient send")).doNothing().when(socket).send(anyString(), anyInt(), any(), anyInt()); when(socket.receive()).thenThrow(new java.io.UncheckedIOException(new IOException("transient receive"))).thenReturn(1); when(payload.parse_trans_respond(any(), anyInt(), anyInt(), anyInt())).thenReturn(1); assertThat(ProtocolDemo.send_data1(socket, payload, "127.0.0.1")).isTrue(); verify(socket, times(3)).send(anyString(), anyInt(), any(), anyInt()); verify(socket, times(3)).receive(); } @Test void persistentSendFailureStopsAfterFiveAttempts() throws Exception { var socket = mock(MyUdpSocket.class); doThrow(new IOException("unreachable")).when(socket).send(anyString(), anyInt(), any(), anyInt()); assertThat(ProtocolDemo.send_data1(socket, mock(LEDSender2010.class), "127.0.0.1")).isFalse(); verify(socket, times(5)).send(anyString(), anyInt(), any(), anyInt()); verify(socket, never()).receive(); } }