ceki        2004/04/20 11:47:59

  Modified:    src/java/org/apache/log4j/scheduler Scheduler.java
               tests/src/java/org/apache/log4j/scheduler SchedulerTest.java
  Log:
  Schduler is now pretty heavily tested.

  Events can be scheduled and scheduled events can be deleted.
  
  Revision  Changes    Path
  1.2       +38 -11    logging-log4j/src/java/org/apache/log4j/scheduler/Scheduler.java
  
  Index: Scheduler.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/scheduler/Scheduler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Scheduler.java    20 Apr 2004 10:04:04 -0000      1.1
  +++ Scheduler.java    20 Apr 2004 18:47:59 -0000      1.2
  @@ -22,9 +22,9 @@
    */
   package org.apache.log4j.scheduler;
   
  -import java.util.Date;
  -import java.util.LinkedList;
   import java.util.List;
  +import java.util.NoSuchElementException;
  +import java.util.Vector;
   
   
   /**
  @@ -40,10 +40,40 @@
     long key;
     
     public Scheduler() {
  -    jobList = new LinkedList();
  +    jobList = new Vector();
     }
  -  public synchronized long schedule(Job job, Date date) {
  -    long timeInMillis = date.getTime();
  +
  +  public synchronized void delete(Job job) {
  +    int size = jobList.size();
  +    boolean found = false;
  +    // find the index i such that 
  +    int i = 0;
  +
  +    for (; i < size; i++) {
  +      ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
  +      if(se.job == job) {
  +        found = true;
  +        break;
  +      }
  +    }
  +    
  +    if(found) {
  +      ScheduledJobEntry se = (ScheduledJobEntry) jobList.remove(i);
  +      if(se.job != job) {
  +        new IllegalStateException();
  +      }
  +      // if the job is the first on the list, then notify the scheduler thread
  +      // to schedule a new job
  +      if(i == 0) {
  +        this.notify();
  +      }
  +    } else {
  +      throw new NoSuchElementException();
  +    }
  +  }
  +  
  +  public synchronized void schedule(Job job, long expectedTime) {
  +   
   
       int size = jobList.size();
   
  @@ -53,16 +83,15 @@
       for (; i < size; i++) {
         ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
   
  -      if (timeInMillis < se.timeInMillis) {
  +      if (expectedTime < se.timeInMillis) {
           break;
         }
       }
  -    jobList.add(i, new ScheduledJobEntry(key, job, timeInMillis));
  +    jobList.add(i, new ScheduledJobEntry(job, expectedTime));
       // if the jobList was empty, then notify the scheduler thread
       if(i == 0) {
         this.notify();
       }
  -    return key++;
     }
   
     public synchronized void run() {
  @@ -104,10 +133,8 @@
   class ScheduledJobEntry {
     long timeInMillis;
     Job job;
  -  long key;
     
  -  ScheduledJobEntry(long key, Job job, long timeInMillis) {
  -    this.key = key;
  +  ScheduledJobEntry(Job job, long timeInMillis) {
       this.timeInMillis = timeInMillis;
       this.job = job;
     }
  
  
  
  1.2       +156 -33   
logging-log4j/tests/src/java/org/apache/log4j/scheduler/SchedulerTest.java
  
  Index: SchedulerTest.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/tests/src/java/org/apache/log4j/scheduler/SchedulerTest.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SchedulerTest.java        20 Apr 2004 10:04:04 -0000      1.1
  +++ SchedulerTest.java        20 Apr 2004 18:47:59 -0000      1.2
  @@ -16,19 +16,23 @@
   
   package org.apache.log4j.scheduler;
   
  -import java.util.Date;
  +import junit.framework.Test;
  +import junit.framework.TestCase;
  +import junit.framework.TestSuite;
  +
   import java.util.Iterator;
  +import java.util.Random;
   import java.util.Vector;
   
  -import junit.framework.TestCase;
  -
   
   /**
    * @author Ceki Gulcu
    *
    */
   public class SchedulerTest extends TestCase {
  -  static final long TOLERATED_GAP = 50;
  +  static final long TOLERATED_GAP = 1000;
  +  Random random = new Random(480361007);
  +  final long START_TIME = System.currentTimeMillis();
     
     public SchedulerTest(String arg0) {
       super(arg0);
  @@ -45,59 +49,178 @@
     public void testBasic() {
       Scheduler scheduler = new Scheduler();
       scheduler.start();
  +
       long now = System.currentTimeMillis();
       long expected = now + 100;
  -    CountingJob cj = new CountingJob(expected);
  -    scheduler.schedule(cj, new Date(expected));
  +    CountingJob cj = new CountingJob(0, expected);
  +    scheduler.schedule(cj, expected);
       sleep(300);
       assertEquals(1, cj.count);
     }
  -  
  -  public void testMultipleEvent() {
  +
  +  public void testMultipleEvents() {
       Vector jobs = new Vector();
       Scheduler scheduler = new Scheduler();
       scheduler.start();
  +
       long now = System.currentTimeMillis();
  -    
  -    for(int i = 0; i < 40; i++) {
  -      long expected = now + i*100;
  -      CountingJob cj = new CountingJob(expected);
  +
  +    int loopLength = 100;
  +
  +    for (int i = 0; i < loopLength; i++) {
  +      long expected = now + (i * 100);
  +      CountingJob cj = new CountingJob(i, expected);
         jobs.add(cj);
  -      scheduler.schedule(cj, new Date(expected));
  +      scheduler.schedule(cj, expected);
  +    }
  +
  +    sleep((100 * loopLength) + 200);
  +
  +    for (Iterator i = jobs.iterator(); i.hasNext();) {
  +      CountingJob cj = (CountingJob) i.next();
  +      assertEquals(1, cj.count);
  +    }
  +  }
  +
  +  public void testDelete() {
  +    Vector jobs = new Vector();
  +    Scheduler scheduler = new Scheduler();
  +    scheduler.start();
  +
  +    long now = System.currentTimeMillis();
  +
  +    long expected0 = now + 200;
  +    CountingJob cj0 = new CountingJob(0, expected0);
  +    long expected1 = expected0 + 200;
  +    CountingJob cj1 = new CountingJob(1, expected1);
  +    scheduler.schedule(cj0, expected0);
  +    scheduler.schedule(cj1, expected1);
  +    scheduler.delete(cj0);
  +    sleep(100 + (3 * 200));
  +    assertEquals(0, cj0.count);
  +    assertEquals(1, cj1.count);
  +  }
  +
  +  /**
  +   * A test that inserts and deltes a large number of jobs at random
  +   */
  +  public void testRandom() {
  +    Scheduler scheduler = new Scheduler();
  +    scheduler.start();
  +
  +    Vector jobVector = new Vector();
  +    Vector deletedVector = new Vector();
  +
  +    // the approximative duration of this test in millisecs
  +    final int TEST_DURATION = 50000;
  +
  +    // the frequncy of operations in millisecs
  +    final int OP_FREQUENCY = 10;
  +
  +    // The number of times we will perform an operation on the scheduler
  +    final int MAX_OPS = TEST_DURATION / OP_FREQUENCY;
  +
  +    long start = System.currentTimeMillis();
  +
  +    for (long i = 0; i < MAX_OPS; i++) {
  +      if (shouldDelete() && !jobVector.isEmpty()) {
  +        int indexToDelete = getRandomIndexToDelete(jobVector.size());
  +        CountingJob j = (CountingJob) jobVector.remove(indexToDelete);
  +        if (j.count == 0) {
  +          scheduler.delete(j);
  +          deletedVector.add(j);
  +          if(j.count == 1) {
  +            fail("Error in the test code itself.");
  +          }
  +        }
  +      } else {
  +        long expected = start + random.nextInt(TEST_DURATION);
  +        CountingJob cj = new CountingJob((int) i, expected);
  +        jobVector.add(cj);
  +        scheduler.schedule(cj, expected);
  +      }
  +    }
  +    long loopEnd = System.currentTimeMillis();
  +    sleep(TEST_DURATION - (loopEnd - start) + 2000);
  +
  +    if (deletedVector.size() > (MAX_OPS/2)) {
  +      fail("too many deleted jobs: " + deletedVector.size());
  +    }
  +     if (jobVector.size() < (MAX_OPS/2)) {
  +      fail("too few jobs: " + jobVector.size());
       }
       
  -    sleep(100*40+200);
  -    for(Iterator i = jobs.iterator(); i.hasNext();) {
  +    for (Iterator i = jobVector.iterator(); i.hasNext();) {
         CountingJob cj = (CountingJob) i.next();
         assertEquals(1, cj.count);
  -    }  
  +    }
  +    for (Iterator i = deletedVector.iterator(); i.hasNext();) {
  +      CountingJob cj = (CountingJob) i.next();
  +      assertEquals(0, cj.count);
  +    }
     }
  -  
  -  
  +
  +  boolean shouldDelete() {
  +    int r = random.nextInt(2);
  +
  +    if (r == 2) {
  +      return true;
  +    } else {
  +      return false;
  +    }
  +  }
  +
  +  // On average, make the index of 1 out of 5 deletes zero
  +  int getRandomIndexToDelete(int range) {
  +     int r = random.nextInt(5);
  +     if(r == 0) {
  +       return 0;
  +     } else {
  +       return random.nextInt(range);
  +     }
  +  }
  +
     void sleep(long duration) {
       try {
         Thread.sleep(duration);
  -    } catch(InterruptedException ie) {
  -   }
  +    } catch (InterruptedException ie) {
  +    }
     }
  -}
   
  -
  -class CountingJob implements Job {
  -
  -  int count = 0; 
  +  public static Test suite() {
  +    TestSuite suite = new TestSuite();
  +    suite.addTest(new SchedulerTest("testRandom"));
  +    return suite;
  +  }
  +  
  +  
  +  
  +  class CountingJob implements Job {
  +  int count = 0;
  +  int id;
     long scheduledTime;
  -  CountingJob(long scheduledTime) {
  +
  +  CountingJob(int id, long scheduledTime) {
  +    this.id = id;
       this.scheduledTime = scheduledTime;
     }
  -  
  +
     public void execute() {
       long now = System.currentTimeMillis();
  -    if(now < scheduledTime) {
  -     throw new IllegalStateException("Job executed too early.");
  -    } else if((now - scheduledTime) > SchedulerTest.TOLERATED_GAP) {
  -      throw new IllegalStateException("Job executed too late");    
  +    count++;
  +    if (now < scheduledTime) {
  +      throw new IllegalStateException("Job executed too early.");
  +    } else if ((now - scheduledTime) > SchedulerTest.TOLERATED_GAP) {
  +      String msg =
  +        "Job id "+id+" executed " + (now - scheduledTime) + " too late "+
  +        "diff "+(scheduledTime-SchedulerTest.this.START_TIME);
  +        System.out.println(msg);
  +      throw new IllegalStateException(msg);
       }
  -    count++;    
     }
  -}
  \ No newline at end of file
  +}
  +}
  +
  +
  +
  +
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to