1818
1919import static org .assertj .core .api .Assertions .assertThat ;
2020
21+ import java .util .Arrays ;
22+ import java .util .Collection ;
23+ import java .util .Collections ;
2124import java .util .Properties ;
25+ import java .util .regex .Pattern ;
26+ import java .util .stream .Stream ;
2227import org .apache .logging .log4j .TestProvider ;
28+ import org .apache .logging .log4j .spi .Provider ;
29+ import org .apache .logging .log4j .test .TestLogger ;
2330import org .apache .logging .log4j .test .TestLoggerContextFactory ;
31+ import org .junit .jupiter .api .BeforeEach ;
2432import org .junit .jupiter .api .Test ;
2533import org .junit .jupiter .api .parallel .Execution ;
2634import org .junit .jupiter .api .parallel .ExecutionMode ;
35+ import org .junit .jupiter .params .ParameterizedTest ;
36+ import org .junit .jupiter .params .provider .Arguments ;
37+ import org .junit .jupiter .params .provider .MethodSource ;
2738
2839@ Execution (ExecutionMode .CONCURRENT )
2940class ProviderUtilTest {
3041
31- /*
32- * Force initialization of ProviderUtil#PROVIDERS
33- */
34- static {
35- ProviderUtil .lazyInit ();
42+ private static final Pattern ERROR_OR_WARNING = Pattern .compile (" (ERROR|WARN) .*" , Pattern .DOTALL );
43+
44+ private static final Provider LOCAL_PROVIDER = new LocalProvider ();
45+ private static final Provider TEST_PROVIDER = new TestProvider ();
46+
47+ private static final Collection <Provider > NO_PROVIDERS = Collections .emptyList ();
48+ private static final Collection <Provider > ONE_PROVIDER = Collections .singleton (TEST_PROVIDER );
49+ private static final Collection <Provider > TWO_PROVIDERS = Arrays .asList (LOCAL_PROVIDER , TEST_PROVIDER );
50+
51+ private TestLogger statusLogger ;
52+
53+ @ BeforeEach
54+ void setup () {
55+ statusLogger = new TestLogger ();
56+ }
57+
58+ @ Test
59+ void should_have_a_fallback_provider () {
60+ final PropertiesUtil properties = new PropertiesUtil (new Properties ());
61+ assertThat (ProviderUtil .selectProvider (properties , NO_PROVIDERS , statusLogger ))
62+ .as ("check selected provider" )
63+ .isNotNull ();
64+ // An error for the absence of providers
65+ assertHasErrorOrWarning (statusLogger );
66+ }
67+
68+ @ Test
69+ void should_be_silent_with_a_single_provider () {
70+ final PropertiesUtil properties = new PropertiesUtil (new Properties ());
71+ assertThat (ProviderUtil .selectProvider (properties , ONE_PROVIDER , statusLogger ))
72+ .as ("check selected provider" )
73+ .isSameAs (TEST_PROVIDER );
74+ assertNoErrorsOrWarnings (statusLogger );
3675 }
3776
3877 @ Test
3978 void should_select_provider_with_highest_priority () {
4079 final PropertiesUtil properties = new PropertiesUtil (new Properties ());
41- assertThat (ProviderUtil .selectProvider (properties ))
80+ assertThat (ProviderUtil .selectProvider (properties , TWO_PROVIDERS , statusLogger ))
4281 .as ("check selected provider" )
43- .isInstanceOf (TestProvider .class );
82+ .isSameAs (TEST_PROVIDER );
83+ // A warning for the presence of multiple providers
84+ assertHasErrorOrWarning (statusLogger );
4485 }
4586
4687 @ Test
4788 void should_recognize_log4j_provider_property () {
4889 final Properties map = new Properties ();
4990 map .setProperty ("log4j.provider" , LocalProvider .class .getName ());
5091 final PropertiesUtil properties = new PropertiesUtil (map );
51- assertThat (ProviderUtil .selectProvider (properties ))
92+ assertThat (ProviderUtil .selectProvider (properties , TWO_PROVIDERS , statusLogger ))
5293 .as ("check selected provider" )
5394 .isInstanceOf (LocalProvider .class );
95+ assertNoErrorsOrWarnings (statusLogger );
5496 }
5597
98+ /**
99+ * Can be removed in the future.
100+ */
56101 @ Test
57102 void should_recognize_log4j_factory_property () {
58103 final Properties map = new Properties ();
59104 map .setProperty ("log4j2.loggerContextFactory" , LocalLoggerContextFactory .class .getName ());
60105 final PropertiesUtil properties = new PropertiesUtil (map );
61- assertThat (ProviderUtil .selectProvider (properties ).getLoggerContextFactory ())
106+ assertThat (ProviderUtil .selectProvider (properties , TWO_PROVIDERS , statusLogger )
107+ .getLoggerContextFactory ())
62108 .as ("check selected logger context factory" )
63109 .isInstanceOf (LocalLoggerContextFactory .class );
110+ // Deprecation warning
111+ assertHasErrorOrWarning (statusLogger );
112+ }
113+
114+ /**
115+ * Can be removed in the future.
116+ */
117+ @ Test
118+ void log4j_provider_property_has_priority () {
119+ final Properties map = new Properties ();
120+ map .setProperty ("log4j.provider" , LocalProvider .class .getName ());
121+ map .setProperty ("log4j2.loggerContextFactory" , TestLoggerContextFactory .class .getName ());
122+ final PropertiesUtil properties = new PropertiesUtil (map );
123+ assertThat (ProviderUtil .selectProvider (properties , TWO_PROVIDERS , statusLogger ))
124+ .as ("check selected provider" )
125+ .isInstanceOf (LocalProvider .class );
126+ // Warning
127+ assertHasErrorOrWarning (statusLogger );
128+ }
129+
130+ static Stream <Arguments > incorrect_configuration_do_not_throw () {
131+ return Stream .of (
132+ Arguments .of ("java.lang.String" , null ),
133+ Arguments .of ("non.existent.Provider" , null ),
134+ // logger context factory without a matching provider
135+ Arguments .of (null , "org.apache.logging.log4j.util.ProviderUtilTest$LocalLoggerContextFactory" ),
136+ Arguments .of (null , "java.lang.String" ),
137+ Arguments .of (null , "non.existent.LoggerContextFactory" ));
138+ }
139+
140+ @ ParameterizedTest
141+ @ MethodSource
142+ void incorrect_configuration_do_not_throw (final String provider , final String contextFactory ) {
143+ final Properties map = new Properties ();
144+ if (provider != null ) {
145+ map .setProperty ("log4j.provider" , provider );
146+ }
147+ if (contextFactory != null ) {
148+ map .setProperty ("log4j2.loggerContextFactory" , contextFactory );
149+ }
150+ final PropertiesUtil properties = new PropertiesUtil (map );
151+ assertThat (ProviderUtil .selectProvider (properties , ONE_PROVIDER , statusLogger ))
152+ .as ("check selected provider" )
153+ .isNotNull ();
154+ // Warnings will be present
155+ assertHasErrorOrWarning (statusLogger );
64156 }
65157
66158 public static class LocalLoggerContextFactory extends TestLoggerContextFactory {}
@@ -73,4 +165,14 @@ public LocalProvider() {
73165 super (0 , CURRENT_VERSION , LocalLoggerContextFactory .class );
74166 }
75167 }
168+
169+ private void assertHasErrorOrWarning (final TestLogger statusLogger ) {
170+ assertThat (statusLogger .getEntries ()).as ("check StatusLogger entries" ).anySatisfy (entry -> assertThat (entry )
171+ .matches (ERROR_OR_WARNING ));
172+ }
173+
174+ private void assertNoErrorsOrWarnings (final TestLogger statusLogger ) {
175+ assertThat (statusLogger .getEntries ()).as ("check StatusLogger entries" ).allSatisfy (entry -> assertThat (entry )
176+ .doesNotMatch (ERROR_OR_WARNING ));
177+ }
76178}
0 commit comments