Skip to content

Commit c1f21e9

Browse files
committed
add test in relation to variable subsitions for levels, report substitions, LOGBACK-1519
Signed-off-by: Ceki Gulcu <[email protected]>
1 parent 7c29474 commit c1f21e9

File tree

4 files changed

+129
-52
lines changed

4 files changed

+129
-52
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!--
3+
~ Logback: the reliable, generic, fast and flexible logging framework.
4+
~ Copyright (C) 1999-2024, QOS.ch. All rights reserved.
5+
~
6+
~ This program and the accompanying materials are dual-licensed under
7+
~ either the terms of the Eclipse Public License v1.0 as published by
8+
~ the Eclipse Foundation
9+
~
10+
~ or (per the licensee's choosing)
11+
~
12+
~ under the terms of the GNU Lesser General Public License version 2.1
13+
~ as published by the Free Software Foundation.
14+
-->
15+
16+
<!DOCTYPE configuration>
17+
18+
<configuration>
19+
<import class="ch.qos.logback.core.read.ListAppender"/>
20+
<import class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
21+
22+
<!-- <statusListener class="OnConsoleStatusListener"/>-->
23+
24+
25+
<appender name="LIST_ROOT" class="ListAppender"/>
26+
27+
<variable name="ROOT_LEVEL" value="TRACE"/>
28+
<variable name="LOGGER_A_LEVEL" value="WARN"/>
29+
<variable name="LOGGER_NESTED_LEVEL" value="ERROR"/>
30+
31+
<logger name="A" level="${LOGGER_A_LEVEL}"/>
32+
33+
<logger name="A_SYS" level="${LOGGER_A_SYS_LEVEL}"/>
34+
35+
<logger name="NESTED">
36+
<level value="${LOGGER_NESTED_LEVEL}" />
37+
</logger>
38+
39+
<logger name="NESTED_SYS">
40+
<level value="${LOGGER_NESTED_SYS_LEVEL}" />
41+
</logger>
42+
43+
<root level="${ROOT_LEVEL}">
44+
<appender-ref ref="LIST_ROOT"/>
45+
</root>
46+
</configuration>

logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java

+74-44
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/**
22
* Logback: the reliable, generic, fast and flexible logging framework.
33
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4-
*
4+
* <p>
55
* This program and the accompanying materials are dual-licensed under
66
* either the terms of the Eclipse Public License v1.0 as published by
77
* the Eclipse Foundation
8-
*
9-
* or (per the licensee's choosing)
10-
*
8+
* <p>
9+
* or (per the licensee's choosing)
10+
* <p>
1111
* under the terms of the GNU Lesser General Public License version 2.1
1212
* as published by the Free Software Foundation.
1313
*/
@@ -121,7 +121,7 @@ public void asyncWithMultipleAppendersInRoot() throws JoranException {
121121
String msg = "hello world";
122122
logger.warn(msg);
123123
}
124-
124+
125125
@Test
126126
public void simpleListWithImports() throws JoranException {
127127
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "simpleListWithImports.xml");
@@ -225,31 +225,31 @@ public void contextRename() throws JoranException {
225225
@Test
226226
public void missingConfigurationElement() throws JoranException {
227227
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/noConfig.xml");
228-
229-
String msg1 = "Exception in body\\(\\) method for action \\["+ParamAction.class.getName()+"\\]";
228+
229+
String msg1 = "Exception in body\\(\\) method for action \\[" + ParamAction.class.getName() + "\\]";
230230
checker.assertContainsMatch(Status.ERROR, msg1);
231-
231+
232232
String msg2 = "current model is null. Is <configuration> element missing?";
233-
checker.assertContainsException(ActionException.class, msg2 );
233+
checker.assertContainsException(ActionException.class, msg2);
234234
}
235235

236236
@Test
237237
public void ignoreUnknownProperty() throws JoranException {
238-
238+
239239
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/unknownProperty.xml");
240-
String msg = IGNORING_UNKNOWN_PROP+" \\[a\\] in \\[ch.qos.logback.classic.LoggerContext\\]";
240+
String msg = IGNORING_UNKNOWN_PROP + " \\[a\\] in \\[ch.qos.logback.classic.LoggerContext\\]";
241241
checker.assertContainsMatch(Status.WARN, msg);
242242
}
243-
243+
244244
// https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=46995
245245
@Test
246246
public void complexCollectionWihhNoKnownClass() throws JoranException {
247-
248-
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/nestedComplexWithNoKnownClass.xml");
249-
String msg = "Could not find an appropriate class for property \\[listener\\]";
250-
checker.assertContainsMatch(Status.ERROR, msg);
247+
248+
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/nestedComplexWithNoKnownClass.xml");
249+
String msg = "Could not find an appropriate class for property \\[listener\\]";
250+
checker.assertContainsMatch(Status.ERROR, msg);
251251
}
252-
252+
253253
@Test
254254
public void turboFilter() throws JoranException {
255255
// Although this test uses turbo filters, it only checks
@@ -296,7 +296,6 @@ public void testLevelFilter() throws JoranException {
296296
}
297297

298298

299-
300299
@Test
301300
public void testTurboDynamicThreshold() throws JoranException {
302301
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "turboDynamicThreshold.xml");
@@ -452,7 +451,7 @@ public void unreferencedAppenderShouldNotTriggerUnknownPropertyMessages() throws
452451
configure(configFileAsStr);
453452
checker.assertContainsMatch(Status.WARN,
454453
"Appender named \\[EMAIL\\] not referenced. Skipping further processing.");
455-
checker.assertNoMatch(IGNORING_UNKNOWN_PROP+" \\[evaluator\\]");
454+
checker.assertNoMatch(IGNORING_UNKNOWN_PROP + " \\[evaluator\\]");
456455
}
457456

458457
@Test
@@ -546,7 +545,7 @@ public void nestedAppendersDisallowed() throws JoranException {
546545
String configFileAsStr = ClassicTestConstants.JORAN_INPUT_PREFIX + "issues/logback_1674.xml";
547546
configure(configFileAsStr);
548547
checker.assertContainsMatch(Status.WARN, NESTED_APPENDERS_WARNING);
549-
checker.assertContainsMatch(Status.WARN,"Appender at line ");
548+
checker.assertContainsMatch(Status.WARN, "Appender at line ");
550549
}
551550

552551
@Test
@@ -622,13 +621,13 @@ public void missingPropertyErrorHandling() throws JoranException {
622621
assertNotNull(listAppender);
623622
assertTrue(listAppender.isStarted());
624623
checker.assertContainsMatch(Status.WARN,
625-
IGNORING_UNKNOWN_PROP+" \\[inexistent\\] in \\[ch.qos.logback.core.read.ListAppender\\]");
624+
IGNORING_UNKNOWN_PROP + " \\[inexistent\\] in \\[ch.qos.logback.core.read.ListAppender\\]");
626625
}
627626

628627
@Test
629628
public void sequenceNumberGenerator() throws JoranException {
630629
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "sequenceNumberGenerator.xml");
631-
final ListAppender<ILoggingEvent> listAppender= (ListAppender<ILoggingEvent>) root.getAppender("LIST");
630+
final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
632631
assertNotNull(listAppender);
633632

634633
logger.atDebug().setMessage("hello").log();
@@ -646,12 +645,12 @@ public void sequenceNumberGenerator() throws JoranException {
646645
public void sequenceNumberGenerator_missingClass() throws JoranException {
647646
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "sequenceNumberGenerator-missingClass.xml");
648647
//StatusPrinter.print(loggerContext);
649-
final ListAppender<ILoggingEvent> listAppender= (ListAppender<ILoggingEvent>) root.getAppender("LIST");
648+
final ListAppender<ILoggingEvent> listAppender = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
650649
assertNotNull(listAppender);
651650
checker.assertContainsMatch(Status.ERROR, "Missing attribute \\[class\\]. See element \\[sequenceNumberGenerator\\]");
652651
}
653652

654-
@Test
653+
@Test
655654
public void kvp() throws JoranException {
656655
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "pattern/kvp.xml");
657656

@@ -680,7 +679,7 @@ public void kvp() throws JoranException {
680679

681680
// See LOGBACK-1746
682681
@Test
683-
public void inclusionWithVariables() throws JoranException {
682+
public void inclusionWithVariables() throws JoranException {
684683
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "include/topLevel0.xml");
685684
Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
686685
//statusPrinter2.print(loggerContext);
@@ -689,9 +688,9 @@ public void inclusionWithVariables() throws JoranException {
689688

690689
// https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=46697
691690
@Test
692-
public void ossFuzz_46697() throws JoranException {
691+
public void ossFuzz_46697() throws JoranException {
693692
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-46697.xml");
694-
693+
695694
checker.assertContainsMatch(Status.ERROR, ErrorCodes.EMPTY_MODEL_STACK);
696695
}
697696

@@ -700,62 +699,98 @@ public void ossFuzz_46697() throws JoranException {
700699
// escape sequences for the 'value' attribute named 'value'. After
701700
// analysis this was deemed superfluous.
702701
@Test
703-
public void ossFuzz_47093() throws JoranException {
702+
public void ossFuzz_47093() throws JoranException {
704703
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47093.xml");
705704
assertEquals("a\\t", loggerContext.getProperty("fuzz-47093-a"));
706705
assertEquals("a\\\\", loggerContext.getProperty("fuzz-47093-b"));
707706
}
708707

709708
@Test
710-
public void ossFuzz_41117() throws JoranException {
709+
public void ossFuzz_41117() throws JoranException {
711710
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47117.xml");
712711
checker.assertContainsMatch(Status.ERROR, ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);
713712
checker.assertErrorCount(2);
714713
//StatusPrinter.print(loggerContext);
715714
}
716715

717716
@Test
718-
public void ossFuzz_41117_bis() throws JoranException {
717+
public void ossFuzz_41117_bis() throws JoranException {
719718
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47117-bis.xml");
720719
checker.assertContainsMatch(Status.ERROR, ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);
721720
}
722721

723722
@Test
724-
public void ossFuzz_41117_bis2() throws JoranException {
723+
public void ossFuzz_41117_bis2() throws JoranException {
725724
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47117-bis2.xml");
726725
checker.assertContainsMatch(Status.ERROR, ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);
727726
}
728727

729728
@Test
730-
public void ossFuzz_47293() throws JoranException {
729+
public void ossFuzz_47293() throws JoranException {
731730
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "ossfuzz/fuzz-47293.xml");
732731
checker.assertContainsMatch(Status.ERROR, ErrorCodes.MISSING_IF_EMPTY_MODEL_STACK);
733732
}
734733

735734

736735
@Test
737-
public void dateConverterWithLocale() throws JoranException {
736+
public void dateConverterWithLocale() throws JoranException {
738737
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "dateWithLocale.xml");
739738
checker.assertContainsMatch(Status.INFO, "Setting zoneId to \"Australia/Perth\"");
740739
checker.assertContainsMatch(Status.INFO, "Setting locale to \"en_AU\"");
741740
//StatusPrinter.print(loggerContext);
742741
}
743742

744743
@Test
745-
public void consoleCharsetTest() throws JoranException {
746-
if(EnvUtil.isJDK21OrHigher()) {
744+
public void consoleCharsetTest() throws JoranException {
745+
if (EnvUtil.isJDK21OrHigher()) {
747746
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "consoleCharset.xml");
748747
checker.assertContainsMatch(Status.INFO, "About to instantiate property definer of type \\[ch.qos.logback.core.property.ConsoleCharsetPropertyDefiner\\]");
749748
checker.assertContainsMatch(Status.WARN, "System.console\\(\\) returned null. Cannot compute console's charset, returning");
750-
checker.assertContainsMatch("Setting property consoleCharset=null in scope LOCAL" );
749+
checker.assertContainsMatch("Setting property consoleCharset=null in scope LOCAL");
751750
checker.assertContainsMatch("Converting the string \\\"null. as Charset.defaultCharset\\(\\)");
752751
//StatusPrinter.print(loggerContext);
753752
}
754753
}
755754

755+
@Test
756+
public void levelFromAPropertyTest() throws JoranException {
757+
758+
759+
String loggerASysLevelKey = "LOGGER_A_SYS_LEVEL";
760+
String loggerNestedSysLevelKey = "LOGGER_NESTED_SYS_LEVEL";
761+
System.setProperty(loggerASysLevelKey, "WARN");
762+
System.setProperty(loggerNestedSysLevelKey, "ERROR");
763+
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "levelFromAProperty.xml");
764+
765+
766+
Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
767+
768+
769+
Logger loggerA = loggerContext.getLogger("A");
770+
Logger loggerA_SYS = loggerContext.getLogger("A_SYS");
771+
772+
Logger loggerNESTED = loggerContext.getLogger("NESTED");
773+
774+
Logger loggerNESTED_SYS = loggerContext.getLogger("NESTED_SYS");
775+
776+
777+
assertEquals(Level.TRACE, root.getLevel());
778+
assertEquals(Level.WARN, loggerA.getLevel());
779+
assertEquals(Level.WARN, loggerA_SYS.getLevel());
780+
781+
assertEquals(Level.ERROR, loggerNESTED.getLevel());
782+
assertEquals(Level.ERROR, loggerNESTED_SYS.getLevel());
783+
784+
checker.assertContainsMatch(Status.INFO, "value \\\"WARN\\\" substituted for \\\"\\$\\{LOGGER_A_LEVEL\\}\\\"");
785+
786+
System.clearProperty(loggerASysLevelKey);
787+
System.clearProperty(loggerNestedSysLevelKey);
788+
789+
}
790+
756791
@Test
757792
public void modelSerialization() throws JoranException, IOException, ClassNotFoundException {
758-
String outputPath = OUTPUT_DIR_PREFIX+"minimal_"+diff+ MODEL_CONFIG_FILE_EXTENSION;
793+
String outputPath = OUTPUT_DIR_PREFIX + "minimal_" + diff + MODEL_CONFIG_FILE_EXTENSION;
759794

760795
loggerContext.putProperty("targetModelFile", outputPath);
761796
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "model/minimal.xml");
@@ -775,25 +810,20 @@ public void modelSerialization() throws JoranException, IOException, ClassNotFou
775810

776811
assertEquals(2, configurationModel.getSubModels().size());
777812

778-
SerializeModelModel smm = (SerializeModelModel) configurationModel.getSubModels().get(0);
813+
SerializeModelModel smm = (SerializeModelModel) configurationModel.getSubModels().get(0);
779814
assertEquals("${targetModelFile}", smm.getFile());
780815

781816

782-
LoggerModel loggerModel = (LoggerModel) configurationModel.getSubModels().get(1);
817+
LoggerModel loggerModel = (LoggerModel) configurationModel.getSubModels().get(1);
783818
assertEquals("ModelSerializationTest", loggerModel.getName());
784819

785820
// <serializeModel file="${targetModelFile}"/>
786821
// <logger name="ModelSerializationTest" level="DEBUG"/>
787822

788823

789-
790824
}
791825

792826

793-
794-
795-
796-
797827
// reproduction requires placing a binary properties file. Probably not worth the effort.
798828
// @Test
799829
// public void ossFuzz_47249() throws JoranException {

logback-core/src/main/java/ch/qos/logback/core/joran/util/StringToObjectConverter.java

+3-7
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,14 @@
1313
*/
1414
package ch.qos.logback.core.joran.util;
1515

16-
import java.io.Console;
16+
import ch.qos.logback.core.CoreConstants;
17+
import ch.qos.logback.core.spi.ContextAware;
18+
1719
import java.lang.reflect.Method;
1820
import java.lang.reflect.Modifier;
1921
import java.nio.charset.Charset;
2022
import java.nio.charset.UnsupportedCharsetException;
2123

22-
import ch.qos.logback.core.Context;
23-
import ch.qos.logback.core.CoreConstants;
24-
import ch.qos.logback.core.spi.ContextAware;
25-
import ch.qos.logback.core.spi.ContextAwareBase;
26-
27-
import static ch.qos.logback.core.CoreConstants.CONSOLE;
2824
import static ch.qos.logback.core.CoreConstants.NULL_STR;
2925

3026
/**

logback-core/src/main/java/ch/qos/logback/core/model/processor/ModelInterpretationContext.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,12 @@ public BeanDescriptionCache getBeanDescriptionCache() {
163163
}
164164

165165
public String subst(String ref) {
166-
return variableSubstitutionsHelper.subst(ref);
166+
167+
String substituted = variableSubstitutionsHelper.subst(ref);
168+
if(ref != null && !ref.equals(substituted)) {
169+
addInfo("value \""+substituted+"\" substituted for \""+ref+"\"");
170+
}
171+
return substituted;
167172
}
168173

169174

0 commit comments

Comments
 (0)