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}