1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j;
19
20 import junit.framework.TestCase;
21 import junit.framework.TestSuite;
22 import junit.framework.Test;
23
24 import java.util.Vector;
25
26 import org.apache.log4j.*;
27 import org.apache.log4j.spi.LoggingEvent;
28 import org.apache.log4j.varia.NullAppender;
29
30 /***
31 A superficial but general test of log4j.
32 */
33 public class AsyncAppenderTestCase extends TestCase {
34
35 public AsyncAppenderTestCase(String name) {
36 super(name);
37 }
38
39 public void setUp() {
40 }
41
42 public void tearDown() {
43 LogManager.shutdown();
44 }
45
46
47 public void closeTest() throws Exception {
48 Logger root = Logger.getRootLogger();
49 Layout layout = new SimpleLayout();
50 VectorAppender vectorAppender = new VectorAppender();
51 AsyncAppender asyncAppender = new AsyncAppender();
52 asyncAppender.setName("async-CloseTest");
53 asyncAppender.addAppender(vectorAppender);
54 root.addAppender(asyncAppender);
55
56 root.debug("m1");
57 asyncAppender.close();
58 root.debug("m2");
59
60 Vector v = vectorAppender.getVector();
61 assertEquals(v.size(), 1);
62 }
63
64
65
66 public void test2() {
67 Logger root = Logger.getRootLogger();
68 Layout layout = new SimpleLayout();
69 VectorAppender vectorAppender = new VectorAppender();
70 AsyncAppender asyncAppender = new AsyncAppender();
71 asyncAppender.setName("async-test2");
72 asyncAppender.addAppender(vectorAppender);
73 root.addAppender(asyncAppender);
74
75 root.debug("m1");
76 asyncAppender.close();
77 root.debug("m2");
78
79 Vector v = vectorAppender.getVector();
80 assertEquals(v.size(), 1);
81 assertTrue(vectorAppender.isClosed());
82 }
83
84
85
86 public void test3() {
87 int LEN = 200;
88 Logger root = Logger.getRootLogger();
89 Layout layout = new SimpleLayout();
90 VectorAppender vectorAppender = new VectorAppender();
91 AsyncAppender asyncAppender = new AsyncAppender();
92 asyncAppender.setName("async-test3");
93 asyncAppender.addAppender(vectorAppender);
94 root.addAppender(asyncAppender);
95
96 for(int i = 0; i < LEN; i++) {
97 root.debug("message"+i);
98 }
99
100 System.out.println("Done loop.");
101 System.out.flush();
102 asyncAppender.close();
103 root.debug("m2");
104
105 Vector v = vectorAppender.getVector();
106 assertEquals(v.size(), LEN);
107 assertTrue(vectorAppender.isClosed());
108 }
109
110 private static class NullPointerAppender extends AppenderSkeleton {
111 public NullPointerAppender() {
112 }
113
114
115 /***
116 This method is called by the {@link org.apache.log4j.AppenderSkeleton#doAppend}
117 method.
118
119 */
120 public void append(org.apache.log4j.spi.LoggingEvent event) {
121 throw new NullPointerException();
122 }
123
124 public void close() {
125 }
126
127 public boolean requiresLayout() {
128 return false;
129 }
130 }
131
132
133 /***
134 * Tests that a bad appender will switch async back to sync.
135 * See bug 23021
136 * @since 1.2.12
137 * @throws Exception thrown if Thread.sleep is interrupted
138 */
139 public void testBadAppender() throws Exception {
140 Appender nullPointerAppender = new NullPointerAppender();
141 AsyncAppender asyncAppender = new AsyncAppender();
142 asyncAppender.addAppender(nullPointerAppender);
143 asyncAppender.setBufferSize(5);
144 asyncAppender.activateOptions();
145 Logger root = Logger.getRootLogger();
146 root.addAppender(nullPointerAppender);
147 try {
148 root.info("Message");
149 Thread.sleep(10);
150 root.info("Message");
151 fail("Should have thrown exception");
152 } catch(NullPointerException ex) {
153
154 }
155 }
156
157 /***
158 * Tests location processing when buffer is full and locationInfo=true.
159 * See bug 41186.
160 */
161 public void testLocationInfoTrue() {
162 BlockableVectorAppender blockableAppender = new BlockableVectorAppender();
163 AsyncAppender async = new AsyncAppender();
164 async.addAppender(blockableAppender);
165 async.setBufferSize(5);
166 async.setLocationInfo(true);
167 async.setBlocking(false);
168 async.activateOptions();
169 Logger rootLogger = Logger.getRootLogger();
170 rootLogger.addAppender(async);
171 Greeter greeter = new Greeter(rootLogger, 100);
172 synchronized(blockableAppender.getMonitor()) {
173 greeter.run();
174 rootLogger.error("That's all folks.");
175 }
176 async.close();
177 Vector events = blockableAppender.getVector();
178 LoggingEvent initialEvent = (LoggingEvent) events.get(0);
179 LoggingEvent discardEvent = (LoggingEvent) events.get(events.size() - 1);
180 PatternLayout layout = new PatternLayout();
181 layout.setConversionPattern("%C:%L %m%n");
182 layout.activateOptions();
183 String initialStr = layout.format(initialEvent);
184 assertEquals(AsyncAppenderTestCase.class.getName(),
185 initialStr.substring(0, AsyncAppenderTestCase.class.getName().length()));
186 String discardStr = layout.format(discardEvent);
187 assertEquals("?:? ", discardStr.substring(0, 4));
188 }
189
190
191 /***
192 * Tests location processing when buffer is full and locationInfo=false.
193 * See bug 41186.
194 */
195 public void testLocationInfoFalse() {
196 BlockableVectorAppender blockableAppender = new BlockableVectorAppender();
197 AsyncAppender async = new AsyncAppender();
198 async.addAppender(blockableAppender);
199 async.setBufferSize(5);
200 async.setLocationInfo(false);
201 async.setBlocking(false);
202 async.activateOptions();
203 Logger rootLogger = Logger.getRootLogger();
204 rootLogger.addAppender(async);
205 Greeter greeter = new Greeter(rootLogger, 100);
206 synchronized(blockableAppender.getMonitor()) {
207 greeter.run();
208 rootLogger.error("That's all folks.");
209 }
210 async.close();
211 Vector events = blockableAppender.getVector();
212 LoggingEvent initialEvent = (LoggingEvent) events.get(0);
213 LoggingEvent discardEvent = (LoggingEvent) events.get(events.size() - 1);
214 PatternLayout layout = new PatternLayout();
215 layout.setConversionPattern("%C:%L %m%n");
216 layout.activateOptions();
217 String initialStr = layout.format(initialEvent);
218 assertEquals("?:? ", initialStr.substring(0, 4));
219 String discardStr = layout.format(discardEvent);
220 assertEquals("?:? ", discardStr.substring(0, 4));
221 }
222
223 /***
224 * Logging request runnable.
225 */
226 private static final class Greeter implements Runnable {
227 /***
228 * Logger.
229 */
230 private final Logger logger;
231
232 /***
233 * Repetitions.
234 */
235 private final int repetitions;
236
237 /***
238 * Create new instance.
239 * @param logger logger, may not be null.
240 * @param repetitions repetitions.
241 */
242 public Greeter(final Logger logger, final int repetitions) {
243 if (logger == null) {
244 throw new IllegalArgumentException("logger");
245 }
246
247 this.logger = logger;
248 this.repetitions = repetitions;
249 }
250
251 /***
252 * {@inheritDoc}
253 */
254 public void run() {
255 try {
256 for (int i = 0; i < repetitions; i++) {
257 logger.info("Hello, World");
258 Thread.sleep(1);
259 }
260 } catch (InterruptedException ex) {
261 Thread.currentThread().interrupt();
262 }
263 }
264 }
265
266
267
268 /***
269 * Vector appender that can be explicitly blocked.
270 */
271 private static final class BlockableVectorAppender extends VectorAppender {
272 /***
273 * Monitor object used to block appender.
274 */
275 private final Object monitor = new Object();
276
277 /***
278 * Thread of last call to append.
279 */
280 private Thread dispatcher;
281
282 /***
283 * Create new instance.
284 */
285 public BlockableVectorAppender() {
286 super();
287 }
288
289 /***
290 * {@inheritDoc}
291 */
292 public void append(final LoggingEvent event) {
293 synchronized (monitor) {
294 dispatcher = Thread.currentThread();
295 super.append(event);
296
297
298
299 if (event.getLevel() == Level.FATAL) {
300 Logger logger = Logger.getLogger(event.getLoggerName());
301 logger.error(event.getMessage().toString());
302 logger.warn(event.getMessage().toString());
303 logger.info(event.getMessage().toString());
304 logger.debug(event.getMessage().toString());
305 }
306 }
307 }
308
309 /***
310 * Get monitor object.
311 * @return monitor.
312 */
313 public Object getMonitor() {
314 return monitor;
315 }
316
317 /***
318 * Get thread of previous call to append.
319 * @return thread, may be null.
320 */
321 public Thread getDispatcher() {
322 synchronized (monitor) {
323 return dispatcher;
324 }
325 }
326 }
327
328
329 }