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