package org.jboss.cache.lock;

import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Tests the various ReadWriteLock implementations
 * @author Bela Ban
 * @version $Id: ReadWriteLockTest.java 1838 2006-05-05 12:06:59Z msurtani $
 */
public class ReadWriteLockTest extends TestCase {
   ReadWriteLock lock;
   Exception  ex=null;


   protected void setUp() throws Exception {
      super.setUp();
      ex=null;
   }

   protected void tearDown() throws Exception {
      super.tearDown();
      lock=null;
      if(ex != null)
         throw ex;
   }


   public void testMoreWriteReleasesThanAcquisitions() throws InterruptedException {
      lock=new ReentrantWriterPreferenceReadWriteLock();
      lock.writeLock().acquire();
      lock.writeLock().release();
      lock.writeLock().release();
   }

   public void testMoreReadReleasesThanAcquisitions() throws InterruptedException {
      lock=new ReentrantWriterPreferenceReadWriteLock();
      lock.readLock().acquire();
      lock.readLock().release();
      try {
         lock.readLock().release();
         fail("read locks cannot be released more than acquired");
      }
      catch(IllegalStateException illegalStateEx) {

      }
   }

   public void testSimple() throws InterruptedException {
      lock=new ReentrantWriterPreferenceReadWriteLock();
      lock.readLock().acquire();
      lock.readLock().acquire();
      lock.writeLock().acquire();
      lock.writeLock().acquire();
   }


   public void testOneWriterMultipleReaders() throws InterruptedException {
      lock=new ReentrantWriterPreferenceReadWriteLock();

      Writer writer=new Writer("writer");
      Reader reader1=new Reader("reader1");
      Reader reader2=new Reader("reader2");

      writer.start();
      reader1.start();
      reader2.start();

      writer.join();
      reader1.join();
      reader2.join();
   }

   class Writer extends Thread {

      public Writer(String name) {
         super(name);
      }

      public void run() {
         try {
            log("acquiring WL");
            lock.writeLock().acquire();
            log("acquired WL successfully");
            sleep(1000);
         }
         catch(InterruptedException e) {
            ex=e;
         }
         finally {
            log("releasing WL");
            lock.writeLock().release();
         }
      }
   }


   class Reader extends Thread {

      public Reader(String name) {
         super(name);
      }


      public void run() {
         try {
            log("acquiring RL");
            lock.readLock().acquire();
            log("acquired RL successfully");
            sleep(500);
         }
         catch(InterruptedException e) {
            ex=e;
         }
         finally {
            log("releasing RL");
            lock.readLock().release();
         }
      }
   }

   static void log(String msg) {
      System.out.println(Thread.currentThread().getName() + ": " +  msg);
   }

   public static Test suite() {
      return new TestSuite(ReadWriteLockTest.class);
   }

   public static void main(String[] args) {
      junit.textui.TestRunner.run(suite());
   }

}
