Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 563   Methods: 15
NCLOC: 383   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
NodeMoveAPITest.java 53.8% 84.8% 86.7% 82.4%
coverage coverage
 1    package org.jboss.cache.api;
 2   
 3    import org.jboss.cache.CacheImpl;
 4    import org.jboss.cache.DefaultCacheFactory;
 5    import org.jboss.cache.Fqn;
 6    import org.jboss.cache.Node;
 7    import org.jboss.cache.NodeNotExistsException;
 8    import org.jboss.cache.config.Configuration;
 9    import org.jboss.cache.loader.AbstractCacheLoaderTestBase;
 10    import org.jboss.cache.loader.DummyInMemoryCacheLoader;
 11    import org.jboss.cache.misc.TestingUtil;
 12   
 13    import javax.transaction.TransactionManager;
 14    import java.util.Map;
 15    import java.util.Random;
 16    import java.util.concurrent.CountDownLatch;
 17   
 18    /**
 19    * Excercises and tests the new move() api
 20    *
 21    * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
 22    * @since 2.0.0
 23    */
 24    public class NodeMoveAPITest extends AbstractCacheLoaderTestBase
 25    {
 26   
 27    protected Node rootNode, nodeA, nodeB, nodeC, nodeD, nodeE;
 28    protected CacheImpl cache;
 29    protected TransactionManager tm;
 30    protected static final Fqn A = Fqn.fromString("/a"), B = Fqn.fromString("/b"), C = Fqn.fromString("/c"), D = Fqn.fromString("/d"), E = Fqn.fromString("/e");
 31    protected Object k = "key", vA = "valueA", vB = "valueB", vC = "valueC", vD = "valueD", vE = "valueE";
 32   
 33    protected boolean optimistic = false;
 34   
 35   
 36  20 protected void setUp() throws Exception
 37    {
 38    // start a single cache instance
 39  20 cache = (CacheImpl) DefaultCacheFactory.getInstance().createCache("META-INF/local-tx-service.xml", false);
 40  20 cache.getConfiguration().setNodeLockingScheme(optimistic ? Configuration.NodeLockingScheme.OPTIMISTIC : Configuration.NodeLockingScheme.PESSIMISTIC);
 41  20 cache.start();
 42  20 rootNode = cache.getRoot();
 43  20 tm = cache.getTransactionManager();
 44    }
 45   
 46  20 protected void tearDown()
 47    {
 48  20 if (cache != null) cache.stop();
 49  20 if (rootNode != null) rootNode = null;
 50    }
 51   
 52   
 53  2 public void testBasicMove()
 54    {
 55  2 nodeA = rootNode.addChild(A);
 56  2 nodeA.put(k, vA);
 57  2 nodeB = rootNode.addChild(B);
 58  2 nodeB.put(k, vB);
 59  2 nodeC = nodeA.addChild(C);
 60  2 nodeC.put(k, vC);
 61    /*
 62    /a/c
 63    /b
 64    */
 65   
 66  2 assertTrue(rootNode.hasChild(A));
 67  2 assertTrue(rootNode.hasChild(B));
 68  2 assertFalse(rootNode.hasChild(C));
 69  2 assertTrue(nodeA.hasChild(C));
 70   
 71    // test data
 72  2 assertEquals("" + nodeA, vA, nodeA.get(k));
 73  2 assertEquals(vB, nodeB.get(k));
 74  2 assertEquals(vC, nodeC.get(k));
 75   
 76    // parentage
 77  2 assertEquals(nodeA, nodeC.getParent());
 78   
 79  2 log.info("BEFORE MOVE " + cache);
 80    // move
 81  2 cache.move(nodeC.getFqn(), nodeB.getFqn());
 82   
 83    // re-fetch nodeC
 84  2 nodeC = cache.get(new Fqn(nodeB.getFqn(), C));
 85   
 86  2 log.info("POST MOVE " + cache);
 87  2 log.info("HC " + nodeC + " " + System.identityHashCode(nodeC));
 88  2 Node x = cache.getRoot().getChild(Fqn.fromString("b/c"));
 89  2 log.info("HC " + x + " " + System.identityHashCode(x));
 90    /*
 91    /a
 92    /b/c
 93    */
 94  2 assertEquals("NODE C " + nodeC, "/b/c", nodeC.getFqn().toString());
 95   
 96  2 assertTrue(rootNode.hasChild(A));
 97  2 assertTrue(rootNode.hasChild(B));
 98  2 assertFalse(rootNode.hasChild(C));
 99  2 assertFalse(nodeA.hasChild(C));
 100  2 assertTrue(nodeB.hasChild(C));
 101   
 102    // test data
 103  2 assertEquals(vA, nodeA.get(k));
 104  2 assertEquals(vB, nodeB.get(k));
 105  2 assertEquals(vC, nodeC.get(k));
 106   
 107    // parentage
 108  2 assertEquals("B is parent of C: " + nodeB, nodeB, nodeC.getParent());
 109    }
 110   
 111  2 public void testMoveWithChildren()
 112    {
 113  2 nodeA = rootNode.addChild(A);
 114  2 nodeA.put(k, vA);
 115  2 nodeB = rootNode.addChild(B);
 116  2 nodeB.put(k, vB);
 117  2 nodeC = nodeA.addChild(C);
 118  2 nodeC.put(k, vC);
 119  2 nodeD = nodeC.addChild(D);
 120  2 nodeD.put(k, vD);
 121  2 nodeE = nodeD.addChild(E);
 122  2 nodeE.put(k, vE);
 123   
 124  2 assertTrue(rootNode.hasChild(A));
 125  2 assertTrue(rootNode.hasChild(B));
 126  2 assertFalse(rootNode.hasChild(C));
 127  2 assertTrue(nodeA.hasChild(C));
 128  2 assertTrue(nodeC.hasChild(D));
 129  2 assertTrue(nodeD.hasChild(E));
 130   
 131    // test data
 132  2 assertEquals(vA, nodeA.get(k));
 133  2 assertEquals(vB, nodeB.get(k));
 134  2 assertEquals(vC, nodeC.get(k));
 135  2 assertEquals(vD, nodeD.get(k));
 136  2 assertEquals(vE, nodeE.get(k));
 137   
 138    // parentage
 139  2 assertEquals(rootNode, nodeA.getParent());
 140  2 assertEquals(rootNode, nodeB.getParent());
 141  2 assertEquals(nodeA, nodeC.getParent());
 142  2 assertEquals(nodeC, nodeD.getParent());
 143  2 assertEquals(nodeD, nodeE.getParent());
 144   
 145    // move
 146  2 log.info("move " + nodeC + " to " + nodeB);
 147  2 cache.move(nodeC.getFqn(), nodeB.getFqn());
 148    //System.out.println("nodeB " + nodeB);
 149    //System.out.println("nodeC " + nodeC);
 150   
 151    // child nodes will need refreshing, since existing pointers will be stale.
 152  2 nodeC = nodeB.getChild(C);
 153  2 nodeD = nodeC.getChild(D);
 154  2 nodeE = nodeD.getChild(E);
 155   
 156  2 System.out.println("Tree " + cache.printLockInfo());
 157   
 158  2 assertTrue(rootNode.hasChild(A));
 159  2 assertTrue(rootNode.hasChild(B));
 160  2 assertFalse(rootNode.hasChild(C));
 161  2 assertFalse(nodeA.hasChild(C));
 162  2 assertTrue(nodeB.hasChild(C));
 163  2 assertTrue(nodeC.hasChild(D));
 164  2 assertTrue(nodeD.hasChild(E));
 165   
 166    // test data
 167  2 assertEquals(vA, nodeA.get(k));
 168  2 assertEquals(vB, nodeB.get(k));
 169  2 assertEquals(vC, nodeC.get(k));
 170  2 assertEquals(vD, nodeD.get(k));
 171  2 assertEquals(vE, nodeE.get(k));
 172   
 173    // parentage
 174  2 assertEquals(rootNode, nodeA.getParent());
 175  2 assertEquals(rootNode, nodeB.getParent());
 176  2 assertEquals(nodeB, nodeC.getParent());
 177  2 assertEquals(nodeC, nodeD.getParent());
 178  2 assertEquals(nodeD, nodeE.getParent());
 179    }
 180   
 181  2 public void testTxCommit() throws Exception
 182    {
 183  2 nodeA = rootNode.addChild(A);
 184  2 nodeB = nodeA.addChild(B);
 185   
 186  2 assertEquals(rootNode, nodeA.getParent());
 187  2 assertEquals(nodeA, nodeB.getParent());
 188  2 assertEquals(nodeA, rootNode.getChildren().iterator().next());
 189  2 assertEquals(nodeB, nodeA.getChildren().iterator().next());
 190   
 191  2 tm.begin();
 192    // move node B up to hang off the root
 193  2 cache.move(nodeB.getFqn(), Fqn.ROOT);
 194   
 195  2 tm.commit();
 196   
 197  2 nodeB = rootNode.getChild(B);
 198   
 199  2 assertEquals(rootNode, nodeA.getParent());
 200  2 assertEquals(rootNode, nodeB.getParent());
 201   
 202  2 assertTrue(rootNode.getChildren().contains(nodeA));
 203  2 assertTrue(rootNode.getChildren().contains(nodeB));
 204   
 205  2 assertTrue(nodeA.getChildren().isEmpty());
 206    }
 207   
 208  2 public void testTxRollback() throws Exception
 209    {
 210  2 nodeA = rootNode.addChild(A);
 211  2 nodeB = nodeA.addChild(B);
 212   
 213  2 assertEquals(rootNode, nodeA.getParent());
 214  2 assertEquals(nodeA, nodeB.getParent());
 215  2 assertEquals(nodeA, rootNode.getChildren().iterator().next());
 216  2 assertEquals(nodeB, nodeA.getChildren().iterator().next());
 217   
 218   
 219  2 tm.begin();
 220    // move node B up to hang off the root
 221  2 cache.move(nodeB.getFqn(), Fqn.ROOT);
 222   
 223    // need to think of a way to test the same with optimistically locked nodes
 224  2 if (!optimistic)
 225    {
 226  1 assertEquals(rootNode, nodeA.getParent());
 227  1 assertEquals(rootNode, nodeB.getParent());
 228  1 assertTrue(rootNode.getChildren().contains(nodeA));
 229  1 assertTrue(rootNode.getChildren().contains(nodeB));
 230  1 assertTrue(nodeA.getChildren().isEmpty());
 231    }
 232   
 233   
 234  2 tm.rollback();
 235   
 236  2 nodeA = rootNode.getChild(A);
 237  2 nodeB = nodeA.getChild(B);
 238   
 239    // should revert
 240  2 assertEquals(rootNode, nodeA.getParent());
 241  2 assertEquals(nodeA, nodeB.getParent());
 242  2 assertEquals(nodeA, rootNode.getChildren().iterator().next());
 243  2 assertEquals(nodeB, nodeA.getChildren().iterator().next());
 244    }
 245   
 246  2 public void testWithCacheloaders() throws Exception
 247    {
 248  2 doCacheLoaderTest(false, false);
 249    }
 250   
 251  2 public void testWithPassivation() throws Exception
 252    {
 253  2 doCacheLoaderTest(true, false);
 254    }
 255   
 256  2 public void testWithCacheloadersTx() throws Exception
 257    {
 258  2 doCacheLoaderTest(false, true);
 259    }
 260   
 261  2 public void testWithPassivationTx() throws Exception
 262    {
 263  2 doCacheLoaderTest(true, true);
 264    }
 265   
 266  8 protected void doCacheLoaderTest(boolean pasv, boolean useTx) throws Exception
 267    {
 268  8 cache.destroy();
 269  8 cache.getConfiguration().setCacheLoaderConfig(getSingleCacheLoaderConfig(pasv, "", DummyInMemoryCacheLoader.class.getName(), null, false, false, false, false));
 270  8 cache.start();
 271   
 272  8 DummyInMemoryCacheLoader loader = (DummyInMemoryCacheLoader) cache.getCacheLoaderManager().getCacheLoader();
 273   
 274  8 rootNode.put("key", "value");
 275   
 276  8 if (!pasv)
 277    {
 278  4 Map m = loader.get(Fqn.ROOT);
 279  4 assertNotNull("Should not be null", m);
 280  4 assertEquals("value", m.get("key"));
 281    }
 282   
 283  8 nodeA = rootNode.addChild(A);
 284  8 nodeA.put(k, vA);
 285  8 nodeB = rootNode.addChild(B);
 286  8 nodeB.put(k, vB);
 287  8 nodeC = nodeA.addChild(C);
 288  8 nodeC.put(k, vC);
 289  8 nodeD = nodeC.addChild(D);
 290  8 nodeD.put(k, vD);
 291  8 nodeE = nodeD.addChild(E);
 292  8 nodeE.put(k, vE);
 293    /*
 294    Node nodeF = nodeE.addChild(Fqn.fromString("F"));
 295    nodeF.put(k, vE);
 296    Node nodeG = nodeF.addChild(Fqn.fromString("G"));
 297    nodeG.put(k, vE);
 298    */
 299   
 300  8 assertNotNull(cache.peek(A, false));
 301  8 assertNotNull(cache.peek(B, false));
 302  8 assertNull(cache.peek(C, false));
 303  8 assertNotNull(cache.peek(new Fqn(A, C), false));
 304  8 assertNotNull(cache.peek(new Fqn(new Fqn(A, C), D), false));
 305  8 assertNotNull(cache.peek(new Fqn(new Fqn(new Fqn(A, C), D), E), false));
 306   
 307    // test data
 308  8 assertEquals(vA, nodeA.get(k));
 309  8 assertEquals(vB, nodeB.get(k));
 310  8 assertEquals(vC, nodeC.get(k));
 311  8 assertEquals(vD, nodeD.get(k));
 312  8 assertEquals(vE, nodeE.get(k));
 313   
 314    // parentage
 315  8 assertEquals(rootNode, nodeA.getParent());
 316  8 assertEquals(rootNode, nodeB.getParent());
 317  8 assertEquals(nodeA, nodeC.getParent());
 318  8 assertEquals(nodeC, nodeD.getParent());
 319  8 assertEquals(nodeD, nodeE.getParent());
 320   
 321  8 System.out.println("Loader" + loader);
 322   
 323  8 log.info("Current tree is " + cache.printDetails());
 324   
 325  8 cache.evict(Fqn.ROOT, true);
 326   
 327  8 log.info("POST EVICT tree is " + cache.printDetails());
 328   
 329    // move
 330  4 if (useTx) tm.begin();
 331  8 cache.move(nodeC.getFqn(), nodeB.getFqn());
 332   
 333    // Fqn[] fqns = {A, B, new Fqn(B, C), new Fqn(new Fqn(B, C), D), new Fqn(new Fqn(new Fqn(B, C), D), E)};
 334    // System.out.println("*** LOADER BEFORE COMMIT ");
 335    // for (Fqn f: fqns)
 336    // {
 337    // System.out.println(" Fqn: " + f);
 338    // System.out.println(" Contents in loader: " + loader.get(f));
 339    // }
 340  4 if (useTx) tm.commit();
 341    // System.out.println("*** LOADER AFTER COMMIT ");
 342    // for (Fqn f: fqns)
 343    // {
 344    // System.out.println(" Fqn: " + f);
 345    // System.out.println(" Contents in loader: " + loader.get(f));
 346    // }
 347   
 348  8 log.info("Post commit tree is " + cache.printDetails());
 349   
 350    // after eviction, the node objects we hold are probably stale.
 351  8 nodeA = rootNode.getChild(A);
 352  8 nodeB = rootNode.getChild(B);
 353  8 nodeC = nodeB.getChild(C);
 354  8 log.info("Current tree is " + cache.printDetails());
 355  8 log.info("nodeC get child B ");
 356  8 nodeD = nodeC.getChild(D);
 357  8 log.info("Current tree is " + cache.printDetails());
 358  8 log.info("nodeD get child E ");
 359  8 nodeE = nodeD.getChild(E);
 360   
 361  8 log.info("Current tree is " + cache.printDetails());
 362   
 363  8 Fqn old_C = new Fqn(C);
 364  8 Fqn old_D = new Fqn(old_C, D);
 365  8 Fqn old_E = new Fqn(old_D, E);
 366   
 367  8 assertNotNull(cache.peek(A, false));
 368  8 assertNotNull(cache.peek(B, false));
 369  8 assertNull(cache.peek(C, false));
 370  8 assertNull(cache.peek(new Fqn(A, C), false));
 371  8 assertNotNull(cache.peek(new Fqn(B, C), false));
 372   
 373  8 assertNotNull(cache.peek(new Fqn(new Fqn(B, C), D), false));
 374  8 assertNotNull(cache.peek(new Fqn(new Fqn(new Fqn(B, C), D), E), false));
 375   
 376    // test data
 377  8 assertEquals(vA, nodeA.get(k));
 378  8 assertEquals(vB, nodeB.get(k));
 379  8 assertEquals(vC, nodeC.get(k));
 380  8 assertEquals(vD, nodeD.get(k));
 381  8 assertEquals(vE, nodeE.get(k));
 382   
 383    // parentage
 384  8 assertEquals(rootNode, nodeA.getParent());
 385  8 assertEquals(rootNode, nodeB.getParent());
 386  8 assertEquals(nodeB, nodeC.getParent());
 387  8 assertEquals(nodeC, nodeD.getParent());
 388  8 assertEquals(nodeD, nodeE.getParent());
 389   
 390  4 if (pasv) cache.evict(Fqn.ROOT, true);
 391   
 392    //now inspect the loader.
 393  8 assertEquals(vA, loader.get(nodeA.getFqn()).get(k));
 394  8 assertEquals(vB, loader.get(nodeB.getFqn()).get(k));
 395  8 assertEquals(vC, loader.get(nodeC.getFqn()).get(k));
 396  8 assertEquals(vD, loader.get(nodeD.getFqn()).get(k));
 397  8 assertEquals(vE, loader.get(nodeE.getFqn()).get(k));
 398   
 399  8 assertNull(loader.get(old_C));
 400  8 assertNull(loader.get(old_D));
 401  8 assertNull(loader.get(old_E));
 402   
 403    }
 404   
 405  1 public void testLocksDeepMove() throws Exception
 406    {
 407  1 nodeA = rootNode.addChild(A);
 408  1 nodeB = nodeA.addChild(B);
 409  1 nodeD = nodeB.addChild(D);
 410  1 nodeC = rootNode.addChild(C);
 411  1 assertEquals(0, cache.getNumberOfLocksHeld());
 412  1 tm.begin();
 413   
 414  1 cache.move(nodeC.getFqn(), nodeB.getFqn());
 415    // nodeC should have a RL, nodeA should have a RL, nodeB should have a WL, nodeD should have a WL
 416   
 417  1 System.out.println("LOCKS: " + cache.printLockInfo());
 418   
 419  1 assertEquals("ROOT should have a RL, nodeC should have a RL, nodeA should have a RL, nodeB should have a WL, nodeD should have a WL", 5, cache.getNumberOfLocksHeld());
 420   
 421   
 422  1 tm.commit();
 423   
 424  1 assertEquals(0, cache.getNumberOfLocksHeld());
 425    }
 426   
 427  1 public void testLocks() throws Exception
 428    {
 429  1 nodeA = rootNode.addChild(A);
 430  1 nodeB = nodeA.addChild(B);
 431  1 nodeC = rootNode.addChild(C);
 432  1 assertEquals(0, cache.getNumberOfLocksHeld());
 433  1 tm.begin();
 434   
 435  1 cache.move(nodeC.getFqn(), nodeB.getFqn());
 436   
 437    // nodeC should have a RL, nodeA should have a RL, nodeB should have a WL
 438   
 439  1 System.out.println("LOCKS: " + cache.printLockInfo());
 440   
 441  1 assertEquals("ROOT should have a RL, nodeC should have a RL, nodeA should have a RL, nodeB should have a WL", 4, cache.getNumberOfLocksHeld());
 442   
 443   
 444  1 tm.commit();
 445   
 446  1 assertEquals(0, cache.getNumberOfLocksHeld());
 447    }
 448   
 449   
 450  0 public void XtestConcurrency() throws InterruptedException
 451    {
 452    // TODO: investigate intermittent failure when in optimistic mode.
 453  0 if (optimistic) return;
 454   
 455  0 final int N = 3;// number of threads
 456  0 final int loops = 1 << 6;// number of loops
 457    // tests a tree structure as such:
 458    // /a
 459    // /b
 460    // /c
 461    // /d
 462    // /e
 463    // /x
 464    // /y
 465   
 466    // N threads constantly move /x and /y around to hang off either /a ~ /e randomly.
 467   
 468  0 final Fqn FQN_A = A, FQN_B = B, FQN_C = C, FQN_D = D, FQN_E = E, FQN_X = Fqn.fromString("/x"), FQN_Y = Fqn.fromString("/y");
 469   
 470    // set up the initial structure.
 471  0 final Node[] NODES = {
 472    rootNode.addChild(FQN_A), rootNode.addChild(FQN_B),
 473    rootNode.addChild(FQN_C), rootNode.addChild(FQN_D), rootNode.addChild(FQN_E)
 474    };
 475   
 476  0 final Node NODE_X = NODES[0].addChild(FQN_X);
 477  0 final Node NODE_Y = NODES[1].addChild(FQN_Y);
 478   
 479  0 Thread[] movers = new Thread[N];
 480  0 final CountDownLatch latch = new CountDownLatch(1);
 481  0 final Random r = new Random();
 482   
 483  0 for (int i = 0; i < N; i++)
 484    {
 485  0 movers[i] = new Thread("Mover-" + i)
 486    {
 487  0 public void run()
 488    {
 489  0 try
 490    {
 491  0 latch.await();
 492    }
 493    catch (InterruptedException e)
 494    {
 495    }
 496   
 497  0 for (int counter = 0; counter < loops; counter++)
 498    {
 499   
 500  0 System.out.println(getName() + ": Attempt " + counter);
 501  0 try
 502    {
 503  0 cache.move(NODE_X.getFqn(), NODES[r.nextInt(NODES.length)].getFqn());
 504    }
 505    catch (NodeNotExistsException e)
 506    {
 507    // this may happen ...
 508    }
 509  0 TestingUtil.sleepRandom(250);
 510  0 try
 511    {
 512  0 cache.move(NODE_Y.getFqn(), NODES[r.nextInt(NODES.length)].getFqn());
 513    }
 514    catch (NodeNotExistsException e)
 515    {
 516    // this may happen ...
 517    }
 518  0 TestingUtil.sleepRandom(250);
 519    }
 520    }
 521    };
 522  0 movers[i].start();
 523    }
 524   
 525  0 latch.countDown();
 526   
 527  0 for (Thread t : movers)
 528    {
 529  0 t.join();
 530    }
 531   
 532  0 assertEquals(0, cache.getNumberOfLocksHeld());
 533  0 boolean found_x = false, found_x_again = false;
 534  0 for (Node n : NODES)
 535    {
 536  0 if (!found_x)
 537    {
 538  0 found_x = n.hasChild(FQN_X);
 539    }
 540    else
 541    {
 542  0 found_x_again = found_x_again || n.hasChild(FQN_X);
 543    }
 544    }
 545  0 boolean found_y = false, found_y_again = false;
 546  0 for (Node n : NODES)
 547    {
 548  0 if (!found_y)
 549    {
 550  0 found_y = n.hasChild(FQN_Y);
 551    }
 552    else
 553    {
 554  0 found_y_again = found_y_again || n.hasChild(FQN_Y);
 555    }
 556    }
 557   
 558  0 assertTrue("Should have found x", found_x);
 559  0 assertTrue("Should have found y", found_y);
 560  0 assertFalse("Should have only found x once", found_x_again);
 561  0 assertFalse("Should have only found y once", found_y_again);
 562    }
 563    }