View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    * <p>
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    * <p>
9    * or (per the licensee's choosing)
10   * <p>
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.classic.rolling;
15  
16  import ch.qos.logback.classic.ClassicTestConstants;
17  import ch.qos.logback.classic.Logger;
18  import ch.qos.logback.classic.LoggerContext;
19  import ch.qos.logback.classic.joran.JoranConfigurator;
20  import ch.qos.logback.classic.spi.ILoggingEvent;
21  import ch.qos.logback.classic.util.LogbackMDCAdapter;
22  import ch.qos.logback.core.CoreConstants;
23  import ch.qos.logback.core.joran.spi.JoranException;
24  import ch.qos.logback.core.rolling.RollingFileAppender;
25  import ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicy;
26  import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
27  import ch.qos.logback.core.rolling.testUtil.ScaffoldingForRollingTests;
28  import ch.qos.logback.core.status.Status;
29  import ch.qos.logback.core.status.testUtil.StatusChecker;
30  import ch.qos.logback.core.util.StatusPrinter;
31  import org.junit.jupiter.api.AfterEach;
32  import org.junit.jupiter.api.BeforeEach;
33  import org.junit.jupiter.api.Test;
34  
35  import java.util.Date;
36  
37  import static org.junit.jupiter.api.Assertions.assertFalse;
38  import static org.junit.jupiter.api.Assertions.assertTrue;
39  
40  public class TimeBasedRollingWithConfigFileTest extends ScaffoldingForRollingTests {
41  
42      LoggerContext loggerContext = new LoggerContext();
43      LogbackMDCAdapter logbackMDCAdapter = new LogbackMDCAdapter();
44      StatusChecker statusChecker = new StatusChecker(loggerContext);
45      Logger logger = loggerContext.getLogger(this.getClass());
46      int fileSize = 0;
47      int fileIndexCounter = -1;
48      int sizeThreshold;
49  
50      @BeforeEach
51      @Override
52      public void setUp() {
53          loggerContext.setName("test");
54          loggerContext.setMDCAdapter(logbackMDCAdapter);
55          super.setUp();
56          loggerContext.putProperty("randomOutputDir", randomOutputDir);
57      }
58  
59      @AfterEach
60      public void tearDown() throws Exception {
61      }
62  
63      void loadConfig(String confifFile) throws JoranException {
64          JoranConfigurator jc = new JoranConfigurator();
65          jc.setContext(loggerContext);
66          jc.doConfigure(confifFile);
67          currentTime = System.currentTimeMillis();
68          recomputeRolloverThreshold(currentTime);
69      }
70  
71      @Test
72      public void basic() throws Exception {
73          String testId = "basic";
74          loggerContext.putProperty("testId", testId);
75          loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
76          statusChecker.assertIsErrorFree();
77  
78          Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
79  
80          expectedFilenameList.add(randomOutputDir + "z" + testId);
81  
82          RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
83  
84          TimeBasedRollingPolicy<ILoggingEvent> tprp = (TimeBasedRollingPolicy<ILoggingEvent>) rfa.getTriggeringPolicy();
85          TimeBasedFileNamingAndTriggeringPolicy<ILoggingEvent> tbnatp = tprp.getTimeBasedFileNamingAndTriggeringPolicy();
86  
87          String prefix = "Hello---";
88          int runLength = 4;
89          for (int i = 0; i < runLength; i++) {
90              logger.debug(prefix + i);
91              addExpectedFileNamedIfItsTime_ByDate(randomOutputDir, testId, false);
92              incCurrentTime(500);
93              tbnatp.setCurrentTime(currentTime);
94          }
95  
96          existenceCheck(expectedFilenameList);
97          sortedContentCheck(randomOutputDir, runLength, prefix);
98      }
99  
100     @Test
101     public void depratedSizeAndTimeBasedFNATPWarning() throws Exception {
102         String testId = "depratedSizeAndTimeBasedFNATPWarning";
103         loggerContext.putProperty("testId", testId);
104         loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
105         StatusPrinter.print(loggerContext);
106         statusChecker.assertContainsMatch(Status.WARN, CoreConstants.SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED);
107     }
108 
109     @Test
110     public void timeAndSize() throws Exception {
111         String testId = "timeAndSize";
112         loggerContext.putProperty("testId", testId);
113         String prefix = "Hello-----";
114 
115         // the number of times the log file will be written to before time based
116         // roll-over occurs
117         int approxWritesPerPeriod = 64;
118         sizeThreshold = prefix.length() * approxWritesPerPeriod;
119         loggerContext.putProperty("sizeThreshold", "" + sizeThreshold);
120         System.out.println("timeAndSize.sizeThreshold="+sizeThreshold);
121         loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
122 
123         StatusPrinter.print(loggerContext);
124         // Test http://jira.qos.ch/browse/LOGBACK-1236
125         statusChecker.assertNoMatch(CoreConstants.SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED);
126 
127         Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
128 
129         expectedFilenameList.add(randomOutputDir + "z" + testId);
130 
131         RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
132 
133         statusChecker.assertIsErrorFree();
134 
135         TimeBasedRollingPolicy<ILoggingEvent> tprp = (TimeBasedRollingPolicy<ILoggingEvent>) rfa.getTriggeringPolicy();
136         TimeBasedFileNamingAndTriggeringPolicy<ILoggingEvent> tbnatp = tprp.getTimeBasedFileNamingAndTriggeringPolicy();
137 
138         int timeIncrement = 1000 / approxWritesPerPeriod;
139         int targetPeriodCount = 3;
140         int runLength = approxWritesPerPeriod * targetPeriodCount;
141         for (int i = 0; i < runLength; i++) {
142             String msg = prefix + i;
143             logger.debug(msg);
144             addExpectedFileNamedIfItsTime(testId, msg, false);
145             incCurrentTime(timeIncrement);
146             tbnatp.setCurrentTime(currentTime);
147         }
148 
149         sortedContentCheck(randomOutputDir, runLength, prefix);
150         int eCount = existenceCount(expectedFilenameList);
151         // for various reasons, it is extremely difficult to have the files
152         // match exactly the expected archive files. Thus, we aim for
153         // an approximate match
154         assertTrue(eCount >= targetPeriodCount || eCount >= expectedFilenameList.size() / 2,
155                 "existenceCount=" + eCount + ", expectedFilenameList.size=" + expectedFilenameList.size());
156     }
157 
158     @Test
159     public void timeAndSizeWithoutIntegerToken() throws Exception {
160         String testId = "timeAndSizeWithoutIntegerToken";
161         loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
162         Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
163         expectedFilenameList.add(randomOutputDir + "z" + testId);
164         RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
165         StatusPrinter.print(loggerContext);
166 
167         statusChecker.assertContainsMatch("Missing integer token");
168         assertFalse(rfa.isStarted());
169     }
170 
171     // see also LOGBACK-1176
172     @Test
173     public void timeAndSizeWithoutMaxFileSize() throws Exception {
174         String testId = "timeAndSizeWithoutMaxFileSize";
175         loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
176         Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
177         // expectedFilenameList.add(randomOutputDir + "z" + testId);
178         RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
179 
180         // statusChecker.assertContainsMatch("Missing integer token");
181         assertFalse(rfa.isStarted());
182         StatusPrinter.print(loggerContext);
183     }
184 
185     @Test
186     public void totalSizeCapSmallerThanMaxFileSize() throws Exception {
187         String testId = "totalSizeCapSmallerThanMaxFileSize";
188         loggerContext.putProperty("testId", testId);
189         loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "rolling/" + testId + ".xml");
190         Logger root = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
191         // expectedFilenameList.add(randomOutputDir + "z" + testId);
192         RollingFileAppender<ILoggingEvent> rfa = (RollingFileAppender<ILoggingEvent>) root.getAppender("ROLLING");
193 
194         statusChecker.assertContainsMatch(
195                 "totalSizeCap of \\[\\d* \\w*\\] is smaller than maxFileSize \\[\\d* \\w*\\] which is non-sensical");
196         assertFalse(rfa.isStarted());
197 
198     }
199 
200     void addExpectedFileNamedIfItsTime(String testId, String msg, boolean gzExtension) {
201         fileSize += msg.getBytes().length;
202 
203         if (passThresholdTime(nextRolloverThreshold)) {
204             fileIndexCounter = 0;
205             fileSize = 0;
206             addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), fileIndexCounter, gzExtension);
207             recomputeRolloverThreshold(currentTime);
208             return;
209         }
210 
211         // windows can delay file size changes, so we only allow for
212         // fileIndexCounter 0 and 1
213         if ((fileIndexCounter < 1) && fileSize > sizeThreshold) {
214             addExpectedFileName(testId, getDateOfPreviousPeriodsStart(), ++fileIndexCounter, gzExtension);
215             fileSize = -1;
216             return;
217         }
218     }
219 
220     void addExpectedFileName(String testId, Date date, int fileIndexCounter, boolean gzExtension) {
221 
222         String fn = randomOutputDir + testId + "-" + SDF.format(date) + "." + fileIndexCounter;
223         if (gzExtension) {
224             fn += ".gz";
225         }
226         System.out.println("Adding " + fn);
227         expectedFilenameList.add(fn);
228     }
229 
230     @Override
231     protected void addExpectedFileNamedIfItsTime_ByDate(String outputDir, String testId, boolean gzExtension) {
232         if (passThresholdTime(nextRolloverThreshold)) {
233             addExpectedFileName_ByDate(outputDir, testId, getDateOfPreviousPeriodsStart(), gzExtension);
234             recomputeRolloverThreshold(currentTime);
235         }
236     }
237 }