1   /**
2    * Logback: the generic, reliable, fast and flexible logging framework.
3    * 
4    * Copyright (C) 1999-2006, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  package ch.qos.logback.classic.net;
11  
12  import static org.junit.Assert.*;
13  
14  import java.util.Map;
15  
16  import org.junit.Test;
17  import org.slf4j.MDC;
18  import org.slf4j.Marker;
19  import org.slf4j.MarkerFactory;
20  
21  import ch.qos.logback.classic.Level;
22  import ch.qos.logback.classic.Logger;
23  import ch.qos.logback.classic.LoggerContext;
24  import ch.qos.logback.classic.spi.LoggerContextRemoteView;
25  import ch.qos.logback.classic.spi.LoggerRemoteView;
26  import ch.qos.logback.classic.spi.LoggingEvent;
27  import ch.qos.logback.core.read.ListAppender;
28  import ch.qos.logback.core.util.StatusPrinter;
29  
30  public class SocketAppenderTest {
31  
32    static final String LIST_APPENDER_NAME = "la";
33    static final int JOIN_OR_WAIT_TIMEOUT = 200;
34    static final int SLEEP_AFTER_LOG = 100;
35    
36    int port = 4561;
37    LoggerContext lc = new LoggerContext();
38    LoggerContext serverLC = new LoggerContext();
39    ListAppender<LoggingEvent> la = new ListAppender<LoggingEvent>();
40    SocketAppender socketAppender = new SocketAppender();
41  
42    private SimpleSocketServer simpleSocketServer;
43  
44    @Test
45    public void startFailNoRemoteHost() {
46      SocketAppender appender = new SocketAppender();
47      appender.setContext(lc);
48      appender.setPort(123);
49      appender.start();
50      assertEquals(1, lc.getStatusManager().getCount());
51    }
52  
53    @Test
54    public void recieveMessage() throws InterruptedException {
55      fireServer();
56      waitForServerToStart();
57      configureClient();
58  
59      Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
60      logger.debug("test msg");
61  
62      Thread.sleep(SLEEP_AFTER_LOG);
63  
64      simpleSocketServer.close();
65      simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT);
66      assertTrue(simpleSocketServer.isClosed());
67      assertEquals(1, la.list.size());
68  
69      LoggingEvent remoteEvent = la.list.get(0);
70      assertEquals("test msg", remoteEvent.getMessage());
71      assertEquals(Level.DEBUG, remoteEvent.getLevel());
72    }
73  
74    @Test
75    public void recieveWithContext() throws InterruptedException {
76      fireServer();
77      waitForServerToStart();
78      configureClient();
79  
80      Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
81      logger.debug("test msg");
82      Thread.sleep(SLEEP_AFTER_LOG);
83  
84      simpleSocketServer.close();
85      simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT);
86      assertTrue(simpleSocketServer.isClosed());
87      assertEquals(1, la.list.size());
88  
89      LoggingEvent remoteEvent = la.list.get(0);
90  
91      LoggerRemoteView loggerRemoteView = remoteEvent.getLoggerRemoteView();
92      assertNotNull(loggerRemoteView);
93      assertEquals("root", loggerRemoteView.getName());
94  
95      LoggerContextRemoteView loggerContextRemoteView = loggerRemoteView
96          .getLoggerContextView();
97      assertNotNull(loggerContextRemoteView);
98      assertEquals("test", loggerContextRemoteView.getName());
99      Map<String, String> props = loggerContextRemoteView.getPropertyMap();
100     assertEquals("testValue", props.get("testKey"));
101   }
102 
103   @Test
104   public void messageWithMDC() throws InterruptedException {
105     fireServer();
106     waitForServerToStart();
107     configureClient();
108 
109     Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
110 
111     MDC.put("key", "testValue");
112     logger.debug("test msg");
113 
114     Thread.sleep(SLEEP_AFTER_LOG);
115     simpleSocketServer.close();
116     simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT);
117     assertTrue(simpleSocketServer.isClosed());
118     ListAppender<LoggingEvent> la = getListAppender();
119     assertEquals(1, la.list.size());
120 
121     LoggingEvent remoteEvent = la.list.get(0);
122     Map<String, String> MDCPropertyMap = remoteEvent.getMDCPropertyMap();
123     assertEquals("testValue", MDCPropertyMap.get("key"));
124   }
125 
126   @Test
127   public void messageWithMarker() throws InterruptedException {
128     fireServer();
129     waitForServerToStart();
130     
131     //Thread.sleep(SLEEP_AFTER_SERVER_START);
132     configureClient();
133 
134     Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
135 
136     Marker marker = MarkerFactory.getMarker("testMarker");
137     logger.debug(marker, "test msg");
138     Thread.sleep(SLEEP_AFTER_LOG);
139 
140     simpleSocketServer.close();
141     simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT);
142     assertTrue(simpleSocketServer.isClosed());
143     assertEquals(1, la.list.size());
144 
145     LoggingEvent remoteEvent = la.list.get(0);
146     assertEquals("testMarker", remoteEvent.getMarker().getName());
147   }
148 
149   @Test
150   public void messageWithUpdatedMDC() throws InterruptedException {
151     fireServer();
152     waitForServerToStart();
153     
154     configureClient();
155 
156     Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
157 
158     MDC.put("key", "testValue");
159     logger.debug("test msg");
160 
161     MDC.put("key", "updatedTestValue");
162     logger.debug("test msg 2");
163     Thread.sleep(SLEEP_AFTER_LOG);
164 
165     simpleSocketServer.close();
166     simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT);
167     assertTrue(simpleSocketServer.isClosed());
168     ListAppender<LoggingEvent> la = getListAppender();
169 
170     assertEquals(2, la.list.size());
171 
172     // We observe the second logging event. It should provide us with
173     // the updated MDC property.
174     LoggingEvent remoteEvent = la.list.get(1);
175     Map<String, String> MDCPropertyMap = remoteEvent.getMDCPropertyMap();
176     assertEquals("updatedTestValue", MDCPropertyMap.get("key"));
177   }
178 
179   @Test
180   public void lateServerLaunch() throws InterruptedException {
181     socketAppender.setReconnectionDelay(20);
182     configureClient();
183     Logger logger = lc.getLogger(LoggerContext.ROOT_NAME);
184     logger.debug("test msg");
185 
186     fireServer();
187     waitForServerToStart();
188     Thread.sleep(SLEEP_AFTER_LOG); // allow time for client and server to connect
189     logger.debug("test msg 2");
190     Thread.sleep(SLEEP_AFTER_LOG);
191     
192     simpleSocketServer.close();
193     Thread.sleep(SLEEP_AFTER_LOG);
194     simpleSocketServer.join(JOIN_OR_WAIT_TIMEOUT);
195     StatusPrinter.print(lc);
196     assertTrue(simpleSocketServer.isClosed());
197     assertEquals(1, la.list.size());
198 
199     LoggingEvent remoteEvent = la.list.get(0);
200     assertEquals("test msg 2", remoteEvent.getMessage());
201     assertEquals(Level.DEBUG, remoteEvent.getLevel());
202   }
203 
204   private void waitForServerToStart() throws InterruptedException {
205     synchronized (simpleSocketServer) {
206       simpleSocketServer.wait(JOIN_OR_WAIT_TIMEOUT);
207     }
208   }
209 
210   private void fireServer() throws InterruptedException {
211     Logger root = serverLC.getLogger("root");
212     la.setName(LIST_APPENDER_NAME);
213     la.setContext(serverLC);
214     la.start();
215     root.addAppender(la);
216     simpleSocketServer = new SimpleSocketServer(serverLC, port);
217     simpleSocketServer.start();
218     Thread.yield();
219   }
220 
221   ListAppender<LoggingEvent> getListAppender() {
222     Logger root = serverLC.getLogger("root");
223     return (ListAppender<LoggingEvent>) root.getAppender(LIST_APPENDER_NAME);
224   }
225 
226   private void configureClient() {
227     lc = new LoggerContext();
228     lc.setName("test");
229     lc.putProperty("testKey", "testValue");
230     Logger root = lc.getLogger(LoggerContext.ROOT_NAME);
231     socketAppender.setContext(lc);
232     socketAppender.setName("socket");
233     socketAppender.setPort(port);
234     socketAppender.setRemoteHost("localhost");
235     root.addAppender(socketAppender);
236     socketAppender.start();
237   }
238 }