1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.joran;
15
16 import ch.qos.logback.classic.*;
17 import ch.qos.logback.classic.joran.serializedModel.HardenedModelInputStream;
18 import ch.qos.logback.classic.model.ConfigurationModel;
19 import ch.qos.logback.classic.model.LoggerModel;
20 import ch.qos.logback.classic.spi.ILoggingEvent;
21 import ch.qos.logback.classic.turbo.DebugUsersTurboFilter;
22 import ch.qos.logback.classic.turbo.NOPTurboFilter;
23 import ch.qos.logback.classic.turbo.TurboFilter;
24 import ch.qos.logback.classic.util.LogbackMDCAdapter;
25 import ch.qos.logback.core.ConsoleAppender;
26 import ch.qos.logback.core.CoreConstants;
27 import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
28 import ch.qos.logback.core.helpers.NOPAppender;
29 import ch.qos.logback.core.joran.action.ParamAction;
30 import ch.qos.logback.core.joran.spi.ActionException;
31 import ch.qos.logback.core.joran.spi.JoranException;
32 import ch.qos.logback.core.model.Model;
33 import ch.qos.logback.core.model.SerializeModelModel;
34 import ch.qos.logback.core.pattern.parser.Parser;
35 import ch.qos.logback.core.read.ListAppender;
36 import ch.qos.logback.core.spi.ErrorCodes;
37 import ch.qos.logback.core.spi.ScanException;
38 import ch.qos.logback.core.status.Status;
39 import ch.qos.logback.core.status.testUtil.StatusChecker;
40 import ch.qos.logback.core.testUtil.RandomUtil;
41 import ch.qos.logback.core.testUtil.StringListAppender;
42 import ch.qos.logback.core.util.CachingDateFormatter;
43 import ch.qos.logback.core.util.EnvUtil;
44 import ch.qos.logback.core.util.StatusPrinter;
45 import ch.qos.logback.core.util.StatusPrinter2;
46 import org.junit.jupiter.api.Disabled;
47 import org.junit.jupiter.api.Test;
48 import org.slf4j.MDC;
49 import org.slf4j.event.KeyValuePair;
50 import org.slf4j.spi.MDCAdapter;
51
52 import java.io.Console;
53 import java.io.FileInputStream;
54 import java.io.IOException;
55 import java.text.SimpleDateFormat;
56 import java.util.Date;
57
58 import static ch.qos.logback.core.CoreConstants.MODEL_CONFIG_FILE_EXTENSION;
59 import static ch.qos.logback.core.joran.sanity.AppenderWithinAppenderSanityChecker.NESTED_APPENDERS_WARNING;
60 import static ch.qos.logback.core.model.processor.ImplicitModelHandler.IGNORING_UNKNOWN_PROP;
61 import static ch.qos.logback.core.model.processor.ShutdownHookModelHandler.RENAME_WARNING;
62 import static ch.qos.logback.core.testUtil.CoreTestConstants.OUTPUT_DIR_PREFIX;
63 import static org.junit.jupiter.api.Assertions.*;
64
65 public class JoranConfiguratorTest {
66
67 LoggerContext loggerContext = new LoggerContext();
68 MDCAdapter mdcAdapter = new LogbackMDCAdapter();
69 Logger logger = loggerContext.getLogger(this.getClass().getName());
70 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
71 StatusPrinter2 statusPrinter2 = new StatusPrinter2();
72 StatusChecker checker = new StatusChecker(loggerContext);
73 int diff = RandomUtil.getPositiveInt();
74
75 void configure(String file) throws JoranException {
76 loggerContext.setMDCAdapter(mdcAdapter);
77 JoranConfigurator jc = new JoranConfigurator();
78 jc.setContext(loggerContext);
79 loggerContext.putProperty("diff", "" + diff);
80 jc.doConfigure(file);
81
82 }
83
84 @Test
85 public void simpleList() throws JoranException {
86 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "simpleList.xml");
87 Logger logger = loggerContext.getLogger(this.getClass().getName());
88 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
89 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
90 assertNotNull(listAppender);
91 assertEquals(0, listAppender.list.size());
92 String msg = "hello world";
93 logger.debug(msg);
94 assertEquals(1, listAppender.list.size());
95 ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0);
96 assertEquals(msg, le.getMessage());
97 }
98
99
100 @Test
101 public void asyncWithMultipleAppendersInRoot() throws JoranException {
102 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "async/logback_1614.xml");
103 Logger logger = loggerContext.getLogger(this.getClass().getName());
104 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
105 AsyncAppender asyncAppender = (AsyncAppender) root.getAppender("ASYNC");
106 assertNotNull(asyncAppender);
107 ConsoleAppender<ILoggingEvent> console = (ConsoleAppender<ILoggingEvent>) root.getAppender("CONSOLE");
108 assertNotNull(console);
109 assertTrue(console.isStarted());
110
111 String msg = "hello world";
112 logger.warn(msg);
113 }
114
115 @Test
116 public void simpleListWithImports() throws JoranException {
117 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "simpleListWithImports.xml");
118 Logger logger = loggerContext.getLogger(this.getClass().getName());
119 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
120 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
121 assertNotNull(listAppender);
122 assertEquals(0, listAppender.list.size());
123 String msg = "hello world";
124 logger.debug(msg);
125 assertEquals(1, listAppender.list.size());
126 ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0);
127 assertEquals(msg, le.getMessage());
128 }
129
130 @Test
131 public void level() throws JoranException {
132 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "simpleLevel.xml");
133 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
134 assertEquals(0, listAppender.list.size());
135 String msg = "hello world";
136 logger.debug(msg);
137 assertEquals(0, listAppender.list.size());
138 }
139
140 @Test
141 public void additivity() throws JoranException {
142 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "additivity.xml");
143 Logger logger = loggerContext.getLogger("additivityTest");
144 assertFalse(logger.isAdditive());
145 }
146
147 @Test
148 public void rootLoggerLevelSettingBySystemProperty() throws JoranException {
149 String propertyName = "logback.level";
150
151 System.setProperty(propertyName, "INFO");
152 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "rootLevelByProperty.xml");
153
154 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
155 assertEquals(0, listAppender.list.size());
156 String msg = "hello world";
157 logger.debug(msg);
158 assertEquals(0, listAppender.list.size());
159 System.clearProperty(propertyName);
160 }
161
162 @Test
163 public void loggerLevelSettingBySystemProperty() throws JoranException {
164 String propertyName = "logback.level";
165 System.setProperty(propertyName, "DEBUG");
166 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "loggerLevelByProperty.xml");
167 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
168 assertEquals(0, listAppender.list.size());
169 String msg = "hello world";
170 logger.debug(msg);
171 assertEquals(1, listAppender.list.size());
172 System.clearProperty(propertyName);
173 }
174
175 @Test
176 public void appenderRefSettingBySystemProperty() throws JoranException {
177 final String propertyName = "logback.appenderRef";
178 System.setProperty(propertyName, "A");
179 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "appenderRefByProperty.xml");
180 final Logger logger = loggerContext.getLogger("ch.qos.logback.classic.joran");
181 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) logger.getAppender("A");
182
183 assertNull(listAppender);
184
185 final String msg = "hello world";
186 logger.info(msg);
187
188 System.clearProperty(propertyName);
189 }
190
191 @Test
192 public void appenderRefSettingBySystemPropertyDefault() throws JoranException {
193
194 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "appenderRefByPropertyDefault.xml");
195 final Logger logger = loggerContext.getLogger("ch.qos.logback.classic.joran");
196 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("A");
197
198 assertNull(listAppender);
199
200 }
201
202
203 @Test
204 public void refToUndefinedAppender() throws JoranException {
205
206 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "refToUndefinedAppender.xml");
207
208 final Logger logger = loggerContext.getLogger("ch.qos.logback.classic.joran");
209 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("A");
210 assertNotNull(listAppender);
211 assertEquals(0, listAppender.list.size());
212 final String msg = "hello world";
213 logger.info(msg);
214
215 assertEquals(1, listAppender.list.size());
216
217 checker.assertContainsMatch(Status.WARN, "Appender named \\[NON_EXISTENT_APPENDER\\] could not be found. Skipping attachment to Logger\\[ROOT\\]");
218 }
219
220 @Test
221 public void refViaDefaultSubstitution() throws JoranException {
222
223 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "refViaDefaultSubstitution.xml");
224 final Logger logger = loggerContext.getLogger("ch.qos.logback.classic.joran");
225 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("A");
226 final NOPAppender<ILoggingEvent> nopAppender = (NOPAppender) root.getAppender("NOP");
227
228 assertNotNull(listAppender);
229 assertNull(nopAppender);
230
231 assertEquals(0, listAppender.list.size());
232 final String msg = "hello world";
233 logger.info(msg);
234
235 assertEquals(1, listAppender.list.size());
236
237 checker.assertContainsMatch("Appender named \\[\\$\\{NONEXISTENT:-NOP\\}\\] could not be found.");
238 }
239
240 @Test
241 public void fauxListener() throws JoranException {
242 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "fauxListener.xml");
243
244
245 assertEquals(0,FauxListener.COUNT);
246 checker.assertContainsMatch(Status.ERROR, "Could not create component \\[listener\\] of type \\[ch.qos.logback.classic.joran.FauxListener\\]");
247
248 }
249 @Test
250 public void statusListener() throws JoranException {
251 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "statusListener.xml");
252
253 checker.assertIsErrorFree();
254 checker.assertContainsMatch(Status.WARN,
255 "Please use \"level\" attribute within <logger> or <root> elements instead.");
256 }
257
258 @Test
259 public void statusListenerWithImports() throws JoranException {
260 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "statusListenerWithImports.xml");
261
262 checker.assertIsErrorFree();
263 checker.assertContainsMatch(Status.WARN,
264 "Please use \"level\" attribute within <logger> or <root> elements instead.");
265 }
266
267 @Test
268 public void contextRename() throws JoranException {
269 loggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME);
270 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "contextRename.xml");
271 assertEquals("wombat", loggerContext.getName());
272 }
273
274 @Test
275 public void missingConfigurationElement() throws JoranException {
276 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/noConfig.xml");
277
278 String msg1 = "Exception in body\\(\\) method for action \\[" + ParamAction.class.getName() + "\\]";
279 checker.assertContainsMatch(Status.ERROR, msg1);
280
281 String msg2 = "current model is null. Is <configuration> element missing?";
282 checker.assertContainsException(ActionException.class, msg2);
283 }
284
285 @Test
286 public void ignoreUnknownProperty() throws JoranException {
287
288 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/unknownProperty.xml");
289 String msg = IGNORING_UNKNOWN_PROP + " \\[a\\] in \\[ch.qos.logback.classic.LoggerContext\\]";
290 checker.assertContainsMatch(Status.WARN, msg);
291 }
292
293
294 @Test
295 public void complexCollectionWihhNoKnownClass() throws JoranException {
296
297 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/nestedComplexWithNoKnownClass.xml");
298 String msg = "Could not find an appropriate class for property \\[listener\\]";
299 checker.assertContainsMatch(Status.ERROR, msg);
300 }
301
302 @Test
303 public void turboFilter() throws JoranException {
304
305
306
307 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "turbo.xml");
308
309 TurboFilter filter = loggerContext.getTurboFilterList().get(0);
310 assertTrue(filter instanceof NOPTurboFilter);
311 }
312
313 @Test
314 public void testTurboFilterWithStringList() throws JoranException {
315
316
317
318
319 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "turbo2.xml");
320
321
322
323 TurboFilter filter = loggerContext.getTurboFilterList().get(0);
324 assertTrue(filter instanceof DebugUsersTurboFilter);
325 DebugUsersTurboFilter dutf = (DebugUsersTurboFilter) filter;
326 assertEquals(2, dutf.getUsers().size());
327 }
328
329 @Test
330 public void testLevelFilter() throws JoranException {
331 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "levelFilter.xml");
332
333
334
335 logger.warn("hello");
336 logger.error("to be ignored");
337
338 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
339
340 assertNotNull(listAppender);
341 assertEquals(1, listAppender.list.size());
342 ILoggingEvent back = listAppender.list.get(0);
343 assertEquals(Level.WARN, back.getLevel());
344 assertEquals("hello", back.getMessage());
345 }
346
347
348 @Test
349 public void testTurboDynamicThreshold() throws JoranException {
350 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "turboDynamicThreshold.xml");
351
352 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
353 assertEquals(0, listAppender.list.size());
354
355
356 MDC.put("userId", "user1");
357 logger.debug("hello user1");
358
359 MDC.put("userId", "user2");
360 logger.debug("hello user2");
361
362 assertEquals(1, listAppender.list.size());
363 ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0);
364 assertEquals("hello user2", le.getMessage());
365 }
366
367 @Test
368 public void testTurboDynamicThreshold2() throws JoranException {
369
370 try {
371 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "turboDynamicThreshold2.xml");
372 } finally {
373
374 }
375 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
376 assertEquals(0, listAppender.list.size());
377
378
379 MDC.put("userId", "user1");
380 logger.debug("hello user1");
381
382 MDC.put("userId", "user2");
383 logger.debug("hello user2");
384
385 MDC.put("userId", "user3");
386 logger.debug("hello user3");
387
388 assertEquals(2, listAppender.list.size());
389 ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0);
390 assertEquals("hello user1", le.getMessage());
391 le = (ILoggingEvent) listAppender.list.get(1);
392 assertEquals("hello user2", le.getMessage());
393 }
394
395 @Test
396 public void timestamp() throws JoranException, IOException, InterruptedException {
397
398 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "timestamp-context.xml";
399 configure(configFileAsStr);
400
401 String r = loggerContext.getProperty("testTimestamp");
402 assertNotNull(r);
403 CachingDateFormatter sdf = new CachingDateFormatter("yyyy-MM");
404 String expected = sdf.format(System.currentTimeMillis());
405 assertEquals(expected, r, "expected \"" + expected + "\" but got " + r);
406 }
407
408 @Test
409 public void timestampLocal() throws JoranException, IOException, InterruptedException {
410
411 String sysProp = "ch.qos.logback.classic.joran.JoranConfiguratorTest.timestampLocal";
412 System.setProperty(sysProp, "");
413
414 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "timestamp-local.xml";
415 configure(configFileAsStr);
416
417
418
419
420
421
422 String r = loggerContext.getProperty("testTimestamp");
423 assertNull(r);
424
425 String expected = "today is " + new SimpleDateFormat("yyyy-MM").format(new Date());
426 String sysPropValue = System.getProperty(sysProp);
427 assertEquals(expected, sysPropValue);
428 }
429
430 @Test
431 public void encoderCharset() throws JoranException, IOException, InterruptedException {
432
433 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "encoderCharset.xml";
434 configure(configFileAsStr);
435
436 ConsoleAppender<ILoggingEvent> consoleAppender = (ConsoleAppender<ILoggingEvent>) root.getAppender("CONSOLE");
437 assertNotNull(consoleAppender);
438 LayoutWrappingEncoder<ILoggingEvent> encoder = (LayoutWrappingEncoder<ILoggingEvent>) consoleAppender
439 .getEncoder();
440
441 assertEquals("UTF-8", encoder.getCharset().displayName());
442
443 checker.assertIsErrorFree();
444 }
445
446
447
448 @Disabled
449 @Test
450 public void onConsoleRetro() throws JoranException, IOException, InterruptedException {
451 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "/onConsoleRetro.xml";
452 configure(configFileAsStr);
453 Thread.sleep(400);
454
455 loggerContext.reset();
456 configure(configFileAsStr);
457 }
458
459 @Test
460 public void unreferencedAppenderShouldNotTriggerUnknownPropertyMessages() throws JoranException {
461 String configFileAsStr = ClassicTestConstants.ISSUES_PREFIX + "/logback1572.xml";
462 configure(configFileAsStr);
463 checker.assertContainsMatch(Status.WARN,
464 "Appender named \\[EMAIL\\] not referenced. Skipping further processing.");
465 checker.assertNoMatch(IGNORING_UNKNOWN_PROP + " \\[evaluator\\]");
466 }
467
468 @Test
469 public void LOGBACK_111() throws JoranException {
470 String configFileAsStr = ClassicTestConstants.ISSUES_PREFIX + "lbcore193.xml";
471 configure(configFileAsStr);
472 checker.assertContainsException(ScanException.class);
473 checker.assertContainsMatch(Status.ERROR, "Expecting RIGHT_PARENTHESIS token but got null");
474 checker.assertContainsMatch(Status.ERROR, "See also " + Parser.MISSING_RIGHT_PARENTHESIS);
475 }
476
477 @Test
478 public void properties() throws JoranException {
479 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "properties.xml";
480 assertNull(System.getProperty("sys"));
481
482 configure(configFileAsStr);
483 assertNotNull(loggerContext.getProperty(CoreConstants.HOSTNAME_KEY));
484 assertNull(loggerContext.getProperty("transientKey1"));
485 assertNull(loggerContext.getProperty("transientKey2"));
486 assertEquals("node0", loggerContext.getProperty("nodeId"));
487 assertEquals("tem", System.getProperty("sys"));
488 assertNotNull(loggerContext.getProperty("path"));
489 checker.assertIsErrorFree();
490 }
491
492 @Test
493 public void hostnameProperty() throws JoranException {
494 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "hostnameProperty.xml";
495 configure(configFileAsStr);
496 assertEquals("A", loggerContext.getProperty(CoreConstants.HOSTNAME_KEY));
497 }
498
499
500 @Test
501 public void sysProps() throws JoranException {
502 System.setProperty("k.lbcore254", ClassicTestConstants.ISSUES_PREFIX + "lbcore254");
503 JoranConfigurator configurator = new JoranConfigurator();
504 configurator.setContext(loggerContext);
505 configurator.doConfigure(ClassicTestConstants.ISSUES_PREFIX + "lbcore254.xml");
506
507 checker.assertIsErrorFree();
508 }
509
510 @Test
511 public void propsWithMissingRightCurlyBrace() throws JoranException {
512 System.setProperty("abc", "not important");
513 JoranConfigurator configurator = new JoranConfigurator();
514 configurator.setContext(loggerContext);
515 configurator.doConfigure(ClassicTestConstants.JORAN_INPUT_PREFIX + "propsMissingRightCurlyBrace.xml");
516 checker.assertContainsMatch(Status.ERROR, "Problem while parsing");
517 }
518
519 @Test
520 public void packageDataDisabledByConfigAttribute() throws JoranException {
521 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "packagingDataDisabled.xml";
522 configure(configFileAsStr);
523 assertFalse(loggerContext.isPackagingDataEnabled());
524 }
525
526 @Test
527 public void packageDataEnabledByConfigAttribute() throws JoranException {
528 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "packagingDataEnabled.xml";
529 try {
530 configure(configFileAsStr);
531 } finally {
532
533 }
534 assertTrue(loggerContext.isPackagingDataEnabled());
535 }
536
537 @Test
538 public void valueOfConvention() throws JoranException {
539 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "valueOfConvention.xml";
540 configure(configFileAsStr);
541 checker.assertIsWarningOrErrorFree();
542 }
543
544 @Test
545 public void shutdownHookTest() throws JoranException {
546 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "issues/logback_1162.xml";
547 loggerContext.putProperty("output_dir", ClassicTestConstants.OUTPUT_DIR_PREFIX + "logback_issue_1162/");
548 configure(configFileAsStr);
549 Thread thread = (Thread) loggerContext.getObject(CoreConstants.SHUTDOWN_HOOK_THREAD);
550 assertNotNull(thread);
551 }
552
553
554 @Test
555 public void nestedAppendersDisallowed() throws JoranException {
556 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "issues/logback_1674.xml";
557 configure(configFileAsStr);
558 checker.assertContainsMatch(Status.WARN, NESTED_APPENDERS_WARNING);
559 checker.assertContainsMatch(Status.WARN, "Appender at line ");
560 }
561
562 @Test
563 public void shutdownHookWithDelayParameter() throws JoranException {
564 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "issues/logback_1672.xml";
565 configure(configFileAsStr);
566
567 Thread thread = (Thread) loggerContext.getObject(CoreConstants.SHUTDOWN_HOOK_THREAD);
568 assertNotNull(thread);
569 checker.assertNoMatch(IGNORING_UNKNOWN_PROP);
570 }
571
572 @Test
573 public void migrateShutdownHookClassName() throws JoranException {
574 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "issues/logback_1678_shutdown.xml";
575 configure(configFileAsStr);
576
577 Thread thread = (Thread) loggerContext.getObject(CoreConstants.SHUTDOWN_HOOK_THREAD);
578 assertNotNull(thread);
579 checker.assertContainsMatch(RENAME_WARNING);
580 }
581
582 @Test
583 public void appenderRefBeforeAppenderTest() throws JoranException {
584 String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "appenderRefBeforeAppender.xml";
585 configure(configFileAsStr);
586 Logger logger = loggerContext.getLogger(this.getClass().getName());
587 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
588 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
589 assertNotNull(listAppender);
590 assertEquals(0, listAppender.list.size());
591 String msg = "hello world";
592 logger.debug(msg);
593 assertEquals(1, listAppender.list.size());
594 ILoggingEvent le = (ILoggingEvent) listAppender.list.get(0);
595 assertEquals(msg, le.getMessage());
596 checker.assertIsErrorFree();
597 }
598
599 @Test
600 public void unreferencedAppendersShouldBeSkipped() throws JoranException {
601 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "unreferencedAppender1.xml");
602
603 final ListAppender<ILoggingEvent> listAppenderA = (ListAppender<ILoggingEvent>) root.getAppender("A");
604 assertNotNull(listAppenderA);
605 checker.assertContainsMatch(Status.WARN, "Appender named \\[B\\] not referenced. Skipping further processing.");
606 }
607
608 @Test
609 public void asynAppenderListFirst() throws JoranException {
610 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "asyncAppender_list_first.xml");
611
612 final AsyncAppender asyncAppender = (AsyncAppender) root.getAppender("ASYNC");
613 assertNotNull(asyncAppender);
614 assertTrue(asyncAppender.isStarted());
615 }
616
617 @Test
618 public void asynAppenderListAfter() throws JoranException {
619 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "asyncAppender_list_after.xml");
620 StatusPrinter.print(loggerContext);
621 final AsyncAppender asyncAppender = (AsyncAppender) root.getAppender("ASYNC");
622 assertNotNull(asyncAppender);
623 assertTrue(asyncAppender.isStarted());
624 }
625
626
627 @Test
628 public void missingPropertyErrorHandling() throws JoranException {
629 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "missingProperty.xml");
630
631 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
632 assertNotNull(listAppender);
633 assertTrue(listAppender.isStarted());
634 checker.assertContainsMatch(Status.WARN,
635 IGNORING_UNKNOWN_PROP + " \\[inexistent\\] in \\[ch.qos.logback.core.read.ListAppender\\]");
636 }
637
638 @Test
639 public void sequenceNumberGenerator() throws JoranException {
640 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "sequenceNumberGenerator.xml");
641 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
642 assertNotNull(listAppender);
643
644 logger.atDebug().setMessage("hello").log();
645 logger.atDebug().setMessage("world").log();
646
647 ILoggingEvent le0 = listAppender.list.get(0);
648 ILoggingEvent le1 = listAppender.list.get(1);
649
650 long se0 = le0.getSequenceNumber();
651 long se1 = le1.getSequenceNumber();
652 assertEquals(1, se1 - se0);
653 }
654
655 @Test
656 public void sequenceNumberGenerator_missingClass() throws JoranException {
657 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "sequenceNumberGenerator-missingClass.xml");
658
659 final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
660 assertNotNull(listAppender);
661 checker.assertContainsMatch(Status.ERROR, "Missing attribute \\[class\\]. See element \\[sequenceNumberGenerator\\]");
662 }
663
664 @Test
665 public void kvp() throws JoranException {
666 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "pattern/kvp.xml");
667
668 String msg = "hello kvp";
669
670 KeyValuePair kvp1 = new KeyValuePair("k" + diff, "v" + diff);
671 KeyValuePair kvp2 = new KeyValuePair("k" + (diff + 1), "v" + (diff + 1));
672 KeyValuePair kvpNullKey = new KeyValuePair(null, "v" + (diff + 2));
673 KeyValuePair kvpNullValue = new KeyValuePair("k" + (diff + 3), null);
674
675 logger.atDebug().addKeyValue(kvp1.key, kvp1.value).log(msg);
676 logger.atDebug().addKeyValue(kvp2.key, kvp2.value).log(msg);
677 logger.atDebug().addKeyValue(kvpNullKey.key, kvpNullKey.value).log(msg);
678 logger.atDebug().addKeyValue(kvpNullValue.key, kvpNullValue.value).log(msg);
679
680 StringListAppender<ILoggingEvent> slAppender = (StringListAppender<ILoggingEvent>) loggerContext
681 .getLogger("root").getAppender("LIST");
682 assertNotNull(slAppender);
683 assertEquals(4, slAppender.strList.size());
684 assertTrue(slAppender.strList.get(0).contains(kvp1.key + "=\"" + kvp1.value + "\" " + msg));
685 assertTrue(slAppender.strList.get(1).contains(kvp2.key + "=\"" + kvp2.value + "\" " + msg));
686 assertTrue(slAppender.strList.get(2).contains("null=\"" + kvpNullKey.value + "\" " + msg));
687 assertTrue(slAppender.strList.get(3).contains(kvpNullValue.key + "=\"null\" " + msg));
688 }
689
690
691
692 @Test
693 public void inclusionWithVariables() throws JoranException {
694 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "include/topLevel0.xml");
695 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
696
697 assertEquals(Level.ERROR, root.getLevel());
698 }
699
700
701 @Test
702 public void ossFuzz_46697() throws JoranException {
703 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-46697.xml");
704
705 checker.assertContainsMatch(Status.ERROR, ErrorCodes.EMPTY_MODEL_STACK);
706 }
707
708
709
710
711
712 @Test
713 public void ossFuzz_47093() throws JoranException {
714 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47093.xml");
715 assertEquals("a\\t", loggerContext.getProperty("fuzz-47093-a"));
716 assertEquals("a\\\\", loggerContext.getProperty("fuzz-47093-b"));
717 }
718
719 @Test
720 public void ossFuzz_41117() throws JoranException {
721 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47117.xml");
722 checker.assertContainsMatch(Status.ERROR, ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);
723 checker.assertErrorCount(2);
724
725 }
726
727 @Test
728 public void ossFuzz_41117_bis() throws JoranException {
729 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47117-bis.xml");
730 checker.assertContainsMatch(Status.ERROR, ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);
731 }
732
733 @Test
734 public void ossFuzz_41117_bis2() throws JoranException {
735 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47117-bis2.xml");
736 checker.assertContainsMatch(Status.ERROR, ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);
737 }
738
739 @Test
740 public void ossFuzz_47293() throws JoranException {
741 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47293.xml");
742 checker.assertContainsMatch(Status.ERROR, ErrorCodes.MISSING_IF_EMPTY_MODEL_STACK);
743 }
744
745
746 @Test
747 public void dateConverterWithLocale() throws JoranException {
748 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "dateWithLocale.xml");
749 checker.assertContainsMatch(Status.INFO, "Setting zoneId to \"Australia/Perth\"");
750 checker.assertContainsMatch(Status.INFO, "Setting locale to \"en_AU\"");
751
752 }
753
754 @Test
755 public void propertyConfiguratorSmoke() throws JoranException {
756 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "propertiesConfigurator/smoke.xml");
757 Logger com_foo_Logger = loggerContext.getLogger("com.toto");
758
759 assertEquals(Level.WARN, com_foo_Logger.getLevel());
760
761
762 }
763
764 @Test
765 public void consoleCharsetTest() throws JoranException {
766 if (EnvUtil.isJDK21OrHigher()) {
767 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "consoleCharset.xml");
768 checker.assertContainsMatch(Status.INFO, "About to instantiate property definer of type \\[ch.qos.logback.core.property.ConsoleCharsetPropertyDefiner\\]");
769
770 Console console = System.console();
771 if(console == null) {
772 checker.assertContainsMatch(Status.WARN, "System.console\\(\\) returned null. Cannot compute console's charset, returning");
773 } else {
774
775 boolean nullCharset = checker.containsMatch("System.console() returned null charset. Returning \"NULL\" string as defined value.");
776 boolean foundCharset = checker.containsMatch("Found value '.*' as returned by System.console().");
777
778 }
779
780 }
781 }
782
783 @Test
784 public void levelFromAPropertyTest() throws JoranException {
785
786
787 String loggerASysLevelKey = "LOGGER_A_SYS_LEVEL";
788 String loggerNestedSysLevelKey = "LOGGER_NESTED_SYS_LEVEL";
789 System.setProperty(loggerASysLevelKey, "WARN");
790 System.setProperty(loggerNestedSysLevelKey, "ERROR");
791 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "levelFromAProperty.xml");
792
793
794 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
795
796
797 Logger loggerA = loggerContext.getLogger("A");
798 Logger loggerA_SYS = loggerContext.getLogger("A_SYS");
799
800 Logger loggerNESTED = loggerContext.getLogger("NESTED");
801
802 Logger loggerNESTED_SYS = loggerContext.getLogger("NESTED_SYS");
803
804
805 assertEquals(Level.TRACE, root.getLevel());
806 assertEquals(Level.WARN, loggerA.getLevel());
807 assertEquals(Level.WARN, loggerA_SYS.getLevel());
808
809 assertEquals(Level.ERROR, loggerNESTED.getLevel());
810 assertEquals(Level.ERROR, loggerNESTED_SYS.getLevel());
811
812 checker.assertContainsMatch(Status.INFO, "value \\\"WARN\\\" substituted for \\\"\\$\\{LOGGER_A_LEVEL\\}\\\"");
813
814 System.clearProperty(loggerASysLevelKey);
815 System.clearProperty(loggerNestedSysLevelKey);
816
817 }
818
819 @Test
820 public void exceptionEventFilter() throws JoranException {
821 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "boolex/exceptionEvaluator.xml");
822 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
823 root.info("deny");
824 root.info("allow", new RuntimeException("test"));
825
826 ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
827 assertNotNull(listAppender);
828 assertEquals(1, listAppender.list.size());
829
830 ILoggingEvent le = listAppender.list.get(0);
831
832 assertNotNull(le.getThrowableProxy());
833 assertEquals(RuntimeException.class.getName(), le.getThrowableProxy().getClassName());
834
835 }
836
837 @Test
838 public void modelSerialization() throws JoranException, IOException, ClassNotFoundException {
839 String outputPath = OUTPUT_DIR_PREFIX + "minimal_" + diff + MODEL_CONFIG_FILE_EXTENSION;
840
841 loggerContext.putProperty("targetModelFile", outputPath);
842 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "model/minimal.xml");
843 StatusPrinter.print(loggerContext);
844
845 FileInputStream fis = new FileInputStream(outputPath);
846 HardenedModelInputStream hmis = new HardenedModelInputStream(fis);
847
848 Model model = (Model) hmis.readObject();
849
850 assertNotNull(model);
851 assertTrue(model instanceof ConfigurationModel);
852
853 ConfigurationModel configurationModel = (ConfigurationModel) model;
854
855 assertEquals("false", configurationModel.getDebugStr());
856
857 assertEquals(2, configurationModel.getSubModels().size());
858
859 SerializeModelModel smm = (SerializeModelModel) configurationModel.getSubModels().get(0);
860 assertEquals("${targetModelFile}", smm.getFile());
861
862
863 LoggerModel loggerModel = (LoggerModel) configurationModel.getSubModels().get(1);
864 assertEquals("ModelSerializationTest", loggerModel.getName());
865
866
867
868 }
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905 }