[logback-dev] svn commit: r2084 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic/turbo logback-classic/src/test/input/joran/hoard logback-classic/src/test/java/ch/qos/logback/classic logback-classic/src/test/java/ch/qos/logback/classic/hoard logback-classic/src/test/java/ch/qos/logback/classic/turbo logback-core/src/main/java/ch/qos/logback/core logback-core/src/main/java/ch/qos/logback/core/helpers logback-core/src/main/java/ch/qos/logback/core/joran/action logback-core/src/main/java/ch/qos/logback/core/read logback-core/src/main/java/ch/qos/logback/core/status logback-core/src/test/java/ch/qos/logback/core

noreply.ceki at qos.ch noreply.ceki at qos.ch
Thu Dec 18 21:11:24 CET 2008


Author: ceki
Date: Thu Dec 18 21:11:24 2008
New Revision: 2084

Added:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java
   logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java
Modified:
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java

Log:
- added DuplicateMessageFilter
- BasicStatusMessages's internal buffer now has two parts, the head part and the tail part.

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java	Thu Dec 18 21:11:24 2008
@@ -0,0 +1,68 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, 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.classic.turbo;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.core.spi.FilterReply;
+
+public class DuplicateMessageFilter extends TurboFilter {
+
+  static final int DEFAULT_CACHE_SIZE = 100;
+  static final int DEFAULT_ALLOWED_REPETITIONS = 5;
+ 
+  public int allowedRepetitions = DEFAULT_ALLOWED_REPETITIONS;
+  public int cacheSize = DEFAULT_CACHE_SIZE;
+  
+  private LRUMessageCache msgCache;
+  
+  @Override
+  public void start() {
+    msgCache = new LRUMessageCache(cacheSize);
+    super.start();
+  }
+ 
+  @Override
+  public void stop() {
+    msgCache.clear();
+    msgCache = null;
+    super.stop();
+  }
+
+  @Override
+  public FilterReply decide(Marker marker, Logger logger, Level level,
+      String format, Object[] params, Throwable t) {
+    int count = msgCache.getMessageCount(format);
+    if(count <= allowedRepetitions) {
+      return FilterReply.NEUTRAL;
+    } else {
+      return FilterReply.DENY;
+    }
+  }
+
+  public int getAllowedRepetitions() {
+    return allowedRepetitions;
+  }
+
+  public void setAllowedRepetitions(int allowedRepetitions) {
+    this.allowedRepetitions = allowedRepetitions;
+  }
+
+  public int getCacheSize() {
+    return cacheSize;
+  }
+
+  public void setCacheSize(int cacheSize) {
+    this.cacheSize = cacheSize;
+  }
+  
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/turbo/LRUMessageCache.java	Thu Dec 18 21:11:24 2008
@@ -0,0 +1,43 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, 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.classic.turbo;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+class LRUMessageCache extends LinkedHashMap<String, Integer> {
+
+  private static final long serialVersionUID = 1L;
+  
+  final int cacheSize;
+  
+  LRUMessageCache(int cacheSize) {
+    super((int) (cacheSize * (4.0f / 3)), 0.75f, true);
+    if (cacheSize < 1) {
+      throw new IllegalArgumentException("Cache size cannnot be smaller than 1");
+    }
+    this.cacheSize = cacheSize;
+  }
+  
+  int getMessageCount(String msg) {
+    Integer i = super.get(msg);
+    if(i == null) {
+      i = 1;
+    } else {
+      i = new Integer(i.intValue()+1);
+    }
+    super.put(msg, i);
+    return i;
+  }
+  
+  protected boolean removeEldestEntry(Map.Entry eldest) {
+    return (size() > cacheSize);
+  }
+}

Added: logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/joran/hoard/completeCycle.xml	Thu Dec 18 21:11:24 2008
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration>
+
+<configuration debug="true">
+
+  <appender name="HOARD"
+    class="ch.qos.logback.classic.hoard.HoardingAppender">
+
+    <mdcKey>cycle</mdcKey>
+    <defaultValue>cycleDefault</defaultValue>
+    <hoard>
+      <appender name="list-${cycle}" class="ch.qos.logback.core.read.ListAppender"/>
+    </hoard>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="HOARD" />
+  </root>
+
+</configuration>

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java	Thu Dec 18 21:11:24 2008
@@ -33,7 +33,7 @@
     suite.addTest(ch.qos.logback.classic.pattern.PackageTest.suite());
     suite.addTest(ch.qos.logback.classic.db.PackageTest.suite());
     suite.addTest(ch.qos.logback.classic.spi.PackageTest.suite());
-    suite.addTest(ch.qos.logback.classic.turbo.PackageTest.suite());
+    suite.addTest(new JUnit4TestAdapter(ch.qos.logback.classic.turbo.PackageTest.class));
     suite.addTest(new JUnit4TestAdapter(
         ch.qos.logback.classic.hoard.PackageTest.class));
 

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/AppenderTrackerTest.java	Thu Dec 18 21:11:24 2008
@@ -24,9 +24,17 @@
     la.setContext(context);
     la.start();
   }
