1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.net;
15
16 import static org.junit.jupiter.api.Assertions.assertEquals;
17 import static org.junit.jupiter.api.Assertions.assertFalse;
18 import static org.junit.jupiter.api.Assertions.assertNotNull;
19 import static org.junit.jupiter.api.Assertions.assertNull;
20 import static org.junit.jupiter.api.Assertions.assertTrue;
21
22 import java.io.IOException;
23 import java.io.ObjectOutputStream;
24 import java.net.InetAddress;
25 import java.net.ServerSocket;
26 import java.net.Socket;
27 import java.net.UnknownHostException;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.TimeUnit;
30
31 import javax.net.SocketFactory;
32
33 import ch.qos.logback.classic.util.LogbackMDCAdapter;
34 import org.junit.jupiter.api.AfterEach;
35 import org.junit.jupiter.api.BeforeEach;
36 import org.junit.jupiter.api.Test;
37
38 import ch.qos.logback.classic.Level;
39 import ch.qos.logback.classic.Logger;
40 import ch.qos.logback.classic.LoggerContext;
41 import ch.qos.logback.classic.net.mock.MockAppender;
42 import ch.qos.logback.classic.spi.ILoggingEvent;
43 import ch.qos.logback.classic.spi.LoggingEvent;
44 import ch.qos.logback.classic.spi.LoggingEventVO;
45 import ch.qos.logback.core.net.SocketConnector;
46 import ch.qos.logback.core.net.server.test.ServerSocketUtil;
47 import ch.qos.logback.core.status.Status;
48
49
50
51
52
53 public class SocketReceiverTest {
54
55 private static final int DELAY = 1000;
56 private static final String TEST_HOST_NAME = "NOT.A.VALID.HOST.NAME";
57
58 private ServerSocket serverSocket;
59 private Socket socket;
60 private MockSocketFactory socketFactory = new MockSocketFactory();
61 private MockSocketConnector connector;
62 private MockAppender appender;
63 private LoggerContext lc;
64 LogbackMDCAdapter logbackMDCAdapter = new LogbackMDCAdapter();
65
66 private Logger logger;
67
68 private InstrumentedSocketReceiver receiver = new InstrumentedSocketReceiver();
69
70 @BeforeEach
71 public void setUp() throws Exception {
72 serverSocket = ServerSocketUtil.createServerSocket();
73 socket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort());
74 connector = new MockSocketConnector(socket);
75
76 lc = new LoggerContext();
77 lc.setMDCAdapter(logbackMDCAdapter);
78 lc.reset();
79 receiver.setContext(lc);
80 appender = new MockAppender();
81 appender.start();
82 logger = lc.getLogger(getClass());
83 logger.addAppender(appender);
84 }
85
86 @AfterEach
87 public void tearDown() throws Exception {
88 receiver.stop();
89 ExecutorService executor = lc.getExecutorService();
90 executor.shutdownNow();
91 assertTrue(executor.awaitTermination(DELAY, TimeUnit.MILLISECONDS));
92 socket.close();
93 serverSocket.close();
94 lc.stop();
95 }
96
97 @Test
98 public void testStartNoRemoteAddress() throws Exception {
99 receiver.start();
100 assertFalse(receiver.isStarted());
101 int count = lc.getStatusManager().getCount();
102 Status status = lc.getStatusManager().getCopyOfStatusList().get(count - 1);
103 assertTrue(status.getMessage().contains("host"));
104 }
105
106 @Test
107 public void testStartNoPort() throws Exception {
108 receiver.setRemoteHost(TEST_HOST_NAME);
109 receiver.start();
110 assertFalse(receiver.isStarted());
111 int count = lc.getStatusManager().getCount();
112 Status status = lc.getStatusManager().getCopyOfStatusList().get(count - 1);
113 assertTrue(status.getMessage().contains("port"));
114 }
115
116 @Test
117 public void testStartUnknownHost() throws Exception {
118 receiver.setPort(6000);
119 receiver.setRemoteHost(TEST_HOST_NAME);
120 receiver.start();
121 assertFalse(receiver.isStarted());
122 int count = lc.getStatusManager().getCount();
123 Status status = lc.getStatusManager().getCopyOfStatusList().get(count - 1);
124 assertTrue(status.getMessage().contains("unknown host"));
125 }
126
127 @Test
128 public void testStartStop() throws Exception {
129 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName());
130 receiver.setPort(6000);
131 receiver.setAcceptConnectionTimeout(DELAY / 2);
132 receiver.start();
133 assertTrue(receiver.isStarted());
134 receiver.awaitConnectorCreated(DELAY);
135 receiver.stop();
136 assertFalse(receiver.isStarted());
137 }
138
139 @Test
140 public void testServerSlowToAcceptConnection() throws Exception {
141 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName());
142 receiver.setPort(6000);
143 receiver.setAcceptConnectionTimeout(DELAY / 4);
144 receiver.start();
145 assertTrue(receiver.awaitConnectorCreated(DELAY / 2));
146
147
148 }
149
150 @Test
151 public void testServerDropsConnection() throws Exception {
152 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName());
153 receiver.setPort(6000);
154 receiver.start();
155 assertTrue(receiver.awaitConnectorCreated(DELAY));
156 Socket socket = serverSocket.accept();
157 socket.close();
158 }
159
160 @Test
161 public void testDispatchEventForEnabledLevel() throws Exception {
162 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName());
163 receiver.setPort(6000);
164 receiver.start();
165 assertTrue(receiver.awaitConnectorCreated(DELAY));
166 Socket socket = serverSocket.accept();
167
168 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
169
170 logger.setLevel(Level.DEBUG);
171 ILoggingEvent event = new LoggingEvent(logger.getName(), logger, Level.DEBUG, "test message", null,
172 new Object[0]);
173
174 LoggingEventVO eventVO = LoggingEventVO.build(event);
175 oos.writeObject(eventVO);
176 oos.flush();
177
178 ILoggingEvent rcvdEvent = appender.awaitAppend(DELAY);
179 assertNotNull(rcvdEvent);
180 assertEquals(event.getLoggerName(), rcvdEvent.getLoggerName());
181 assertEquals(event.getLevel(), rcvdEvent.getLevel());
182 assertEquals(event.getMessage(), rcvdEvent.getMessage());
183 }
184
185 @Test
186 public void testNoDispatchEventForDisabledLevel() throws Exception {
187 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName());
188 receiver.setPort(6000);
189 receiver.start();
190 assertTrue(receiver.awaitConnectorCreated(DELAY));
191 Socket socket = serverSocket.accept();
192
193 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
194
195 logger.setLevel(Level.INFO);
196 ILoggingEvent event = new LoggingEvent(logger.getName(), logger, Level.DEBUG, "test message", null,
197 new Object[0]);
198
199 LoggingEventVO eventVO = LoggingEventVO.build(event);
200 oos.writeObject(eventVO);
201 oos.flush();
202
203 assertNull(appender.awaitAppend(DELAY));
204 }
205
206
207
208
209 private class InstrumentedSocketReceiver extends SocketReceiver {
210
211 private boolean connectorCreated;
212
213 @Override
214 protected synchronized SocketConnector newConnector(InetAddress address, int port, int initialDelay,
215 int retryDelay) {
216 connectorCreated = true;
217 notifyAll();
218 return connector;
219 }
220
221 @Override
222 protected SocketFactory getSocketFactory() {
223 return socketFactory;
224 }
225
226 public synchronized boolean awaitConnectorCreated(long delay) throws InterruptedException {
227 while (!connectorCreated) {
228 wait(delay);
229 }
230 return connectorCreated;
231 }
232
233 }
234
235
236
237
238 private static class MockSocketConnector implements SocketConnector {
239
240 private final Socket socket;
241
242 public MockSocketConnector(Socket socket) {
243 this.socket = socket;
244 }
245
246 public Socket call() throws InterruptedException {
247 return socket;
248 }
249
250 public void setExceptionHandler(ExceptionHandler exceptionHandler) {
251 }
252
253 public void setSocketFactory(SocketFactory socketFactory) {
254 }
255
256 }
257
258
259
260
261 private static class MockSocketFactory extends SocketFactory {
262
263 @Override
264 public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
265 throws IOException {
266 throw new UnsupportedOperationException();
267 }
268
269 @Override
270 public Socket createSocket(InetAddress host, int port) throws IOException {
271 throw new UnsupportedOperationException();
272 }
273
274 @Override
275 public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
276 throws IOException, UnknownHostException {
277 throw new UnsupportedOperationException();
278 }
279
280 @Override
281 public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
282 throw new UnsupportedOperationException();
283 }
284
285 }
286
287 }