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.core.joran.action; 015 016import static org.junit.Assert.assertEquals; 017import static org.junit.Assert.assertTrue; 018 019import java.io.File; 020import java.io.FileInputStream; 021import java.io.FileOutputStream; 022import java.io.IOException; 023import java.net.MalformedURLException; 024import java.util.Arrays; 025import java.util.HashMap; 026import java.util.Stack; 027 028import org.junit.After; 029import org.junit.Before; 030import org.junit.Test; 031import org.xml.sax.SAXParseException; 032 033import ch.qos.logback.core.Context; 034import ch.qos.logback.core.ContextBase; 035import ch.qos.logback.core.joran.TrivialConfigurator; 036import ch.qos.logback.core.joran.action.ext.StackAction; 037import ch.qos.logback.core.joran.spi.ElementSelector; 038import ch.qos.logback.core.joran.spi.JoranException; 039import ch.qos.logback.core.status.Status; 040import ch.qos.logback.core.testUtil.CoreTestConstants; 041import ch.qos.logback.core.testUtil.FileTestUtil; 042import ch.qos.logback.core.testUtil.RandomUtil; 043import ch.qos.logback.core.testUtil.StatusChecker; 044import ch.qos.logback.core.util.StatusPrinter; 045 046public class IncludeActionTest { 047 048 final static String INCLUDE_KEY = "includeKey"; 049 final static String SUB_FILE_KEY = "subFileKey"; 050 final static String SECOND_FILE_KEY = "secondFileKey"; 051 052 Context context = new ContextBase(); 053 StatusChecker statusChecker = new StatusChecker(context); 054 TrivialConfigurator tc; 055 056 static final String INCLUSION_DIR_PREFIX = CoreTestConstants.JORAN_INPUT_PREFIX + "inclusion/"; 057 058 static final String TOP_BY_FILE = INCLUSION_DIR_PREFIX + "topByFile.xml"; 059 060 static final String TOP_OPTIONAL = INCLUSION_DIR_PREFIX + "topOptional.xml"; 061 062 static final String TOP_OPTIONAL_RESOURCE = INCLUSION_DIR_PREFIX + "topOptionalResource.xml"; 063 064 static final String INTERMEDIARY_FILE = INCLUSION_DIR_PREFIX + "intermediaryByFile.xml"; 065 066 static final String SUB_FILE = INCLUSION_DIR_PREFIX + "subByFile.xml"; 067 068 static final String MULTI_INCLUDE_BY_FILE = INCLUSION_DIR_PREFIX + "multiIncludeByFile.xml"; 069 070 static final String SECOND_FILE = INCLUSION_DIR_PREFIX + "second.xml"; 071 072 static final String TOP_BY_URL = INCLUSION_DIR_PREFIX + "topByUrl.xml"; 073 074 static final String TOP_BY_ENTITY = INCLUSION_DIR_PREFIX + "topByEntity.xml"; 075 076 static final String INCLUDE_BY_RESOURCE = INCLUSION_DIR_PREFIX + "topByResource.xml"; 077 078 static final String INCLUDED_FILE = INCLUSION_DIR_PREFIX + "included.xml"; 079 static final String URL_TO_INCLUDE = "file:./" + INCLUDED_FILE; 080 081 static final String INVALID = INCLUSION_DIR_PREFIX + "invalid.xml"; 082 083 static final String INCLUDED_AS_RESOURCE = "asResource/joran/inclusion/includedAsResource.xml"; 084 085 int diff = RandomUtil.getPositiveInt(); 086 087 StackAction stackAction = new StackAction(); 088 089 @Before 090 public void setUp() throws Exception { 091 FileTestUtil.makeTestOutputDir(); 092 HashMap<ElementSelector, Action> rulesMap = new HashMap<ElementSelector, Action>(); 093 rulesMap.put(new ElementSelector("x"), new NOPAction()); 094 rulesMap.put(new ElementSelector("x/include"), new IncludeAction()); 095 rulesMap.put(new ElementSelector("x/stack"), stackAction); 096 097 tc = new TrivialConfigurator(rulesMap); 098 tc.setContext(context); 099 } 100 101 @After 102 public void tearDown() throws Exception { 103 StatusPrinter.printInCaseOfErrorsOrWarnings(context); 104 context = null; 105 System.clearProperty(INCLUDE_KEY); 106 System.clearProperty(SECOND_FILE_KEY); 107 System.clearProperty(SUB_FILE_KEY); 108 // StackAction.reset(); 109 } 110 111 @Test 112 public void basicFile() throws JoranException { 113 System.setProperty(INCLUDE_KEY, INCLUDED_FILE); 114 tc.doConfigure(TOP_BY_FILE); 115 verifyConfig(new String[] { "IA", "IB" }); 116 } 117 118 @Test 119 public void optionalFile() throws JoranException { 120 tc.doConfigure(TOP_OPTIONAL); 121 verifyConfig(new String[] { "IA", "IB" }); 122 StatusPrinter.print(context); 123 } 124 125 @Test 126 public void optionalResource() throws JoranException { 127 tc.doConfigure(TOP_OPTIONAL_RESOURCE); 128 verifyConfig(new String[] { "IA", "IB" }); 129 StatusPrinter.print(context); 130 assertEquals(Status.INFO, statusChecker.getHighestLevel(0)); 131 } 132 133 @Test 134 public void basicResource() throws JoranException { 135 System.setProperty(INCLUDE_KEY, INCLUDED_AS_RESOURCE); 136 tc.doConfigure(INCLUDE_BY_RESOURCE); 137 verifyConfig(new String[] { "AR_A", "AR_B" }); 138 } 139 140 @Test 141 public void basicURL() throws JoranException { 142 System.setProperty(INCLUDE_KEY, URL_TO_INCLUDE); 143 tc.doConfigure(TOP_BY_URL); 144 verifyConfig(new String[] { "IA", "IB" }); 145 } 146 147 @Test 148 public void noFileFound() throws JoranException { 149 System.setProperty(INCLUDE_KEY, "toto"); 150 tc.doConfigure(TOP_BY_FILE); 151 assertEquals(Status.WARN, statusChecker.getHighestLevel(0)); 152 } 153 154 @Test 155 public void withCorruptFile() throws JoranException, IOException { 156 String tmpOut = copyToTemp(INVALID); 157 System.setProperty(INCLUDE_KEY, tmpOut); 158 tc.doConfigure(TOP_BY_FILE); 159 assertEquals(Status.ERROR, statusChecker.getHighestLevel(0)); 160 StatusPrinter.print(context); 161 assertTrue(statusChecker.containsException(SAXParseException.class)); 162 163 // we like to erase the temp file in order to see 164 // if http://jira.qos.ch/browse/LBCORE-122 was fixed 165 File f = new File(tmpOut); 166 assertTrue(f.exists()); 167 assertTrue(f.delete()); 168 169 } 170 171 String copyToTemp(String in) throws IOException { 172 FileInputStream fis = new FileInputStream(in); 173 String out = CoreTestConstants.OUTPUT_DIR_PREFIX + "out" + diff; 174 FileOutputStream fos = new FileOutputStream(out); 175 int b; 176 while ((b = fis.read()) != -1) { 177 fos.write(b); 178 } 179 fis.close(); 180 fos.close(); 181 return out; 182 } 183 184 @Test 185 public void malformedURL() throws JoranException { 186 System.setProperty(INCLUDE_KEY, "htp://logback.qos.ch"); 187 tc.doConfigure(TOP_BY_URL); 188 assertEquals(Status.ERROR, statusChecker.getHighestLevel(0)); 189 assertTrue(statusChecker.containsException(MalformedURLException.class)); 190 } 191 192 @Test 193 public void unknownURL() throws JoranException { 194 System.setProperty(INCLUDE_KEY, "http://logback2345.qos.ch"); 195 tc.doConfigure(TOP_BY_URL); 196 assertEquals(Status.WARN, statusChecker.getHighestLevel(0)); 197 } 198 199 @Test 200 public void nestedInclude() throws JoranException { 201 System.setProperty(SUB_FILE_KEY, SUB_FILE); 202 System.setProperty(INCLUDE_KEY, INTERMEDIARY_FILE); 203 tc.doConfigure(TOP_BY_FILE); 204 Stack<String> witness = new Stack<String>(); 205 witness.push("a"); 206 witness.push("b"); 207 witness.push("c"); 208 assertEquals(witness, stackAction.getStack()); 209 } 210 211 @Test 212 public void multiInclude() throws JoranException { 213 System.setProperty(INCLUDE_KEY, INCLUDED_FILE); 214 System.setProperty(SECOND_FILE_KEY, SECOND_FILE); 215 tc.doConfigure(MULTI_INCLUDE_BY_FILE); 216 verifyConfig(new String[] { "IA", "IB", "SECOND" }); 217 } 218 219 @Test 220 public void includeAsEntity() throws JoranException { 221 tc.doConfigure(TOP_BY_ENTITY); 222 verifyConfig(new String[] { "EA", "EB" }); 223 } 224 225 void verifyConfig(String[] expected) { 226 Stack<String> witness = new Stack<String>(); 227 witness.addAll(Arrays.asList(expected)); 228 assertEquals(witness, stackAction.getStack()); 229 } 230 231 232 233}