[logback-dev] svn commit: r2419 - in logback/trunk/logback-core/src: main/java/ch/qos/logback/core/rolling main/java/ch/qos/logback/core/rolling/helper test/java/ch/qos/logback/core/rolling test/java/ch/qos/logback/core/rolling/helper

noreply.ceki at qos.ch noreply.ceki at qos.ch
Fri Aug 7 18:30:50 CEST 2009


Author: ceki
Date: Fri Aug  7 18:30:50 2009
New Revision: 2419

Added:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java
      - copied, changed from r2417, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToSRegexUtil.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java
      - copied, changed from r2418, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithHistoryCleanTest.java
Removed:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToSRegexUtil.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithHistoryCleanTest.java
Modified:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java

Log:
- FileNamePattern now slashifies its pattern argument at construction time
  This eliminates the need to slashify regular expression at a later time 
  (since the original pattern is already slashified)
- While cleaning archived log files, empty fodlers are taken into account, especially if
  they are in cronolog-style "/var/tmp/2009/08/04/foo.log". 
- old archives are cleaned for time-based triggering as well as size-and-time-based triggering
- relevant test cases


Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java	Fri Aug  7 18:30:50 2009
@@ -11,6 +11,7 @@
 
 import ch.qos.logback.core.FileAppender;
 import ch.qos.logback.core.rolling.helper.CompressionMode;
+import ch.qos.logback.core.rolling.helper.FileFilterUtil;
 import ch.qos.logback.core.rolling.helper.FileNamePattern;
 import ch.qos.logback.core.spi.ContextAwareBase;
 
@@ -24,6 +25,7 @@
     RollingPolicy {
   protected CompressionMode compressionMode = CompressionMode.NONE;
   protected FileNamePattern fileNamePattern;
+  // fileNamePatternStr is always slashified, see setter
   protected String fileNamePatternStr;
 
   private FileAppender parent;
@@ -76,7 +78,6 @@
   }
 
   public void setParent(FileAppender appender) {
-    addInfo("Adding parent to RollingPolicy: " + appender.getName());
     this.parent = appender;
   }
 

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java	Fri Aug  7 18:30:50 2009
@@ -14,6 +14,7 @@
 
 import ch.qos.logback.core.joran.spi.NoAutoStart;
 import ch.qos.logback.core.rolling.helper.FileFilterUtil;
+import ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover;
 import ch.qos.logback.core.util.FileSize;
 
 @NoAutoStart
@@ -30,12 +31,14 @@
     // in super.start()
     super.start();
 
+    archiveRemover = new SizeAndTimeBasedArchiveRemover(tbrp.fileNamePattern, rc);
+    
     // we need to get the correct value of currentPeriodsCounter.
     // usually the value is 0, unless the appender or the application
     // is stopped and restarted within the same period
     if (tbrp.getParentsRawFileProperty() == null) {
-      String slashifiedRegex = tbrp.fileNamePattern.toSRegex(dateInCurrentPeriod);
-      String stemRegex = FileFilterUtil.afterLastSlash(slashifiedRegex);
+      String regex = tbrp.fileNamePattern.toRegex(dateInCurrentPeriod);
+      String stemRegex = FileFilterUtil.afterLastSlash(regex);
       computeCurrentPeriodsHighestCounterValue(stemRegex);
     }
     started = true;
