View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.rolling.testUtil;
15  
16  import ch.qos.logback.core.Context;
17  import ch.qos.logback.core.ContextBase;
18  import ch.qos.logback.core.encoder.EchoEncoder;
19  import ch.qos.logback.core.rolling.helper.FileFilterUtil;
20  import ch.qos.logback.core.rolling.helper.FileNamePattern;
21  import ch.qos.logback.core.testUtil.CoreTestConstants;
22  import ch.qos.logback.core.testUtil.FileToBufferUtil;
23  import ch.qos.logback.core.testUtil.RandomUtil;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.sql.Date;
28  import java.text.SimpleDateFormat;
29  import java.util.ArrayList;
30  import java.util.Calendar;
31  import java.util.Enumeration;
32  import java.util.List;
33  import java.util.concurrent.Future;
34  import java.util.concurrent.TimeUnit;
35  import java.util.zip.ZipEntry;
36  import java.util.zip.ZipFile;
37  
38  import static org.junit.Assert.assertEquals;
39  import static org.junit.Assert.assertTrue;
40  
41  /**
42   * Scaffolding for various rolling tests. Some assumptions are made: - rollover
43   * periodicity is 1 second (without precluding size based roll-over)
44   *
45   * @author Ceki Gülcü
46   */
47  public class ScaffoldingForRollingTests {
48  
49      static public final String DATE_PATTERN_WITH_SECONDS = "yyyy-MM-dd_HH_mm_ss";
50      static public final String DATE_PATTERN_BY_DAY = "yyyy-MM-dd";
51      static public final SimpleDateFormat SDF = new SimpleDateFormat(DATE_PATTERN_WITH_SECONDS);
52  
53      int diff = RandomUtil.getPositiveInt();
54      protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/";
55      protected EchoEncoder<Object> encoder = new EchoEncoder<Object>();
56      protected Context context = new ContextBase();
57      protected List<String> expectedFilenameList = new ArrayList<String>();
58      protected long nextRolloverThreshold; // initialized in setUp()
59      protected long currentTime; // initialized in setUp()
60      protected List<Future<?>> futureList = new ArrayList<Future<?>>();
61  
62      Calendar calendar = Calendar.getInstance();
63  
64      public void setUp() {
65          context.setName("test");
66          calendar.set(Calendar.MILLISECOND, 333);
67          currentTime = calendar.getTimeInMillis();
68          recomputeRolloverThreshold(currentTime);
69      }
70  
71      public static void existenceCheck(String filename) {
72          assertTrue("File " + filename + " does not exist", new File(filename).exists());
73      }
74  
75      public static File[] getFilesInDirectory(String outputDirStr) {
76          File outputDir = new File(outputDirStr);
77          return outputDir.listFiles();
78      }
79  
80      public static void fileContentCheck(File[] fileArray, int runLength, String prefix) throws IOException {
81          fileContentCheck(fileArray, runLength, prefix, 0);
82      }
83  
84      public static void fileContentCheck(File[] fileArray, int runLength, String prefix, int runStart) throws IOException {
85          List<String> stringList = new ArrayList<String>();
86          for (File file : fileArray) {
87              FileToBufferUtil.readIntoList(file, stringList);
88          }
89  
90          List<String> witnessList = new ArrayList<String>();
91  
92          for (int i = runStart; i < runLength; i++) {
93              witnessList.add(prefix + i);
94          }
95          assertEquals(witnessList, stringList);
96      }
97  
98      public static void sortedContentCheck(String outputDirStr, int runLength, String prefix) throws IOException {
99          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 }