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.rolling;
015
016import static org.junit.Assert.assertEquals;
017import static org.junit.Assert.assertFalse;
018import static org.junit.Assert.assertNull;
019import static org.junit.Assert.assertTrue;
020
021import org.junit.After;
022import org.junit.Before;
023import org.junit.Test;
024
025import ch.qos.logback.core.Appender;
026import ch.qos.logback.core.Context;
027import ch.qos.logback.core.ContextBase;
028import ch.qos.logback.core.appender.AbstractAppenderTest;
029import ch.qos.logback.core.encoder.DummyEncoder;
030import ch.qos.logback.core.status.Status;
031import ch.qos.logback.core.testUtil.CoreTestConstants;
032import ch.qos.logback.core.testUtil.RandomUtil;
033import ch.qos.logback.core.testUtil.StatusChecker;
034import ch.qos.logback.core.util.StatusPrinter;
035
036public class RollingFileAppenderTest extends AbstractAppenderTest<Object> {
037
038    RollingFileAppender<Object> rfa = new RollingFileAppender<Object>();
039    Context context = new ContextBase();
040
041    TimeBasedRollingPolicy<Object> tbrp = new TimeBasedRollingPolicy<Object>();
042    int diff = RandomUtil.getPositiveInt();
043    String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/";
044
045    @Before
046    public void setUp() throws Exception {
047        // noStartTest fails if the context is set in setUp
048        // rfa.setContext(context);
049
050        rfa.setEncoder(new DummyEncoder<Object>());
051        rfa.setName("test");
052        tbrp.setContext(context);
053        tbrp.setParent(rfa);
054    }
055
056    @After
057    public void tearDown() throws Exception {
058    }
059
060    @Override
061    protected Appender<Object> getAppender() {
062        return rfa;
063    }
064
065    @Override
066    protected Appender<Object> getConfiguredAppender() {
067        rfa.setContext(context);
068        tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log");
069        tbrp.start();
070        rfa.setRollingPolicy(tbrp);
071
072        rfa.start();
073        return rfa;
074    }
075
076    @Test
077    public void testPrudentModeLogicalImplications() {
078        rfa.setContext(context);
079        // prudent mode will force "file" property to be null
080        rfa.setFile("some non null value");
081        rfa.setAppend(false);
082        rfa.setPrudent(true);
083
084        tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log");
085        tbrp.start();
086        rfa.setRollingPolicy(tbrp);
087
088        rfa.start();
089
090        assertTrue(rfa.isAppend());
091        assertNull(rfa.rawFileProperty());
092        assertTrue(rfa.isStarted());
093    }
094
095    @Test
096    public void testPrudentModeLogicalImplicationsOnCompression() {
097        rfa.setContext(context);
098        rfa.setAppend(false);
099        rfa.setPrudent(true);
100
101        tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log.zip");
102        tbrp.start();
103        rfa.setRollingPolicy(tbrp);
104
105        rfa.start();
106
107        StatusChecker checker = new StatusChecker(context);
108        assertFalse(rfa.isStarted());
109        assertEquals(Status.ERROR, checker.getHighestLevel(0));
110    }
111
112    @Test
113    public void testFilePropertyAfterRollingPolicy() {
114        rfa.setContext(context);
115        rfa.setRollingPolicy(tbrp);
116        rfa.setFile("x");
117        StatusPrinter.print(context);
118        StatusChecker statusChecker = new StatusChecker(context.getStatusManager());
119        statusChecker.assertContainsMatch(Status.ERROR, "File property must be set before any triggeringPolicy ");
120    }
121
122    @Test
123    public void testFilePropertyAfterTriggeringPolicy() {
124        rfa.setContext(context);
125        rfa.setTriggeringPolicy(new SizeBasedTriggeringPolicy<Object>());
126        rfa.setFile("x");
127        StatusChecker statusChecker = new StatusChecker(context.getStatusManager());
128        statusChecker.assertContainsMatch(Status.ERROR, "File property must be set before any triggeringPolicy ");
129    }
130
131    @Test
132    public void testFileNameWithParenthesis() {
133        // if ')' is not escaped, the test throws
134        // java.lang.IllegalStateException: FileNamePattern [.../program(x86)/toto-%d.log] does not contain a valid
135        // DateToken
136        rfa.setContext(context);
137        tbrp.setFileNamePattern(randomOutputDir + "program(x86)/toto-%d.log");
138        tbrp.start();
139        rfa.setRollingPolicy(tbrp);
140        rfa.start();
141        rfa.doAppend("hello");
142    }
143
144    @Test
145    public void stopTimeBasedRollingPolicy() {
146        rfa.setContext(context);
147
148        tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log.zip");
149        tbrp.start();
150        rfa.setRollingPolicy(tbrp);
151        rfa.start();
152
153        StatusPrinter.print(context);
154        assertTrue(tbrp.isStarted());
155        assertTrue(rfa.isStarted());
156        rfa.stop();
157        assertFalse(rfa.isStarted());
158        assertFalse(tbrp.isStarted());
159
160    }
161
162    @Test
163    public void stopFixedWindowRollingPolicy() {
164        rfa.setContext(context);
165        rfa.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-.log");
166
167        FixedWindowRollingPolicy fwRollingPolicy = new FixedWindowRollingPolicy();
168        fwRollingPolicy.setContext(context);
169        fwRollingPolicy.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%i.log.zip");
170        fwRollingPolicy.setParent(rfa);
171        fwRollingPolicy.start();
172        SizeBasedTriggeringPolicy<Object> sbTriggeringPolicy = new SizeBasedTriggeringPolicy<Object>();
173        sbTriggeringPolicy.setContext(context);
174        sbTriggeringPolicy.start();
175
176        rfa.setRollingPolicy(fwRollingPolicy);
177        rfa.setTriggeringPolicy(sbTriggeringPolicy);
178
179        rfa.start();
180
181        StatusPrinter.print(context);
182        assertTrue(fwRollingPolicy.isStarted());
183        assertTrue(sbTriggeringPolicy.isStarted());
184        assertTrue(rfa.isStarted());
185        rfa.stop();
186        assertFalse(rfa.isStarted());
187        assertFalse(fwRollingPolicy.isStarted());
188        assertFalse(sbTriggeringPolicy.isStarted());
189
190    }
191
192    /**
193     * Test for http://jira.qos.ch/browse/LOGBACK-796
194     */
195    @Test
196    public void testFileShouldNotMatchFileNamePattern() {
197        rfa.setContext(context);
198        rfa.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX + "x-2013-04.log");
199        tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "x-%d{yyyy-MM}.log");
200        tbrp.start();
201
202        rfa.setRollingPolicy(tbrp);
203        rfa.start();
204        StatusChecker statusChecker = new StatusChecker(context);
205        final String msg = "File property collides with fileNamePattern. Aborting.";
206        boolean containsMatch = statusChecker.containsMatch(Status.ERROR, msg);
207        assertTrue("Missing error: " + msg, containsMatch);
208    }
209
210    @Test
211    public void collidingTimeformat() {
212        rfa.setContext(context);
213        rfa.setAppend(false);
214        rfa.setPrudent(true);
215
216        tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d{dd}.log.zip");
217        tbrp.start();
218        rfa.setRollingPolicy(tbrp);
219
220        rfa.start();
221
222        StatusChecker checker = new StatusChecker(context);
223        assertFalse(rfa.isStarted());
224        assertEquals(Status.ERROR, checker.getHighestLevel(0));
225        StatusPrinter.print(context);
226        checker.assertContainsMatch("The date format in FileNamePattern will result");
227    }
228
229    @Test
230    public void collidingFileNamePattern() {
231        String filenamePattern = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "-collision-%d.log.zip";
232
233        RollingFileAppender<Object> appender0 = new RollingFileAppender<Object>();
234        appender0.setName("FA0");
235        appender0.setContext(context);
236        appender0.setEncoder(new DummyEncoder<Object>());
237        TimeBasedRollingPolicy<Object> tbrp0 = new TimeBasedRollingPolicy<Object>();
238        tbrp0.setContext(context);
239        tbrp0.setFileNamePattern(filenamePattern);
240        tbrp0.setParent(appender0);
241        tbrp0.start();
242        appender0.setRollingPolicy(tbrp0);
243        appender0.start();
244        assertTrue(appender0.isStarted());
245
246        RollingFileAppender<Object> appender1 = new RollingFileAppender<Object>();
247        appender1.setName("FA1");
248        appender1.setFile("X");
249        appender1.setContext(context);
250        appender1.setEncoder(new DummyEncoder<Object>());
251        TimeBasedRollingPolicy<Object> tbrp1 = new TimeBasedRollingPolicy<Object>();
252        tbrp1.setContext(context);
253        tbrp1.setFileNamePattern(filenamePattern);
254        tbrp1.setParent(appender1);
255        tbrp1.start();
256        appender1.setRollingPolicy(tbrp1);
257        appender1.start();
258
259        // StatusPrinter.print(context);
260
261        assertFalse(appender1.isStarted());
262        StatusChecker checker = new StatusChecker(context);
263        checker.assertContainsMatch(Status.ERROR, "'FileNamePattern' option has the same value");
264    }
265    
266}