001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic.net; 015 016import static org.junit.Assert.assertEquals; 017import static org.junit.Assert.assertFalse; 018import static org.junit.Assert.assertNotNull; 019import static org.junit.Assert.assertNull; 020import static org.junit.Assert.assertTrue; 021 022import java.io.IOException; 023import java.io.ObjectOutputStream; 024import java.net.InetAddress; 025import java.net.ServerSocket; 026import java.net.Socket; 027import java.net.UnknownHostException; 028import java.util.concurrent.ExecutorService; 029import java.util.concurrent.TimeUnit; 030 031import javax.net.SocketFactory; 032 033import org.junit.After; 034import org.junit.Before; 035import org.junit.Ignore; 036import org.junit.Test; 037 038import ch.qos.logback.classic.Level; 039import ch.qos.logback.classic.Logger; 040import ch.qos.logback.classic.LoggerContext; 041import ch.qos.logback.classic.net.mock.MockAppender; 042import ch.qos.logback.classic.spi.ILoggingEvent; 043import ch.qos.logback.classic.spi.LoggingEvent; 044import ch.qos.logback.classic.spi.LoggingEventVO; 045import ch.qos.logback.core.net.SocketConnector; 046import ch.qos.logback.core.net.server.test.ServerSocketUtil; 047import ch.qos.logback.core.status.Status; 048 049/** 050 * Unit tests for {@link SocketReceiver}. 051 * 052 * @author Carl Harris 053 */ 054@Ignore 055public class SocketReceiverTest { 056 057 private static final int DELAY = 1000; 058 private static final String TEST_HOST_NAME = "NOT.A.VALID.HOST.NAME"; 059 060 private ServerSocket serverSocket; 061 private Socket socket; 062 private MockSocketFactory socketFactory = new MockSocketFactory(); 063 private MockSocketConnector connector; 064 private MockAppender appender; 065 private LoggerContext lc; 066 private Logger logger; 067 068 private InstrumentedSocketReceiver receiver = new InstrumentedSocketReceiver(); 069 070 @Before 071 public void setUp() throws Exception { 072 serverSocket = ServerSocketUtil.createServerSocket(); 073 socket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); 074 connector = new MockSocketConnector(socket); 075 076 lc = new LoggerContext(); 077 lc.reset(); 078 receiver.setContext(lc); 079 appender = new MockAppender(); 080 appender.start(); 081 logger = lc.getLogger(getClass()); 082 logger.addAppender(appender); 083 } 084 085 @After 086 public void tearDown() throws Exception { 087 receiver.stop(); 088 ExecutorService executor = lc.getExecutorService(); 089 executor.shutdownNow(); 090 assertTrue(executor.awaitTermination(DELAY, TimeUnit.MILLISECONDS)); 091 socket.close(); 092 serverSocket.close(); 093 lc.stop(); 094 } 095 096 @Test 097 public void testStartNoRemoteAddress() throws Exception { 098 receiver.start(); 099 assertFalse(receiver.isStarted()); 100 int count = lc.getStatusManager().getCount(); 101 Status status = lc.getStatusManager().getCopyOfStatusList().get(count - 1); 102 assertTrue(status.getMessage().contains("host")); 103 } 104 105 @Test 106 public void testStartNoPort() throws Exception { 107 receiver.setRemoteHost(TEST_HOST_NAME); 108 receiver.start(); 109 assertFalse(receiver.isStarted()); 110 int count = lc.getStatusManager().getCount(); 111 Status status = lc.getStatusManager().getCopyOfStatusList().get(count - 1); 112 assertTrue(status.getMessage().contains("port")); 113 } 114 115 @Test 116 public void testStartUnknownHost() throws Exception { 117 receiver.setPort(6000); 118 receiver.setRemoteHost(TEST_HOST_NAME); 119 receiver.start(); 120 assertFalse(receiver.isStarted()); 121 int count = lc.getStatusManager().getCount(); 122 Status status = lc.getStatusManager().getCopyOfStatusList().get(count - 1); 123 assertTrue(status.getMessage().contains("unknown host")); 124 } 125 126 @Test 127 public void testStartStop() throws Exception { 128 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName()); 129 receiver.setPort(6000); 130 receiver.setAcceptConnectionTimeout(DELAY / 2); 131 receiver.start(); 132 assertTrue(receiver.isStarted()); 133 receiver.awaitConnectorCreated(DELAY); 134 receiver.stop(); 135 assertFalse(receiver.isStarted()); 136 } 137 138 @Test 139 public void testServerSlowToAcceptConnection() throws Exception { 140 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName()); 141 receiver.setPort(6000); 142 receiver.setAcceptConnectionTimeout(DELAY / 4); 143 receiver.start(); 144 assertTrue(receiver.awaitConnectorCreated(DELAY / 2)); 145 // note that we don't call serverSocket.accept() here 146 // but processPriorToRemoval (in tearDown) should still clean up everything 147 } 148 149 @Test 150 public void testServerDropsConnection() throws Exception { 151 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName()); 152 receiver.setPort(6000); 153 receiver.start(); 154 assertTrue(receiver.awaitConnectorCreated(DELAY)); 155 Socket socket = serverSocket.accept(); 156 socket.close(); 157 } 158 159 @Test 160 public void testDispatchEventForEnabledLevel() throws Exception { 161 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName()); 162 receiver.setPort(6000); 163 receiver.start(); 164 assertTrue(receiver.awaitConnectorCreated(DELAY)); 165 Socket socket = serverSocket.accept(); 166 167 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 168 169 logger.setLevel(Level.DEBUG); 170 ILoggingEvent event = new LoggingEvent(logger.getName(), logger, Level.DEBUG, "test message", null, new Object[0]); 171 172 LoggingEventVO eventVO = LoggingEventVO.build(event); 173 oos.writeObject(eventVO); 174 oos.flush(); 175 176 ILoggingEvent rcvdEvent = appender.awaitAppend(DELAY); 177 assertNotNull(rcvdEvent); 178 assertEquals(event.getLoggerName(), rcvdEvent.getLoggerName()); 179 assertEquals(event.getLevel(), rcvdEvent.getLevel()); 180 assertEquals(event.getMessage(), rcvdEvent.getMessage()); 181 } 182 183 @Test 184 public void testNoDispatchEventForDisabledLevel() throws Exception { 185 receiver.setRemoteHost(InetAddress.getLocalHost().getHostName()); 186 receiver.setPort(6000); 187 receiver.start(); 188 assertTrue(receiver.awaitConnectorCreated(DELAY)); 189 Socket socket = serverSocket.accept(); 190 191 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 192 193 logger.setLevel(Level.INFO); 194 ILoggingEvent event = new LoggingEvent(logger.getName(), logger, Level.DEBUG, "test message", null, new Object[0]); 195 196 LoggingEventVO eventVO = LoggingEventVO.build(event); 197 oos.writeObject(eventVO); 198 oos.flush(); 199 200 assertNull(appender.awaitAppend(DELAY)); 201 } 202 203 /** 204 * A {@link SocketReceiver} with instrumentation for unit testing. 205 */ 206 private class InstrumentedSocketReceiver extends SocketReceiver { 207 208 private boolean connectorCreated; 209 210 @Override 211 protected synchronized SocketConnector newConnector(InetAddress address, int port, int initialDelay, int retryDelay) { 212 connectorCreated = true; 213 notifyAll(); 214 return connector; 215 } 216 217 @Override 218 protected SocketFactory getSocketFactory() { 219 return socketFactory; 220 } 221 222 public synchronized boolean awaitConnectorCreated(long delay) throws InterruptedException { 223 while (!connectorCreated) { 224 wait(delay); 225 } 226 return connectorCreated; 227 } 228 229 } 230 231 /** 232 * A {@link SocketConnector} with instrumentation for unit testing. 233 */ 234 private static class MockSocketConnector implements SocketConnector { 235 236 private final Socket socket; 237 238 public MockSocketConnector(Socket socket) { 239 this.socket = socket; 240 } 241 242 public Socket call() throws InterruptedException { 243 return socket; 244 } 245 246 public void setExceptionHandler(ExceptionHandler exceptionHandler) { 247 } 248 249 public void setSocketFactory(SocketFactory socketFactory) { 250 } 251 252 } 253 254 /** 255 * A no-op {@link SocketFactory} to support unit testing. 256 */ 257 private static class MockSocketFactory extends SocketFactory { 258 259 @Override 260 public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { 261 throw new UnsupportedOperationException(); 262 } 263 264 @Override 265 public Socket createSocket(InetAddress host, int port) throws IOException { 266 throw new UnsupportedOperationException(); 267 } 268 269 @Override 270 public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { 271 throw new UnsupportedOperationException(); 272 } 273 274 @Override 275 public Socket createSocket(String host, int port) throws IOException, UnknownHostException { 276 throw new UnsupportedOperationException(); 277 } 278 279 } 280 281}