View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.util;
15  
16  import static org.junit.Assert.assertEquals;
17  import static org.junit.Assert.assertNotNull;
18  import static org.junit.Assert.assertNull;
19  import static org.junit.Assert.assertSame;
20  import static org.junit.Assert.assertTrue;
21  import static org.junit.Assert.fail;
22  import static org.junit.Assume.assumeTrue;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.MalformedURLException;
27  import java.net.URL;
28  import java.util.Enumeration;
29  import java.util.List;
30  import java.util.Vector;
31  
32  import org.junit.After;
33  import org.junit.Before;
34  import org.junit.Ignore;
35  import org.junit.Test;
36  
37  import ch.qos.logback.classic.ClassicConstants;
38  import ch.qos.logback.classic.ClassicTestConstants;
39  import ch.qos.logback.classic.Logger;
40  import ch.qos.logback.classic.LoggerContext;
41  import ch.qos.logback.classic.spi.ILoggingEvent;
42  import ch.qos.logback.core.Appender;
43  import ch.qos.logback.core.ConsoleAppender;
44  import ch.qos.logback.core.CoreConstants;
45  import ch.qos.logback.core.LogbackException;
46  import ch.qos.logback.core.joran.spi.JoranException;
47  import ch.qos.logback.core.status.StatusListener;
48  import ch.qos.logback.core.testUtil.TrivialStatusListener;
49  import ch.qos.logback.core.util.Loader;
50  
51  public class ContextInitializerTest {
52  
53      LoggerContext loggerContext = new LoggerContext();
54      Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
55  
56      @Before
57      public void setUp() throws Exception {
58      }
59  
60      @After
61      public void tearDown() throws Exception {
62          System.clearProperty(ClassicConstants.CONFIG_FILE_PROPERTY);
63          System.clearProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY);
64          MockConfigurator.context = null;
65      }
66  
67      @Test
68      @Ignore
69      // this test works only if logback-test.xml or logback.xml files are on the classpath.
70      // However, this is something we try to avoid in order to simplify the life
71      // of users trying to follow the manual and logback-examples from an IDE
72      public void reset() throws JoranException {
73          {
74              new ContextInitializer(loggerContext).autoConfig();
75              Appender<ILoggingEvent> appender = root.getAppender("STDOUT");
76              assertNotNull(appender);
77              assertTrue(appender instanceof ConsoleAppender);
78          }
79          {
80              loggerContext.stop();
81              Appender<ILoggingEvent> appender = root.getAppender("STDOUT");
82              assertNull(appender);
83          }
84      }
85  
86      @Test
87      public void autoConfigFromSystemProperties() throws JoranException {
88          doAutoConfigFromSystemProperties(ClassicTestConstants.INPUT_PREFIX + "autoConfig.xml");
89          doAutoConfigFromSystemProperties("autoConfigAsResource.xml");
90          // test passing a URL. note the relative path syntax with file:src/test/...
91          doAutoConfigFromSystemProperties("file:" + ClassicTestConstants.INPUT_PREFIX + "autoConfig.xml");
92      }
93  
94      public void doAutoConfigFromSystemProperties(String val) throws JoranException {
95          // lc.reset();
96          System.setProperty(ClassicConstants.CONFIG_FILE_PROPERTY, val);
97          new ContextInitializer(loggerContext).autoConfig();
98          Appender<ILoggingEvent> appender = root.getAppender("AUTO_BY_SYSTEM_PROPERTY");
99          assertNotNull(appender);
100     }
101 
102     @Test
103     public void autoConfigFromServiceLoaderJDK6andAbove() throws Exception {
104         assumeTrue(!isJDK5());
105         setupMockServiceLoader();
106         assertNull(MockConfigurator.context);
107         new ContextInitializer(loggerContext).autoConfig();
108         assertNotNull(MockConfigurator.context);
109         assertSame(loggerContext, MockConfigurator.context);
110     }
111 
112     @Test
113     public void autoConfigFromServiceLoaderJDK5() throws Exception {
114         assumeTrue(isJDK5());
115         setupMockServiceLoader();
116         assertNull(MockConfigurator.context);
117         new ContextInitializer(loggerContext).autoConfig();
118         assertNull(MockConfigurator.context);
119     }
120 
121     @Test
122     public void autoStatusListener() throws JoranException {
123         System.setProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY, TrivialStatusListener.class.getName());
124         List<StatusListener> statusListenerList = loggerContext.getStatusManager().getCopyOfStatusListenerList();
125         assertEquals(0, statusListenerList.size());
126         doAutoConfigFromSystemProperties(ClassicTestConstants.INPUT_PREFIX + "autoConfig.xml");
127         statusListenerList = loggerContext.getStatusManager().getCopyOfStatusListenerList();
128         assertTrue(statusListenerList.size() + " should be 1", statusListenerList.size() == 1);
129         // LOGBACK-767
130         TrivialStatusListener tsl = (TrivialStatusListener) statusListenerList.get(0);
131         assertTrue("expecting at least one event in list", tsl.list.size() > 0);
132     }
133 
134     @Test
135     public void autoOnConsoleStatusListener() throws JoranException {
136         System.setProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY, CoreConstants.SYSOUT);
137         List<StatusListener> sll = loggerContext.getStatusManager().getCopyOfStatusListenerList();
138         assertEquals(0, sll.size());
139         doAutoConfigFromSystemProperties(ClassicTestConstants.INPUT_PREFIX + "autoConfig.xml");
140         sll = loggerContext.getStatusManager().getCopyOfStatusListenerList();
141         assertTrue(sll.size() + " should be 1", sll.size() == 1);
142     }
143 
144     @Test
145     public void shouldConfigureFromXmlFile() throws MalformedURLException, JoranException {
146         LoggerContext loggerContext = new LoggerContext();
147         ContextInitializer initializer = new ContextInitializer(loggerContext);
148         assertNull(loggerContext.getObject(CoreConstants.SAFE_JORAN_CONFIGURATION));
149 
150         URL configurationFileUrl = Loader.getResource("BOO_logback-test.xml", Thread.currentThread().getContextClassLoader());
151         initializer.configureByResource(configurationFileUrl);
152 
153         assertNotNull(loggerContext.getObject(CoreConstants.SAFE_JORAN_CONFIGURATION));
154     }
155 
156 //    @Test
157 //    public void shouldConfigureFromGroovyScript() throws MalformedURLException, JoranException {
158 //        LoggerContext loggerContext = new LoggerContext();
159 //        ContextInitializer initializer = new ContextInitializer(loggerContext);
160 //        assertNull(loggerContext.getObject(CoreConstants.CONFIGURATION_WATCH_LIST));
161 //
162 //        URL configurationFileUrl = Loader.getResource("test.groovy", Thread.currentThread().getContextClassLoader());
163 //        initializer.configureByResource(configurationFileUrl);
164 //
165 //        assertNotNull(loggerContext.getObject(CoreConstants.CONFIGURATION_WATCH_LIST));
166 //    }
167 
168     @Test
169     public void shouldThrowExceptionIfUnexpectedConfigurationFileExtension() throws JoranException {
170         LoggerContext loggerContext = new LoggerContext();
171         ContextInitializer initializer = new ContextInitializer(loggerContext);
172 
173         URL configurationFileUrl = Loader.getResource("README.txt", Thread.currentThread().getContextClassLoader());
174         try {
175             initializer.configureByResource(configurationFileUrl);
176             fail("Should throw LogbackException");
177         } catch (LogbackException expectedException) {
178             // pass
179         }
180     }
181 
182     private static boolean isJDK5() {
183         String ver = System.getProperty("java.version");
184         boolean jdk5 = ver.startsWith("1.5.") || ver.equals("1.5");
185         return jdk5;
186     }
187 
188     private void setupMockServiceLoader() {
189         final ClassLoader realLoader = EnvUtil.class.getClassLoader();
190         EnvUtil.testServiceLoaderClassLoader = new WrappedClassLoader(realLoader) {
191 
192             @Override
193             public Enumeration<URL> getResources(String name) throws IOException {
194                 final Enumeration<URL> r;
195                 if (name.endsWith("META-INF/services/ch.qos.logback.classic.spi.Configurator")) {
196                     Vector<URL> vs = new Vector<URL>();
197                     URL u = super.getResource("FAKE_META_INF_SERVICES_ch_qos_logback_classic_spi_Configurator");
198                     vs.add(u);
199                     return vs.elements();
200                 } else {
201                     r = super.getResources(name);
202                 }
203                 return r;
204             }
205         };
206     }
207 
208     static class WrappedClassLoader extends ClassLoader {
209         final ClassLoader delegate;
210 
211         public WrappedClassLoader(ClassLoader delegate) {
212             super();
213             this.delegate = delegate;
214         }
215 
216         public Class<?> loadClass(String name) throws ClassNotFoundException {
217             return delegate.loadClass(name);
218         }
219 
220         public URL getResource(String name) {
221             return delegate.getResource(name);
222         }
223 
224         public Enumeration<URL> getResources(String name) throws IOException {
225             return delegate.getResources(name);
226         }
227 
228         public InputStream getResourceAsStream(String name) {
229             return delegate.getResourceAsStream(name);
230         }
231 
232         public void setDefaultAssertionStatus(boolean enabled) {
233             delegate.setDefaultAssertionStatus(enabled);
234         }
235 
236         public void setPackageAssertionStatus(String packageName, boolean enabled) {
237             delegate.setPackageAssertionStatus(packageName, enabled);
238         }
239 
240         public void setClassAssertionStatus(String className, boolean enabled) {
241             delegate.setClassAssertionStatus(className, enabled);
242         }
243 
244         public void clearAssertionStatus() {
245             delegate.clearAssertionStatus();
246         }
247     }
248 
249 }