1
2
3
4
5
6
7
8
9
10
11
12
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.function.UnaryOperator;
36 import java.util.zip.ZipEntry;
37 import java.util.zip.ZipFile;
38
39 import static org.junit.jupiter.api.Assertions.assertEquals;
40 import static org.junit.jupiter.api.Assertions.assertTrue;
41
42
43
44
45
46
47
48 public class ScaffoldingForRollingTests {
49
50 static public final String DATE_PATTERN_WITH_SECONDS = "yyyy-MM-dd_HH_mm_ss";
51 static public final String DATE_PATTERN_BY_DAY = "yyyy-MM-dd";
52 static public final SimpleDateFormat SDF = new SimpleDateFormat(DATE_PATTERN_WITH_SECONDS);
53
54 int diff = RandomUtil.getPositiveInt();
55 protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/";
56 protected EchoEncoder<Object> encoder = new EchoEncoder<Object>();
57 protected Context context = new ContextBase();
58 protected List<String> expectedFilenameList = new ArrayList<String>();
59 protected long nextRolloverThreshold;
60 protected long currentTime;
61 protected List<Future<?>> futureList = new ArrayList<Future<?>>();
62
63 Calendar calendar = Calendar.getInstance();
64
65 public void setUp() {
66 context.setName("test");
67 calendar.set(Calendar.MILLISECOND, 333);
68 currentTime = calendar.getTimeInMillis();
69 recomputeRolloverThreshold(currentTime);
70 }
71
72 public static void existenceCheck(String filename) {
73 assertTrue(new File(filename).exists(), "File " + filename + " does not exist");
74 }
75
76 public static File[] getFilesInDirectory(String outputDirStr) {
77 File outputDir = new File(outputDirStr);
78 return outputDir.listFiles();
79 }
80
81 public static void fileContentCheck(File[] fileArray, int runLength, String prefix) throws IOException {
82 fileContentCheck(fileArray, runLength, prefix, 0);
83 }
84
85 public static void fileContentCheck(File[] fileArray, int runLength, String prefix, int runStart)
86 throws IOException {
87 List<String> stringList = new ArrayList<String>();
88 for (File file : fileArray) {
89 FileToBufferUtil.readIntoList(file, stringList);
90 }
91
92 List<String> witnessList = new ArrayList<String>();
93
94 for (int i = runStart; i < runLength; i++) {
95 witnessList.add(prefix + i);
96 }
97 assertEquals(witnessList, stringList);
98 }
99
100 public static void sortedContentCheck(String outputDirStr, int runLength, String prefix) throws IOException {
101 sortedContentCheck(outputDirStr, runLength, prefix, 0);
102 }
103
104 public static void sortedContentCheck(String outputDirStr, int runLength, String prefix, int runStart)
105 throws IOException {
106 File[] fileArray = getFilesInDirectory(outputDirStr);
107 FileFilterUtil.sortFileArrayByName(fileArray);
108 fileContentCheck(fileArray, runLength, prefix, runStart);
109 }
110
111 public static void reverseSortedContentCheck(String outputDirStr, int runLength, String prefix) throws IOException {
112 File[] fileArray = getFilesInDirectory(outputDirStr);
113 FileFilterUtil.reverseSortFileArrayByName(fileArray);
114 fileContentCheck(fileArray, runLength, prefix);
115 }
116
117 public static void existenceCheck(List<String> filenameList) {
118 for (String filename : filenameList) {
119 assertTrue(new File(filename).exists(), "File " + filename + " does not exist");
120 }
121 }
122
123 public static int existenceCount(List<String> filenameList) {
124 int existenceCounter = 0;
125 for (String filename : filenameList) {
126 if (new File(filename).exists()) {
127 existenceCounter++;
128 }
129 }
130 return existenceCounter;
131 }
132
133 protected String nullFileName(String testId) {
134 return null;
135 }
136
137 protected String impossibleFileName(String testId) {
138 throw new RuntimeException("implement");
139 }
140
141 protected String testId2FileName(String testId) {
142 return randomOutputDir + testId + ".log";
143 }
144
145
146 protected void recomputeRolloverThreshold(long ct) {
147 long delta = ct % 1000;
148 nextRolloverThreshold = (ct - delta) + 1000;
149 }
150
151 protected boolean passThresholdTime(long nextRolloverThreshold) {
152 return currentTime >= nextRolloverThreshold;
153 }
154
155 protected void incCurrentTime(long increment) {
156 currentTime += increment;
157 }
158
159 protected Date getDateOfCurrentPeriodsStart() {
160 long delta = currentTime % 1000;
161 return new Date(currentTime - delta);
162 }
163
164 protected Date getDateOfPreviousPeriodsStart() {
165 long delta = currentTime % 1000;
166 return new Date(currentTime - delta - 1000);
167 }
168
169 protected long getMillisOfCurrentPeriodsStart() {
170 long delta = currentTime % 1000;
171 return (currentTime - delta);
172 }
173
174 protected void addExpectedFileName_ByDate(String patternStr, long millis) {
175 FileNamePattern fileNamePattern = new FileNamePattern(patternStr, context);
176 String fn = fileNamePattern.convert(new Date(millis));
177 expectedFilenameList.add(fn);
178 }
179
180 protected void addExpectedFileNamedIfItsTime_ByDate(String fileNamePatternStr) {
181 if (passThresholdTime(nextRolloverThreshold)) {
182 addExpectedFileName_ByDate(fileNamePatternStr, getMillisOfCurrentPeriodsStart());
183 recomputeRolloverThreshold(currentTime);
184 }
185 }
186
187 protected void addExpectedFileName_ByDate(String outputDir, String testId, Date date, boolean gzExtension) {
188
189 String fn = outputDir + testId + "-" + SDF.format(date);
190 if (gzExtension) {
191 fn += ".gz";
192 }
193 expectedFilenameList.add(fn);
194 }
195
196 protected void addExpectedFileName_ByFileIndexCounter(String randomOutputDir, String testId, long millis,
197 int fileIndexCounter, String compressionSuffix) {
198 String fn = randomOutputDir + testId + "-" + SDF.format(millis) + "-" + fileIndexCounter + ".txt"
199 + compressionSuffix;
200 expectedFilenameList.add(fn);
201 }
202
203 protected List<String> filterElementsInListBySuffix(String suffix) {
204 List<String> zipFiles = new ArrayList<String>();
205 for (String filename : expectedFilenameList) {
206 if (filename.endsWith(suffix))
207 zipFiles.add(filename);
208 }
209 return zipFiles;
210 }
211
212 protected void addExpectedFileNamedIfItsTime_ByDate(String outputDir, String testId, boolean gzExtension) {
213 if (passThresholdTime(nextRolloverThreshold)) {
214 addExpectedFileName_ByDate(outputDir, testId, getDateOfCurrentPeriodsStart(), gzExtension);
215 recomputeRolloverThreshold(currentTime);
216 }
217 }
218
219 protected void massageExpectedFilesToCorresponToCurrentTarget(String testId,
220 UnaryOperator<String> filenameFunction) {
221 int lastIndex = expectedFilenameList.size() - 1;
222 String last = expectedFilenameList.remove(lastIndex);
223
224 String filename = filenameFunction.apply(testId);
225 if (filename != null) {
226 expectedFilenameList.add(filename);
227 } else if (last.endsWith(".gz")) {
228 int lastLen = last.length();
229 String stem = last.substring(0, lastLen - 3);
230 expectedFilenameList.add(stem);
231 }
232 }
233
234 String addGZIfNotLast(int i) {
235 int lastIndex = expectedFilenameList.size() - 1;
236 if (i != lastIndex) {
237 return ".gz";
238 } else {
239 return "";
240 }
241 }
242
243 protected void zipEntryNameCheck(List<String> expectedFilenameList, String pattern) throws IOException {
244 for (String filepath : expectedFilenameList) {
245 checkZipEntryName(filepath, pattern);
246 }
247 }
248
249 protected void checkZipEntryMatchesZipFilename(List<String> expectedFilenameList) throws IOException {
250 for (String filepath : expectedFilenameList) {
251 String stripped = stripStemFromZipFilename(filepath);
252 checkZipEntryName(filepath, stripped);
253 }
254 }
255
256 String stripStemFromZipFilename(String filepath) {
257 File filepathAsFile = new File(filepath);
258 String stem = filepathAsFile.getName();
259 int stemLen = stem.length();
260 return stem.substring(0, stemLen - ".zip".length());
261
262 }
263
264 void checkZipEntryName(String filepath, String pattern) throws IOException {
265 ZipFile zf = new ZipFile(filepath);
266
267 try {
268 Enumeration<? extends ZipEntry> entries = zf.entries();
269 assert ((entries.hasMoreElements()));
270 ZipEntry firstZipEntry = entries.nextElement();
271 assert ((!entries.hasMoreElements()));
272 assertTrue(firstZipEntry.getName().matches(pattern));
273 } finally {
274 if (zf != null)
275 zf.close();
276 }
277 }
278
279 protected void add(Future<?> future) {
280 if (future == null)
281 return;
282 if (!futureList.contains(future)) {
283 futureList.add(future);
284 }
285 }
286
287 protected void waitForJobsToComplete() {
288 for (Future<?> future : futureList) {
289 try {
290 future.get(10, TimeUnit.SECONDS);
291 } catch (Exception e) {
292 new RuntimeException("unexpected exception while testing", e);
293 }
294 }
295 futureList.clear();
296 }
297 }