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.rolling;
015
016import static org.junit.Assert.assertFalse;
017import static org.junit.Assert.assertTrue;
018
019import java.util.Date;
020
021import org.junit.After;
022import org.junit.Before;
023import org.junit.Test;
024
025import ch.qos.logback.classic.ClassicTestConstants;
026import ch.qos.logback.classic.Logger;
027import ch.qos.logback.classic.LoggerContext;
028import ch.qos.logback.classic.joran.JoranConfigurator;
029import ch.qos.logback.classic.spi.ILoggingEvent;
030import ch.qos.logback.core.CoreConstants;
031import ch.qos.logback.core.joran.spi.JoranException;
032import ch.qos.logback.core.rolling.RollingFileAppender;
033import ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicy;
034import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
035import ch.qos.logback.core.rolling.testUtil.ScaffoldingForRollingTests;
036import ch.qos.logback.core.status.Status;
037import ch.qos.logback.core.testUtil.StatusChecker;
038import ch.qos.logback.core.util.StatusPrinter;
039
040public class TimeBasedRollingWithConfigFileTest extends ScaffoldingForRollingTests {
041
042    LoggerContext lc = new LoggerContext();
043    StatusChecker statusChecker = new StatusChecker(lc);
044    Logger logger = lc.getLogger(this.getClass());
045    int fileSize = 0;
046    int fileIndexCounter = -1;
047    int sizeThreshold;
048
049    @Before
050    @Override
051    public void setUp() {
052        lc.setName("test");
053        super.setUp();
054        lc.putProperty("randomOutputDir", randomOutputDir);
055    }
056
057    @After
058    public void tearDown() throws Exception {
059    }
060
061    void loadConfig(String confifFile) throws JoranException {
062        JoranConfigurator jc = new JoranConfigurator();
063        jc.setContext(lc);
064        jc.doConfigure(confifFile);
065        currentTime = System.currentTimeMillis();
066        recomputeRolloverThreshold(currentTime);
067    }
068
069    @Test
070    public void basic() throws Exception {
071        String testId = "basic";
072        lc.putProperty("testId", testId);
073        loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
074        statusChecker.assertIsErrorFree();
075
076        Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
077
078        expectedFilenameList.add(randomOutputDir + "z" + testId);
079
080        RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
081
082        TimeBasedRollingPolicy<ILoggingEvent> tprp = (TimeBasedRollingPolicy<ILoggingEvent>) rfa.getTriggeringPolicy();
083        TimeBasedFileNamingAndTriggeringPolicy<ILoggingEvent> tbnatp = tprp.getTimeBasedFileNamingAndTriggeringPolicy();
084
085        String prefix = "Hello---";
086        int runLength = 4;
087        for (int i = 0; i < runLength; i++) {
088            logger.debug(prefix + i);
089            addExpectedFileNamedIfItsTime_ByDate(randomOutputDir, testId, false);
090            incCurrentTime(500);
091            tbnatp.setCurrentTime(currentTime);
092        }
093
094        existenceCheck(expectedFilenameList);
095        sortedContentCheck(randomOutputDir, runLength, prefix);
096    }
097
098    @Test
099    public void depratedSizeAndTimeBasedFNATPWarning() throws Exception {
100        String testId = "depratedSizeAndTimeBasedFNATPWarning";
101        lc.putProperty("testId", testId);
102        loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
103        StatusPrinter.print(lc);
104        statusChecker.assertContainsMatch(Status.WARN, CoreConstants.SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED);
105    }
106    
107    @Test
108    public void timeAndSize() throws Exception {
109        String testId = "timeAndSize";
110        lc.putProperty("testId", testId);
111        String prefix = "Hello-----";
112
113        // the number of times the log file will be written to before time based
114        // roll-over occurs
115        int approxWritesPerPeriod = 64;
116        sizeThreshold = prefix.length() * approxWritesPerPeriod;
117        lc.putProperty("sizeThreshold", "" + sizeThreshold);
118        loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
119        
120        StatusPrinter.print(lc);
121        // Test http://jira.qos.ch/browse/LOGBACK-1236
122        statusChecker.assertNoMatch(CoreConstants.SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED);
123        
124        Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
125
126        expectedFilenameList.add(randomOutputDir + "z" + testId);
127
128        RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
129
130        statusChecker.assertIsErrorFree();
131
132        TimeBasedRollingPolicy<ILoggingEvent> tprp = (TimeBasedRollingPolicy<ILoggingEvent>) rfa.getTriggeringPolicy();
133        TimeBasedFileNamingAndTriggeringPolicy<ILoggingEvent> tbnatp = tprp.getTimeBasedFileNamingAndTriggeringPolicy();
134
135        int timeIncrement = 1000 / approxWritesPerPeriod;
136        int runLength = approxWritesPerPeriod * 3;
137        for (int i = 0; i < runLength; i++) {
138            String msg = prefix + i;
139            logger.debug(msg);
140            addExpectedFileNamedIfItsTime(testId, msg, false);
141            incCurrentTime(timeIncrement);
142            tbnatp.setCurrentTime(currentTime);
143        }
144
145        sortedContentCheck(randomOutputDir, runLength, prefix);
146        int eCount = existenceCount(expectedFilenameList);
147        // for various reasons, it is extremely difficult to have the files
148        // match exactly the expected archive files. Thus, we aim for
149        // an approximate match
150        assertTrue("exitenceCount=" + eCount + ", expectedFilenameList.size=" + expectedFilenameList.size(),
151                        eCount >= 4 && eCount > expectedFilenameList.size() / 2);
152    }
153
154    @Test
155    public void timeAndSizeWithoutIntegerToken() throws Exception {
156        String testId = "timeAndSizeWithoutIntegerToken";
157        loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
158        Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
159        expectedFilenameList.add(randomOutputDir + "z" + testId);
160        RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
161        StatusPrinter.print(lc);
162
163        statusChecker.assertContainsMatch("Missing integer token");
164        assertFalse(rfa.isStarted());
165    }
166
167
168    // see also LOGBACK-1176
169    @Test
170    public void timeAndSizeWithoutMaxFileSize() throws Exception {
171        String testId = "timeAndSizeWithoutMaxFileSize";
172        loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
173        Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
174        //expectedFilenameList.add(randomOutputDir + "z" + testId);
175        RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
176      
177
178        //statusChecker.assertContainsMatch("Missing integer token");
179        assertFalse(rfa.isStarted());
180        StatusPrinter.print(lc);
181    }
182
183    @Test
184    public void totalSizeCapSmallerThanMaxFileSize() throws Exception {
185        String testId = "totalSizeCapSmallerThanMaxFileSize";
186        lc.putProperty("testId", testId);
187        loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
188        Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
189        //expectedFilenameList.add(randomOutputDir + "z" + testId);
190        RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
191      
192        statusChecker.assertContainsMatch("totalSizeCap of \\[\\d* \\w*\\] is smaller than maxFileSize \\[\\d* \\w*\\] which is non-sensical");
193        assertFalse(rfa.isStarted());
194      
195    }
196
197    void addExpectedFileNamedIfItsTime(String testId, String msg, boolean gzExtension) {
198        fileSize += msg.getBytes().length;
199
200        if (passThresholdTime(nextRolloverThreshold)) {
201            fileIndexCounter = 0;
202            fileSize = 0;
203            addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), fileIndexCounter, gzExtension);
204            recomputeRolloverThreshold(currentTime);
205            return;
206        }
207
208        // windows can delay file size changes, so we only allow for
209        // fileIndexCounter 0 and 1
210        if ((fileIndexCounter < 1) && fileSize > sizeThreshold) {
211            addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), ++fileIndexCounter, gzExtension);
212            fileSize = -1;
213            return;
214        }
215    }
216
217    void addExpectedFileName(String testId, Date date, int fileIndexCounter, boolean gzExtension) {
218
219        String fn = randomOutputDir + testId + "-" + SDF.format(date) + "." + fileIndexCounter;
220        System.out.println("Adding " + fn);
221        if (gzExtension) {
222            fn += ".gz";
223        }
224        expectedFilenameList.add(fn);
225    }
226
227    @Override
228    protected void addExpectedFileNamedIfItsTime_ByDate(String outputDir, String testId, boolean gzExtension) {
229        if (passThresholdTime(nextRolloverThreshold)) {
230            addExpectedFileName_ByDate(outputDir, testId, getDateOfPreviousPeriodsStart(), gzExtension);
231            recomputeRolloverThreshold(currentTime);
232        }
233    }
234}