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