1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.rolling;
15
16 import ch.qos.logback.core.util.Duration;
17 import ch.qos.logback.core.util.FileSize;
18 import ch.qos.logback.core.util.FileUtil;
19 import org.junit.jupiter.api.AfterEach;
20 import org.junit.jupiter.api.Assertions;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.DisplayName;
23 import org.junit.jupiter.api.Test;
24
25 import ch.qos.logback.core.Appender;
26 import ch.qos.logback.core.Context;
27 import ch.qos.logback.core.ContextBase;
28 import ch.qos.logback.core.appender.AbstractAppenderTest;
29 import ch.qos.logback.core.testUtil.DummyEncoder;
30 import ch.qos.logback.core.status.Status;
31 import ch.qos.logback.core.testUtil.CoreTestConstants;
32 import ch.qos.logback.core.testUtil.RandomUtil;
33 import ch.qos.logback.core.status.testUtil.StatusChecker;
34
35 import java.io.File;
36 import java.io.FileInputStream;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.nio.file.Files;
40 import java.util.Collections;
41 import java.util.List;
42
43
44 public class RollingFileAppenderTest extends AbstractAppenderTest<Object> {
45
46 RollingFileAppender<Object> rfa = new RollingFileAppender<Object>();
47 Context context = new ContextBase();
48
49 TimeBasedRollingPolicy<Object> tbrp = new TimeBasedRollingPolicy<Object>();
50 int diff = RandomUtil.getPositiveInt();
51 String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/";
52 DummyEncoder<Object> encoder;
53
54 @BeforeEach
55 public void setUp() throws Exception {
56
57
58 encoder = new DummyEncoder<>();
59 rfa.setEncoder(encoder);
60 rfa.setName("test");
61 tbrp.setContext(context);
62 tbrp.setParent(rfa);
63 }
64
65 @AfterEach
66 public void tearDown() throws Exception {
67 }
68
69 @Override
70 protected Appender<Object> getAppender() {
71 return rfa;
72 }
73
74 @Override
75 protected Appender<Object> getConfiguredAppender() {
76 rfa.setContext(context);
77 tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log");
78 tbrp.start();
79 rfa.setRollingPolicy(tbrp);
80
81 rfa.start();
82 return rfa;
83 }
84
85 @Test
86 public void testPrudentModeLogicalImplications() {
87 rfa.setContext(context);
88
89 rfa.setFile("some non null value");
90 rfa.setAppend(false);
91 rfa.setPrudent(true);
92
93 tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log");
94 tbrp.start();
95 rfa.setRollingPolicy(tbrp);
96
97 rfa.start();
98
99 Assertions.assertTrue(rfa.isAppend());
100 Assertions.assertNull(rfa.rawFileProperty());
101 Assertions.assertTrue(rfa.isStarted());
102 }
103
104 @Test
105 public void testPrudentModeLogicalImplicationsOnCompression() {
106 rfa.setContext(context);
107 rfa.setAppend(false);
108 rfa.setPrudent(true);
109
110 tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log.zip");
111 tbrp.start();
112 rfa.setRollingPolicy(tbrp);
113
114 rfa.start();
115
116 StatusChecker checker = new StatusChecker(context);
117 Assertions.assertFalse(rfa.isStarted());
118 Assertions.assertEquals(Status.ERROR, checker.getHighestLevel(0));
119 }
120
121 @Test
122 public void testFilePropertyAfterRollingPolicy() {
123 rfa.setContext(context);
124 rfa.setRollingPolicy(tbrp);
125 rfa.setFile("x");
126
127 StatusChecker statusChecker = new StatusChecker(context.getStatusManager());
128 statusChecker.assertContainsMatch(Status.ERROR, "File property must be set before any triggeringPolicy ");
129 }
130
131 @Test
132 public void testFilePropertyAfterTriggeringPolicy() {
133 rfa.setContext(context);
134 rfa.setTriggeringPolicy(new SizeBasedTriggeringPolicy<Object>());
135 rfa.setFile("x");
136 StatusChecker statusChecker = new StatusChecker(context.getStatusManager());
137 statusChecker.assertContainsMatch(Status.ERROR, "File property must be set before any triggeringPolicy ");
138 }
139
140 @Test
141 public void testFileNameWithParenthesis() {
142
143
144
145
146 rfa.setContext(context);
147 tbrp.setFileNamePattern(randomOutputDir + "program(x86)/toto-%d.log");
148 tbrp.start();
149 rfa.setRollingPolicy(tbrp);
150 rfa.start();
151 rfa.doAppend("hello");
152 }
153
154 @Test
155 public void stopTimeBasedRollingPolicy() {
156 rfa.setContext(context);
157
158 tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d.log.zip");
159 tbrp.start();
160 rfa.setRollingPolicy(tbrp);
161 rfa.start();
162
163
164 Assertions.assertTrue(tbrp.isStarted());
165 Assertions.assertTrue(rfa.isStarted());
166 rfa.stop();
167 Assertions.assertFalse(rfa.isStarted());
168 Assertions.assertFalse(tbrp.isStarted());
169
170 }
171
172 @Test
173 public void stopFixedWindowRollingPolicy() {
174 rfa.setContext(context);
175 rfa.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-.log");
176
177 FixedWindowRollingPolicy fwRollingPolicy = new FixedWindowRollingPolicy();
178 fwRollingPolicy.setContext(context);
179 fwRollingPolicy.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%i.log.zip");
180 fwRollingPolicy.setParent(rfa);
181 fwRollingPolicy.start();
182 SizeBasedTriggeringPolicy<Object> sbTriggeringPolicy = new SizeBasedTriggeringPolicy<Object>();
183 sbTriggeringPolicy.setContext(context);
184 sbTriggeringPolicy.start();
185
186 rfa.setRollingPolicy(fwRollingPolicy);
187 rfa.setTriggeringPolicy(sbTriggeringPolicy);
188
189 rfa.start();
190
191
192 Assertions.assertTrue(fwRollingPolicy.isStarted());
193 Assertions.assertTrue(sbTriggeringPolicy.isStarted());
194 Assertions.assertTrue(rfa.isStarted());
195 rfa.stop();
196 Assertions.assertFalse(rfa.isStarted());
197 Assertions.assertFalse(fwRollingPolicy.isStarted());
198 Assertions.assertFalse(sbTriggeringPolicy.isStarted());
199
200 }
201
202
203
204
205 @Test
206 public void testFileShouldNotMatchFileNamePattern() {
207 rfa.setContext(context);
208 rfa.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX + "x-2013-04.log");
209 tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "x-%d{yyyy-MM}.log");
210 tbrp.start();
211
212 rfa.setRollingPolicy(tbrp);
213 rfa.start();
214 StatusChecker statusChecker = new StatusChecker(context);
215 final String msg = "File property collides with fileNamePattern. Aborting.";
216 boolean containsMatch = statusChecker.containsMatch(Status.ERROR, msg);
217 Assertions.assertTrue(containsMatch, "Missing error: " + msg);
218 }
219
220 @Test
221 public void collidingTimeformat() {
222 rfa.setContext(context);
223 rfa.setAppend(false);
224 rfa.setPrudent(true);
225
226 tbrp.setFileNamePattern(CoreTestConstants.OUTPUT_DIR_PREFIX + "toto-%d{dd}.log.zip");
227 tbrp.start();
228 rfa.setRollingPolicy(tbrp);
229
230 rfa.start();
231
232 StatusChecker checker = new StatusChecker(context);
233 Assertions.assertFalse(rfa.isStarted());
234 Assertions.assertEquals(Status.ERROR, checker.getHighestLevel(0));
235
236 checker.assertContainsMatch("The date format in FileNamePattern will result");
237 }
238
239 @Test
240 public void collidingFileNamePattern() {
241 String filenamePattern = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "-collision-%d.log.zip";
242
243 RollingFileAppender<Object> appender0 = new RollingFileAppender<Object>();
244 appender0.setName("FA0");
245 appender0.setContext(context);
246 appender0.setEncoder(new DummyEncoder<Object>());
247 TimeBasedRollingPolicy<Object> tbrp0 = new TimeBasedRollingPolicy<Object>();
248 tbrp0.setContext(context);
249 tbrp0.setFileNamePattern(filenamePattern);
250 tbrp0.setParent(appender0);
251 tbrp0.start();
252 appender0.setRollingPolicy(tbrp0);
253 appender0.start();
254 Assertions.assertTrue(appender0.isStarted());
255
256 RollingFileAppender<Object> appender1 = new RollingFileAppender<Object>();
257 appender1.setName("FA1");
258 appender1.setFile("X");
259 appender1.setContext(context);
260 appender1.setEncoder(new DummyEncoder<Object>());
261 TimeBasedRollingPolicy<Object> tbrp1 = new TimeBasedRollingPolicy<Object>();
262 tbrp1.setContext(context);
263 tbrp1.setFileNamePattern(filenamePattern);
264 tbrp1.setParent(appender1);
265 tbrp1.start();
266 appender1.setRollingPolicy(tbrp1);
267 appender1.start();
268
269
270
271 Assertions.assertFalse(appender1.isStarted());
272 StatusChecker checker = new StatusChecker(context);
273 checker.assertContainsMatch(Status.ERROR, "'FileNamePattern' option has the same value");
274 }
275
276 @Test
277 @DisplayName("Checks header and footer are written when the files are rolled")
278 public void testHeaderFooterWritten() throws IOException, InterruptedException {
279
280 String folderPrefix = CoreTestConstants.OUTPUT_DIR_PREFIX+diff+"/";
281 String namePrefix = folderPrefix+"header-";
282 File folderFile = new File(folderPrefix);
283 FileUtil.createMissingParentDirectories(folderFile);
284
285
286 encoder.setFileHeader("HEADER");
287 encoder.setFileFooter("FOOTER");
288 rfa.setContext(context);
289 FixedWindowRollingPolicy fixedWindowRollingPolicy = new FixedWindowRollingPolicy();
290 fixedWindowRollingPolicy.setContext(context);
291 fixedWindowRollingPolicy.setParent(rfa);
292 fixedWindowRollingPolicy.setMaxIndex(3);
293 String fileNamePattern = namePrefix + "%i.log";
294 fixedWindowRollingPolicy.setFileNamePattern(fileNamePattern);
295 rfa.setRollingPolicy(fixedWindowRollingPolicy);
296 rfa.setFile(namePrefix+"0.log");
297 fixedWindowRollingPolicy.start();
298 rfa.setImmediateFlush(true);
299 SizeBasedTriggeringPolicy<Object> sbtp = new SizeBasedTriggeringPolicy<>();
300 sbtp.setMaxFileSize(new FileSize(10));
301 sbtp.setCheckIncrement(Duration.buildByMilliseconds(10));
302
303 rfa.setTriggeringPolicy(sbtp);
304 rfa.getTriggeringPolicy().start();
305 rfa.start();
306
307 for (int i = 0; i < 100; i++) {
308 rfa.doAppend("data" + i);
309 File file = new File(namePrefix + fixedWindowRollingPolicy.getMaxIndex() + ".log");
310 if (file.exists()) {
311 break;
312 }
313 Thread.sleep(5);
314 }
315 rfa.stop();
316
317 for (int i = 0; i < fixedWindowRollingPolicy.getMaxIndex(); i++) {
318 File file = new File(namePrefix + i + ".log");
319 Assertions.assertTrue(file.exists());
320 List<String> lines = Files.readAllLines(file.toPath());
321 Assertions.assertTrue(lines.size() > 2, "At least 2 lines per file are expected in " + file);
322 Assertions.assertEquals("HEADER", lines.get(0));
323 Assertions.assertEquals("FOOTER", lines.get(lines.size() - 1));
324 Assertions.assertEquals(1, Collections.frequency(lines, "HEADER"));
325 Assertions.assertEquals(1, Collections.frequency(lines, "FOOTER"));
326 }
327 }
328
329 }