+
   
   @Test
-  public void empty() {
+  public void empty0() {
+    long now = 3000;
+    appenderTracker.stopStaleAppenders(now);
+    assertEquals(0, appenderTracker.keyList().size());
+  }
+  
+  @Test
+  public void empty1() {
     long now = 3000;
     assertNull(appenderTracker.get("a", now++));
     now += AppenderTrackerImpl.THRESHOLD+1000;

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/hoard/HoardingAppenderTest.java	Thu Dec 18 21:11:24 2008
@@ -16,7 +16,9 @@
 import java.util.List;
 
 import org.junit.Test;
+import org.slf4j.MDC;
 
+import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
@@ -56,8 +58,8 @@
     long timestamp = 0;
     HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
     ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("smoke", timestamp);
-    StatusPrinter.print(loggerContext);
     
+    StatusPrinter.print(loggerContext);
     assertNotNull(listAppender);
     List<LoggingEvent> eventList = listAppender.list;
     assertEquals(1, listAppender.list.size());
@@ -65,11 +67,28 @@
   }
 
   @Test
-  public void testLevel() throws JoranException {
-    configure(PREFIX + "hoard0.xml");
-    logger.debug("ss");
-    //StatusPrinter.print(loggerContext);
+  public void testWholeCycle() throws JoranException {
+    String mdcKey = "cycle";
+    configure(PREFIX + "completeCycle.xml");
+    MDC.put(mdcKey, "a");
+    logger.debug("smoke");
+    long timestamp = System.currentTimeMillis();
+    HoardingAppender ha = (HoardingAppender) root.getAppender("HOARD");
+    ListAppender<LoggingEvent> listAppender = (ListAppender<LoggingEvent>) ha.appenderTracker.get("a", timestamp);
+    StatusPrinter.print(loggerContext);
     
-  }
+    assertNotNull(listAppender);
+    List<LoggingEvent> eventList = listAppender.list;
+    assertEquals(1, listAppender.list.size());
+    assertEquals("smoke", eventList.get(0).getMessage());
 
+    MDC.remove(mdcKey);
+    LoggingEvent le = new LoggingEvent("x", logger, Level.INFO, "hello", null, null);
+    le.setTimeStamp(timestamp+AppenderTracker.THRESHOLD*2);
+    ha.doAppend(le);
+    assertFalse(listAppender.isStarted());
+    assertEquals(1, ha.appenderTracker.keyList().size());
+    assertEquals("cycleDefault", ha.appenderTracker.keyList().get(0));
+    
+  }
 }

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/DuplicateMessageFilterTest.java	Thu Dec 18 21:11:24 2008
@@ -0,0 +1,54 @@
+package ch.qos.logback.classic.turbo;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import ch.qos.logback.core.spi.FilterReply;
+
+
+public class DuplicateMessageFilterTest {
+
+  
+  @Test
+  public void smoke() {
+    DuplicateMessageFilter dmf = new DuplicateMessageFilter();
+    dmf.setAllowedRepetitions(1);
+    dmf.start();
+    assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "x", null, null));
+    assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "y", null, null));
+    assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "x", null, null));
+    assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "y", null, null));
+  }
+  
+  @Test
+  public void memoryLoss() {
+    DuplicateMessageFilter dmf = new DuplicateMessageFilter();
+    dmf.setAllowedRepetitions(1);
+    dmf.setCacheSize(1);
+    dmf.start();
+    assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, null));
+    assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "b", null, null));
+    assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a", null, null));
+  }
+
+  
+  @Test
+  public void many() {
+    DuplicateMessageFilter dmf = new DuplicateMessageFilter();
+    dmf.setAllowedRepetitions(1);
+    int cacheSize = 10;
+    int margin  = 2;
+    dmf.setCacheSize(cacheSize);
+    dmf.start();
+    for(int i = 0; i < cacheSize+margin; i++) {
+      assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a"+i, null, null));
+    }
+    for(int i = cacheSize-1; i >= margin; i--) {
+      assertEquals(FilterReply.DENY, dmf.decide(null, null, null, "a"+i, null, null));
+    }
+    for(int i = margin-1; i >= 0; i--) {
+      assertEquals(FilterReply.NEUTRAL, dmf.decide(null, null, null, "a"+i, null, null));
+    }
+  }
+}

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/MarkerFilterTest.java	Thu Dec 18 21:11:24 2008
@@ -1,30 +1,23 @@
 package ch.qos.logback.classic.turbo;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
 import org.slf4j.Marker;
 import org.slf4j.MarkerFactory;
 
 import ch.qos.logback.core.spi.FilterReply;
 
