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.testUtil; 015 016import ch.qos.logback.core.Context; 017import ch.qos.logback.core.ContextBase; 018import ch.qos.logback.core.encoder.EchoEncoder; 019import ch.qos.logback.core.rolling.helper.FileFilterUtil; 020import ch.qos.logback.core.rolling.helper.FileNamePattern; 021import ch.qos.logback.core.testUtil.CoreTestConstants; 022import ch.qos.logback.core.testUtil.FileToBufferUtil; 023import ch.qos.logback.core.testUtil.RandomUtil; 024 025import java.io.File; 026import java.io.IOException; 027import java.sql.Date; 028import java.text.SimpleDateFormat; 029import java.util.ArrayList; 030import java.util.Calendar; 031import java.util.Enumeration; 032import java.util.List; 033import java.util.concurrent.Future; 034import java.util.concurrent.TimeUnit; 035import java.util.zip.ZipEntry; 036import java.util.zip.ZipFile; 037 038import static org.junit.Assert.assertEquals; 039import static org.junit.Assert.assertTrue; 040 041/** 042 * Scaffolding for various rolling tests. Some assumptions are made: - rollover 043 * periodicity is 1 second (without precluding size based roll-over) 044 * 045 * @author Ceki Gülcü 046 */ 047public class ScaffoldingForRollingTests { 048 049 static public final String DATE_PATTERN_WITH_SECONDS = "yyyy-MM-dd_HH_mm_ss"; 050 static public final String DATE_PATTERN_BY_DAY = "yyyy-MM-dd"; 051 static public final SimpleDateFormat SDF = new SimpleDateFormat(DATE_PATTERN_WITH_SECONDS); 052 053 int diff = RandomUtil.getPositiveInt(); 054 protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/"; 055 protected EchoEncoder<Object> encoder = new EchoEncoder<Object>(); 056 protected Context context = new ContextBase(); 057 protected List<String> expectedFilenameList = new ArrayList<String>(); 058 protected long nextRolloverThreshold; // initialized in setUp() 059 protected long currentTime; // initialized in setUp() 060 protected List<Future<?>> futureList = new ArrayList<Future<?>>(); 061 062 Calendar calendar = Calendar.getInstance(); 063 064 public void setUp() { 065 context.setName("test"); 066 calendar.set(Calendar.MILLISECOND, 333); 067 currentTime = calendar.getTimeInMillis(); 068 recomputeRolloverThreshold(currentTime); 069 } 070 071 public static void existenceCheck(String filename) { 072 assertTrue("File " + filename + " does not exist", new File(filename).exists()); 073 } 074 075 public static File[] getFilesInDirectory(String outputDirStr) { 076 File outputDir = new File(outputDirStr); 077 return outputDir.listFiles(); 078 } 079 080 public static void fileContentCheck(File[] fileArray, int runLength, String prefix) throws IOException { 081 fileContentCheck(fileArray, runLength, prefix, 0); 082 } 083 084 public static void fileContentCheck(File[] fileArray, int runLength, String prefix, int runStart) throws IOException { 085 List<String> stringList = new ArrayList<String>(); 086 for (File file : fileArray) { 087 FileToBufferUtil.readIntoList(file, stringList); 088 } 089 090 List<String> witnessList = new ArrayList<String>(); 091 092 for (int i = runStart; i < runLength; i++) { 093 witnessList.add(prefix + i); 094 } 095 assertEquals(witnessList, stringList); 096 } 097 098 public static void sortedContentCheck(String outputDirStr, int runLength, String prefix) throws IOException { 099 sortedContentCheck(outputDirStr, runLength, prefix, 0); 100 } 101 102 public static void sortedContentCheck(String outputDirStr, int runLength, String prefix, int runStart) throws IOException { 103 File[] fileArray = getFilesInDirectory(outputDirStr); 104 FileFilterUtil.sortFileArrayByName(fileArray); 105 fileContentCheck(fileArray, runLength, prefix, runStart); 106 } 107 108 public static void reverseSortedContentCheck(String outputDirStr, int runLength, String prefix) throws IOException { 109 File[] fileArray = getFilesInDirectory(outputDirStr); 110 FileFilterUtil.reverseSortFileArrayByName(fileArray); 111 fileContentCheck(fileArray, runLength, prefix); 112 } 113 114 public static void existenceCheck(List<String> filenameList) { 115 for (String filename : filenameList) { 116 assertTrue("File " + filename + " does not exist", new File(filename).exists()); 117 } 118 } 119 120 public static int existenceCount(List<String> filenameList) { 121 int existenceCounter = 0; 122 for (String filename : filenameList) { 123 if (new File(filename).exists()) { 124 existenceCounter++; 125 } 126 } 127 return existenceCounter; 128 } 129 130 protected String testId2FileName(String testId) { 131 return randomOutputDir + testId + ".log"; 132 } 133 134 // assuming rollover every second 135 protected void recomputeRolloverThreshold(long ct) { 136 long delta = ct % 1000; 137 nextRolloverThreshold = (ct - delta) + 1000; 138 } 139 140 protected boolean passThresholdTime(long nextRolloverThreshold) { 141 return currentTime >= nextRolloverThreshold; 142 } 143 144 protected void incCurrentTime(long increment) { 145 currentTime += increment; 146 } 147 148 protected Date getDateOfCurrentPeriodsStart() { 149 long delta = currentTime % 1000; 150 return new Date(currentTime - delta); 151 } 152 153 protected Date getDateOfPreviousPeriodsStart() { 154 long delta = currentTime % 1000; 155 return new Date(currentTime - delta - 1000); 156 } 157 158 protected long getMillisOfCurrentPeriodsStart() { 159 long delta = currentTime % 1000; 160 return (currentTime - delta); 161 } 162 163 protected void addExpectedFileName_ByDate(String patternStr, long millis) { 164 FileNamePattern fileNamePattern = new FileNamePattern(patternStr, context); 165 String fn = fileNamePattern.convert(new Date(millis)); 166 expectedFilenameList.add(fn); 167 } 168 169 protected void addExpectedFileNamedIfItsTime_ByDate(String fileNamePatternStr) { 170 if (passThresholdTime(nextRolloverThreshold)) { 171 addExpectedFileName_ByDate(fileNamePatternStr, getMillisOfCurrentPeriodsStart()); 172 recomputeRolloverThreshold(currentTime); 173 } 174 } 175 176 protected void addExpectedFileName_ByDate(String outputDir, String testId, Date date, boolean gzExtension) { 177 178 String fn = outputDir + testId + "-" + SDF.format(date); 179 if (gzExtension) { 180 fn += ".gz"; 181 } 182 expectedFilenameList.add(fn); 183 } 184 185 protected void addExpectedFileName_ByFileIndexCounter(String randomOutputDir, String testId, long millis, int fileIndexCounter, String compressionSuffix) { 186 String fn = randomOutputDir + testId + "-" + SDF.format(millis) + "-" + fileIndexCounter + ".txt" + compressionSuffix; 187 expectedFilenameList.add(fn); 188 } 189 190 protected List<String> filterElementsInListBySuffix(String suffix) { 191 List<String> zipFiles = new ArrayList<String>(); 192 for (String filename : expectedFilenameList) { 193 if (filename.endsWith(suffix)) 194 zipFiles.add(filename); 195 } 196 return zipFiles; 197 } 198 199 protected void addExpectedFileNamedIfItsTime_ByDate(String outputDir, String testId, boolean gzExtension) { 200 if (passThresholdTime(nextRolloverThreshold)) { 201 addExpectedFileName_ByDate(outputDir, testId, getDateOfCurrentPeriodsStart(), gzExtension); 202 recomputeRolloverThreshold(currentTime); 203 } 204 } 205 206 protected void massageExpectedFilesToCorresponToCurrentTarget(String fileName, boolean fileOptionIsSet) { 207 int lastIndex = expectedFilenameList.size() - 1; 208 String last = expectedFilenameList.remove(lastIndex); 209 210 if (fileOptionIsSet) { 211 expectedFilenameList.add(fileName); 212 } else if (last.endsWith(".gz")) { 213 int lastLen = last.length(); 214 String stem = last.substring(0, lastLen - 3); 215 expectedFilenameList.add(stem); 216 } 217 } 218 219 String addGZIfNotLast(int i) { 220 int lastIndex = expectedFilenameList.size() - 1; 221 if (i != lastIndex) { 222 return ".gz"; 223 } else { 224 return ""; 225 } 226 } 227 228 protected void zipEntryNameCheck(List<String> expectedFilenameList, String pattern) throws IOException { 229 for (String filepath : expectedFilenameList) { 230 checkZipEntryName(filepath, pattern); 231 } 232 } 233 234 protected void checkZipEntryMatchesZipFilename(List<String> expectedFilenameList) throws IOException { 235 for (String filepath : expectedFilenameList) { 236 String stripped = stripStemFromZipFilename(filepath); 237 checkZipEntryName(filepath, stripped); 238 } 239 } 240 241 String stripStemFromZipFilename(String filepath) { 242 File filepathAsFile = new File(filepath); 243 String stem = filepathAsFile.getName(); 244 int stemLen = stem.length(); 245 return stem.substring(0, stemLen - ".zip".length()); 246 247 } 248 249 void checkZipEntryName(String filepath, String pattern) throws IOException { 250 System.out.println("Checking [" + filepath + "]"); 251 ZipFile zf = new ZipFile(filepath); 252 253 try { 254 Enumeration<? extends ZipEntry> entries = zf.entries(); 255 assert ((entries.hasMoreElements())); 256 ZipEntry firstZipEntry = entries.nextElement(); 257 assert ((!entries.hasMoreElements())); 258 System.out.println("Testing zip entry [" + firstZipEntry.getName() + "]"); 259 assertTrue(firstZipEntry.getName().matches(pattern)); 260 } finally { 261 if (zf != null) 262 zf.close(); 263 } 264 } 265 266 protected void add(Future<?> future) { 267 if (future == null) 268 return; 269 if (!futureList.contains(future)) { 270 futureList.add(future); 271 } 272 } 273 274 protected void waitForJobsToComplete() { 275 for (Future<?> future : futureList) { 276 try { 277 future.get(10, TimeUnit.SECONDS); 278 } catch (Exception e) { 279 new RuntimeException("unexpected exception while testing", e); 280 } 281 } 282 futureList.clear(); 283 } 284}