/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.lock;

import junit.framework.TestCase;
import junit.framework.Test;
import junit.framework.TestSuite;
import EDU.oswego.cs.dl.util.concurrent.Sync;
import org.jboss.cache.misc.TestingUtil;

/**
 * Tests ReentrantWriterPreferenceReadWriteLock
 * @author Bela Ban
 * @version $Id: ReentrantWriterPreference2Readers1WriterLockTest.java 1838 2006-05-05 12:06:59Z msurtani $
 */
public class ReentrantWriterPreference2Readers1WriterLockTest extends TestCase {
   // ReentrantWriterPreferenceReadWriteLock lock;
   SimpleReadWriteLock lock;
   Sync rl, wl;
   Exception thread_ex=null;

   protected void setUp() throws Exception {
      super.setUp();
      // lock=new ReentrantWriterPreferenceReadWriteLock();
      lock=new SimpleReadWriteLock();
      rl=lock.readLock();
      wl=lock.writeLock();
      thread_ex=null;
   }

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



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

    public void test2ReadersAnd1Writer() throws InterruptedException {
      Upgrader upgrader=new Upgrader("Upgrader");
      Reader reader=new Reader("Reader");
      upgrader.start();
      reader.start();

      TestingUtil.sleepThread(500);
      synchronized(upgrader) {
         upgrader.notify();
      }
      TestingUtil.sleepThread(500);
      synchronized(reader) {
         reader.notify();
      }
      reader.join();
      upgrader.join(3000);
      assertTrue("Known failure. See JBCACHE-461; This is due to a bug in ReentrantWriterPreferenceReadWriteLock !", upgrader.wasUpgradeSuccessful());
   }



   class Reader extends Thread {

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

      public void run() {
         try {
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquiring RL");
            rl.acquire();
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquired RL");
            synchronized(this) {
               this.wait();
            }
            ReentrantWriterPreference2Readers1WriterLockTest.log("releasing RL");
            rl.release();
            ReentrantWriterPreference2Readers1WriterLockTest.log("released RL");
         }
         catch(InterruptedException e) {
            ;
         }
      }
   }


   class Writer extends Thread {

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

      public void run() {
         try {
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquiring WL");
            wl.acquire();
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquired WL");
            synchronized(this) {
               this.wait();
            }
            ReentrantWriterPreference2Readers1WriterLockTest.log("releasing WL");
            wl.release();
            ReentrantWriterPreference2Readers1WriterLockTest.log("released WL");
         }
         catch(InterruptedException e) {
            ;
         }
      }
   }


   class Upgrader extends Thread {
      boolean upgradeSuccessful=false;
      public Upgrader(String name) {
         super(name);
      }

      public boolean wasUpgradeSuccessful() {
         return upgradeSuccessful;
      }


      public void run() {
         try {
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquiring RL");
            rl.acquire();
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquired RL");
            synchronized(this) {
               this.wait();
            }
            ReentrantWriterPreference2Readers1WriterLockTest.log("attempting to acquire WL");
            // rl.release();
            wl.acquire();
            upgradeSuccessful=true;
            ReentrantWriterPreference2Readers1WriterLockTest.log("acquired WL");
            ReentrantWriterPreference2Readers1WriterLockTest.log("releasing WL/RL");
            wl.release();
            ReentrantWriterPreference2Readers1WriterLockTest.log("released WL/RL");
         }
         catch(InterruptedException e) {
            ;
         }
      }
   }



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

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

}
