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