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}