Clover coverage report -
Coverage timestamp: Wed Jan 31 2007 15:38:53 EST
file stats: LOC: 1,174   Methods: 48
NCLOC: 835   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
TransactionTest.java 60% 91.2% 97.9% 90.7%
coverage coverage
 1    /*
 2    *
 3    * JBoss, the OpenSource J2EE webOS
 4    *
 5    * Distributable under LGPL license.
 6    * See terms of license at gnu.org.
 7    */
 8   
 9    package org.jboss.cache.transaction;
 10   
 11    import junit.framework.Test;
 12    import junit.framework.TestCase;
 13    import junit.framework.TestSuite;
 14    import org.jboss.cache.CacheException;
 15    import org.jboss.cache.CacheImpl;
 16    import org.jboss.cache.DefaultCacheFactory;
 17    import org.jboss.cache.Fqn;
 18    import org.jboss.cache.GlobalTransaction;
 19    import org.jboss.cache.Node;
 20    import org.jboss.cache.NodeSPI;
 21    import org.jboss.cache.lock.IsolationLevel;
 22    import org.jboss.cache.lock.NodeLock;
 23   
 24    import javax.naming.Context;
 25    import javax.naming.InitialContext;
 26    import javax.transaction.HeuristicMixedException;
 27    import javax.transaction.HeuristicRollbackException;
 28    import javax.transaction.NotSupportedException;
 29    import javax.transaction.RollbackException;
 30    import javax.transaction.SystemException;
 31    import javax.transaction.Transaction;
 32    import javax.transaction.UserTransaction;
 33    import java.util.HashMap;
 34    import java.util.Map;
 35    import java.util.Properties;
 36    import java.util.Set;
 37   
 38    /**
 39    * Tests transactional access to a local CacheImpl.
 40    * Note: we use DummpyTranasctionManager to replace jta
 41    *
 42    * @version $Id: TransactionTest.java,v 1.26 2007/01/31 17:41:11 msurtani Exp $
 43    */
 44    public class TransactionTest extends TestCase
 45    {
 46    CacheImpl cache = null;
 47    UserTransaction tx = null;
 48    Properties p = null;
 49    String old_factory = null;
 50    final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory";
 51    Exception thread_ex;
 52   
 53   
 54  34 public TransactionTest(String name)
 55    {
 56  34 super(name);
 57    }
 58   
 59  34 public void setUp() throws Exception
 60    {
 61  34 super.setUp();
 62  34 old_factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
 63  34 System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
 64  34 DummyTransactionManager.getInstance();
 65  34 if (p == null)
 66    {
 67  34 p = new Properties();
 68  34 p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
 69    }
 70   
 71  34 tx = (UserTransaction) new InitialContext(p).lookup("UserTransaction");
 72  34 cache = (CacheImpl) DefaultCacheFactory.getInstance().createCache(false);
 73  34 cache.getConfiguration().setClusterName("test");
 74  34 cache.getConfiguration().setInitialStateRetrievalTimeout(10000);
 75  34 cache.getConfiguration().setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
 76  34 cache.getConfiguration().setIsolationLevel(IsolationLevel.SERIALIZABLE);
 77  34 cache.getConfiguration().setLockParentForChildInsertRemove(true); // this test case is written to assume this.
 78  34 cache.create();
 79  34 cache.start();
 80  34 thread_ex = null;
 81    }
 82   
 83  34 public void tearDown() throws Exception
 84    {
 85  34 super.tearDown();
 86  34 if (cache != null)
 87    {
 88  34 cache.stop();
 89  34 cache = null;
 90    }
 91   
 92    // BW. kind of a hack to destroy jndi binding and thread local tx before next run.
 93  34 DummyTransactionManager.destroy();
 94  34 if (old_factory != null)
 95    {
 96  33 System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old_factory);
 97  33 old_factory = null;
 98    }
 99   
 100  34 if (tx != null)
 101    {
 102  34 try
 103    {
 104  34 tx.rollback();
 105    }
 106    catch (Throwable t)
 107    {
 108    }
 109  34 tx = null;
 110    }
 111    }
 112   
 113   
 114  1 public void testPutTx() throws Exception
 115    {
 116  1 tx.begin();
 117  1 cache.put("/a/b/c", "age", 38);
 118    // the tx interceptor should know that we're in the same tx.
 119  1 assertEquals(cache.get("/a/b/c", "age"), 38);
 120   
 121  1 cache.put("/a/b/c", "age", 39);
 122  1 tx.commit();
 123   
 124    // This test is done outside the TX, it wouldn't work if someone else
 125    // modified "age". This works because we're the only TX running.
 126  1 assertEquals(cache.get("/a/b/c", "age"), 39);
 127    }
 128   
 129   
 130  1 public void testRollbackTx1()
 131    {
 132  1 try
 133    {
 134  1 tx.begin();
 135  1 cache.put("/a/b/c", "age", 38);
 136  1 cache.put("/a/b/c", "age", 39);
 137  1 tx.rollback();
 138   
 139    // This test is done outside the TX, it wouldn't work if someone else
 140    // modified "age". This works because we're the only TX running.
 141  1 assertNull(cache.get("/a/b/c", "age"));
 142    }
 143    catch (Throwable t)
 144    {
 145  0 t.printStackTrace();
 146  0 fail(t.toString());
 147    }
 148    }
 149   
 150   
 151  1 public void testGetAfterRemovalRollback() throws Exception
 152    {
 153  1 assertEquals(0, cache.getNumberOfLocksHeld());
 154  1 cache.put("/a/b", null);
 155  1 assertEquals(0, cache.getNumberOfLocksHeld());
 156  1 assertTrue(cache.exists("/a/b"));
 157  1 tx.begin();
 158  1 cache.remove("/a/b");
 159  1 assertFalse(cache.exists("/a/b"));
 160  1 tx.rollback();
 161  1 assertTrue(cache.exists("/a/b"));
 162  1 assertEquals(0, cache.getNumberOfLocksHeld());
 163    // new tx in new thread
 164  1 Thread th = new Thread()
 165    {
 166  1 public void run()
 167    {
 168  1 try
 169    {
 170  1 cache.getTransactionManager().begin();
 171  1 assertNotNull(cache.get("/a/b"));
 172  1 cache.getTransactionManager().rollback();
 173    }
 174    catch (Exception e)
 175    {
 176  0 e.printStackTrace();
 177  0 fail("Caught exception");
 178    }
 179    }
 180    };
 181   
 182  1 th.start();
 183  1 th.join();
 184   
 185  1 assertEquals(0, cache.getNumberOfLocksHeld());
 186    }
 187   
 188  1 public void testRollbackTx2()
 189    {
 190  1 try
 191    {
 192  1 tx.begin();
 193  1 cache.put("/a/b/c", "age", 38);
 194  1 cache.remove("/a/b/c", "age");
 195  1 tx.rollback();
 196   
 197    // This test is done outside the TX, it wouldn't work if someone else
 198    // modified "age". This works because we're the only TX running.
 199  1 assertNull(cache.get("/a/b/c", "age"));
 200    }
 201    catch (Throwable t)
 202    {
 203  0 t.printStackTrace();
 204  0 fail(t.toString());
 205    }
 206    }
 207   
 208  1 public void testRollbackTx2a()
 209    {
 210  1 try
 211    {
 212  1 System.out.println("locks " + cache.printLockInfo());
 213  1 cache.put("/a/b/c", "age", 38);
 214  1 System.out.println("locks " + cache.printLockInfo());
 215  1 tx.begin();
 216  1 cache.remove("/a/b/c", "age");
 217  1 tx.rollback();
 218   
 219    // This test is done outside the TX, it wouldn't work if someone else
 220    // modified "age". This works because we're the only TX running.
 221  1 assertEquals(38, cache.get("/a/b/c", "age"));
 222    }
 223    catch (Throwable t)
 224    {
 225  0 t.printStackTrace();
 226  0 fail(t.toString());
 227    }
 228    }
 229   
 230  1 public void testRollbackTx3()
 231    {
 232  1 try
 233    {
 234  1 java.util.Map map1 = new java.util.HashMap();
 235  1 map1.put("age", 38);
 236  1 java.util.Map map2 = new java.util.HashMap();
 237  1 map2.put("age", 39);
 238  1 tx.begin();
 239  1 cache.put("/a/b/c", map1);
 240  1 cache.put("/a/b/c", map2);
 241  1 tx.rollback();
 242   
 243    // This test is done outside the TX, it wouldn't work if someone else
 244    // modified "age". This works because we're the only TX running.
 245  1 assertNull(cache.get("/a/b/c", "age"));
 246    }
 247    catch (Throwable t)
 248    {
 249  0 t.printStackTrace();
 250  0 fail(t.toString());
 251    }
 252    }
 253   
 254   
 255  1 public void testRollbackTx4()
 256    {
 257  1 try
 258    {
 259  1 Map map = new HashMap();
 260  1 map.put("age", 38);
 261  1 tx.begin();
 262  1 cache.put("/a/b/c", map);
 263  1 cache.remove("/a/b/c");
 264  1 tx.rollback();
 265   
 266    // This test is done outside the TX, it wouldn't work if someone else
 267    // modified "age". This works because we're the only TX running.
 268  1 assertNull(cache.get("/a/b/c", "age"));
 269    }
 270    catch (Throwable t)
 271    {
 272  0 t.printStackTrace();
 273  0 fail(t.toString());
 274    }
 275    }
 276   
 277  1 public void testNodeCreationRollback()
 278    {
 279  1 try
 280    {
 281  1 tx.begin();
 282  1 System.out.println("initial state:\n" + cache);
 283  1 cache.put("/bela/ban", "key", "value");
 284  1 System.out.println("after put():\n" + cache);
 285  1 tx.rollback();
 286  1 System.out.println("after rollback():\n" + cache);
 287   
 288  1 assertNull("node should be not existent", cache.get("/bela/ban"));
 289    }
 290    catch (Throwable t)
 291    {
 292  0 t.printStackTrace();
 293  0 fail(t.toString());
 294    }
 295    }
 296   
 297  1 public void testNodeCreationRollback2()
 298    {
 299  1 try
 300    {
 301  1 cache.put("/bela/ban", null);
 302  1 tx.begin();
 303  1 cache.put("/bela/ban/michelle", null);
 304  1 tx.rollback();
 305  1 assertNotNull("node should be not null", cache.get("/bela/ban"));
 306  1 assertNull("node should be not existent", cache.get("/bela/ban/michelle"));
 307    }
 308    catch (Throwable t)
 309    {
 310  0 t.printStackTrace();
 311  0 fail(t.toString());
 312    }
 313    }
 314   
 315  1 public void testNodeDeletionRollback()
 316    {
 317  1 try
 318    {
 319  1 cache.put("/a/b/c", null);
 320  1 tx.begin();
 321  1 cache.remove("/a/b/c");
 322  1 assertNull(cache.get("/a/b/c"));
 323  1 cache.remove("/a/b");
 324  1 assertNull(cache.get("/a/b"));
 325  1 cache.remove("/a");
 326  1 assertNull(cache.get("/a"));
 327  1 tx.rollback();
 328  1 assertNotNull(cache.get("/a/b/c"));
 329  1 assertNotNull(cache.get("/a/b"));
 330  1 assertNotNull(cache.get("/a"));
 331    }
 332    catch (Throwable t)
 333    {
 334  0 t.printStackTrace();
 335  0 fail(t.toString());
 336    }
 337    }
 338   
 339  1 public void testNodeDeletionRollback2() throws Exception
 340    {
 341  1 cache.put("/a/b/c", null);
 342  1 cache.put("/a/b/c1", null);
 343  1 cache.put("/a/b/c2", null);
 344  1 tx.begin();
 345  1 cache.remove("/a");
 346  1 assertNull(cache.get("/a/b/c"));
 347  1 assertNull(cache.get("/a/b/c1"));
 348  1 assertNull(cache.get("/a/b/c2"));
 349  1 assertNull(cache.get("/a/b"));
 350  1 assertNull(cache.get("/a"));
 351  1 Set children = cache.getChildrenNames("/a/b");
 352  1 assertTrue(children.isEmpty());
 353  1 children = cache.getChildrenNames("/a");
 354  1 assertTrue(children.isEmpty());
 355  1 tx.rollback();
 356  1 assertNotNull(cache.get("/a"));
 357  1 assertNotNull(cache.get("/a/b"));
 358  1 assertNotNull(cache.get("/a/b/c"));
 359  1 assertNotNull(cache.get("/a/b/c1"));
 360  1 assertNotNull(cache.get("/a/b/c2"));
 361  1 children = cache.getChildrenNames("/a/b");
 362  1 assertEquals(3, children.size());
 363    }
 364   
 365   
 366  1 public void testNodeCreation() throws Exception
 367    {
 368  1 GlobalTransaction gtx;
 369  1 cache.put("/a/b", null);
 370  1 tx.begin();
 371  1 gtx = cache.getCurrentTransaction();
 372  1 cache.put("/a/b/c", null);
 373  1 assertLocked(gtx, "/a", false);
 374  1 assertLocked(gtx, "/a/b", true);
 375  1 assertLocked(gtx, "/a/b/c", true);
 376  1 System.out.println("locks: " + cache.printLockInfo());
 377    }
 378   
 379   
 380  1 public void testNodeCreation2() throws Exception
 381    {
 382  1 GlobalTransaction gtx;
 383  1 tx.begin();
 384  1 gtx = cache.getCurrentTransaction();
 385  1 cache.put("/a/b/c", null);
 386  1 assertLocked(gtx, "/a", true);
 387  1 assertLocked(gtx, "/a/b", true);
 388  1 assertLocked(gtx, "/a/b/c", true);
 389  1 System.out.println("locks: " + cache.printLockInfo());
 390    }
 391   
 392   
 393  1 public void testNodeRemoval()
 394    {
 395  1 GlobalTransaction gtx;
 396  1 try
 397    {
 398  1 cache.put("/a/b/c", null);
 399  1 tx.begin();
 400  1 gtx = cache.getCurrentTransaction();
 401  1 cache.remove("/a/b/c");// need to remove the node, not just the data in the node.
 402  1 System.out.println("Locks: " + cache.printLockInfo());
 403  1 assertLocked(gtx, "/a", false);
 404  1 assertLocked(gtx, "/a/b", true);
 405  1 assertLocked(gtx, "/a/b/c", true);
 406  1 System.out.println("locks: " + cache.printLockInfo());
 407    }
 408    catch (Throwable t)
 409    {
 410  0 t.printStackTrace();
 411  0 fail(t.toString());
 412    }
 413    }
 414   
 415   
 416  1 public void testNodeRemoval2()
 417    {
 418  1 GlobalTransaction gtx;
 419  1 try
 420    {
 421  1 cache.put("/a/b/c", null);
 422  1 tx.begin();
 423  1 gtx = cache.getCurrentTransaction();
 424  1 cache.remove("/a/b");// need to remove the node, not just the data in the node.
 425  1 assertLocked(gtx, "/a", true);
 426  1 assertLocked(gtx, "/a/b", true);
 427  1 assertLocked(gtx, "/a/b/c", true);
 428  1 System.out.println("locks: " + cache.printLockInfo());
 429    }
 430    catch (Throwable t)
 431    {
 432  0 t.printStackTrace();
 433  0 fail(t.toString());
 434    }
 435    }
 436   
 437  1 public void testIntermediateNodeCreationOnWrite() throws Exception
 438    {
 439  1 cache.put("/a", null);
 440  1 tx.begin();
 441  1 cache.put("/a/b/c", null);
 442    // expecting WLs on /a, /a/b and /a/b/c.
 443  1 GlobalTransaction gtx = cache.getCurrentTransaction();
 444  1 assertLocked(gtx, "/a", true);
 445  1 assertLocked(gtx, "/a/b", true);
 446  1 assertLocked(gtx, "/a/b/c", true);
 447  1 tx.rollback();
 448   
 449    }
 450   
 451  1 public void testIntermediateNodeCreationOnRead() throws Exception
 452    {
 453  1 cache.put("/a", null);
 454  1 tx.begin();
 455  1 cache.get("/a/b/c");
 456   
 457    // expecting RLs on /, /a
 458    // /a/b, /a/b/c should NOT be created!
 459  1 GlobalTransaction gtx = cache.getCurrentTransaction();
 460  1 assertLocked(gtx, "/", false);
 461  1 assertLocked(gtx, "/a", false);
 462  1 assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
 463  1 assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
 464  1 tx.rollback();
 465  1 assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
 466  1 assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
 467   
 468    }
 469   
 470   
 471  1 public void testIntermediateNodeCreationOnRemove() throws Exception
 472    {
 473  1 cache.put("/a", null);
 474  1 tx.begin();
 475  1 cache.remove("/a/b/c");
 476   
 477    // expecting RLs on /, /a
 478    // /a/b, /a/b/c should NOT be created!
 479  1 GlobalTransaction gtx = cache.getCurrentTransaction();
 480  1 assertLocked(gtx, "/", false);
 481  1 assertLocked(gtx, "/a", false);
 482  1 assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
 483  1 assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
 484  1 tx.rollback();
 485  1 assertNull("/a/b should not exist", cache.peek(Fqn.fromString("/a/b"), true));
 486  1 assertNull("/a/b/c should not exist", cache.peek(Fqn.fromString("/a/b/c"), true));
 487   
 488    }
 489   
 490   
 491  1 public void testNodeDeletionRollback3() throws Exception
 492    {
 493  1 GlobalTransaction gtx;
 494  1 cache.put("/a/b/c1", null);
 495   
 496  1 tx.begin();
 497  1 gtx = cache.getCurrentTransaction();
 498  1 cache.put("/a/b/c1", null);
 499  1 assertLocked(gtx, "/a", false);
 500  1 assertLocked(gtx, "/a/b", false);
 501  1 assertLocked(gtx, "/a/b/c1", true);
 502   
 503  1 cache.put("/a/b/c2", null);
 504  1 assertLocked(gtx, "/a/b", true);
 505  1 assertLocked(gtx, "/a/b/c2", true);
 506   
 507  1 cache.put("/a/b/c3", null);
 508  1 cache.put("/a/b/c1/one", null);
 509  1 assertLocked(gtx, "/a/b/c1", true);
 510  1 assertLocked(gtx, "/a/b/c1/one", true);
 511   
 512  1 cache.put("/a/b/c1/two", null);
 513  1 cache.put("/a/b/c1/one/1", null);
 514  1 assertLocked(gtx, "/a/b/c1", true);
 515  1 assertLocked(gtx, "/a/b/c1/one", true);
 516  1 assertLocked(gtx, "/a/b/c1/one/1", true);
 517   
 518  1 cache.put("/a/b/c1/two/2/3/4", null);
 519  1 assertLocked(gtx, "/a/b/c1", true);
 520  1 assertLocked(gtx, "/a/b/c1/two", true);
 521  1 assertLocked(gtx, "/a/b/c1/two/2", true);
 522  1 assertLocked(gtx, "/a/b/c1/two/2/3", true);
 523  1 assertLocked(gtx, "/a/b/c1/two/2/3/4", true);
 524   
 525  1 System.out.println("locks: " + cache.printLockInfo());
 526   
 527  1 cache.remove("/a/b");
 528  1 tx.rollback();
 529  1 assertTrue(cache.getChildrenNames("/a/b/c1").isEmpty());
 530  1 Set cn = cache.getChildrenNames("/a/b");
 531  1 assertEquals(1, cn.size());
 532  1 assertEquals("c1", cn.iterator().next());
 533    }
 534   
 535  1 public void testDoubleLocks() throws Exception
 536    {
 537  1 tx.begin();
 538  1 GlobalTransaction gtx = cache.getCurrentTransaction();
 539  1 cache.put("/a/b/c", null);
 540  1 cache.put("/a/b/c", null);
 541   
 542  1 NodeSPI n = (NodeSPI) cache.get("/a");
 543  1 NodeLock lock = n.getLock();
 544  1 int num = lock.getReaderOwners().size();
 545  1 assertEquals(0, num);
 546    // make sure this is write locked.
 547  1 assertLocked(gtx, "/a", true);
 548   
 549  1 n = (NodeSPI) cache.get("/a/b");
 550  1 lock = n.getLock();
 551  1 num = lock.getReaderOwners().size();
 552  1 assertEquals(0, num);
 553    // make sure this is write locked.
 554  1 assertLocked(gtx, "/a/b", true);
 555   
 556  1 n = (NodeSPI) cache.get("/a/b/c");
 557  1 lock = n.getLock();
 558  1 num = lock.getReaderOwners().size();
 559  1 assertEquals(0, num);
 560    // make sure this is write locked.
 561  1 assertLocked(gtx, "/a/b/c", true);
 562   
 563  1 tx.rollback();
 564  1 assertEquals(0, cache.getNumberOfLocksHeld());
 565    }
 566   
 567  37 private void assertLocked(Object owner, String fqn, boolean write_locked) throws Exception
 568    {
 569  37 NodeSPI n = cache.peek(Fqn.fromString(fqn), true);
 570  37 NodeLock lock = n.getLock();
 571  37 if (owner == null)
 572    {
 573  0 owner = Thread.currentThread();
 574    }
 575  37 assertTrue("node " + fqn + " is not locked", lock.isLocked());
 576  37 if (write_locked)
 577    {
 578  29 assertTrue("node " + fqn + " is not write-locked" + (lock.isReadLocked() ? " but is read-locked instead!" : "!"), lock.isWriteLocked());
 579    }
 580    else
 581    {
 582  8 assertTrue("node " + fqn + " is not read-locked" + (lock.isWriteLocked() ? " but is write-locked instead!" : "!"), lock.isReadLocked());
 583    }
 584  37 assertTrue("owner " + owner + "is not owner", lock.isOwner(owner));
 585    }
 586   
 587  1 public void testConcurrentNodeAccessOnRemovalWithTx() throws Exception
 588    {
 589  1 cache.put("/a/b/c", null);
 590  1 tx.begin();
 591  1 cache.remove("/a/b/c");
 592    // this node should now be locked.
 593  1 Transaction t = cache.getTransactionManager().suspend();
 594  1 Transaction t2 = null;
 595  1 try
 596    {
 597  1 System.out.println(cache.printLockInfo());
 598    // start a new tx
 599  1 cache.getTransactionManager().begin();
 600  1 t2 = cache.getTransactionManager().getTransaction();
 601  1 cache.get("/a/b/c");// should fail
 602  0 t2.commit();
 603  0 fail("Should not be able to get a hold of /a/b/c until the deleting tx completes");
 604    }
 605    catch (Exception e)
 606    {
 607    // expected
 608  1 t2.commit();
 609    }
 610   
 611  1 cache.getTransactionManager().resume(t);
 612  1 tx.rollback();
 613   
 614  1 assertNotNull(cache.get("/a/b/c"));
 615  1 assertEquals(0, cache.getNumberOfLocksHeld());
 616    }
 617   
 618  1 public void testConcurrentNodeAccessOnRemovalWithoutTx() throws Exception
 619    {
 620  1 cache.put("/a/b/c", null);
 621  1 tx.begin();
 622  1 cache.remove("/a/b/c");
 623    // this node should now be locked.
 624  1 Transaction t = cache.getTransactionManager().suspend();
 625  1 Thread th = new Thread()
 626    {
 627  1 public void run()
 628    {
 629  1 try
 630    {
 631  1 System.out.println(cache.printLockInfo());
 632  1 cache.get("/a/b/c");// should fail
 633   
 634  0 fail("Should not be able to get a hold of /a/b/c until the deleting tx completes");
 635    }
 636    catch (Exception e)
 637    {
 638    // expected
 639    }
 640    }
 641    };
 642   
 643  1 th.start();
 644  1 th.join();
 645   
 646  1 cache.getTransactionManager().resume(t);
 647  1 tx.rollback();
 648   
 649  1 assertNotNull(cache.get("/a/b/c"));
 650  1 assertEquals(0, cache.getNumberOfLocksHeld());
 651    }
 652   
 653   
 654  1 public void testRemove() throws CacheException, SystemException, NotSupportedException, HeuristicMixedException, HeuristicRollbackException, RollbackException
 655    {
 656  1 cache.put("/a/b/c", null);
 657  1 cache.put("/a/b/c/1", null);
 658  1 cache.put("/a/b/c/2", null);
 659  1 cache.put("/a/b/c/3", null);
 660  1 cache.put("/a/b/c/3/a/b/c", null);
 661   
 662  1 assertEquals(0, cache.getNumberOfLocksHeld());
 663  1 assertEquals(0, cache.getLockTable().size());
 664   
 665  1 tx.begin();
 666  1 cache.remove("/a/b/c");
 667  1 System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo());
 668    // this used to test for 2 locks held. After the fixes for JBCACHE-875 however, 2 more locks are acquired - for the root node as well as the deleted node.
 669    // and since we would lock all children of the deleted node as well, we have 10 locks here.
 670  1 assertEquals(10, cache.getNumberOfLocksHeld());
 671  1 tx.commit();
 672  1 System.out.println("locks held (after committing /a/b/c): \n" + cache.printLockInfo());
 673  1 assertEquals(0, cache.getNumberOfLocksHeld());
 674    }
 675   
 676   
 677  1 public void testRemoveAndRollback() throws CacheException, SystemException, NotSupportedException, HeuristicMixedException, HeuristicRollbackException, RollbackException
 678    {
 679  1 cache.put("/a/b/c", null);
 680  1 cache.put("/a/b/c/1", null);
 681  1 cache.put("/a/b/c/2", null);
 682  1 cache.put("/a/b/c/3", null);
 683  1 cache.put("/a/b/c/3/a/b/c", null);
 684   
 685  1 assertEquals(0, cache.getNumberOfLocksHeld());
 686  1 assertEquals(0, cache.getLockTable().size());
 687   
 688  1 tx.begin();
 689  1 System.out.println("locks held (before removing /a/b/c): \n" + cache.printLockInfo());
 690  1 cache.remove("/a/b/c");
 691  1 System.out.println("locks held (after removing /a/b/c): \n" + cache.printLockInfo());
 692  1 assertEquals(10, cache.getNumberOfLocksHeld());
 693  1 tx.rollback();
 694  1 System.out.println("locks held (after rollback): \n" + cache.printLockInfo());
 695  1 assertEquals(0, cache.getNumberOfLocksHeld());
 696   
 697  1 assertTrue(cache.exists("/a/b/c"));
 698  1 assertTrue(cache.exists("/a/b/c/1"));
 699  1 assertTrue(cache.exists("/a/b/c/2"));
 700  1 assertTrue(cache.exists("/a/b/c/3"));
 701  1 assertTrue(cache.exists("/a/b/c/3/a"));
 702  1 assertTrue(cache.exists("/a/b/c/3/a/b"));
 703  1 assertTrue(cache.exists("/a/b/c/3/a/b/c"));
 704    }
 705   
 706   
 707  1 public void testRemoveKeyRollback() throws CacheException, SystemException, NotSupportedException
 708    {
 709  1 cache.put("/bela/ban", "name", "Bela");
 710  1 tx.begin();
 711  1 cache.remove("/bela/ban", "name");
 712  1 assertNull(cache.get("/bela/ban", "name"));
 713  1 tx.rollback();
 714  1 assertEquals("Bela", cache.get("/bela/ban", "name"));
 715    }
 716   
 717   
 718  1 public void testRemoveKeyRollback2()
 719    {
 720  1 try
 721    {
 722  1 Map m = new HashMap();
 723  1 m.put("name", "Bela");
 724  1 m.put("id", 322649);
 725  1 cache.put("/bela/ban", m);
 726  1 tx.begin();
 727  1 cache.remove("/bela/ban", "name");
 728  1 assertNull(cache.get("/bela/ban", "name"));
 729  1 tx.rollback();
 730  1 assertEquals("Bela", cache.get("/bela/ban", "name"));
 731    }
 732    catch (Throwable t)
 733    {
 734  0 t.printStackTrace();
 735  0 fail(t.toString());
 736    }
 737    }
 738   
 739  1 public void testRemoveKeyRollback3()
 740    {
 741  1 try
 742    {
 743  1 cache.put("/bela/ban", "name", "Bela");
 744  1 tx.begin();
 745  1 cache.put("/bela/ban", "name", "Michelle");
 746  1 cache.remove("/bela/ban", "name");
 747  1 assertNull(cache.get("/bela/ban", "name"));
 748  1 tx.rollback();
 749  1 assertEquals("Bela", cache.get("/bela/ban", "name"));
 750    }
 751    catch (Throwable t)
 752    {
 753  0 t.printStackTrace();
 754  0 fail(t.toString());
 755    }
 756    }
 757   
 758   
 759  1 public void testDoubleRemovalOfSameData()
 760    {
 761  1 try
 762    {
 763  1 tx.begin();
 764  1 cache.put("/foo/1", "item", 1);
 765  1 assertEquals(cache.get("/foo/1", "item"), 1);
 766  1 cache.remove("/foo/1");
 767  1 assertNull(cache.get("/foo/1", "item"));
 768  1 cache.remove("/foo/1");
 769  1 assertNull(cache.get("/foo/1", "item"));
 770  1 tx.rollback();
 771  1 assertFalse(cache.exists("/foo/1"));
 772  1 assertNull(cache.get("/foo/1", "item"));
 773    }
 774    catch (Throwable t)
 775    {
 776  0 t.printStackTrace();
 777  0 fail(t.toString());
 778    }
 779    }
 780   
 781    /**
 782    * put(Fqn, Map) with a previous null map
 783    */
 784  1 public void testPutDataRollback1()
 785    {
 786  1 try
 787    {
 788  1 cache.put("/bela/ban", null);// create a node /bela/ban with a null map
 789  1 tx.begin();
 790  1 Map m = new HashMap();
 791  1 m.put("name", "Bela");
 792  1 m.put("id", 322649);
 793  1 cache.put("/bela/ban", m);
 794  1 tx.rollback();
 795   
 796  1 Node n = cache.get("/bela/ban");
 797  0 if (n.getData() == null) return;
 798  1 assertEquals("map should be empty", 0, n.getData().size());
 799    }
 800    catch (Throwable t)
 801    {
 802  0 t.printStackTrace();
 803  0 fail(t.toString());
 804    }
 805    }
 806   
 807    /**
 808    * put(Fqn, Map) with a previous non-null map
 809    */
 810  1 public void testputDataRollback2()
 811    {
 812  1 Map m1, m2;
 813  1 m1 = new HashMap();
 814  1 m1.put("name", "Bela");
 815  1 m1.put("id", 322649);
 816  1 m2 = new HashMap();
 817  1 m2.put("other", "bla");
 818  1 m2.put("name", "Michelle");
 819   
 820  1 try
 821    {
 822  1 cache.put("/bela/ban", m1);
 823  1 tx.begin();
 824   
 825  1 cache.put("/bela/ban", m2);
 826  1 Map tmp = cache.get("/bela/ban").getData();
 827  1 assertEquals(3, tmp.size());
 828  1 assertEquals("Michelle", tmp.get("name"));
 829  1 assertEquals(tmp.get("id"), 322649);
 830  1 assertEquals("bla", tmp.get("other"));
 831  1 tx.rollback();
 832   
 833  1 tmp = cache.get("/bela/ban").getData();
 834  1 assertEquals(2, tmp.size());
 835  1 assertEquals("Bela", tmp.get("name"));
 836  1 assertEquals(tmp.get("id"), 322649);
 837    }
 838    catch (Throwable t)
 839    {
 840  0 t.printStackTrace();
 841  0 fail(t.toString());
 842    }
 843    }
 844   
 845   
 846  1 public void testPutRollback()
 847    {
 848  1 try
 849    {
 850  1 cache.put("/bela/ban", null);// /bela/ban needs to exist
 851  1 tx.begin();
 852  1 cache.put("/bela/ban", "name", "Bela");
 853  1 assertEquals("Bela", cache.get("/bela/ban", "name"));
 854  1 tx.rollback();
 855  1 assertNull(cache.get("/bela/ban", "name"));
 856    }
 857    catch (Throwable t)
 858    {
 859  0 t.printStackTrace();
 860  0 fail(t.toString());
 861    }
 862    }
 863   
 864   
 865  1 public void testPutRollback2()
 866    {
 867  1 try
 868    {
 869  1 cache.put("/bela/ban", "name", "Bela");// /bela/ban needs to exist
 870  1 tx.begin();
 871  1 cache.put("/bela/ban", "name", "Michelle");
 872  1 assertEquals("Michelle", cache.get("/bela/ban", "name"));
 873  1 tx.rollback();
 874  1 assertEquals("Bela", cache.get("/bela/ban", "name"));
 875    }
 876    catch (Throwable t)
 877    {
 878  0 t.printStackTrace();
 879  0 fail(t.toString());
 880    }
 881    }
 882   
 883   
 884  1 public void testSimpleRollbackTransactions() throws Exception
 885    {
 886  1 final Fqn FQN = Fqn.fromString("/a/b/c");
 887  1 tx.begin();
 888  1 cache.put(FQN, "entry", "commit");
 889  1 tx.commit();
 890   
 891  1 tx.begin();
 892  1 cache.put(FQN, "entry", "rollback");
 893  1 cache.remove(FQN);
 894  1 tx.rollback();
 895  1 assertEquals("Node should keep the commited value", "commit", cache.get(FQN).get("entry"));
 896   
 897  1 tx.begin();
 898  1 cache.remove(FQN);
 899  1 cache.put(FQN, "entry", "rollback");
 900  1 tx.rollback();
 901  1 assertEquals("Node should keep the commited value", "commit", cache.get(FQN).get("entry"));// THIS FAILS
 902    }
 903   
 904   
 905  2 private Transaction startTransaction() throws Exception
 906    {
 907  2 DummyTransactionManager mgr = DummyTransactionManager.getInstance();
 908  2 mgr.begin();
 909  2 return mgr.getTransaction();
 910    }
 911   
 912   
 913  1 public void testConcurrentReadAndWriteAccess() throws Exception
 914    {
 915  1 cache.stop();
 916  1 cache.getConfiguration().setIsolationLevel(IsolationLevel.REPEATABLE_READ);
 917  1 cache.start();
 918   
 919  1 cache.put("/1/2/3/4", "foo", "bar");// no TX, no locks held after put() returns
 920   
 921   
 922    class Reader extends Thread
 923    {
 924    Transaction thread_tx;
 925   
 926  1 public Reader()
 927    {
 928  1 super("Reader");
 929    }
 930   
 931  1 public void run()
 932    {
 933  1 try
 934    {
 935  1 thread_tx = startTransaction();
 936  1 log("acquiring RL");
 937  1 cache.get("/1/2/3", "foo");// acquires RLs on all 3 nodes
 938  1 log("RL acquired successfully");
 939  1 sleep(2000);
 940  1 log("committing TX");
 941  1 thread_tx.commit();// releases RLs
 942  1 log("committed TX");
 943    }
 944    catch (Exception e)
 945    {
 946  0 thread_ex = e;
 947    }
 948    }
 949    }
 950   
 951    class Writer extends Thread
 952    {
 953    Transaction thread_tx;
 954   
 955  1 public Writer()
 956    {
 957  1 super("Writer");
 958    }
 959   
 960  1 public void run()
 961    {
 962  1 try
 963    {
 964  1 sleep(500);// give the Reader a chance to acquire the RLs
 965  1 thread_tx = startTransaction();
 966  1 log("acquiring WL");
 967  1 cache.put("/1", "foo", "bar2");// needs to acquired a WL on /1
 968  1 log("acquired WL successfully");
 969  1 log("committing TX");
 970  1 thread_tx.commit();
 971  1 log("committed TX");
 972    }
 973    catch (Exception e)
 974    {
 975  0 thread_ex = e;
 976    }
 977    }
 978    }
 979   
 980  1 Reader reader = new Reader();
 981  1 Writer writer = new Writer();
 982  1 reader.start();
 983  1 writer.start();
 984  1 reader.join();
 985  1 writer.join();
 986  1 if (thread_ex != null)
 987    {
 988  0 throw thread_ex;
 989    }
 990    }
 991   
 992   
 993    /* public void testConcurrentReadAccess() throws Exception {
 994    cache.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
 995    cache.setUseMbean(false);
 996   
 997    cache.put("/1/2/3/4", "foo", "bar"); // no TX, no locks held after put() returns
 998   
 999   
 1000    class Reader extends Thread {
 1001    Transaction thread_tx;
 1002   
 1003    public Reader(String name) {
 1004    super(name);
 1005    }
 1006   
 1007    public void run() {
 1008    try {
 1009    thread_tx=startTransaction();
 1010    log("acquiring RL");
 1011    cache.get("/1/2/3", "foo"); // acquires RLs on all 3 nodes
 1012    log("RL acquired successfully");
 1013    sleep(200000);
 1014    log("committing TX");
 1015    thread_tx.commit(); // releases RLs
 1016    log("committed TX");
 1017    }
 1018    catch(Exception e) {
 1019    thread_ex=e;
 1020    }
 1021    }
 1022    }
 1023   
 1024   
 1025    Reader reader=new Reader("R1");
 1026    Reader reader2=new Reader("R2");
 1027    reader.start();
 1028    reader2.start();
 1029    reader.join();
 1030    reader2.join();
 1031    if(thread_ex != null)
 1032    throw thread_ex;
 1033    }
 1034   
 1035    */
 1036  8 private static void log(String msg)
 1037    {
 1038  8 System.out.println(Thread.currentThread().getName() + ": " + msg);
 1039    }
 1040   
 1041    // public void testRaceConditionOnNotInCacheCondition() throws Exception {
 1042    // cache.setIsolationLevel(IsolationLevel.SERIALIZABLE);
 1043    //
 1044    // tx.begin();
 1045    // // we now read the null entry, and decide that we need to go do something.
 1046    //
 1047    // Object cachedObject=cache.get("/SecurityInfo/", Integer.toString(23));
 1048    // assertNull(cachedObject); // we expect this in this test
 1049    //
 1050    // /**
 1051    // * now start another Thread to go do the same action, looking for the value, but it SHOULD
 1052    // * see the result of the main thread put once it commits.
 1053    // */
 1054    // Thread thread=new Thread(new Runnable() {
 1055    // UserTransaction tx2=(UserTransaction)new InitialContext(p).lookup("UserTransaction");
 1056    // public void run() {
 1057    // try {
 1058    // tx2.begin();
 1059    // log("OtherThread: inspecting the cache");
 1060    // Object cachedObject=cache.get("/SecurityInfo", Integer.toString(23));
 1061    //
 1062    // log("OtherThread: read from cache: " + cachedObject);
 1063    // Thread.sleep(3000);
 1064    //
 1065    // cachedObject=cache.get("/SecurityInfo", Integer.toString(23));
 1066    // log("OtherThread: read(second time) from cache:" + cachedObject);
 1067    //
 1068    // /**
 1069    // * This should really fail because the other thread should actually have put something else there.
 1070    // */
 1071    // cache.put("/SecurityInfo", Integer.toString(23), "HelloWorldDIRTY!");
 1072    //
 1073    // log("OtherThread: Has put something in the cache tha shouldn't be there");
 1074    // }
 1075    // catch(Exception e) {
 1076    // e.printStackTrace();
 1077    // }
 1078    // finally {
 1079    // if(tx2 != null)
 1080    // try {tx2.commit();} catch(Exception e) {e.printStackTrace();}
 1081    // }
 1082    // log("OthreThread: exiting");
 1083    //
 1084    // }
 1085    // });
 1086    //
 1087    // thread.start();
 1088    // log("MainThread is now waiting a little bit");
 1089    // Thread.sleep(2000); // wait long enough for the other thread to block a bit. Simulate a DB read
 1090    // log("MainThread is now putting something in the cache");
 1091    // cache.put("/SecurityInfo", Integer.toString(23), "HelloWorld");
 1092    // Thread.sleep(2000); // wait long enough for the other thread to block a bit. Simulate a DB read
 1093    // tx.commit();
 1094    // log("MainThread: committed");
 1095    // thread.join(30000);
 1096    //
 1097    // log(cache.get("/SecurityInfo", Integer.toString(23)).toString());
 1098    // }
 1099   
 1100    // public void testConcurrentReadsWithSerializableIsolationLevel() throws CacheException, InterruptedException {
 1101    // final long TIMEOUT=5000;
 1102    // cache.setIsolationLevel(IsolationLevel.SERIALIZABLE);
 1103    // cache.put("/testfqn", "testkey", "testvalue"); // add initial value, to be read by threads
 1104    // Reader r1, r2;
 1105    // r1=new Reader("reader1", 3000);
 1106    // r2=new Reader("reader2", 0);
 1107    // r1.start();
 1108    // pause(100); // make sure thread1 starts and acquires the lock before thread2
 1109    // r2.start();
 1110    // r1.join(TIMEOUT);
 1111    // r2.join(TIMEOUT);
 1112    // }
 1113    //
 1114    // class Reader extends Thread {
 1115    // long timeout;
 1116    //
 1117    // public Reader(String name, long timeout) {
 1118    // super(name);
 1119    // this.timeout=timeout;
 1120    // }
 1121    //
 1122    // public void run() {
 1123    // UserTransaction trans=null;
 1124    // try {
 1125    // trans=(UserTransaction)new InitialContext(p).lookup("UserTransaction");
 1126    // trans.begin();
 1127    // Object retval=null;
 1128    // log2("accessing tree");
 1129    // retval=cache.get("testfqn", "testkey");
 1130    // log2("retval: " + retval);
 1131    // if(timeout > 0) {
 1132    // log2("sleeping for " + timeout + " ms");
 1133    // pause(timeout);
 1134    // }
 1135    // }
 1136    // catch(Exception e) {
 1137    // e.printStackTrace();
 1138    // }
 1139    // finally {
 1140    // try {trans.commit();} catch(Throwable t) {}
 1141    // log2("done");
 1142    // }
 1143    // }
 1144    // }
 1145   
 1146    // private void pause(long timeout) {
 1147    // try {
 1148    // Thread.sleep(timeout);
 1149    // }
 1150    // catch(InterruptedException e) {
 1151    // }
 1152    // }
 1153    //
 1154    // private void log(String msg) {
 1155    // System.out.println("-- [" + Thread.currentThread() + "]: " + msg);
 1156    // }
 1157    //
 1158    // private void log2(String msg) {
 1159    // System.out.println("-- [" + System.currentTimeMillis() + " " + Thread.currentThread() + "]: " + msg);
 1160    // }
 1161   
 1162   
 1163  1 public static Test suite() throws Exception
 1164    {
 1165  1 return new TestSuite(TransactionTest.class);
 1166    }
 1167   
 1168  0 public static void main(String[] args) throws Exception
 1169    {
 1170  0 junit.textui.TestRunner.run(suite());
 1171    }
 1172   
 1173   
 1174    }