View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.spi;
15  
16  import static org.junit.Assert.assertEquals;
17  import static org.junit.Assert.assertNotNull;
18  import static org.junit.Assert.assertNull;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectOutputStream;
25  import java.io.Serializable;
26  import java.util.Arrays;
27  import java.util.Map;
28  
29  import org.junit.After;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.slf4j.MDC;
33  import org.slf4j.Marker;
34  import org.slf4j.MarkerFactory;
35  
36  import ch.qos.logback.classic.Level;
37  import ch.qos.logback.classic.Logger;
38  import ch.qos.logback.classic.LoggerContext;
39  import ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer;
40  import ch.qos.logback.classic.net.server.HardenedLoggingEventInputStream;
41  import ch.qos.logback.core.spi.PreSerializationTransformer;
42  
43  public class LoggingEventSerializationTest {
44  
45      LoggerContext loggerContext;
46      Logger logger;
47  
48      ByteArrayOutputStream bos;
49      ObjectOutputStream oos;
50      ObjectInputStream inputStream;
51      PreSerializationTransformer<ILoggingEvent> pst = new LoggingEventPreSerializationTransformer();
52  
53      @Before
54      public void setUp() throws Exception {
55          loggerContext = new LoggerContext();
56          loggerContext.setName("testContext");
57          logger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
58          // create the byte output stream
59          bos = new ByteArrayOutputStream();
60          oos = new ObjectOutputStream(bos);
61      }
62  
63      @After
64      public void tearDown() throws Exception {
65          loggerContext = null;
66          logger = null;
67          oos.close();
68      }
69  
70      @Test
71      public void smoke() throws Exception {
72          ILoggingEvent event = createLoggingEvent();
73          ILoggingEvent remoteEvent = writeAndRead(event);
74          checkForEquality(event, remoteEvent);
75      }
76  
77      @Test
78      public void context() throws Exception {
79          loggerContext.putProperty("testKey", "testValue");
80          ILoggingEvent event = createLoggingEvent();
81          ILoggingEvent remoteEvent = writeAndRead(event);
82          checkForEquality(event, remoteEvent);
83  
84          assertNotNull(remoteEvent.getLoggerName());
85          assertEquals(Logger.ROOT_LOGGER_NAME, remoteEvent.getLoggerName());
86  
87          LoggerContextVO loggerContextRemoteView = remoteEvent.getLoggerContextVO();
88          assertNotNull(loggerContextRemoteView);
89          assertEquals("testContext", loggerContextRemoteView.getName());
90          Map<String, String> props = loggerContextRemoteView.getPropertyMap();
91          assertNotNull(props);
92          assertEquals("testValue", props.get("testKey"));
93      }
94  
95      @Test
96      public void MDC() throws Exception {
97          MDC.put("key", "testValue");
98          ILoggingEvent event = createLoggingEvent();
99          ILoggingEvent remoteEvent = writeAndRead(event);
100         checkForEquality(event, remoteEvent);
101         Map<String, String> MDCPropertyMap = remoteEvent.getMDCPropertyMap();
102         assertEquals("testValue", MDCPropertyMap.get("key"));
103     }
104 
105     @Test
106     public void updatedMDC() throws Exception {
107         MDC.put("key", "testValue");
108         ILoggingEvent event1 = createLoggingEvent();
109         Serializable s1 = pst.transform(event1);
110         oos.writeObject(s1);
111 
112         MDC.put("key", "updatedTestValue");
113         ILoggingEvent event2 = createLoggingEvent();
114         Serializable s2 = pst.transform(event2);
115         oos.writeObject(s2);
116 
117         // create the input stream based on the ouput stream
118         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
119         inputStream = new ObjectInputStream(bis);
120 
121         // skip over one object
122         inputStream.readObject();
123         ILoggingEvent remoteEvent2 = (ILoggingEvent) inputStream.readObject();
124 
125         // We observe the second logging event. It should provide us with
126         // the updated MDC property.
127         Map<String, String> MDCPropertyMap = remoteEvent2.getMDCPropertyMap();
128         assertEquals("updatedTestValue", MDCPropertyMap.get("key"));
129     }
130 
131     @Test
132     public void nonSerializableParameters() throws Exception {
133         LoggingEvent event = createLoggingEvent();
134         LuckyCharms lucky0 = new LuckyCharms(0);
135         event.setArgumentArray(new Object[] { lucky0, null });
136         ILoggingEvent remoteEvent = writeAndRead(event);
137         checkForEquality(event, remoteEvent);
138 
139         Object[] aa = remoteEvent.getArgumentArray();
140         assertNotNull(aa);
141         assertEquals(2, aa.length);
142         assertEquals("LC(0)", aa[0]);
143         assertNull(aa[1]);
144     }
145 
146     @Test
147     public void testWithThrowable() throws Exception {
148         Throwable throwable = new Throwable("just testing");
149         LoggingEvent event = createLoggingEventWithThrowable(throwable);
150         ILoggingEvent remoteEvent = writeAndRead(event);
151         checkForEquality(event, remoteEvent);
152     }
153 
154     @Test
155     public void testWithMarker() throws Exception {
156         Marker marker = MarkerFactory.getMarker("A_MARKER");
157         LoggingEvent event = createLoggingEvent();
158 
159         event.addMarker(marker);
160         assertNotNull(event.getMarkerList());
161 
162         ILoggingEvent remoteEvent = writeAndRead(event);
163         checkForEquality(event, remoteEvent);
164 
165         assertNotNull(remoteEvent.getMarkerList());
166         assertEquals(Arrays.asList(marker), remoteEvent.getMarkerList());
167     }
168 
169     @Test
170     public void testWithTwoMarkers() throws Exception {
171         Marker marker = MarkerFactory.getMarker("A_MARKER");
172         Marker marker2 = MarkerFactory.getMarker("B_MARKER");
173         marker.add(marker2);
174         LoggingEvent event = createLoggingEvent();
175 
176         event.addMarker(marker);
177         assertNotNull(event.getMarkerList());
178 
179         ILoggingEvent remoteEvent = writeAndRead(event);
180         checkForEquality(event, remoteEvent);
181 
182         assertNotNull(remoteEvent.getMarkerList());
183         assertEquals(Arrays.asList(marker), remoteEvent.getMarkerList());
184     }
185 
186     @Test
187     public void testWithCallerData() throws Exception {
188         LoggingEvent event = createLoggingEvent();
189         event.getCallerData();
190         ILoggingEvent remoteEvent = writeAndRead(event);
191         checkForEquality(event, remoteEvent);
192     }
193 
194     @Test
195     public void extendendeThrowable() throws Exception {
196         LoggingEvent event = createLoggingEvent();
197         Throwable throwable = new Throwable("just testing");
198         ThrowableProxy tp = new ThrowableProxy(throwable);
199         event.setThrowableProxy(tp);
200         tp.calculatePackagingData();
201         ILoggingEvent remoteEvent = writeAndRead(event);
202         checkForEquality(event, remoteEvent);
203     }
204 
205     @Test
206     public void serializeLargeArgs() throws Exception {
207 
208         StringBuilder buffer = new StringBuilder();
209         for (int i = 0; i < 100000; i++) {
210             buffer.append("X");
211         }
212         String largeString = buffer.toString();
213         Object[] argArray = new Object[] { new LuckyCharms(2), largeString };
214 
215         LoggingEvent event = createLoggingEvent();
216         event.setArgumentArray(argArray);
217 
218         ILoggingEvent remoteEvent = writeAndRead(event);
219         checkForEquality(event, remoteEvent);
220         Object[] aa = remoteEvent.getArgumentArray();
221         assertNotNull(aa);
222         assertEquals(2, aa.length);
223         String stringBack = (String) aa[1];
224         assertEquals(largeString, stringBack);
225     }
226 
227     private LoggingEvent createLoggingEvent() {
228         return new LoggingEvent(this.getClass().getName(), logger, Level.DEBUG, "test message", null, null);
229     }
230 
231     private LoggingEvent createLoggingEventWithThrowable(Throwable t) {
232         return new LoggingEvent(this.getClass().getName(), logger, Level.DEBUG, "test message", t, null);
233     }
234 
235     private void checkForEquality(ILoggingEvent original, ILoggingEvent afterSerialization) {
236         assertEquals(original.getLevel(), afterSerialization.getLevel());
237         assertEquals(original.getFormattedMessage(), afterSerialization.getFormattedMessage());
238         assertEquals(original.getMessage(), afterSerialization.getMessage());
239 
240         System.out.println();
241 
242         ThrowableProxyVO witness = ThrowableProxyVO.build(original.getThrowableProxy());
243         assertEquals(witness, afterSerialization.getThrowableProxy());
244 
245     }
246 
247     private ILoggingEvent writeAndRead(ILoggingEvent event) throws IOException, ClassNotFoundException {
248         Serializable ser = pst.transform(event);
249         oos.writeObject(ser);
250         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
251         inputStream = new HardenedLoggingEventInputStream(bis);
252 
253         return (ILoggingEvent) inputStream.readObject();
254     }
255 
256 }