@@ -79,9 +82,11 @@
     }
 
     if (activeFile.length() >= maxFileSize.getSize()) {
+      System.out.println("Size based trigger, currentPeriodsCounter="+currentPeriodsCounter);
       elapsedPeriodsFileName = tbrp.fileNamePatternWCS
           .convertMultipleArguments(dateInCurrentPeriod, currentPeriodsCounter);
       currentPeriodsCounter++;
+      System.out.println("Size based trigger, currentPeriodsCounter="+currentPeriodsCounter);
       return true;
     }
 

Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java (from r2417, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToSRegexUtil.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToSRegexUtil.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexUtil.java	Fri Aug  7 18:30:50 2009
@@ -21,21 +21,21 @@
  * @author Ceki Gülcü
  * 
  */
-public class DatePatternToSRegexUtil {
+public class DatePatternToRegexUtil {
 
   final String datePattern;
   final int length;
 
-  DatePatternToSRegexUtil(String datePattern) {
+  DatePatternToRegexUtil(String datePattern) {
     this.datePattern = datePattern;
     length = datePattern.length();
   }
 
-  String toSRegex() {
+  String toRegex() {
     List<SequenceToRegex4SDF> sequenceList = tokenize();
     StringBuilder sb = new StringBuilder();
     for (SequenceToRegex4SDF seq : sequenceList) {
-      sb.append(seq.toSRegex());
+      sb.append(seq.toRegex());
     }
     return sb.toString();
   }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DateTokenConverter.java	Fri Aug  7 18:30:50 2009
@@ -67,8 +67,8 @@
     return (o instanceof Date);
   }
 
-  public String toSRegex() {
-    DatePatternToSRegexUtil toRegex = new DatePatternToSRegexUtil(datePattern);
-    return toRegex.toSRegex();
+  public String toRegex() {
+    DatePatternToRegexUtil toRegex = new DatePatternToRegexUtil(datePattern);
+    return toRegex.toRegex();
   }
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java	Fri Aug  7 18:30:50 2009
@@ -13,16 +13,55 @@
 import java.io.File;
 import java.util.Date;
 
+import ch.qos.logback.core.pattern.Converter;
+import ch.qos.logback.core.pattern.LiteralConverter;
+
 public class DefaultArchiveRemover implements ArchiveRemover {
 
-  FileNamePattern fileNamePattern;
-  RollingCalendar rc;
+  final FileNamePattern fileNamePattern;
+  final RollingCalendar rc;
   int maxHistory;
   int periodOffset;
-  
-  public DefaultArchiveRemover(FileNamePattern fileNamePattern, RollingCalendar rc) {
+  final boolean parentClean;
+
+  public DefaultArchiveRemover(FileNamePattern fileNamePattern,
+      RollingCalendar rc) {
     this.fileNamePattern = fileNamePattern;
     this.rc = rc;
+    this.parentClean = computeParentCleaningFlag(fileNamePattern);
+  }
+
+  boolean computeParentCleaningFlag(FileNamePattern fileNamePattern) {
+    DateTokenConverter dtc = fileNamePattern.getDateTokenConverter();
+    // if the date pattern has a /, then we need parent cleaning
+    if(dtc.getDatePattern().indexOf('/') != -1) {
+      return true;
+    }
+    // if the literal string subsequent to the dtc contains a /, we also need
+    // parent cleaning
+    
+    Converter<Object> p = fileNamePattern.headTokenConverter;
+    
+    // find the date converter
+    while(p != null) {
+      if(p instanceof DateTokenConverter) {
+        break;
+      }
+      p = p.getNext();
+    }
+    
+    while(p != null) {
+      if(p instanceof LiteralConverter) {
+        String s = p.convert(null);
+        if(s.indexOf('/') != -1) {
+          return true;
+        }
+      }
+      p = p.getNext();
+    }
+    
+    // no /, so we don't need parent cleaning
+    return false;
   }
 
   public void clean(Date now) {
@@ -34,12 +73,34 @@
 
     if (file2Delete.exists() && file2Delete.isFile()) {
       file2Delete.delete();
+      if (parentClean) {
+        removeFolderIfEmpty(file2Delete.getParentFile(), 0);
+      }
+    }
+  }
+
+  /**
+   * Will remove the directory passed as parameter if empty. After that, if the
+   * parent is also becomes empty, remove the parent dir as well but at most 3
+   * times.
+   * 
+   * @param dir
+   * @param recursivityCount
+   */
+  void removeFolderIfEmpty(File dir, int recursivityCount) {
+    // we should never go more than 3 levels higher
+    if (recursivityCount >= 3) {
+      return;
+    }
+    if (dir.isDirectory() && FileFilterUtil.isEmptyDirectory(dir)) {
+      dir.delete();
+      removeFolderIfEmpty(dir.getParentFile(), recursivityCount + 1);
     }
   }
 
   public void setMaxHistory(int maxHistory) {
     this.maxHistory = maxHistory;
-    this.periodOffset = -maxHistory -1;
+    this.periodOffset = -maxHistory - 1;
   }
 
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileFilterUtil.java	Fri Aug  7 18:30:50 2009
@@ -48,6 +48,18 @@
     }
   }
 
+  static public boolean isEmptyDirectory(File dir) {
+    if (!dir.isDirectory()) {
+      throw new IllegalArgumentException("[" + dir + "] must be a directory");
+    }
+    String[] filesInDir = dir.list();
+    if (filesInDir == null || filesInDir.length == 0) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
   /**
    * Return the set of files matching the stemRegex as found in 'directory'. A
    * stemRegex does not contain any slash characters or any folder seperators.
@@ -87,7 +99,20 @@
     return counter;
   }
 
-  static String slashify(String in) {
+  public static String slashify(String in) {
     return in.replace('\\', '/');
   }
+
+  public static void removeEmptyParentDirectories(File file,
+      int recursivityCount) {
+    // we should never go more than 3 levels higher
+    if (recursivityCount >= 3) {
+      return;
+    }
+    File parent = file.getParentFile();
+    if (parent.isDirectory() && FileFilterUtil.isEmptyDirectory(parent)) {
+      parent.delete();
+      removeEmptyParentDirectories(parent, recursivityCount + 1);
+    }
+  }
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java	Fri Aug  7 18:30:50 2009
@@ -46,7 +46,8 @@
   Converter<Object> headTokenConverter;
 
   public FileNamePattern(String patternArg, Context contextArg) {
-    setPattern(patternArg);
+    // the pattern is slashified
+    setPattern(FileFilterUtil.slashify(patternArg));
     setContext(contextArg);
     parse();
     ConverterUtil.startConverters(this.headTokenConverter);
@@ -141,20 +142,20 @@
   }
 
   /**
-   * Given date, convert this instance to a slashified regular expression. A
+   * Given date, convert this instance to a  regular expression. A
    * slashified regex, is a regex with naturally occurring forward slash
    * characters replaced by back slashes.
     */
-  public String toSRegex(Date date) {
+  public String toRegex(Date date) {
     StringBuilder buf = new StringBuilder();
     Converter<Object> p = headTokenConverter;
     while (p != null) {
       if (p instanceof LiteralConverter) {
-        buf.append(FileFilterUtil.slashify(p.convert(null)));
+        buf.append(p.convert(null));
       } else if (p instanceof IntegerTokenConverter) {
         buf.append("(\\d{1,2})");
       } else if (p instanceof DateTokenConverter) {
-        buf.append(FileFilterUtil.slashify(p.convert(date)));
+        buf.append(p.convert(date));
       }
       p = p.getNext();
     }
@@ -162,19 +163,19 @@
   }
 
   /**
-   * Given date, convert this instance to a slashified regular expression
+   * Given date, convert this instance to a regular expression
    */
-  public String toSRegex() {
+  public String toRegex() {
     StringBuilder buf = new StringBuilder();
     Converter<Object> p = headTokenConverter;
     while (p != null) {
       if (p instanceof LiteralConverter) {
-        buf.append(FileFilterUtil.slashify(p.convert(null)));
+        buf.append(p.convert(null));
       } else if (p instanceof IntegerTokenConverter) {
         buf.append("\\d{1,2}");
       } else if (p instanceof DateTokenConverter) {
         DateTokenConverter<Object> dtc = (DateTokenConverter<Object>) p;
-        buf.append(dtc.toSRegex());
+        buf.append(dtc.toRegex());
       }
       p = p.getNext();
     }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SequenceToRegex4SDF.java	Fri Aug  7 18:30:50 2009
@@ -29,8 +29,7 @@
     occurrences++;
   }
 
-  // slashified regex
-  String toSRegex() {
+  String toRegex() {
     switch (c) {
     case 'G':
       return ".*";
@@ -64,12 +63,8 @@
       return "(\\+|-)\\d{4}";
     case '.':
       return "\\.";
-    case '\\':  // slashify
-      String s = "";
-      for(int i = 0; i < occurrences;i++) {
-        s += "/";
-      }
-      return s;
+    case '\\': 
+      throw new IllegalStateException("Forward slashes are not allowed");
     default:
       if (occurrences == 1) {
         return "" + c;

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java	Fri Aug  7 18:30:50 2009
@@ -0,0 +1,45 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2009, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.core.rolling.helper;
+
+import java.io.File;
+import java.util.Date;
+
+public class SizeAndTimeBasedArchiveRemover extends DefaultArchiveRemover {
+
+  public SizeAndTimeBasedArchiveRemover(FileNamePattern fileNamePattern,
+      RollingCalendar rc) {
+    super(fileNamePattern, rc);
+  }
+
+  @Override
+  public void clean(Date now) {
+    Date dateOfPeriodToClean = rc.getRelativeDate(now, periodOffset);
+
+    String regex = fileNamePattern.toRegex(dateOfPeriodToClean);
+    String stemRegex = FileFilterUtil.afterLastSlash(regex);
+    File archive0 = new File(fileNamePattern.convertMultipleArguments(
+        dateOfPeriodToClean, 0));
+
+    File parentDir = archive0.getParentFile();
+    File[] matchingFileArray = FileFilterUtil.filesInFolderMatchingStemRegex(
+        parentDir, stemRegex);
+
+    for (File f : matchingFileArray) {
+      f.delete();
+    }
+
+    if (parentClean) {
+      removeFolderIfEmpty(parentDir, 0);
+    }
+  }
+
+}

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java	Fri Aug  7 18:30:50 2009
@@ -5,7 +5,7 @@
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses( { RenamingTest.class, SizeBasedRollingTest.class,
-    TimeBasedRollingTest.class, TimeBasedRollingWithHistoryCleanTest.class,
+    TimeBasedRollingTest.class, TimeBasedRollingWithArchiveRemovalTest.class,
     MultiThreadedRollingTest.class,
     SizeAndTimeBasedFNATP_Test.class,
     ch.qos.logback.core.rolling.helper.PackageTest.class })

Copied: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java (from r2418, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithHistoryCleanTest.java)
==============================================================================
--- /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithHistoryCleanTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java	Fri Aug  7 18:30:50 2009
@@ -3,7 +3,9 @@
 import static org.junit.Assert.assertEquals;
 
 import java.io.File;
-import java.io.FilenameFilter;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import org.junit.After;
@@ -13,59 +15,117 @@
 import ch.qos.logback.core.Context;
 import ch.qos.logback.core.ContextBase;
 import ch.qos.logback.core.layout.EchoLayout;
+import ch.qos.logback.core.testUtil.RandomUtil;
 import ch.qos.logback.core.util.CoreTestConstants;
 
-public class TimeBasedRollingWithHistoryCleanTest {
+public class TimeBasedRollingWithArchiveRemovalTest {
 
   Context context = new ContextBase();
   EchoLayout<Object> layout = new EchoLayout<Object>();
 
   static final String MONTHLY_DATE_PATTERN = "yyyy-MM";
+  static final String MONTHLY_CROLOLOG_DATE_PATTERN = "yyyy/MM";
+
   static final String DAILY_DATE_PATTERN = "yyyy-MM-dd";
+  static final String DAILY_CROLOLOG_DATE_PATTERN = "yyyy/MM/dd";
 
   static final long MILLIS_IN_MINUTE = 60 * 1000;
   static final long MILLIS_IN_HOUR = 60 * MILLIS_IN_MINUTE;
   static final long MILLIS_IN_DAY = 24 * MILLIS_IN_HOUR;
   static final long MILLIS_IN_MONTH = 30 * MILLIS_IN_DAY;
 
+  int diff = RandomUtil.getPositiveInt();
+  protected String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff
+      + "/";
+  int slashCount;
+
+  // by default tbfnatp is an instance of
+  // DefaultTimeBasedFileNamingAndTriggeringPolicy
+  TimeBasedFileNamingAndTriggeringPolicy<Object> tbfnatp = new DefaultTimeBasedFileNamingAndTriggeringPolicy<Object>();
+
   @Before
   public void setUp() throws Exception {
     context.setName("test");
-
-    // remove all files containing the string 'clean'
-    File dir = new File(CoreTestConstants.OUTPUT_DIR_PREFIX);
-    if (dir.isDirectory()) {
-      File[] toDelete = dir.listFiles(new FilenameFilter() {
-        public boolean accept(File dir, String name) {
-          return name.contains("clean");
-        }
-      });
-      for (File f : toDelete) {
-        System.out.println(f);
-        f.delete();
-      }
-    }
   }
 
   @After
   public void tearDown() throws Exception {
   }
 
+  int computeSlashCount(String datePattern) {
+    int fromIndex = 0;
+    int count = 0;
+    while (true) {
+      int i = datePattern.indexOf('/', fromIndex);
+      if (i == -1) {
+        break;
+      } else {
+        count++;
+        fromIndex = i + 1;
+        if (fromIndex >= datePattern.length()) {
+          break;
+        }
+      }
+    }
+    return count;
+  }
+
   @Test
   public void montlyRollover() throws Exception {
-    doRollover(CoreTestConstants.OUTPUT_DIR_PREFIX + "clean-%d{" + MONTHLY_DATE_PATTERN
-        + "}.txt", MILLIS_IN_MONTH, 20);
+    slashCount = computeSlashCount(MONTHLY_DATE_PATTERN);
+    // large maxPeriod, a 3 times as many number of periods to simulate
+    doRollover(randomOutputDir + "clean-%d{" + MONTHLY_DATE_PATTERN + "}.txt",
+        MILLIS_IN_MONTH, 20, 20 * 3, expectedCountWithoutDirs(20));
+  }
 
+  @Test
+  public void montlyRolloverOverManyPeriods() throws Exception {
+    // small maxHistory, many periods
+    slashCount = computeSlashCount(MONTHLY_CROLOLOG_DATE_PATTERN);
+    doRollover(randomOutputDir + "/%d{" + MONTHLY_CROLOLOG_DATE_PATTERN
+        + "}/clean.txt.zip", MILLIS_IN_MONTH, 5, 40, expectedCountWithDirs(5));
   }
 
   @Test
   public void dailyRollover() throws Exception {
-    doRollover(CoreTestConstants.OUTPUT_DIR_PREFIX + "clean-%d{" + DAILY_DATE_PATTERN
-        + "}.txt.zip", MILLIS_IN_DAY, 5);
+    slashCount = computeSlashCount(DAILY_DATE_PATTERN);
+    doRollover(
+        randomOutputDir + "clean-%d{" + DAILY_DATE_PATTERN + "}.txt.zip",
+        MILLIS_IN_DAY, 5, 5 * 3, expectedCountWithoutDirs(5));
   }
 
-  void doRollover(String fileNamePattern, long delay, int maxHistory)
-      throws Exception {
+  @Test
+  public void dailyCronologRollover() throws Exception {
+    slashCount = computeSlashCount(DAILY_CROLOLOG_DATE_PATTERN);
+    doRollover(randomOutputDir + "/%d{" + DAILY_CROLOLOG_DATE_PATTERN
+        + "}/clean.txt.zip", MILLIS_IN_DAY, 8, 8 * 3, expectedCountWithDirs(8));
+  }
+
+  @Test
+  public void dailySizeBasedRollover() throws Exception {
+    SizeAndTimeBasedFNATP<Object> sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP<Object>();
+    sizeAndTimeBasedFNATP.setMaxFileSize("1");
+    tbfnatp = sizeAndTimeBasedFNATP;
+
+    slashCount = computeSlashCount(DAILY_DATE_PATTERN);
+    doRollover(randomOutputDir + "/%d{" + DAILY_DATE_PATTERN
+        + "}-clean.%i.zip", MILLIS_IN_DAY, 5, 5 * 4, expectedCountWithoutDirs(5));
+  }
+
+  
+  @Test
+  public void dailyChronologSizeBasedRollover() throws Exception {
+    SizeAndTimeBasedFNATP<Object> sizeAndTimeBasedFNATP = new SizeAndTimeBasedFNATP<Object>();
+    sizeAndTimeBasedFNATP.setMaxFileSize("1");
+    tbfnatp = sizeAndTimeBasedFNATP;
+
+    slashCount = computeSlashCount(DAILY_CROLOLOG_DATE_PATTERN);
+    doRollover(randomOutputDir + "/%d{" + DAILY_DATE_PATTERN
+        + "}/clean.%i.zip", MILLIS_IN_DAY, 5, 5 * 4, xexpectedCountWithDirs_NoSlash(5));
+  }
+
+  void doRollover(String fileNamePattern, long periodDurationInMillis,
+      int maxHistory, int simulatedNumberOfPeriods, int expectedCount) throws Exception {
     long currentTime = System.currentTimeMillis();
 
     RollingFileAppender<Object> rfa = new RollingFileAppender<Object>();
@@ -78,36 +138,71 @@
 
     tbrp.setMaxHistory(maxHistory);
     tbrp.setParent(rfa);
-    tbrp.timeBasedTriggering = new DefaultTimeBasedFileNamingAndTriggeringPolicy<Object>();
+    tbrp.timeBasedTriggering = tbfnatp;
     tbrp.timeBasedTriggering.setCurrentTime(currentTime);
     tbrp.start();
     rfa.setRollingPolicy(tbrp);
     rfa.start();
 
-    for (int i = 0; i < maxHistory * 3; i++) {
+    int ticksPerPeriod = 64;
+    long runLength = simulatedNumberOfPeriods * ticksPerPeriod;
+
+    for (long i = 0; i < runLength; i++) {
       rfa.doAppend("Hello---" + i);
-      tbrp.timeBasedTriggering.setCurrentTime(addTime(tbrp.timeBasedTriggering.getCurrentTime(), delay / 2));
+      tbrp.timeBasedTriggering.setCurrentTime(addTime(tbrp.timeBasedTriggering
+          .getCurrentTime(), periodDurationInMillis / ticksPerPeriod));
+
       if (tbrp.future != null) {
         tbrp.future.get(200, TimeUnit.MILLISECONDS);
       }
     }
     rfa.stop();
-    check(maxHistory + 1);
+    check(expectedCount);
   }
 
-  void check(int expectedCount) {
-    // remove all files containing the string 'clean'
-    File dir = new File(CoreTestConstants.OUTPUT_DIR_PREFIX);
+  void recursiveDirectoryDescent(File dir, List<File> fileList,
+      final String pattern) {
     if (dir.isDirectory()) {
-      File[] match = dir.listFiles(new FilenameFilter() {
-        public boolean accept(File dir, String name) {
-          return name.contains("clean");
+      File[] match = dir.listFiles(new FileFilter() {
+        public boolean accept(File f) {
+          if (f.isDirectory()) {
+            return true;
+          } else {
+            return f.getName().contains(pattern);
+          }
         }
       });
-      //System.out.println(Arrays.toString(match));
-      assertEquals(expectedCount, match.length);
+      for (File f : match) {
+        fileList.add(f);
+        if (f.isDirectory()) {
+          recursiveDirectoryDescent(f, fileList, pattern);
+        }
+      }
     }
+  }
 
+  int expectedCountWithoutDirs(int maxHistory) {
+    // maxHistory plus the currently active file
+    return maxHistory+1;
+  }
+  
+  int expectedCountWithDirs(int maxHistory) {
+    // each slash adds a new directory
+    // + one file and one directory per archived log file
+    return (maxHistory + 1) * 2 + slashCount;
+  }
+
+  int xexpectedCountWithDirs_NoSlash(int maxHistory) {
+    // each slash adds a new directory
+    // + one file and one directory per archived log file
+    return (maxHistory + 1) * 2;
+  }
+  
+  void check(int expectedCount) {
+    File dir = new File(randomOutputDir);
+    List<File> fileList = new ArrayList<File>();
+    recursiveDirectoryDescent(dir, fileList, "clean");
+    assertEquals(expectedCount, fileList.size());
   }
 
   static long addTime(long currentTime, long timeToWait) {

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/DatePatternToRegexTest.java	Fri Aug  7 18:30:50 2009
@@ -46,10 +46,6 @@
     doTest("yyyy-MMMM-dd", CAL_2009_08_3_NIGHT);
   }
 
-  @Test
-  public void slash() {
-    doTest("yyyy\\MMM\\dd", CAL_2009_08_3_NIGHT, true);
-  }
 
   @Test
   public void dot() {
@@ -93,7 +89,7 @@
     if(slashified) {
       expected = expected.replace('\\', '/');
     }
-    String regex = dtc.toSRegex();
+    String regex = dtc.toRegex();
     //System.out.println("expected="+expected);
     //System.out.println(regex);
     assertTrue("[" + expected + "] does not match regex [" + regex + "]",

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java	Fri Aug  7 18:30:50 2009
@@ -28,19 +28,12 @@
 
   @Test
   public void testSmoke() {
-    // System.out.println("Testing [t]");
     FileNamePattern pp = new FileNamePattern("t", context);
     assertEquals("t", pp.convertInt(3));
 
-    // System.out.println("Testing [foo]");
     pp = new FileNamePattern("foo", context);
     assertEquals("foo", pp.convertInt(3));
 
-    // System.out.println("Testing [foo%]");
-    // pp = new FileNamePattern("foo%", context);
-    // StatusPrinter.print(context.getStatusManager());
-    // assertEquals("foo%", pp.convertInt(3));
-
     pp = new FileNamePattern("%i foo", context);
 
     assertEquals("3 foo", pp.convertInt(3));
@@ -54,11 +47,11 @@
     pp = new FileNamePattern("foo.%i.log", context);
     assertEquals("foo.3.log", pp.convertInt(3));
 
-    pp = new FileNamePattern("%i.foo\\%", context);
-    assertEquals("3.foo%", pp.convertInt(3));
+    //pp = new FileNamePattern("%i.foo\\%", context);
+    //assertEquals("3.foo%", pp.convertInt(3));
 
-    pp = new FileNamePattern("\\%foo", context);
-    assertEquals("%foo", pp.convertInt(3));
+    //pp = new FileNamePattern("\\%foo", context);
+    //assertEquals("%foo", pp.convertInt(3));
   }
 
   @Test
@@ -94,7 +87,7 @@
   @Test
   public void withBackslash() {
     FileNamePattern pp = new FileNamePattern("c:\\foo\\bar.%i", context);
-    assertEquals("c:\\foo\\bar.3", pp.convertInt(3));
+    assertEquals("c:/foo/bar.3", pp.convertInt(3));
   }
 
   @Test
@@ -116,13 +109,13 @@
     {
       FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt",
           context);
-      String regex = fnp.toSRegex(cal.getTime());
+      String regex = fnp.toRegex(cal.getTime());
       assertEquals("foo-2003.05.20-(\\d{1,2}).txt", regex);
     }
     {
       FileNamePattern fnp = new FileNamePattern("\\toto\\foo-%d{yyyy\\MM\\dd}-%i.txt",
           context);
-      String regex = fnp.toSRegex(cal.getTime());
+      String regex = fnp.toRegex(cal.getTime());
       assertEquals("/toto/foo-2003/05/20-(\\d{1,2}).txt", regex);
     }
   }
@@ -133,7 +126,7 @@
     cal.set(2003, 4, 20, 17, 55);
     FileNamePattern fnp = new FileNamePattern("foo-%d{yyyy.MM.dd}-%i.txt",
         context);
-    String regex = fnp.toSRegex();
+    String regex = fnp.toRegex();
     assertEquals("foo-\\d{4}\\.\\d{2}\\.\\d{2}-\\d{1,2}.txt", regex);
   }
 


More information about the logback-dev mailing list