001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic.util; 015 016import static org.junit.Assert.assertEquals; 017import static org.junit.Assert.assertNotNull; 018import static org.junit.Assert.assertNull; 019import static org.junit.Assert.assertSame; 020import static org.junit.Assert.assertTrue; 021import static org.junit.Assert.fail; 022import static org.junit.Assume.assumeTrue; 023 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.MalformedURLException; 027import java.net.URL; 028import java.util.Enumeration; 029import java.util.List; 030import java.util.Vector; 031 032import org.junit.After; 033import org.junit.Before; 034import org.junit.Ignore; 035import org.junit.Test; 036 037import ch.qos.logback.classic.ClassicConstants; 038import ch.qos.logback.classic.ClassicTestConstants; 039import ch.qos.logback.classic.Logger; 040import ch.qos.logback.classic.LoggerContext; 041import ch.qos.logback.classic.spi.ILoggingEvent; 042import ch.qos.logback.core.Appender; 043import ch.qos.logback.core.ConsoleAppender; 044import ch.qos.logback.core.CoreConstants; 045import ch.qos.logback.core.LogbackException; 046import ch.qos.logback.core.joran.spi.JoranException; 047import ch.qos.logback.core.status.StatusListener; 048import ch.qos.logback.core.testUtil.TrivialStatusListener; 049import ch.qos.logback.core.util.Loader; 050 051public class ContextInitializerTest { 052 053 LoggerContext loggerContext = new LoggerContext(); 054 Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); 055 056 @Before 057 public void setUp() throws Exception { 058 } 059 060 @After 061 public void tearDown() throws Exception { 062 System.clearProperty(ClassicConstants.CONFIG_FILE_PROPERTY); 063 System.clearProperty(CoreConstants.STATUS_LISTENER_CLASS_KEY); 064 MockConfigurator.context = null; 065 } 066 067 @Test 068 @Ignore 069 // this test works only if logback-test.xml or logback.xml files are on the classpath. 070 // However, this is something we try to avoid in order to simplify the life 071 // of users trying to follow the manual and logback-examples from an IDE 072 public void reset() throws JoranException { 073 { 074 new ContextInitializer(loggerContext).autoConfig(); 075 Appender<ILoggingEvent> appender = root.getAppender("STDOUT"); 076 assertNotNull(appender); 077 assertTrue(appender instanceof ConsoleAppender); 078 } 079 { 080 loggerContext.stop(); 081 Appender<ILoggingEvent> appender = root.getAppender("STDOUT"); 082 assertNull(appender); 083 } 084 } 085 086 @Test 087 public void autoConfigFromSystemProperties() throws JoranException { 088 doAutoConfigFromSystemProperties(ClassicTestConstants.INPUT_PREFIX + "autoConfig.xml"); 089 doAutoConfigFromSystemProperties("autoConfigAsResource.xml"); 090 // test passing a URL. note the relative path syntax with file:src/test/... 091 doAutoConfigFromSystemProperties("file:" + ClassicTestConstants.INPUT_PREFIX + "autoConfig.xml"); 092 } 093 094 public void doAutoConfigFromSystemProperties(String val) throws JoranException { 095 // lc.reset(); 096 System.setProperty(ClassicConstants.CONFIG_FILE_PROPERTY, val); 097 new ContextInitializer(loggerContext).autoConfig(); 098 Appender<ILoggingEvent> appender = root.getAppender("AUTO_BY_SYSTEM_PROPERTY"); 099 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}