1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.net;
19
20 import junit.framework.TestCase;
21
22 import org.apache.log4j.AsyncAppender;
23 import org.apache.log4j.Layout;
24 import org.apache.log4j.Level;
25 import org.apache.log4j.LogManager;
26 import org.apache.log4j.Logger;
27 import org.apache.log4j.PatternLayout;
28 import org.apache.log4j.VectorErrorHandler;
29 import org.apache.log4j.HTMLLayout;
30
31 import java.util.StringTokenizer;
32 import java.net.DatagramSocket;
33 import java.net.DatagramPacket;
34 import java.text.SimpleDateFormat;
35 import java.util.Locale;
36 import java.util.Date;
37 import java.util.Calendar;
38
39
40 /***
41 * Tests for SyslogAppender
42 *
43 *
44 * */
45 public class SyslogAppenderTest extends TestCase {
46 /***
47 * Create new instance of SyslogAppenderTest.
48 * @param testName test name
49 */
50 public SyslogAppenderTest(final String testName) {
51 super(testName);
52 }
53
54 /***
55 * Resets configuration after every test.
56 */
57 public void tearDown() {
58 LogManager.resetConfiguration();
59 }
60
61 /***
62 * Test default constructor.
63 */
64 public void testDefaultConstructor() {
65 SyslogAppender appender = new SyslogAppender();
66 assertEquals("user", appender.getFacility());
67 assertEquals(false, appender.getFacilityPrinting());
68 assertNull(appender.getLayout());
69 assertNull(appender.getSyslogHost());
70 assertTrue(appender.requiresLayout());
71 }
72
73 /***
74 * Test two parameter constructor.
75 */
76 public void testTwoParamConstructor() {
77 Layout layout = new PatternLayout();
78 SyslogAppender appender = new SyslogAppender(layout, 24);
79 assertEquals("daemon", appender.getFacility());
80 assertEquals(false, appender.getFacilityPrinting());
81 assertEquals(layout, appender.getLayout());
82 assertNull(appender.getSyslogHost());
83 assertTrue(appender.requiresLayout());
84 }
85
86 /***
87 * Test two parameter constructor with unexpected facility.
88 */
89 public void testTwoParamConstructorBadFacility() {
90 Layout layout = new PatternLayout();
91 SyslogAppender appender = new SyslogAppender(layout, 25);
92 assertEquals("user", appender.getFacility());
93 assertEquals(false, appender.getFacilityPrinting());
94 assertEquals(layout, appender.getLayout());
95 assertNull(appender.getSyslogHost());
96 assertTrue(appender.requiresLayout());
97 }
98
99 /***
100 * Test three parameter constructor.
101 */
102 public void testThreeParamConstructor() {
103 Layout layout = new PatternLayout();
104 SyslogAppender appender =
105 new SyslogAppender(layout, "syslog.example.org", 24);
106 assertEquals("daemon", appender.getFacility());
107 assertEquals(false, appender.getFacilityPrinting());
108 assertEquals(layout, appender.getLayout());
109 assertEquals("syslog.example.org", appender.getSyslogHost());
110 assertTrue(appender.requiresLayout());
111 }
112
113 /***
114 * Test getFacilityString for expected facility codes.
115 */
116 public void testGetFacilityString() {
117 String expected =
118 "kern user mail daemon auth syslog lpr news "
119 + "uucp cron authpriv ftp local0 local1 local2 local3 "
120 + "local4 local5 local6 local7 ";
121 StringBuffer actual = new StringBuffer();
122
123 for (int i = 0; i <= 11; i++) {
124 actual.append(SyslogAppender.getFacilityString(i << 3));
125 actual.append(' ');
126 }
127
128 for (int i = 16; i <= 23; i++) {
129 actual.append(SyslogAppender.getFacilityString(i << 3));
130 actual.append(' ');
131 }
132
133 assertEquals(expected, actual.toString());
134 }
135
136 /***
137 * Test getFacilityString for some unexpected facility codes.
138 */
139 public void testGetFacilityStringUnexpected() {
140 assertNull(SyslogAppender.getFacilityString(1));
141 assertNull(SyslogAppender.getFacilityString(12 << 3));
142 }
143
144 /***
145 * Test getFacility with a bogus facility name.
146 */
147 public void testGetFacilityBogus() {
148 assertEquals(-1, SyslogAppender.getFacility("bogus"));
149 }
150
151 /***
152 * Test getFacility with a null facility name.
153 */
154 public void testGetFacilityNull() {
155 assertEquals(-1, SyslogAppender.getFacility(null));
156 }
157
158 /***
159 * Test getFacility for expected system facility names.
160 */
161 public void testGetFacilitySystemNames() {
162 String[] names =
163 new String[] {
164 "kErn", "usEr", "MaIL", "daemOn", "auTh", "syslOg", "lPr", "newS",
165 "Uucp", "croN", "authprIv", "ftP"
166 };
167
168 for (int i = 0; i <= 11; i++) {
169 assertEquals(i << 3, SyslogAppender.getFacility(names[i]));
170 }
171 }
172
173 /***
174 * Test getFacility for expected system facility names.
175 */
176 public void testGetFacilityLocalNames() {
177 String[] names =
178 new String[] {
179 "lOcal0", "LOCAL1", "loCal2", "locAl3", "locaL4", "local5", "LOCal6",
180 "loCAL7"
181 };
182
183 for (int i = 0; i <= 7; i++) {
184 assertEquals((16 + i) << 3, SyslogAppender.getFacility(names[i]));
185 }
186 }
187
188 /***
189 * Test setFacilityPrinting.
190 */
191 public void testSetFacilityPrinting() {
192 SyslogAppender appender = new SyslogAppender();
193 assertFalse(appender.getFacilityPrinting());
194 appender.setFacilityPrinting(true);
195 assertTrue(appender.getFacilityPrinting());
196 appender.setFacilityPrinting(false);
197 assertFalse(appender.getFacilityPrinting());
198 }
199
200 /***
201 * Test of SyslogAppender constants.
202 */
203 public void testConstants() {
204 assertEquals(0 << 3, SyslogAppender.LOG_KERN);
205 assertEquals(1 << 3, SyslogAppender.LOG_USER);
206 assertEquals(2 << 3, SyslogAppender.LOG_MAIL);
207 assertEquals(3 << 3, SyslogAppender.LOG_DAEMON);
208 assertEquals(4 << 3, SyslogAppender.LOG_AUTH);
209 assertEquals(5 << 3, SyslogAppender.LOG_SYSLOG);
210 assertEquals(6 << 3, SyslogAppender.LOG_LPR);
211 assertEquals(7 << 3, SyslogAppender.LOG_NEWS);
212 assertEquals(8 << 3, SyslogAppender.LOG_UUCP);
213 assertEquals(9 << 3, SyslogAppender.LOG_CRON);
214 assertEquals(10 << 3, SyslogAppender.LOG_AUTHPRIV);
215 assertEquals(11 << 3, SyslogAppender.LOG_FTP);
216 assertEquals(16 << 3, SyslogAppender.LOG_LOCAL0);
217 assertEquals(17 << 3, SyslogAppender.LOG_LOCAL1);
218 assertEquals(18 << 3, SyslogAppender.LOG_LOCAL2);
219 assertEquals(19 << 3, SyslogAppender.LOG_LOCAL3);
220 assertEquals(20 << 3, SyslogAppender.LOG_LOCAL4);
221 assertEquals(21 << 3, SyslogAppender.LOG_LOCAL5);
222 assertEquals(22 << 3, SyslogAppender.LOG_LOCAL6);
223 assertEquals(23 << 3, SyslogAppender.LOG_LOCAL7);
224 }
225
226 /***
227 * Test setFacility with null.
228 * Should have no effect.
229 */
230 public void testSetFacilityKern() {
231 SyslogAppender appender = new SyslogAppender();
232 appender.setFacility("kern");
233 appender.setFacility(null);
234 assertEquals("kern", appender.getFacility());
235 }
236
237 /***
238 * Test setFacility with null.
239 * Should have no effect.
240 */
241 public void testSetFacilityNull() {
242 SyslogAppender appender = new SyslogAppender();
243 appender.setFacility("kern");
244 appender.setFacility(null);
245 assertEquals("kern", appender.getFacility());
246 }
247
248 /***
249 * Test setFacility with bogus value.
250 * Should reset to user.
251 */
252 public void testSetFacilityBogus() {
253 SyslogAppender appender = new SyslogAppender();
254 appender.setFacility("kern");
255 appender.setFacility("bogus");
256 assertEquals("user", appender.getFacility());
257 }
258
259 /***
260 * Tests calling setFacility after appender has been activated.
261 */
262 public void testSetFacilityAfterActivation() {
263 SyslogAppender appender = new SyslogAppender();
264 appender.setName("foo");
265 appender.setThreshold(Level.INFO);
266 appender.setSyslogHost("localhost");
267 appender.setFacility("user");
268 appender.setLayout(new PatternLayout("%m%n"));
269
270 VectorErrorHandler errorHandler = new VectorErrorHandler();
271 appender.setErrorHandler(errorHandler);
272 appender.activateOptions();
273 appender.setFacility("kern");
274 assertEquals("kern", appender.getFacility());
275 }
276
277 /***
278 * Tests that append method drops messages below threshold.
279 * Can't reach isSevereAsThreshold call in SyslogAppender.append
280 * since it is checked in AppenderSkeleton.doAppend.
281 */
282 public void testAppendBelowThreshold() {
283 SyslogAppender appender = new SyslogAppender();
284 appender.setThreshold(Level.ERROR);
285 appender.activateOptions();
286
287 Logger logger = Logger.getRootLogger();
288 logger.addAppender(appender);
289 logger.info(
290 "Should not be logged by SyslogAppenderTest.testAppendBelowThreshold.");
291 }
292
293 /***
294 * Tests that append method drops messages below threshold.
295 */
296 public void testAppendNoHost() {
297 SyslogAppender appender = new SyslogAppender();
298 appender.setName("foo");
299 appender.setThreshold(Level.INFO);
300
301 VectorErrorHandler errorHandler = new VectorErrorHandler();
302 appender.setErrorHandler(errorHandler);
303 appender.setLayout(new PatternLayout("%m%n"));
304 appender.activateOptions();
305
306 Logger logger = Logger.getRootLogger();
307 logger.addAppender(appender);
308 logger.info(
309 "Should not be logged by SyslogAppenderTest.testAppendNoHost.");
310 assertEquals(1, errorHandler.size());
311
312
313
314
315 assertEquals(
316 "No syslog host is set for SyslogAppedender named \"foo\".",
317 errorHandler.getMessage(0));
318 }
319
320 /***
321 * Tests append method under normal conditions.
322 */
323 public void testAppend() {
324 SyslogAppender appender = new SyslogAppender();
325 appender.setName("foo");
326 appender.setThreshold(Level.INFO);
327 appender.setSyslogHost("localhost");
328 appender.setFacility("user");
329 appender.setLayout(new PatternLayout("%m%n"));
330
331 VectorErrorHandler errorHandler = new VectorErrorHandler();
332 appender.setErrorHandler(errorHandler);
333 appender.activateOptions();
334
335
336
337
338
339 AsyncAppender asyncAppender = new AsyncAppender();
340 asyncAppender.addAppender(appender);
341 asyncAppender.activateOptions();
342
343 Logger logger = Logger.getRootLogger();
344 logger.addAppender(asyncAppender);
345
346 Exception e =
347 new Exception("Expected exception from SyslogAppenderTest.testAppend");
348 logger.info(
349 "Expected message from log4j unit test SyslogAppenderTest.testAppend.", e);
350 assertEquals(0, errorHandler.size());
351 }
352
353 /***
354 * Tests SyslogAppender with IPv6 address.
355 */
356 public void testIPv6() {
357 SyslogAppender appender = new SyslogAppender();
358 appender.setSyslogHost("::1");
359 }
360
361 /***
362 * Tests SyslogAppender with IPv6 address enclosed in square brackets.
363 */
364 public void testIPv6InBrackets() {
365 SyslogAppender appender = new SyslogAppender();
366 appender.setSyslogHost("[::1]");
367 }
368
369 /***
370 * Tests SyslogAppender with IPv6 address enclosed in square brackets
371 * followed by port specification.
372 */
373 public void testIPv6AndPort() {
374 SyslogAppender appender = new SyslogAppender();
375 appender.setSyslogHost("[::1]:1514");
376 }
377
378 /***
379 * Tests SyslogAppender with host name enclosed in square brackets
380 * followed by port specification.
381 */
382 public void testHostNameAndPort() {
383 SyslogAppender appender = new SyslogAppender();
384 appender.setSyslogHost("localhost:1514");
385 }
386
387
388 /***
389 * Tests SyslogAppender with IPv4 address followed by port specification.
390 */
391 public void testIPv4AndPort() {
392 SyslogAppender appender = new SyslogAppender();
393 appender.setSyslogHost("127.0.0.1:1514");
394 }
395
396 private static String[] log(final boolean header,
397 final String msg,
398 final Exception ex,
399 final int packets) throws Exception {
400 DatagramSocket ds = new DatagramSocket();
401 ds.setSoTimeout(2000);
402
403 SyslogAppender appender = new SyslogAppender();
404 appender.setSyslogHost("localhost:" + ds.getLocalPort());
405 appender.setName("name");
406 appender.setHeader(header);
407 PatternLayout pl = new PatternLayout("%m");
408 appender.setLayout(pl);
409 appender.activateOptions();
410
411 Logger l = Logger.getRootLogger();
412 l.addAppender(appender);
413 if (ex == null) {
414 l.info(msg);
415 } else {
416 l.error(msg, ex);
417 }
418 appender.close();
419 String[] retval = new String[packets];
420 byte[] buf = new byte[1000];
421 for(int i = 0; i < packets; i++) {
422 DatagramPacket p = new DatagramPacket(buf, 0, buf.length);
423 ds.receive(p);
424 retval[i] = new String(p.getData(), 0, p.getLength());
425 }
426 ds.close();
427 return retval;
428 }
429
430 public void testActualLogging() throws Exception {
431 String s = log(false, "greetings", null, 1)[0];
432 StringTokenizer st = new StringTokenizer(s, "<>() ");
433 assertEquals("14", st.nextToken());
434 assertEquals("greetings", st.nextToken());
435 }
436
437 /***
438 * Exception with printStackTrace that breaks earlier SyslogAppender.
439 */
440 private static class MishandledException extends Exception {
441
442
443
444 public MishandledException() {
445 }
446
447 /***
448 * Print stack trace.
449 * @param w print writer, may not be null.
450 */
451 public void printStackTrace(final java.io.PrintWriter w) {
452 w.println("Mishandled stack trace follows:");
453 w.println("");
454 w.println("No tab here");
455 w.println("\ttab here");
456 w.println("\t");
457 }
458 }
459
460 /***
461 * Tests fix for bug 40502.
462 * @throws Exception on IOException.
463 */
464 public void testBadTabbing() throws Exception {
465 String[] s = log(false, "greetings", new MishandledException(), 6);
466 StringTokenizer st = new StringTokenizer(s[0], "<>() ");
467 assertEquals("11", st.nextToken());
468 assertEquals("greetings", st.nextToken());
469 assertEquals("<11>Mishandled stack trace follows:", s[1]);
470 assertEquals("<11>", s[2]);
471 assertEquals("<11>No tab here", s[3]);
472 assertEquals("<11>" + SyslogAppender.TAB + "tab here", s[4]);
473 assertEquals("<11>" + SyslogAppender.TAB, s[5]);
474 }
475
476 /***
477 * Tests presence of timestamp if header = true.
478 *
479 * @throws Exception if IOException.
480 */
481 public void testHeaderLogging() throws Exception {
482 Date preDate = new Date();
483 String s = log(true, "greetings", null, 1)[0];
484 Date postDate = new Date();
485 assertEquals("<14>", s.substring(0, 4));
486
487 String syslogDateStr = s.substring(4, 20);
488 SimpleDateFormat fmt = new SimpleDateFormat("MMM dd HH:mm:ss ", Locale.ENGLISH);
489 Date syslogDate = fmt.parse(syslogDateStr);
490 Calendar cal = Calendar.getInstance(Locale.ENGLISH);
491 cal.setTime(syslogDate);
492 int syslogMonth = cal.get(Calendar.MONTH);
493 int syslogDay = cal.get(Calendar.DATE);
494 if (syslogDay < 10) {
495 assertEquals(' ', syslogDateStr.charAt(4));
496 }
497 cal.setTime(preDate);
498 int preMonth = cal.get(Calendar.MONTH);
499 cal.set(Calendar.MILLISECOND, 0);
500 preDate = cal.getTime();
501 int syslogYear;
502 if (preMonth == syslogMonth) {
503 syslogYear = cal.get(Calendar.YEAR);
504 } else {
505 cal.setTime(postDate);
506 syslogYear = cal.get(Calendar.YEAR);
507 }
508 cal.setTime(syslogDate);
509 cal.set(Calendar.YEAR, syslogYear);
510 syslogDate = cal.getTime();
511 assertTrue(syslogDate.compareTo(preDate) >= 0);
512 assertTrue(syslogDate.compareTo(postDate) <= 0);
513 }
514
515
516 /***
517 * Tests that any header or footer in layout is sent.
518 * @throws Exception if exception during test.
519 */
520 public void testLayoutHeader() throws Exception {
521 DatagramSocket ds = new DatagramSocket();
522 ds.setSoTimeout(2000);
523
524 SyslogAppender appender = new SyslogAppender();
525 appender.setSyslogHost("localhost:" + ds.getLocalPort());
526 appender.setName("name");
527 appender.setHeader(false);
528 HTMLLayout pl = new HTMLLayout();
529 appender.setLayout(pl);
530 appender.activateOptions();
531
532 Logger l = Logger.getRootLogger();
533 l.addAppender(appender);
534 l.info("Hello, World");
535 appender.close();
536 String[] s = new String[3];
537 byte[] buf = new byte[1000];
538 for(int i = 0; i < 3; i++) {
539 DatagramPacket p = new DatagramPacket(buf, 0, buf.length);
540 ds.receive(p);
541 s[i] = new String(p.getData(), 0, p.getLength());
542 }
543 ds.close();
544 assertEquals("<14><!DOCTYPE", s[0].substring(0,13));
545 assertEquals("<14></table>", s[2].substring(0,12));
546 }
547
548 /***
549 * Tests that syslog packets do not exceed 1024 bytes.
550 * See bug 42087.
551 * @throws Exception if exception during test.
552 */
553 public void testBigPackets() throws Exception {
554 DatagramSocket ds = new DatagramSocket();
555 ds.setSoTimeout(2000);
556
557 SyslogAppender appender = new SyslogAppender();
558 appender.setSyslogHost("localhost:" + ds.getLocalPort());
559 appender.setName("name");
560 appender.setHeader(false);
561 PatternLayout pl = new PatternLayout("%m");
562 appender.setLayout(pl);
563 appender.activateOptions();
564
565 Logger l = Logger.getRootLogger();
566 l.addAppender(appender);
567 StringBuffer msgbuf = new StringBuffer();
568 while(msgbuf.length() < 8000) {
569 msgbuf.append("0123456789");
570 }
571 String msg = msgbuf.toString();
572 l.info(msg);
573 appender.close();
574 String[] s = new String[8];
575 byte[] buf = new byte[1200];
576 for(int i = 0; i < 8; i++) {
577 DatagramPacket p = new DatagramPacket(buf, 0, buf.length);
578 ds.receive(p);
579 assertTrue(p.getLength() <= 1024);
580 s[i] = new String(p.getData(), 0, p.getLength());
581 }
582 ds.close();
583 StringBuffer rcvbuf = new StringBuffer(s[0]);
584 rcvbuf.delete(0, 4);
585 for(int i = 1; i < 8; i++) {
586 rcvbuf.setLength(rcvbuf.length() - 3);
587 rcvbuf.append(s[i].substring(s[i].indexOf("...") + 3));
588 }
589 assertEquals(msg.length(), rcvbuf.length());
590 assertEquals(msg, rcvbuf.toString());
591 }
592
593 }