Clover coverage report -
Coverage timestamp: Wed Jan 31 2007 15:38:53 EST
file stats: LOC: 235   Methods: 7
NCLOC: 163   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
IsolationLevelReadCommittedNodeCreationRollbackTest.java 12.5% 82.2% 100% 77.3%
coverage coverage
 1    /*
 2    * JBoss, Home of Professional Open Source
 3    *
 4    * Distributable under LGPL license.
 5    * See terms of license at gnu.org.
 6    */
 7    package org.jboss.cache.transaction;
 8   
 9    import junit.framework.AssertionFailedError;
 10    import junit.framework.Test;
 11    import junit.framework.TestCase;
 12    import junit.framework.TestSuite;
 13    import org.jboss.cache.CacheImpl;
 14    import org.jboss.cache.DefaultCacheFactory;
 15    import org.jboss.cache.DummyTransactionManagerLookup;
 16    import org.jboss.cache.Fqn;
 17    import org.jboss.cache.config.Configuration;
 18    import org.jboss.cache.lock.IsolationLevel;
 19    import org.jboss.cache.lock.TimeoutException;
 20   
 21    import javax.transaction.NotSupportedException;
 22    import javax.transaction.SystemException;
 23    import javax.transaction.Transaction;
 24    import java.util.concurrent.CountDownLatch;
 25    import java.util.concurrent.TimeUnit;
 26   
 27    /**
 28    * Tests READ_COMMITED isolation level.
 29    *
 30    * @author <a href="mailto:ovidiu@jboss.org">Ovidiu Feodorov</a>
 31    * @version $Id: IsolationLevelReadCommittedNodeCreationRollbackTest.java,v 1.6 2007/01/31 02:40:20 msurtani Exp $
 32    */
 33   
 34    public class IsolationLevelReadCommittedNodeCreationRollbackTest extends TestCase
 35    {
 36   
 37    private CacheImpl cache = null;
 38    private final Fqn FQN = Fqn.fromString("/a/b/c");
 39    private final String KEY = "key";
 40    private final String VALUE = "value";
 41   
 42    private volatile boolean writerFailed;
 43    private volatile boolean readerFailed;
 44    private volatile AssertionFailedError writerError;
 45    private volatile AssertionFailedError readerError;
 46   
 47  1 protected void setUp() throws Exception
 48    {
 49  1 super.setUp();
 50   
 51  1 writerFailed = false;
 52  1 readerFailed = false;
 53   
 54  1 writerError = null;
 55  1 readerError = null;
 56   
 57  1 cache = (CacheImpl) DefaultCacheFactory.getInstance().createCache(false);
 58  1 cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
 59  1 cache.getConfiguration().setIsolationLevel(IsolationLevel.READ_COMMITTED);
 60  1 cache.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
 61  1 cache.start();
 62    }
 63   
 64   
 65  1 protected void tearDown() throws Exception
 66    {
 67  1 super.tearDown();
 68   
 69  1 cache.stop();
 70  1 cache.destroy();
 71  1 cache = null;
 72    }
 73   
 74   
 75  1 public void testNodeCreationRollback() throws Exception
 76    {
 77  1 final CountDownLatch secondCanWrite = new CountDownLatch(1);
 78  1 final CountDownLatch secondCanRead = new CountDownLatch(1);
 79  1 final CountDownLatch secondDone = new CountDownLatch(1);
 80  1 final CountDownLatch firstCanRollback = new CountDownLatch(1);
 81  1 final CountDownLatch firstDone = new CountDownLatch(1);
 82   
 83  1 final Fqn PARENT = Fqn.fromString("/a");
 84   
 85    // start a first thread and a transaction
 86   
 87  1 Thread firstThread = new Thread(new Runnable()
 88    {
 89  1 public void run()
 90    {
 91  1 try
 92    {
 93  1 Transaction tx = startTransaction();
 94   
 95  1 System.out.println("Writing /a/1");
 96   
 97    // Create an empty parent node and a node with data
 98  1 Fqn a1 = new Fqn(PARENT, "1");
 99  1 cache.put(a1, KEY, VALUE);
 100   
 101    // notify the second thread it can write
 102  1 secondCanWrite.countDown();
 103   
 104    // wait until the second thread writes and allows me to rollback or until I timeout
 105  1 firstCanRollback.await(3000, TimeUnit.MILLISECONDS);
 106   
 107  1 System.out.println("rolling back");
 108   
 109  1 tx.rollback();
 110   
 111  1 assertNull("a1 empty", cache.get(a1, KEY));
 112   
 113    // notify the reading thread
 114  1 secondCanRead.countDown();
 115    }
 116    catch (AssertionFailedError e)
 117    {
 118  0 writerError = e;
 119    }
 120    catch (Throwable t)
 121    {
 122  0 t.printStackTrace();
 123  0 writerFailed = true;
 124    }
 125    finally
 126    {
 127  1 System.out.println("first thread exits");
 128  1 secondCanWrite.countDown();
 129  1 secondCanRead.countDown();
 130  1 firstDone.countDown();
 131    }
 132    }
 133    }, "FIRST");
 134  1 firstThread.start();
 135   
 136    // start a second thread; no transaction is necessary here
 137   
 138  1 Thread secondThread = new Thread(new Runnable()
 139    {
 140  1 public void run()
 141    {
 142  1 try
 143    {
 144    // wait until the first thread has created PARENT and a child
 145  1 secondCanWrite.await();
 146   
 147  1 System.out.println("writing a2");
 148   
 149    // create a second child under parent
 150  1 Fqn a2 = new Fqn(PARENT, "2");
 151  1 try
 152    {
 153  1 cache.put(a2, KEY, VALUE);
 154    }
 155    catch (TimeoutException good)
 156    {
 157    // first thread locked us out of parent
 158  0 System.out.println("Prevented from writing a2 -- " +
 159    good.getLocalizedMessage());
 160  0 return;
 161    }
 162   
 163    // let the first thread know it can rollback
 164  1 firstCanRollback.countDown();
 165   
 166    // wait until the first thread rolls back.
 167  1 secondCanRead.await();
 168   
 169    // I should still see the value I put
 170  1 assertEquals("Known issue JBCACHE-407 -- write lock not acquired on " +
 171    "creation of an empty node", VALUE, cache.get(a2, KEY));
 172    }
 173    catch (AssertionFailedError e)
 174    {
 175  1 readerError = e;
 176    }
 177    catch (Throwable t)
 178    {
 179  0 t.printStackTrace();
 180  0 readerFailed = true;
 181    }
 182    finally
 183    {
 184  1 System.out.println("second thread exits");
 185  1 firstCanRollback.countDown();
 186  1 secondDone.countDown();
 187    }
 188    }
 189    }, "SECOND");
 190  1 secondThread.start();
 191   
 192    // wait for both threads to finish
 193  1 secondDone.await();
 194  1 firstDone.await();
 195   
 196    // If any assertion failed, throw on the AssertionFailedError
 197  1 if (readerError != null)
 198    {
 199  1 throw readerError;
 200    }
 201   
 202  0 if (writerError != null)
 203    {
 204  0 throw writerError;
 205    }
 206   
 207  0 if (readerFailed)
 208    {
 209  0 fail("The second thread exited incorrectly. Watch the log for previous stack traces");
 210    }
 211   
 212  0 if (writerFailed)
 213    {
 214  0 fail("The first thread exited incorrectly. Watch the log for previous stack traces");
 215    }
 216    }
 217   
 218   
 219  1 private Transaction startTransaction() throws SystemException, NotSupportedException
 220    {
 221  1 DummyTransactionManager mgr = DummyTransactionManager.getInstance();
 222  1 mgr.begin();
 223  1 return mgr.getTransaction();
 224    }
 225   
 226   
 227  1 public static Test suite()
 228    {
 229   
 230  1 return new TestSuite(IsolationLevelReadCommittedNodeCreationRollbackTest.class);
 231   
 232    }
 233   
 234   
 235    }