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.assertFalse;
017
018import java.io.File;
019import java.io.IOException;
020import java.util.Date;
021import java.util.List;
022import java.util.concurrent.ExecutionException;
023
024import org.junit.Before;
025import org.junit.Test;
026
027import ch.qos.logback.core.encoder.EchoEncoder;
028import ch.qos.logback.core.rolling.testUtil.ScaffoldingForRollingTests;
029import ch.qos.logback.core.status.InfoStatus;
030import ch.qos.logback.core.status.StatusManager;
031import ch.qos.logback.core.testUtil.StatusChecker;
032import ch.qos.logback.core.util.FileSize;
033
034public class SizeAndTimeBasedFNATP_Test extends ScaffoldingForRollingTests {
035    private SizeAndTimeBasedFNATP<Object> sizeAndTimeBasedFNATP = null;
036    private RollingFileAppender<Object> rfa1 = new RollingFileAppender<Object>();
037    private TimeBasedRollingPolicy<Object> tbrp1 = new TimeBasedRollingPolicy<Object>();
038    private RollingFileAppender<Object> rfa2 = new RollingFileAppender<Object>();
039    private TimeBasedRollingPolicy<Object> tbrp2 = new TimeBasedRollingPolicy<Object>();
040
041    private EchoEncoder<Object> encoder = new EchoEncoder<Object>();
042    int fileSize = 0;
043    int fileIndexCounter = 0;
044    int sizeThreshold = 0;
045
046    @Before
047    public void setUp() {
048        super.setUp();
049    }
050
051    private void initRollingFileAppender(RollingFileAppender<Object> rfa, String filename) {
052        rfa.setContext(context);
053        rfa.setEncoder(encoder);
054        if (filename != null) {
055            rfa.setFile(filename);
056        }
057    }
058
059    private void initPolicies(RollingFileAppender<Object> rfa, TimeBasedRollingPolicy<Object> tbrp, String filenamePattern, int sizeThreshold, long givenTime,
060                    long lastCheck) {
061        sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP<Object>();
062        tbrp.setContext(context);
063        sizeAndTimeBasedFNATP.setMaxFileSize(new FileSize(sizeThreshold));
064        tbrp.setTimeBasedFileNamingAndTriggeringPolicy(sizeAndTimeBasedFNATP);
065        tbrp.setFileNamePattern(filenamePattern);
066        tbrp.setParent(rfa);
067        tbrp.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(givenTime);
068        rfa.setRollingPolicy(tbrp);
069        tbrp.start();
070        rfa.start();
071    }
072
073    private void addExpectedFileNamedIfItsTime(String randomOutputDir, String testId, String msg, String compressionSuffix) {
074        fileSize = fileSize + msg.getBytes().length;
075        if (passThresholdTime(nextRolloverThreshold)) {
076            fileIndexCounter = 0;
077            fileSize = 0;
078            addExpectedFileName_ByFileIndexCounter(randomOutputDir, testId, getMillisOfCurrentPeriodsStart(), fileIndexCounter, compressionSuffix);
079            recomputeRolloverThreshold(currentTime);
080            return;
081        }
082
083        // windows can delay file size changes, so we only allow for fileIndexCounter 0
084        if ((fileIndexCounter == 0) && fileSize > sizeThreshold) {
085            addExpectedFileName_ByFileIndexCounter(randomOutputDir, testId, getMillisOfCurrentPeriodsStart(), fileIndexCounter, compressionSuffix);
086            fileIndexCounter = fileIndexCounter + 1;
087            fileSize = 0;
088        }
089    }
090
091    void generic(String testId, String stem, boolean withSecondPhase, String compressionSuffix) throws IOException, InterruptedException, ExecutionException {
092        String file = (stem != null) ? randomOutputDir + stem : null;
093        initRollingFileAppender(rfa1, file);
094        sizeThreshold = 300;
095
096        initPolicies(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + DATE_PATTERN_WITH_SECONDS + "}-%i.txt" + compressionSuffix, sizeThreshold, currentTime, 0);
097        addExpectedFileName_ByFileIndexCounter(randomOutputDir, testId, getMillisOfCurrentPeriodsStart(), fileIndexCounter, compressionSuffix);
098        incCurrentTime(100);
099        tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime);
100        int runLength = 100;
101        String prefix = "Hello -----------------";
102
103        for (int i = 0; i < runLength; i++) {
104            String msg = prefix + i;
105            rfa1.doAppend(msg);
106            addExpectedFileNamedIfItsTime(randomOutputDir, testId, msg, compressionSuffix);
107            incCurrentTime(20);
108            tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime);
109            add(tbrp1.compressionFuture);
110            add(tbrp1.cleanUpFuture);
111        }
112
113        if (withSecondPhase) {
114            secondPhase(testId, file, stem, compressionSuffix, runLength, prefix);
115            runLength = runLength * 2;
116        }
117
118        if (stem != null)
119            massageExpectedFilesToCorresponToCurrentTarget(file, true);
120
121        Thread.yield();
122        // wait for compression to finish
123        waitForJobsToComplete();
124
125        // StatusPrinter.print(context);
126        existenceCheck(expectedFilenameList);
127        sortedContentCheck(randomOutputDir, runLength, prefix);
128    }
129
130    void secondPhase(String testId, String file, String stem, String compressionSuffix, int runLength, String prefix) {
131        rfa1.stop();
132
133        if (stem != null) {
134            File f = new File(file);
135            f.setLastModified(currentTime);
136        }
137
138        StatusManager sm = context.getStatusManager();
139        sm.add(new InfoStatus("Time when rfa1 is stopped: " + new Date(currentTime), this));
140        sm.add(new InfoStatus("currentTime%1000=" + (currentTime % 1000), this));
141
142        initRollingFileAppender(rfa2, file);
143        initPolicies(rfa2, tbrp2, randomOutputDir + testId + "-%d{" + DATE_PATTERN_WITH_SECONDS + "}-%i.txt" + compressionSuffix, sizeThreshold, currentTime, 0);
144
145        for (int i = runLength; i < runLength * 2; i++) {
146            incCurrentTime(100);
147            tbrp2.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime);
148            String msg = prefix + i;
149            rfa2.doAppend(msg);
150            addExpectedFileNamedIfItsTime(randomOutputDir, testId, msg, compressionSuffix);
151        }
152    }
153
154    static final boolean FIRST_PHASE_ONLY = false;
155    static final boolean WITH_SECOND_PHASE = true;
156    static final String DEFAULT_COMPRESSION_SUFFIX = "";
157
158    @Test
159    public void noCompression_FileSet_NoRestart_1() throws InterruptedException, ExecutionException, IOException {
160        generic("test1", "toto.log", FIRST_PHASE_ONLY, DEFAULT_COMPRESSION_SUFFIX);
161    }
162
163    @Test
164    public void noCompression_FileBlank_NoRestart_2() throws Exception {
165        generic("test2", null, FIRST_PHASE_ONLY, DEFAULT_COMPRESSION_SUFFIX);
166    }
167
168    @Test
169    public void noCompression_FileBlank_WithStopStart_3() throws Exception {
170        generic("test3", null, WITH_SECOND_PHASE, DEFAULT_COMPRESSION_SUFFIX); 
171    }
172
173    @Test
174    public void noCompression_FileSet_WithStopStart_4() throws Exception {
175        generic("test4", "test4.log", WITH_SECOND_PHASE, DEFAULT_COMPRESSION_SUFFIX);
176    }
177
178    @Test
179    public void withGZCompression_FileSet_NoRestart_5() throws Exception {
180        generic("test5", "toto.log", FIRST_PHASE_ONLY, ".gz");
181    }
182
183    @Test
184    public void withGZCompression_FileBlank_NoRestart_6() throws Exception {
185        generic("test6", null, FIRST_PHASE_ONLY, ".gz");
186    }
187
188    @Test
189    public void withZipCompression_FileSet_NoRestart_7() throws Exception {
190        generic("test7", "toto.log", FIRST_PHASE_ONLY, ".zip");
191        List<String> zipFiles = filterElementsInListBySuffix(".zip");
192        checkZipEntryMatchesZipFilename(zipFiles);
193    }
194
195    @Test
196    public void checkMissingIntToken() {
197        String stem = "toto.log";
198        String testId = "checkMissingIntToken";
199        String compressionSuffix = "gz";
200
201        String file = (stem != null) ? randomOutputDir + stem : null;
202        initRollingFileAppender(rfa1, file);
203        sizeThreshold = 300;
204        initPolicies(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + DATE_PATTERN_WITH_SECONDS + "}.txt" + compressionSuffix, sizeThreshold, currentTime, 0);
205
206        // StatusPrinter.print(context);
207        assertFalse(rfa1.isStarted());
208        StatusChecker checker = new StatusChecker(context);
209        checker.assertContainsMatch("Missing integer token");
210    }
211
212    @Test
213    public void checkDateCollision() {
214        String stem = "toto.log";
215        String testId = "checkDateCollision";
216        String compressionSuffix = "gz";
217
218        String file = (stem != null) ? randomOutputDir + stem : null;
219        initRollingFileAppender(rfa1, file);
220        sizeThreshold = 300;
221        initPolicies(rfa1, tbrp1, randomOutputDir + testId + "-%d{EE}.txt" + compressionSuffix, sizeThreshold, currentTime, 0);
222
223        // StatusPrinter.print(context);
224        assertFalse(rfa1.isStarted());
225        StatusChecker checker = new StatusChecker(context);
226        checker.assertContainsMatch("The date format in FileNamePattern");
227    }
228
229    // @Test
230    // public void testHistoryAsFileCount() throws IOException {
231    // String testId = "testHistoryAsFileCount";
232    // int maxHistory = 10;
233    // initRollingFileAppender(rfa1, randomOutputDir + "~" + testId);
234    // sizeThreshold = 50;
235    // System.out.println("testHistoryAsFileCount started on "+new Date(currentTime));
236    // initPolicies(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + DATE_PATTERN_WITH_SECONDS + "}-%i.txt",
237    // sizeThreshold, currentTime, 0, maxHistory, true);
238    //
239    // incCurrentTime(100);
240    // tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime);
241    // int runLength = 1000;
242    //
243    // for (int i = 0; i < runLength; i++) {
244    // String msg = "" + i;
245    // rfa1.doAppend(msg);
246    // incCurrentTime(20);
247    // tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime);
248    // add(tbrp1.future);
249    // }
250    //
251    // Thread.yield();
252    // // wait for compression to finish
253    // waitForJobsToComplete();
254    //
255    // assertEquals(maxHistory + 1, getFilesInDirectory(randomOutputDir).length);
256    // sortedContentCheck(randomOutputDir, 1000, "", 863);
257    // }
258}