-import junit.framework.TestCase;
-
-public class MarkerFilterTest extends TestCase {
+public class MarkerFilterTest {
 
   static String MARKER_NAME = "toto";
   
   Marker totoMarker = MarkerFactory.getMarker(MARKER_NAME);
   
-  public MarkerFilterTest(String arg0) {
-    super(arg0);
-  }
-
-  protected void setUp() throws Exception {
-    super.setUp();
-  }
-
-  protected void tearDown() throws Exception {
-    super.tearDown();
-  }
 
+  @Test
   public void testNoMarker() {
     MarkerFilter mkt = new MarkerFilter();
     mkt.start();
@@ -33,7 +26,9 @@
     assertEquals(FilterReply.NEUTRAL, mkt.decide(null, null, null, null, null, null));
 
   }
-  
+
+
+  @Test
   public void testBasic() {
     MarkerFilter mkt = new MarkerFilter();
     mkt.setMarker(MARKER_NAME);

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/turbo/PackageTest.java	Thu Dec 18 21:11:24 2008
@@ -10,15 +10,11 @@
 package ch.qos.logback.classic.turbo;
 
 
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
 
-public class PackageTest extends TestCase {
-  
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTestSuite(MarkerFilterTest.class);
-    return suite;
-  }
+ at RunWith(Suite.class)
+ at SuiteClasses( { MarkerFilterTest.class, DuplicateMessageFilterTest.class})
+public class PackageTest  {
 }
\ No newline at end of file

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java	Thu Dec 18 21:11:24 2008
@@ -12,18 +12,22 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import ch.qos.logback.core.helpers.CyclicBuffer;
 import ch.qos.logback.core.status.Status;
 import ch.qos.logback.core.status.StatusListener;
 import ch.qos.logback.core.status.StatusManager;
 
 public class BasicStatusManager implements StatusManager {
 
-  public static final int MAX_COUNT = 200;
+  public static final int MAX_HEADER_COUNT = 150;
+  public static final int TAIL_SIZE = 150; 
 
   int count = 0;
 
   // protected access was requested in http://jira.qos.ch/browse/LBCORE-36
   final protected List<Status> statusList = new ArrayList<Status>();
+  final protected CyclicBuffer<Status> tailBuffer = new CyclicBuffer<Status>(
+      TAIL_SIZE);
   final protected Object statusListLock = new Object();
 
   int level = Status.INFO;
@@ -34,7 +38,7 @@
 
   // Note on synchronization
   // This class contains two separate locks statusListLock and
-  // statusListenerListLock guarding respectively the statusList and
+  // statusListenerListLock guarding respectively the statusList+tailBuffer and
   // statusListenerList fields. The locks are used internally
   // without cycles. They are exposed to derived classes which should be careful
   // not to create deadlock cycles.
@@ -49,21 +53,28 @@
     // LBCORE-72: fire event before the count check
     fireStatusAddEvent(newStatus);
 
-    if (count > MAX_COUNT) {
-      return;
-    }
     count++;
-
     if (newStatus.getLevel() > level) {
       level = newStatus.getLevel();
     }
 
     synchronized (statusListLock) {
-      statusList.add(newStatus);
+      if (statusList.size() < MAX_HEADER_COUNT) {
+        statusList.add(newStatus);
+      } else {
+        tailBuffer.add(newStatus);
+      }
     }
 
   }
-
+  public List<Status> getCopyOfStatusList() {
+    synchronized (statusListLock) {
+      List<Status> tList = new ArrayList<Status>(statusList);
+      tList.addAll(tailBuffer.asList());
+      return tList;
+    }
+  }
+  
   private void fireStatusAddEvent(Status status) {
     synchronized (statusListenerListLock) {
       for (StatusListener sl : statusListenerList) {
@@ -72,12 +83,6 @@
     }
   }
 
-  public List<Status> getCopyOfStatusList() {
-    synchronized (statusListLock) {
-      return new ArrayList<Status>(statusList);
-    }
-  }
-
   public int getLevel() {
     return level;
   }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java	Thu Dec 18 21:11:24 2008
@@ -10,14 +10,14 @@
 
 package ch.qos.logback.core.helpers;
 
+import java.util.ArrayList;
+import java.util.List;
 
 /**
+ * CyclicBuffer holds values in a cyclic array.
  * 
- * CyclicBuffer is used by other appenders to hold
- * objects for immediate or differed display.
- * <p>
- * This buffer gives read access to any element in the buffer not just the first
- * or last element.
+ * <p>It allows read access to any element in the buffer not just the first or
+ * last element.
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
@@ -35,7 +35,7 @@
    * The <code>maxSize</code> argument must a positive integer.
    * 
    * @param maxSize
-   *          The maximum number of elements in the buffer.
+   *                The maximum number of elements in the buffer.
    */
   @SuppressWarnings("unchecked")
   public CyclicBuffer(int maxSize) throws IllegalArgumentException {
@@ -45,7 +45,7 @@
     }
     init(maxSize);
   }
-  
+
   @SuppressWarnings("unchecked")
   private void init(int maxSize) {
     this.maxSize = maxSize;
@@ -54,10 +54,9 @@
     last = 0;
     numElems = 0;
   }
-  
+
   /**
-   * Clears the buffer
-   * and resets all attributes.
+   * Clears the buffer and resets all attributes.
    */
   public void clear() {
     init(this.maxSize);
@@ -94,7 +93,6 @@
     return maxSize;
   }
 
-
   /**
    * Get the oldest (first) element in the buffer. The oldest element is removed
    * from the buffer.
@@ -110,6 +108,14 @@
     }
     return r;
   }
+  
+  public List<E> asList() {
+    List<E> tList = new ArrayList<E>();
+    for(int i = 0; i < length(); i++) {
+      tList.add(get(i));
+    }
+    return tList;
+  }
 
   /**
    * Get the number of elements in the buffer. This number is guaranteed to be
@@ -123,7 +129,7 @@
    * Resize the cyclic buffer to <code>newSize</code>.
    * 
    * @throws IllegalArgumentException
-   *           if <code>newSize</code> is negative.
+   *                 if <code>newSize</code> is negative.
    */
   @SuppressWarnings("unchecked")
   public void resize(int newSize) {

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java	Thu Dec 18 21:11:24 2008
@@ -52,7 +52,7 @@
 
       appender.setContext(context);
 
-      String appenderName = attributes.getValue(NAME_ATTRIBUTE);
+      String appenderName = ec.subst(attributes.getValue(NAME_ATTRIBUTE));
 
       if (OptionHelper.isEmpty(appenderName)) {
         addWarn("No appender name given for appender of type " + className

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/read/ListAppender.java	Thu Dec 18 21:11:24 2008
@@ -1,11 +1,11 @@
 /**
- * LOGBack: the generic, reliable, fast and flexible logging framework.
- *
- * Copyright (C) 1999-2006, 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.
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, 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.read;
 

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/status/StatusBase.java	Thu Dec 18 21:11:24 2008
@@ -139,4 +139,33 @@
     return buf.toString();
   }
 
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + level;
+    result = prime * result + ((message == null) ? 0 : message.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    final StatusBase other = (StatusBase) obj;
+    if (level != other.level)
+      return false;
+    if (message == null) {
+      if (other.message != null)
+        return false;
+    } else if (!message.equals(other.message))
+      return false;
+    return true;
+  }
+
+  
 }

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java	Thu Dec 18 21:11:24 2008
@@ -14,7 +14,8 @@
 import org.junit.runners.Suite.SuiteClasses;
 
 @RunWith(Suite.class)
- at SuiteClasses({ch.qos.logback.core.util.PackageTest.class,
+ at SuiteClasses({BasicStatusManagerTest.class,
+  ch.qos.logback.core.util.PackageTest.class,
   ch.qos.logback.core.helpers.PackageTest.class,
   ch.qos.logback.core.pattern.PackageTest.class,
   ch.qos.logback.core.PackageTest.class,

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/BasicStatusManagerTest.java	Thu Dec 18 21:11:24 2008
@@ -0,0 +1,53 @@
+package ch.qos.logback.core;
+
+import static ch.qos.logback.core.BasicStatusManager.MAX_HEADER_COUNT;
+import static ch.qos.logback.core.BasicStatusManager.TAIL_SIZE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import ch.qos.logback.core.status.ErrorStatus;
+import ch.qos.logback.core.status.Status;
+
+
+public class BasicStatusManagerTest {
+
+  
+  BasicStatusManager bsm = new BasicStatusManager();
+  
+  @Test
+  public void smoke() {
+    bsm.add(new ErrorStatus("hello", this));
+    assertEquals(Status.ERROR, bsm.getLevel());
+    
+    List<Status> statusList = bsm.getCopyOfStatusList();
+    assertNotNull(statusList);
+    assertEquals(1, statusList.size());
+    assertEquals("hello", statusList.get(0).getMessage());
+  }
+  
+  @Test
+  public void many() {
+    int margin = 300;
+    int len = MAX_HEADER_COUNT+TAIL_SIZE+margin;
+    for(int i = 0; i < len; i++) {
+      bsm.add(new ErrorStatus(""+i, this));
+    }
+    
+    List<Status> statusList = bsm.getCopyOfStatusList();
+    assertNotNull(statusList);
+    assertEquals(MAX_HEADER_COUNT+TAIL_SIZE, statusList.size());
+    List<Status> witness = new ArrayList<Status>();
+    for(int i = 0; i < MAX_HEADER_COUNT; i++) {
+      witness.add(new ErrorStatus(""+i, this));
+    }
+    for(int i = 0; i < TAIL_SIZE; i++) {
+      witness.add(new ErrorStatus(""+(MAX_HEADER_COUNT+margin+i), this));
+    }
+    assertEquals(witness, statusList);
+  }
+}


More information about the logback-dev mailing list