[jboss-cvs] JBossAS SVN: r64237 - in trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg: test and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Jul 23 23:27:28 EDT 2007


Author: bstansberry at jboss.com
Date: 2007-07-23 23:27:28 -0400 (Mon, 23 Jul 2007)
New Revision: 64237

Added:
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/DRMTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/FamilyClusterInfoUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAServiceMBeanSupportUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonControllerUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonElectionPolicyTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonSupportUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/PartitionRestartUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/RPCTestCase.java
Log:
[JBAS-4552] Move cluster tests into cluster package
[JBAS-4553] Reorg cluster tests to prevent unnecessary repetition


Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/DRMTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/DRMTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/DRMTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,1333 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.List;
+import java.util.HashSet;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+import javax.management.Notification;
+
+import junit.framework.Test;
+
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.RuntimeConfig;
+import org.jboss.cache.jmx.CacheJmxWrapper;
+import org.jboss.ha.framework.interfaces.ClusterNode;
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager.ReplicantListener;
+import org.jboss.ha.framework.server.ClusterPartition;
+import org.jboss.ha.framework.server.ClusterPartitionConfig;
+import org.jboss.ha.framework.server.DistributedReplicantManagerImpl;
+import org.jboss.ha.framework.server.DistributedStateImpl;
+import org.jboss.ha.framework.server.JChannelFactory;
+import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
+import org.jboss.jmx.adaptor.rmi.RMIAdaptorExt;
+import org.jboss.jmx.adaptor.rmi.RMINotificationListener;
+import org.jboss.logging.Logger;
+import org.jboss.test.JBossClusteredTestCase;
+import org.jboss.test.cluster.hapartition.drm.IReplicants;
+import org.jboss.test.cluster.testutil.MockHAPartition;
+import org.jgroups.stack.GossipRouter;
+import org.jgroups.stack.IpAddress;
+
+
+import EDU.oswego.cs.dl.util.concurrent.Semaphore;
+
+/** Tests of the DistributedReplicantManagerImpl
+ *
+ * @author  Scott.Stark at jboss.org
+ * @author  Brian.Stansberry at jboss.com
+ * @version $Revision$
+ */
+public class DRMTestCase extends JBossClusteredTestCase
+{  
+   private static final String SERVICEA = "serviceA";
+   private static final String SERVICEB = "serviceB";
+   
+   static class TestListener extends UnicastRemoteObject
+      implements RMINotificationListener
+   {
+      private static final long serialVersionUID = 1;
+      private Logger log;
+
+      public TestListener(Logger log) throws RemoteException
+      {
+         this.log = log;
+      }
+      public void handleNotification(Notification notification, Object handback)
+         throws RemoteException
+      {
+         log.info("handleNotification, "+notification);
+      }
+   }
+   
+   /**
+    * Thread that will first register a DRM ReplicantLister that synchronizes
+    * on the test class' lock object, and then calls DRM add or remove,
+    * causing the thread to block if the lock object's monitor is held.
+    */
+   static class BlockingListenerThread extends Thread 
+      implements DistributedReplicantManager.ReplicantListener
+   {
+      private DistributedReplicantManagerImpl drm;
+      private String nodeName;
+      private boolean add;
+      private boolean blocking;
+      private Exception ex;
+      
+      BlockingListenerThread(DistributedReplicantManagerImpl drm,
+                             boolean add,
+                             String nodeName)
+      {
+         this.drm = drm;
+         this.add =add;
+         this.nodeName = nodeName;
+         drm.registerListener("TEST", this);         
+      }
+
+      public void replicantsChanged(String key, List newReplicants, int newReplicantsViewId)
+      {
+         blocking = true;
+         synchronized(lock)
+         {
+            blocking = false;
+         }
+      }
+      
+      public void run()
+      {
+         try
+         {
+            if (add)
+            {
+               if (nodeName == null)
+                  drm.add("TEST", "local-replicant");
+               else
+                  drm._add("TEST", nodeName, "remote-replicant");
+            }
+            else 
+            {
+               if (nodeName == null)
+                  drm.remove("TEST");
+               else
+                  drm._remove("TEST", nodeName);
+            }
+         }
+         catch (Exception e)
+         {
+            ex = e;
+         }
+      }
+      
+      public boolean isBlocking()
+      {
+         return blocking;
+      }
+      
+      public Exception getException()
+      {
+         return ex;
+      }
+      
+   }
+   
+   /**
+    * Thread that registers and then unregisters a DRM ReplicantListener.
+    */
+   static class RegistrationThread extends Thread
+   {
+      private DistributedReplicantManager drm;
+      private boolean registered = false;
+      private boolean unregistered = true;
+      
+      RegistrationThread(DistributedReplicantManager drm)
+      {
+         this.drm = drm;
+      }
+      
+      public void run()
+      {
+         NullListener listener = new NullListener();
+         drm.registerListener("DEADLOCK", listener);
+         registered = true;
+         drm.unregisterListener("DEADLOCK", listener);
+         unregistered = true;
+      }
+      
+      public boolean isRegistered()
+      {
+         return registered;
+      }
+      
+      public boolean isUnregistered()
+      {
+         return unregistered;
+      }
+      
+   }
+   
+   /**
+    * A DRM ReplicantListener that does nothing.
+    */
+   static class NullListener
+      implements DistributedReplicantManager.ReplicantListener
+   {
+      public void replicantsChanged(String key, List newReplicants, 
+                                    int newReplicantsViewId)
+      {
+         // no-op
+      }
+   }
+   
+   /**
+    * DRM ReplicantListener that mimics the HASingletonDeployer service
+    * by deploying/undeploying a service if it's notified that by that DRM
+    * that it is the master replica for its key.
+    */
+   static class MockHASingletonDeployer
+      implements DistributedReplicantManager.ReplicantListener
+   {
+      DistributedReplicantManager drm;
+      MockDeployer deployer;
+      String key;
+      boolean master = false;
+      NullListener deploymentListener = new NullListener();
+      Exception ex;
+      Logger log;
+      Object mutex = new Object();
+      
+      MockHASingletonDeployer(MockDeployer deployer, String key, Logger log)
+      {
+         this.drm = deployer.getDRM();
+         this.deployer = deployer;
+         this.key = key;
+         this.log = log;
+      }
+
+      public void replicantsChanged(String key, 
+                                    List newReplicants, 
+                                    int newReplicantsViewId)
+      {
+         if (this.key.equals(key))
+         {
+            synchronized(mutex)
+            {
+               boolean nowMaster = drm.isMasterReplica(key);
+               
+               try
+               {
+                  if (!master && nowMaster) {
+                     log.debug(Thread.currentThread().getName() + 
+                               " Deploying " + key);
+                     deployer.deploy(key + "A", key, deploymentListener);
+                  }
+                  else if (master && !nowMaster) {
+                     log.debug(Thread.currentThread().getName() + 
+                               " undeploying " + key);
+                     deployer.undeploy(key + "A", deploymentListener);
+                  }
+                  else 
+                  {
+                     log.debug(Thread.currentThread().getName() + 
+                               " -- no status change in " + key + 
+                               " -- master = " + master);   
+                  }
+                  master = nowMaster;
+               }
+               catch (Exception e)
+               {
+                  e.printStackTrace();
+                  if (ex == null)
+                     ex = e;
+               }
+            }
+         }         
+      }
+      
+      public Exception getException()
+      {
+         return ex;
+      }
+      
+   }
+   
+   /**
+    * Thread the repeatedly deploys and undeploys a MockHASingletonDeployer.
+    */
+   static class DeployerThread extends Thread
+   {
+      Semaphore semaphore;
+      MockDeployer deployer;
+      DistributedReplicantManager.ReplicantListener listener;
+      String key;
+      Exception ex;
+      int count = -1;
+      Logger log;
+      
+      DeployerThread(MockDeployer deployer, 
+                     String key, 
+                     DistributedReplicantManager.ReplicantListener listener,
+                     Semaphore semaphore,
+                     Logger log)
+      {
+         super("Deployer " + key);
+         this.deployer = deployer;
+         this.listener = listener;
+         this.key = key;
+         this.semaphore = semaphore;
+         this.log = log;
+      }
+      
+      public void run()
+      {
+         boolean acquired = false;
+         try
+         {
+            acquired = semaphore.attempt(60000);
+            if (!acquired)
+               throw new Exception("Cannot acquire semaphore");
+            SecureRandom random = new SecureRandom();
+            for (count = 0; count < LOOP_COUNT; count++)
+            {
+               deployer.deploy(key, "JGroups", listener);
+
+               sleepThread(random.nextInt(50));
+               deployer.undeploy(key, listener);
+            }
+         }
+         catch (Exception e)
+         {
+            e.printStackTrace();
+            ex = e;
+         }
+         finally
+         {
+            if (acquired)
+               semaphore.release();
+         }
+      }
+      
+      public Exception getException()
+      {
+         return ex;
+      }
+      
+      public int getCount()
+      {
+         return count;
+      }
+   }
+   
+   /**
+    * Thread that mimics the JGroups up-handler thread that calls into the DRM.
+    * Repeatedly and randomly calls adds or removes a replicant for a set
+    * of keys. 
+    */
+   static class JGroupsThread extends Thread
+   {
+      Semaphore semaphore;
+      DistributedReplicantManagerImpl drm;
+      String[] keys;
+      String nodeName;
+      Exception ex;
+      int count = -1;
+      int weightFactor;
+      
+      JGroupsThread(DistributedReplicantManagerImpl drm, 
+                    String[] keys,
+                    String nodeName,
+                    Semaphore semaphore)
+      {
+         super("JGroups");
+         this.drm = drm;
+         this.keys = keys;
+         this.semaphore = semaphore;
+         this.nodeName = nodeName;
+         this.weightFactor = (int) 2.5 * keys.length;
+      }
+      
+      public void run()
+      {
+         boolean acquired = false;
+         try
+         {
+            acquired = semaphore.attempt(60000);
+            if (!acquired)
+               throw new Exception("Cannot acquire semaphore");
+            boolean[] added = new boolean[keys.length];
+            SecureRandom random = new SecureRandom();
+            
+            for (count = 0; count < weightFactor * LOOP_COUNT; count++)
+            {
+               int pos = random.nextInt(keys.length);
+               if (added[pos])
+               {
+                  drm._remove(keys[pos], nodeName);
+                  added[pos] = false;
+               }
+               else
+               {
+                  drm._add(keys[pos], nodeName, "");
+                  added[pos] = true;
+               }
+               sleepThread(random.nextInt(30));
+            }
+         }
+         catch (Exception e)
+         {
+            e.printStackTrace();
+            ex = e;
+         }
+         finally
+         {
+            if (acquired)
+               semaphore.release();
+         }
+      }
+      
+      public Exception getException()
+      {
+         return ex;
+      }
+      
+      public int getCount()
+      {
+         return (count / weightFactor);
+      }
+      
+   }
+   
+   /**
+    * Mocks the deployer of a service that registers/unregisters DRM listeners 
+    * and replicants. Only allows a single thread of execution, a la the
+    * org.jboss.system.ServiceController.
+    */
+   static class MockDeployer
+   {
+      DistributedReplicantManager drm;
+      
+      MockDeployer(DistributedReplicantManager drm)
+      {
+         this.drm = drm;
+      }
+      
+      void deploy(String key, String replicant, 
+                  DistributedReplicantManager.ReplicantListener listener)
+            throws Exception 
+      {
+         synchronized(this)
+         {
+            drm.registerListener(key, listener);
+            drm.add(key, replicant);
+            sleepThread(10);
+         }
+      }
+      
+      void undeploy(String key, 
+                    DistributedReplicantManager.ReplicantListener listener)
+         throws Exception 
+      {
+         synchronized(this)
+         {
+            drm.remove(key);
+            drm.unregisterListener(key, listener);
+            sleepThread(10);
+         }
+      }
+      
+      DistributedReplicantManager getDRM()
+      {
+         return drm;
+      }
+   }
+   
+   /** ReplicantListener that caches the list of replicants */
+   static class CachingListener implements ReplicantListener
+   {
+      List replicants = null;
+      boolean clean = true;
+      
+      public void replicantsChanged(String key, List newReplicants, 
+                                    int newReplicantsViewId)
+      {
+         this.replicants = newReplicants;
+         if (clean && newReplicants != null)
+         {
+            int last = Integer.MIN_VALUE;
+            for (Iterator iter = newReplicants.iterator(); iter.hasNext(); )
+            {
+               int cur = ((Integer) iter.next()).intValue();
+               if (last >= cur)
+               {
+                  clean = false;
+                  break;
+               }
+               
+               last = cur;
+            }
+         }
+      }
+      
+   }
+
+   private static Object lock = new Object();
+   private static int LOOP_COUNT = 30;
+   
+   public static Test suite() throws Exception
+   {
+      Test t1 = getDeploySetup(DRMTestCase.class, "drm-tests.sar");
+      return t1;
+   }
+
+   public DRMTestCase(String name)
+   {
+      super(name);
+   }
+
+   public void testStateReplication()
+      throws Exception
+   {
+      log.debug("+++ testStateReplication");
+      log.info("java.rmi.server.hostname="+System.getProperty("java.rmi.server.hostname"));
+      RMIAdaptor[] adaptors = getAdaptors();
+      String[] servers = super.getServers();
+      RMIAdaptorExt server0 = (RMIAdaptorExt) adaptors[0];
+      log.info("server0: "+server0);
+      ObjectName clusterService = new ObjectName("jboss:service=DefaultPartition");
+      Vector view0 = (Vector) server0.getAttribute(clusterService, "CurrentView");
+      log.info("server0: CurrentView, "+view0);
+      log.debug("+++ testStateReplication 1");
+      ObjectName drmService = new ObjectName("jboss.test:service=DRMTestCase");
+      IReplicants drm0 = (IReplicants)
+         MBeanServerInvocationHandler.newProxyInstance(server0, drmService,
+         IReplicants.class, true);
+      log.debug("+++ testStateReplication 2");
+      log.info(MBeanServerInvocationHandler.class.getProtectionDomain());
+      TestListener listener = new TestListener(log);
+      server0.addNotificationListener(drmService, listener, null, null);
+      log.info("server0 addNotificationListener");
+      log.debug("+++ testStateReplication 3");
+      String address = (String) drm0.lookupLocalReplicant();
+      log.debug("+++ testStateReplication 4");
+      log.info("server0: lookupLocalReplicant: "+address);
+      assertTrue("server0: address("+address+") == server0("+servers[0]+")",
+         address.equals(servers[0]));
+
+      RMIAdaptorExt server1 = (RMIAdaptorExt) adaptors[1];
+      log.info("server1: "+server1);
+      Vector view1 = (Vector) server1.getAttribute(clusterService, "CurrentView");
+      log.info("server1: CurrentView, "+view1);
+      IReplicants drm1 = (IReplicants)
+         MBeanServerInvocationHandler.newProxyInstance(server1, drmService,
+         IReplicants.class, true);
+      server1.addNotificationListener(drmService, listener, null, null);
+      log.info("server1 addNotificationListener");
+      address = (String) drm1.lookupLocalReplicant();
+      log.info("server1: lookupLocalReplicant: "+address);
+      assertTrue("server1: address("+address+") == server1("+servers[1]+")",
+         address.equals(servers[1]));
+
+      List replicants0 = drm0.lookupReplicants();
+      List replicants1 = drm1.lookupReplicants();
+      assertTrue("size of replicants0 == replicants1)",
+         replicants0.size() == replicants1.size());
+      HashSet testSet = new HashSet(replicants0);
+      for(int n = 0; n < replicants0.size(); n ++)
+      {
+         Object entry = replicants1.get(n);
+         assertTrue("replicants0 contains:"+entry, testSet.contains(entry));
+      }
+
+      //
+      for(int n = 0; n < 10; n ++)
+      {
+         drm0.add("key"+n, "data"+n+".0");
+         drm1.add("key"+n, "data"+n+".1");
+      }
+      for(int n = 0; n < 10; n ++)
+      {
+         String key = "key"+n;
+         log.info("key: "+key);
+         replicants0 = drm0.lookupReplicants(key);
+         replicants1 = drm1.lookupReplicants(key);
+         log.info("replicants0: "+replicants0);
+         log.info("replicants1: "+replicants1);
+         HashSet testSet0 = new HashSet(replicants0);
+         HashSet testSet1 = new HashSet(replicants1);
+         assertTrue("size of replicants0 == replicants1)",
+            replicants0.size() == replicants1.size());
+         Object entry = drm0.lookupLocalReplicant(key);
+         log.info("drm0.lookupLocalReplicant, key="+key+", entry="+entry);
+         assertTrue("replicants0 contains:"+entry, testSet0.contains(entry));
+         assertTrue("replicants1 contains:"+entry, testSet1.contains(entry));
+         entry = drm1.lookupLocalReplicant(key);
+         log.info("drm1.lookupLocalReplicant, key="+key+", entry="+entry);
+         assertTrue("replicants0 contains:"+entry, testSet0.contains(entry));
+         assertTrue("replicants1 contains:"+entry, testSet1.contains(entry));
+      }
+
+      for(int n = 0; n < 10; n ++)
+         drm0.remove("key"+n);
+
+      server0.removeNotificationListener(drmService, listener);
+      server1.removeNotificationListener(drmService, listener);
+   }
+   
+   /**
+    * Tests the functionality of isMasterReplica(), also testing merge
+    * handling.  This test creates and manipulates two HAPartition instances in memory 
+    * so it doesn't require a server deployment.  The partition instances communicate via
+    * a GossipRouter.  The router is stopped and restarted to simulate a merge condition.
+    * 
+    * TODO move this test out of the testsuite and into the cluster module
+    *      itself, since it doesn't rely on the container.
+    * 
+    * @throws Exception
+    */
+   public void testIsMasterReplica() throws Exception
+   {
+      GossipRouter router = null;
+      log.debug("+++ testIsMasterReplica()");
+
+      try
+      {  
+         String partitionName = "DRMTestCasePartition";
+         String muxFile = "jgroups-multiplexer.sar/META-INF/multiplexer-stacks.xml";
+         String stackName = "tunnel";
+         
+         log.info("DRMTestCase.testIsMasterReplica() - starting GossipRouter");
+         // router characteristics here must match the definition in the stack configuration
+         router = new GossipRouter(12001, "127.0.0.1");
+         router.start();
+         Thread.sleep(10000);
+         
+         Configuration cacheConfig1 = new Configuration();
+         cacheConfig1.setMultiplexerStack(stackName);
+         RuntimeConfig cacheRuntimeConfig1 = new RuntimeConfig();
+         JChannelFactory factory1 = new JChannelFactory();
+         factory1.setMultiplexerConfig(muxFile);
+         factory1.setNamingServicePort(1099);
+         cacheRuntimeConfig1.setMuxChannelFactory(factory1);
+         cacheConfig1.setRuntimeConfig(cacheRuntimeConfig1);
+         CacheJmxWrapper wrapper1 = new CacheJmxWrapper();
+         wrapper1.setConfiguration(cacheConfig1);
+         wrapper1.create();
+         wrapper1.start();
+         
+         DistributedStateImpl ds1 = new DistributedStateImpl();
+         ds1.setClusteredCache(wrapper1.getCache());
+         
+         ClusterPartitionConfig config1 = new ClusterPartitionConfig();
+         config1.setPartitionName(partitionName);
+         config1.setNodeUniqueId("DRMTestCaseNode1");
+         config1.setClusteredCache(wrapper1.getCache());
+         config1.setDistributedState(ds1);
+         config1.setStateTransferTimeout(30000);
+         config1.setMethodCallTimeout(60000);
+         ClusterPartition partition1 = new ClusterPartition(config1);
+         partition1.setBindIntoJndi(false);
+         partition1.create();
+         partition1.start();
+         Thread.sleep(10000);
+         
+         Configuration cacheConfig2 = new Configuration();
+         cacheConfig2.setMultiplexerStack(stackName);
+         RuntimeConfig cacheRuntimeConfig2 = new RuntimeConfig();
+         JChannelFactory factory2 = new JChannelFactory();
+         factory2.setMultiplexerConfig(muxFile);
+         factory2.setNamingServicePort(1099);
+         cacheRuntimeConfig2.setMuxChannelFactory(factory2);
+         cacheConfig2.setRuntimeConfig(cacheRuntimeConfig2);
+         CacheJmxWrapper wrapper2 = new CacheJmxWrapper();
+         wrapper2.setConfiguration(cacheConfig2);
+         wrapper2.create();
+         wrapper2.start();
+         
+         DistributedStateImpl ds2 = new DistributedStateImpl();
+         ds2.setClusteredCache(wrapper2.getCache());
+         
+         ClusterPartitionConfig config2 = new ClusterPartitionConfig();
+         config2.setPartitionName(partitionName);
+         config2.setNodeUniqueId("DRMTestCaseNode2");
+         config2.setClusteredCache(wrapper2.getCache());
+         config2.setDistributedState(ds2);
+         config2.setStateTransferTimeout(30000);
+         config2.setMethodCallTimeout(60000);
+         ClusterPartition partition2 = new ClusterPartition(config2);
+         partition2.setBindIntoJndi(false);
+         partition2.create();
+         partition2.start();
+         Thread.sleep(10000);
+
+         DistributedReplicantManager drm1 = partition1.getDistributedReplicantManager();
+         DistributedReplicantManager drm2 = partition2.getDistributedReplicantManager();
+         
+         // confirm that each partition contains two nodes   
+         assertEquals("Partition1 should contain two nodes; ", 2, partition1.getCurrentView().size());
+         assertEquals("Partition2 should contain two nodes; ", 2, partition2.getCurrentView().size());
+         
+         drm1.add(SERVICEA, "valueA1");
+         drm2.add(SERVICEA, "valueA2");
+         drm2.add(SERVICEB, "valueB2");
+         
+         // test that only one node is the master replica for serviceA
+         assertTrue("ServiceA must have a master replica", 
+                 drm1.isMasterReplica(SERVICEA) || drm2.isMasterReplica(SERVICEA));
+         assertTrue("ServiceA must have a single master replica", 
+                 drm1.isMasterReplica(SERVICEA) != drm2.isMasterReplica(SERVICEA));
+ 
+         // ServiceB should only be a master replica on partition2
+         assertFalse("ServiceB should not be a master replica on partition1", 
+                 drm1.isMasterReplica(SERVICEB));
+         assertTrue("ServiceB must have a master replica on partition2", 
+                 drm2.isMasterReplica(SERVICEB));
+         
+         // confirm that each partition contains correct DRM replicants for services A and B  
+         assertEquals("Partition1 should contain two DRM replicants for serviceA; ", 
+                 2, drm1.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition2 should contain two DRM replicants for serviceA; ", 
+                 2, drm2.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition1 should contain one DRM replicant for serviceB; ", 
+                 1, drm1.lookupReplicants(SERVICEB).size());
+         assertEquals("Partition2 should contain one DRM replicant for serviceB; ", 
+                 1, drm2.lookupReplicants(SERVICEB).size());
+
+         // simulate a split of the partition
+         log.info("DRMTestCase.testIsMasterReplica() - stopping GossipRouter");
+         router.stop();
+         sleepThread(15000);
+         
+         // confirm that each partition contains one node   
+         assertEquals("Partition1 should contain one node after split; ", 
+                 1, partition1.getCurrentView().size());
+         assertEquals("Partition2 should contain one node after split; ", 
+                 1, partition2.getCurrentView().size());
+        
+         // confirm that each node is a master replica for serviceA after the split
+         assertTrue("ServiceA should be a master replica on partition1 after split", 
+                 drm1.isMasterReplica(SERVICEA));
+         assertTrue("ServiceA should be a master replica on partition2 after split", 
+                 drm2.isMasterReplica(SERVICEA));
+         
+         // ServiceB should still only be a master replica on partition2 after split
+         assertFalse("ServiceB should not be a master replica on partition1 after split", 
+                 drm1.isMasterReplica(SERVICEB));
+         assertTrue("ServiceB must have a master replica on partition2 after split", 
+                 drm2.isMasterReplica(SERVICEB));
+         
+         // Remove ServiceA replicant from partition1         
+         drm1.remove(SERVICEA);
+         
+         // test that this node is not the master replica         
+         assertFalse("partition1 is not master replica after dropping ServiceA replicant", 
+                 drm1.isMasterReplica(SERVICEA));
+         
+         //Restore the local replicant         
+         drm1.add(SERVICEA, "valueA1a");
+         
+         // simulate a merge
+         log.info("DRMTestCase.testIsMasterReplica() - restarting GossipRouter");
+         router.start();
+         // it seems to take more than 15 seconds for the merge to take effect
+         sleepThread(30000);
+         
+         assertTrue(router.isStarted());
+
+         // confirm that each partition contains two nodes again
+         assertEquals("Partition1 should contain two nodes after merge; ", 
+               2, partition1.getCurrentView().size());
+         assertEquals("Partition2 should contain two nodes after merge; ", 
+                 2, partition2.getCurrentView().size());
+         
+         // test that only one node is the master replica for serviceA after merge
+         assertTrue("ServiceA must have a master replica after merge", 
+                 drm1.isMasterReplica(SERVICEA) || drm2.isMasterReplica(SERVICEA));
+         assertTrue("ServiceA must have a single master replica after merge", 
+                 drm1.isMasterReplica(SERVICEA) != drm2.isMasterReplica(SERVICEA));
+ 
+         // ServiceB should only be a master replica on partition2 after merge
+         assertFalse("ServiceB should not be a master replica on partition1 after merge", 
+                 drm1.isMasterReplica(SERVICEB));
+         assertTrue("ServiceB must have a master replica on partition2 after merge", 
+                 drm2.isMasterReplica(SERVICEB));
+         
+         // confirm that each partition contains correct DRM replicants for services A and B after merge 
+         assertEquals("Partition1 should contain two DRM replicants for serviceA after merge; ", 
+                 2, drm1.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition2 should contain two DRM replicants for serviceA after merge; ", 
+                 2, drm2.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition1 should contain one DRM replicant for serviceB after merge; ", 
+                 1, drm1.lookupReplicants(SERVICEB).size());
+         assertEquals("Partition2 should contain one DRM replicant for serviceB after merge; ", 
+                 1, drm2.lookupReplicants(SERVICEB).size());
+         
+         partition1.stop();
+         partition2.stop();
+      }
+      finally
+      {
+         log.info("DRMTestCase.testIsMasterReplica() - cleaning up resources");
+         if (router != null)
+            router.stop();
+      }
+   }
+   
+   /**
+    * Tests that one thread blocking in DRM.notifyKeyListeners() does not
+    * prevent other threads registering/unregistering listeners. JBAS-2539
+    * 
+    * TODO move this test out of the testsuite and into the cluster module
+    *      itself, since it doesn't rely on the container.
+    * 
+    * @throws Exception
+    */
+   public void testKeyListenerDeadlock() throws Exception
+   {
+      log.debug("+++ testKeyListenerDeadlock()");
+      
+      MBeanServer mbeanServer = 
+         MBeanServerFactory.createMBeanServer("mockPartition");
+      try {
+         ClusterNode localAddress = new ClusterNode(new IpAddress("127.0.0.1", 12345));
+         MockHAPartition partition = new MockHAPartition(localAddress);
+      
+         DistributedReplicantManagerImpl drm = 
+               new DistributedReplicantManagerImpl(partition);
+
+         drm.create();
+         
+         // Create a fake view for the MockHAPartition
+         
+         Vector remoteAddresses = new Vector();
+         for (int i = 1; i < 5; i++)
+            remoteAddresses.add(new ClusterNode(new IpAddress("127.0.0.1", 12340 + i)));
+         
+         Vector allNodes = new Vector(remoteAddresses);
+         allNodes.add(localAddress);
+         partition.setCurrentViewClusterNodes(allNodes);
+         
+         drm.start();
+         
+         BlockingListenerThread blt = 
+            new BlockingListenerThread(drm, true, null);
+         
+         // Hold the lock monitor so the test thread can't acquire it
+         // This keeps the blocking thread alive.
+         synchronized(lock) {
+            // Spawn a thread that will change a key and then block on the
+            // notification back to itself
+            blt.start();
+
+            sleepThread(50);
+            
+            assertTrue("Test thread is alive", blt.isAlive());            
+            assertTrue("Test thread is blocking", blt.isBlocking());
+            
+            RegistrationThread rt = new RegistrationThread(drm);
+            rt.start();
+
+            sleepThread(50);
+            
+            assertTrue("No deadlock on listener registration", rt.isRegistered());
+            
+            assertTrue("No deadlock on listener unregistration", rt.isUnregistered());
+            
+            assertNull("No exception in deadlock tester", blt.getException());
+            
+            assertTrue("Test thread is still blocking", blt.isBlocking());
+            assertTrue("Test thread is still alive", blt.isAlive());
+         }
+         
+         drm.unregisterListener("TEST", blt);
+         
+         sleepThread(50);
+         
+         // Test going through remove
+         blt = new BlockingListenerThread(drm, false, null);
+         
+         // Hold the lock monitor so the test thread can't acquire it
+         // This keeps the blocking thread alive.
+         synchronized(lock) {
+            // Spawn a thread that will change a key and then block on the
+            // notification back to itself
+            blt.start();
+
+            sleepThread(50);
+            
+            assertTrue("Test thread is alive", blt.isAlive());            
+            assertTrue("Test thread is blocking", blt.isBlocking());
+            
+            RegistrationThread rt = new RegistrationThread(drm);
+            rt.start();
+
+            sleepThread(50);
+            
+            assertTrue("No deadlock on listener registration", rt.isRegistered());
+            
+            assertTrue("No deadlock on listener unregistration", rt.isUnregistered());
+            
+            assertNull("No exception in deadlock tester", blt.getException());
+            
+            assertTrue("Test thread is still blocking", blt.isBlocking());
+            assertTrue("Test thread is still alive", blt.isAlive());
+         }
+      }
+      finally {
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      }
+   }
+   
+   
+   /**
+    * Tests that remotely-originated calls don't block.
+    * 
+    * TODO move this test out of the testsuite and into the cluster module
+    *      itself, since it doesn't rely on the container.
+    * 
+    * @throws Exception
+    */
+   public void testRemoteCallBlocking() throws Exception
+   {
+      log.debug("+++ testRemoteCallBlocking()");
+      
+      MBeanServer mbeanServer = 
+         MBeanServerFactory.createMBeanServer("mockPartition");
+      try {
+         ClusterNode localAddress = new ClusterNode(new IpAddress("127.0.0.1", 12345));
+         MockHAPartition partition = new MockHAPartition(localAddress);
+      
+         DistributedReplicantManagerImpl drm = 
+               new DistributedReplicantManagerImpl(partition);
+
+         drm.create();
+         
+         // Create a fake view for the MockHAPartition
+         
+         Vector remoteAddresses = new Vector();
+         for (int i = 1; i < 5; i++)
+            remoteAddresses.add(new ClusterNode(new IpAddress("127.0.0.1", 12340 + i)));
+         
+         Vector allNodes = new Vector(remoteAddresses);
+         allNodes.add(localAddress);
+         partition.setCurrentViewClusterNodes(allNodes);
+         
+         drm.start();
+         
+         String sender = ((ClusterNode)remoteAddresses.get(0)).getName();
+         BlockingListenerThread blt = 
+            new BlockingListenerThread(drm, true, sender);
+         
+         // Hold the lock monitor so the test thread can't acquire it
+         // This keeps the blocking thread alive.
+         synchronized(lock) {
+            // Spawn a thread that will change a key and then block on the
+            // notification back to itself
+            blt.start();
+
+            sleepThread(50);
+            
+            assertFalse("JGroups thread is not alive", blt.isAlive());            
+            assertTrue("Async handler thread is blocking", blt.isBlocking());
+            
+            assertNull("No exception in JGroups thread", blt.getException());
+         }
+         
+         drm.unregisterListener("TEST", blt);
+         
+         sleepThread(50);
+         
+         // Test going through remove
+         blt = new BlockingListenerThread(drm, false, sender);
+         
+         // Hold the lock monitor so the test thread can't acquire it
+         // This keeps the blocking thread alive.
+         synchronized(lock) {
+            // Spawn a thread that will change a key and then block on the
+            // notification back to itself
+            blt.start();
+
+            sleepThread(50);
+            
+            assertFalse("JGroups thread is not alive", blt.isAlive());            
+            assertTrue("Async handler thread is blocking", blt.isBlocking());
+            
+            assertNull("No exception in JGroups thread", blt.getException());
+         }
+      }
+      finally {
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      }
+   }
+   
+   /**
+    * Tests that one thread blocking in DRM.notifyKeyListeners() does not
+    * prevent other threads that use different keys adding/removing 
+    * replicants. JBAS-2169
+    * 
+    * TODO move this test out of the testsuite and into the cluster module
+    *      itself, since it doesn't rely on the container.
+    * 
+    * @throws Exception
+    */
+   public void testNonConflictingAddRemoveDeadlock() throws Exception
+   {
+
+      log.debug("+++ testNonConflictingAddRemoveDeadlock()");
+      
+      addRemoveDeadlockTest(false);
+   }
+   
+   /**
+    * Tests that one thread blocking in DRM.notifyKeyListeners() does not
+    * prevent other threads that use the same keys adding/removing 
+    * replicants. JBAS-1151
+    * 
+    * NOTE: This test basically demonstrates a small race condition that can
+    * happen with the way HASingletonSupport's startService() method is
+    * implemented (actually HAServiceMBeanSupport, but relevant in the case
+    * of subclass HASingletonSupport, and in particular in its use in the
+    * HASingletonDeployer service).  However, since the test doesn't actually
+    * use the relevant code, but rather uses mock objects that work the same
+    * way, this test is disabled -- its purpose has been achieved.  JIRA issue 
+    * JBAS-1151 tracks the real problem; when it's resolved we'll create a test 
+    * case against the real code that proves that fact.
+    * 
+    * TODO move this test out of the testsuite and into the cluster module
+    *      itself, since it doesn't rely on the container.
+    * 
+    * @throws Exception
+    */
+   public void badtestConflictingAddRemoveDeadlock() throws Exception
+   {
+      log.debug("+++ testConflictingAddRemoveDeadlock()");
+      
+      addRemoveDeadlockTest(true);
+   }  
+   
+   private void addRemoveDeadlockTest(boolean conflicting) throws Exception
+   {  
+      String[] keys = { "A", "B", "C", "D", "E" };
+      int count = keys.length;
+      
+      MBeanServer mbeanServer = 
+         MBeanServerFactory.createMBeanServer("mockPartition");
+      try {
+         ClusterNode localAddress = new ClusterNode(new IpAddress("127.0.0.1", 12345));
+         MockHAPartition partition = new MockHAPartition(localAddress);
+      
+         DistributedReplicantManagerImpl drm = 
+               new DistributedReplicantManagerImpl(partition);
+
+         drm.create();
+         
+         // Create a fake view for the MockHAPartition
+         
+         Vector remoteAddresses = new Vector();
+         ClusterNode remote = new ClusterNode(new IpAddress("127.0.0.1", 12341));
+         remoteAddresses.add(remote);
+         
+         Vector allNodes = new Vector(remoteAddresses);
+         allNodes.add(localAddress);
+         partition.setCurrentViewClusterNodes(allNodes);
+         
+         drm.start();
+         
+         MockDeployer deployer = new MockDeployer(drm);
+         
+         if (!conflicting)
+         {
+            // Register a MockHASingletonDeployer, but since we're in
+            // non-conflicting mode, the DeployerThreads won't deal with it
+            MockHASingletonDeployer listener = 
+                  new MockHASingletonDeployer(deployer, "HASingleton", log);
+            
+            drm.registerListener("HASingleton", listener);
+            drm.add("HASingleton", "HASingleton");            
+         }
+         
+         // Create a semaphore to gate the threads and acquire all its permits
+         Semaphore semaphore = new Semaphore(count + 1);
+         for (int i = 0; i <= count; i++)
+            semaphore.acquire();
+         
+         DeployerThread[] deployers = new DeployerThread[keys.length];
+         for (int i = 0; i < count; i++)
+         {
+            DistributedReplicantManager.ReplicantListener listener = null;
+            if (conflicting)
+            {
+               listener = new MockHASingletonDeployer(deployer, keys[i], log);
+            }
+            else
+            {
+               listener = new NullListener();
+            }
+            deployers[i] = new DeployerThread(deployer, keys[i], listener, semaphore, log);
+            deployers[i].start();
+         }
+         
+         String[] jgKeys = keys;
+         if (!conflicting)
+         {
+            // The JGroups thread also deals with the MockHASingletonDeployer
+            // key that the DeployerThreads don't
+            jgKeys = new String[keys.length + 1];
+            System.arraycopy(keys, 0, jgKeys, 0, keys.length);
+            jgKeys[keys.length] = "HASingleton";            
+         }
+         JGroupsThread jgThread = new JGroupsThread(drm, jgKeys, remote.getName(), semaphore);
+         jgThread.start();
+         
+         // Launch the threads
+         semaphore.release(count + 1);
+         
+         boolean reacquired = false;
+         try
+         {
+            // Give the threads 5 secs to acquire the semaphore
+            long maxElapsed = System.currentTimeMillis() + 5000;
+            for (int i = 0; i < keys.length; i++)
+            {
+               if (deployers[i].getCount() < 0)
+               {
+                  assertTrue("Thread " + keys[i] + " started in time",
+                              maxElapsed - System.currentTimeMillis() > 0);
+                  sleepThread(10);
+                  i--; // try again
+               }   
+            }
+            
+            while (jgThread.getCount() < 0)
+            {
+               assertTrue("jgThread started in time",
+                           maxElapsed - System.currentTimeMillis() > 0);
+               sleepThread(10);               
+            }
+            // Reaquire all the permits, thus showing the threads didn't deadlock
+            
+            // Give them 500 ms per loop
+            maxElapsed = System.currentTimeMillis() + (500 * LOOP_COUNT);
+            for (int i = 0; i <= count; i++)
+            {
+               long waitTime = maxElapsed - System.currentTimeMillis();
+               assertTrue("Acquired thread " + i, semaphore.attempt(waitTime));
+            }
+            
+            reacquired = true;
+            
+            // Ensure there were no exceptions
+            for (int i = 0; i < keys.length; i++)
+            {
+               assertEquals("Thread " + keys[i] + " finished", LOOP_COUNT, deployers[i].getCount());
+               assertNull("Thread " + keys[i] + " saw no exceptions", deployers[i].getException());
+            }
+            assertEquals("JGroups Thread finished", LOOP_COUNT, jgThread.getCount());
+            assertNull("JGroups Thread saw no exceptions", jgThread.getException());
+         }
+         finally
+         {
+
+            if (!reacquired)
+            {
+               for (int i = 0; i < keys.length; i++)
+               {
+                  if (deployers[i].getException() != null)
+                  {
+                     System.out.println("Exception in deployer " + i);
+                     deployers[i].getException().printStackTrace(System.out);
+                  }
+                  else
+                  {
+                     System.out.println("Thread " + i + " completed " + deployers[i].getCount());
+                  }
+               }
+               if (jgThread.getException() != null)
+               {
+                  System.out.println("Exception in jgThread");
+                  jgThread.getException().printStackTrace(System.out);
+               }
+               else
+               {
+                  System.out.println("jgThread completed " + jgThread.getCount());
+               }
+            }
+            
+            // Be sure the threads are dead
+            if (jgThread.isAlive())
+            {
+               jgThread.interrupt();
+               sleepThread(5);   
+               printStackTrace(jgThread.getName(), jgThread.getException());
+            }
+            for (int i = 0; i < keys.length; i++)
+            {
+               if (deployers[i].isAlive())
+               {
+                  deployers[i].interrupt();
+                  sleepThread(5);
+                  printStackTrace(deployers[i].getName(), deployers[i].getException());
+               }
+            }
+               
+         }
+      }
+      finally {
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      }
+   }
+   
+   public void testReplicantOrder() throws Exception
+   {
+      MBeanServer mbeanServer =
+         MBeanServerFactory.createMBeanServer("mockPartitionA");
+      try {
+         
+         //  Create a fake view for the MockHAPartition
+         ClusterNode[] nodes = new ClusterNode[5];
+         String[] names = new String[nodes.length];
+         Integer[] replicants = new Integer[nodes.length];
+         Vector allNodes = new Vector();
+         for (int i = 0; i < nodes.length; i++)
+         {
+            nodes[i] = new ClusterNode(new IpAddress("127.0.0.1", 12340 + i));
+            allNodes.add(nodes[i]);
+            names[i] = nodes[i].getName();
+            replicants[i] = new Integer(i);
+         }
+         
+         MockHAPartition partition = new MockHAPartition(nodes[2]);
+         partition.setCurrentViewClusterNodes(allNodes);
+         
+         DistributedReplicantManagerImpl drm = 
+               new DistributedReplicantManagerImpl(partition);
+         drm.create();
+         drm.start();
+         
+         CachingListener listener = new CachingListener();
+         drm.registerListener("TEST", listener);
+         
+         SecureRandom random = new SecureRandom();
+         boolean[] added = new boolean[nodes.length];
+         List lookup = null;
+         for (int i = 0; i < 10; i++)
+         {
+            int node = random.nextInt(nodes.length);
+            if (added[node])
+            {
+               if (node == 2)
+                  drm.remove("TEST");
+               else
+                  drm._remove("TEST", nodes[node].getName());
+               added[node] = false;
+            }
+            else
+            {     
+               if (node == 2)
+                  drm.add("TEST", replicants[node]);
+               else
+                  drm._add("TEST", nodes[node].getName(), replicants[node]);   
+               added[node] = true;
+            }
+            
+            // Confirm the proper order of the replicant node names
+            lookup = maskListClass(drm.lookupReplicantsNodeNames("TEST"));
+            confirmReplicantList(lookup, names, added);
+            
+            // Confirm the proper order of the replicants via lookupReplicants
+            lookup = maskListClass(drm.lookupReplicants("TEST"));
+            confirmReplicantList(lookup, replicants, added);
+            
+            // Confirm the listener got the same list
+//            assertEquals("Listener received a correct list", lookup, 
+//                         maskListClass(listener.replicants));
+         }
+         
+         // Let the asynchronous notification thread catch up
+         sleep(25);
+         
+         // Confirm all lists presented to the listener were properly ordered
+         assertTrue("Listener saw no misordered lists", listener.clean);
+         
+      }
+      finally {
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      }
+   }
+   
+   private void confirmReplicantList(List current, Object[] all, boolean[] added)
+   {
+      Iterator iter = current.iterator();
+      for (int i = 0; i < added.length; i++)
+      {
+         if (added[i])
+         {
+            assertTrue("List has more replicants", iter.hasNext());
+            assertEquals("Replicant for node " + i + " is next", 
+                         all[i], iter.next());
+         }
+      }
+      assertFalse("List has no extra replicants", iter.hasNext());
+   }
+   
+   /** Converts the given list to an ArrayList, if it isn't already */
+   private List maskListClass(List toMask)
+   {
+      if (toMask instanceof ArrayList)
+         return toMask;
+      else if (toMask == null)
+         return new ArrayList();
+      else
+         return new ArrayList(toMask);
+   }
+
+   private static void sleepThread(long millis)
+   {
+      try
+      {
+         Thread.sleep(millis);
+      }
+      catch (InterruptedException e) {
+         e.printStackTrace();
+      }
+   }
+   
+   private static void printStackTrace(String threadName, Exception e)
+   {
+      if (e instanceof InterruptedException)
+      {
+         System.out.println("Stack trace for " + threadName);
+         e.printStackTrace(System.out);
+         System.out.println();
+      }
+   }
+
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/DRMTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/FamilyClusterInfoUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/FamilyClusterInfoUnitTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/FamilyClusterInfoUnitTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,368 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.jboss.ha.framework.interfaces.ClusteringTargetsRepository;
+import org.jboss.ha.framework.interfaces.FamilyClusterInfo;
+
+import junit.framework.TestCase;
+
+/**
+ * Test of FamilyClusterInfoImpl.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision$
+ */
+public class FamilyClusterInfoUnitTestCase extends TestCase
+{
+   private abstract class FCIChanger extends Thread
+   {
+      private boolean started;
+      private boolean stopped;
+      private Throwable caught;
+      
+      protected FamilyClusterInfo fci;
+      
+      FCIChanger(FamilyClusterInfo fci)
+      {
+         this.fci = fci;
+      }
+      
+      abstract void update();
+      
+      
+      public void run()
+      {
+         try
+         {
+            started = true;
+            
+            while (!stopped)
+            {
+               if (interrupted())
+                  throw new InterruptedException();
+               
+               update();
+            }
+            
+         }
+         catch (InterruptedException ie)
+         {
+            if (!stopped)
+               caught = ie;
+         }
+         catch (Throwable t)
+         {
+            caught = t;
+         }
+         finally
+         {
+            started = false;
+         }
+      }
+      
+      void beginUpdates()
+      {
+         this.start();
+         while (!started)
+         {
+            try
+            {
+               sleep(10);
+            }
+            catch (InterruptedException e)
+            {
+               caught = e;
+            }
+         }
+      }
+      
+      void endUpdates()
+      {
+         if (started)
+         {
+            stopped = true;
+            try
+            {
+               this.join(250);
+            }
+            catch (InterruptedException ignored) {}
+         }
+         
+         if (started)
+            interrupt();
+      }
+      
+      Throwable getThrowable()
+      {
+         return caught;
+      }
+   }
+   
+   private class Updater extends FCIChanger
+   {
+      private ArrayList targets = new ArrayList();
+      private int viewId;
+      
+      Updater(FamilyClusterInfo fci)
+      {
+         super(fci);
+      }
+      
+      void update()
+      {
+         targets.add(new Object());
+         viewId++;
+         fci.updateClusterInfo((ArrayList) targets.clone(), viewId);         
+      }
+   }
+   
+   private class Remover extends FCIChanger
+   {
+      Remover(FamilyClusterInfo fci)
+      {
+         super(fci);
+      }
+      
+      void update()
+      {
+         List targets = fci.getTargets();
+         if (targets.size() > 0)
+            fci.removeDeadTarget(targets.get(0));
+      }
+      
+   }
+   
+   private class Resetter extends FCIChanger
+   {
+      Resetter(FamilyClusterInfo fci)
+      {
+         super(fci);
+      }
+      
+      void update()
+      {
+         fci.resetView();
+      }      
+   }
+   
+   public void testSynchronization() throws Exception
+   {
+      ClusteringTargetsRepository.initTarget("testSynchronization", new ArrayList(), 0);
+      FamilyClusterInfo fci = ClusteringTargetsRepository.getFamilyClusterInfo("testSynchronization");
+      
+      Updater updater = new Updater(fci);
+      Remover remover = new Remover(fci);
+      Resetter resetter = new Resetter(fci);
+      
+      updater.beginUpdates();
+      
+      checkFCIConsistency(fci, 150, false);
+      
+      remover.beginUpdates();
+      
+      checkFCIConsistency(fci, 150, true);
+      
+      resetter.beginUpdates();
+      
+      checkFCIConsistency(fci, 150, true);
+      
+      updater.endUpdates();
+      remover.endUpdates();
+      resetter.endUpdates();
+      
+      assertNull("Updater had no exceptions", updater.getThrowable());
+      assertNull("Remover had no exceptions", remover.getThrowable());
+      assertNull("Resetter had no exceptions", resetter.getThrowable());
+      
+   }
+   
+   public void testTargetListImmutability() throws Exception
+   {
+      ArrayList targets = new ArrayList();
+      targets.add("ONE");
+      targets.add("TWO");
+      ClusteringTargetsRepository.initTarget("testImmutability", targets, 0);
+      FamilyClusterInfo fci = ClusteringTargetsRepository.getFamilyClusterInfo("testImmutability");
+      
+      List fciTargets = fci.getTargets();
+      
+      // Confirm the targets are what we expect
+      assertEquals("Expected number of targets", 2, fciTargets.size());
+      assertEquals("First target as expected", "ONE", fciTargets.get(0));
+      assertEquals("Second target as expected", "TWO", fciTargets.get(1));
+      
+      try 
+      { 
+         fciTargets.add("FAIL");
+         fail("add call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      try 
+      { 
+         fciTargets.addAll(targets);
+         fail("addAll call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      try 
+      { 
+         fciTargets.clear();
+         fail("clear call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      try 
+      { 
+         fciTargets.remove(0);
+         fail("remove call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      try 
+      { 
+         fciTargets.set(0, "FAIL");
+         fail("set call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      try 
+      { 
+         fciTargets.removeAll(targets);
+         fail("removeAll call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      try 
+      { 
+         fciTargets.retainAll(targets);
+         fail("retainAll call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      Iterator iter = fciTargets.iterator();
+      int count = 0;
+      while (iter.hasNext())
+      {
+         iter.next();
+         count++;         
+      }
+      assertEquals("Correct count", 2, count);
+      try 
+      { 
+         iter.remove();
+         fail("Iterator.remove call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      ListIterator listIter = fciTargets.listIterator();
+      count = 0;
+      while (listIter.hasNext())
+      {
+         listIter.next();
+         count++;         
+      }
+      assertEquals("Correct count", 2, count);
+      try 
+      { 
+         listIter.remove();
+         fail("Iterator.remove call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      while (listIter.hasPrevious())
+      {
+         listIter.previous();
+         count--;
+      }
+      assertEquals("Correct count", 0, count);
+      
+      listIter = fciTargets.listIterator(1);
+      while (listIter.hasNext())
+      {
+         listIter.next();
+         count++;         
+      }
+      assertEquals("Correct count", 1, count);
+      try 
+      { 
+         listIter.remove();
+         fail("Iterator.remove call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      while (listIter.hasPrevious())
+      {
+         listIter.previous();
+         count--;
+      }
+      assertEquals("Correct count", -1, count);
+      
+      // Check the lists returned by other methods
+      fciTargets = fci.updateClusterInfo(targets, 0);
+
+      try 
+      { 
+         fciTargets.add("FAIL");
+         fail("add call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+      fciTargets = fci.removeDeadTarget(targets.get(0));
+
+      try 
+      { 
+         fciTargets.add("FAIL");
+         fail("add call did not fail");
+      } 
+      catch (UnsupportedOperationException good) {}
+      
+   }
+      
+   private void checkFCIConsistency(FamilyClusterInfo fci, int checks, boolean allowOutOfSync)
+   {
+      
+      for (int i = 0; i < checks; i++)
+      {
+         synchronized (fci)
+         {
+            if (fci.currentMembershipInSyncWithViewId())
+            {
+               List targets = fci.getTargets();
+               long vid = fci.getCurrentViewId();
+               assertEquals("targets and vid match", vid, targets.size());
+            }
+            else
+            {
+               assertTrue("OK for FCI view to be out of sync", allowOutOfSync);
+            }
+         }
+      }
+      
+   }
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/FamilyClusterInfoUnitTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,165 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.jboss.invocation.ServiceUnavailableException;
+import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
+import org.jboss.test.JBossClusteredTestCase;
+import org.jboss.test.cluster.invokerha.HAServiceRemote;
+
+import junit.framework.Test;
+
+/**
+ * Tests for ha invoker.
+ *
+ * @author <a href="mailto:brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision$
+ */
+public class HAInvokerUnitTestCase
+   extends JBossClusteredTestCase
+{
+   private static boolean deployed0_ = true;
+   private static boolean deployed1_ = true;
+   
+   public HAInvokerUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+      throws Exception
+   {
+      return JBossClusteredTestCase.getDeploySetup(HAInvokerUnitTestCase.class, "ha-invoker.sar");
+   }
+
+//   public void testUnifiedHAProxyFailover()
+//      throws Exception
+//   {
+//      haProxyFailoverTest("jmx/HAServiceUnified");
+//   }
+
+//   public void testPooledHAProxyFailover()
+//      throws Exception
+//   {
+//      haProxyFailoverTest("jmx/HAServicePooled");
+//   }
+//
+   public void testJRMPHAProxyFailover()
+      throws Exception
+   {
+      haProxyFailoverTest("jmx/HAService");
+   }
+   
+   private void haProxyFailoverTest(String jndiName) throws Exception
+   {
+      getLog().debug("testHAProxyFailover"); 
+      
+      String[] urls = getNamingURLs();
+      Properties env = new Properties();
+      env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+         "org.jnp.interfaces.NamingContextFactory");
+      env.setProperty(Context.PROVIDER_URL, urls[0]);
+      Context ctx = new InitialContext(env);
+      getLog().debug("Got InitialContext with " + urls[0]);
+      
+      HAServiceRemote remote = (HAServiceRemote) ctx.lookup(jndiName);
+      getLog().debug("Found " + jndiName);
+      assertEquals("Hello", remote.hello());
+      String nodeA = remote.getClusterNode();
+      assertNotNull("Got clusterNode", nodeA);
+      getLog().debug("nodeA OK");
+      // Invoke again to check it works with load balancing
+      assertFalse("Requests load balanced", nodeA.equals(remote.getClusterNode()));
+      getLog().debug("nodeA load balanced OK");
+      
+      // Undeploy from one node
+      reconfigureCluster();
+      
+      // Check it still works
+      try
+      {
+         assertEquals("Hello", remote.hello());
+         getLog().debug("OK after reconfigure");
+      }
+      catch (ServiceUnavailableException sue)
+      {
+         fail("Known issue JBAS-3194: " + sue.getMessage());
+      }
+   }   
+   
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      configureCluster();
+   }
+
+   protected String getDeploymentName()
+   {
+      return "ha-invoker.sar";
+   }
+
+   protected void configureCluster() throws Exception
+   {
+      RMIAdaptor[] adaptors = getAdaptors();
+      String warName = getDeploymentName();
+      if (!deployed0_)
+      {
+         deploy(adaptors[0], warName);
+         getLog().debug("Deployed " + warName + " on server0");
+         deployed0_ = true;
+      }
+      if (!deployed1_)
+      {
+         deploy(adaptors[1], warName);
+         getLog().debug("Deployed " + warName + " on server1");
+         deployed1_ = true;
+      }
+   
+      sleep(2000);
+   }
+   
+   protected void reconfigureCluster() throws Exception
+   {
+      RMIAdaptor[] adaptors = getAdaptors();
+      if (!deployed1_)
+      {
+         deploy(adaptors[1], getDeploymentName());
+         deployed1_ = true;
+         
+         sleep(2000);
+      }
+      
+      if (deployed0_)
+      {
+         undeploy(adaptors[0], getDeploymentName());
+         deployed0_ = false;
+         
+         sleep(2000);
+      }
+   }
+
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAServiceMBeanSupportUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAServiceMBeanSupportUnitTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAServiceMBeanSupportUnitTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,160 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.util.EmptyStackException;
+
+import javax.management.AttributeChangeNotification;
+import javax.management.Notification;
+
+import junit.framework.TestCase;
+
+import org.jboss.test.cluster.haservice.HAServiceMBeanSupportTester;
+
+/**
+ * 
+ * @author  Ivelin Ivanov <ivelin at apache.org>
+ *
+ */
+public class HAServiceMBeanSupportUnitTestCase extends TestCase
+{
+
+  private HAServiceMBeanSupportTester haServiceMBeanSupportTester_ = null;
+
+  public HAServiceMBeanSupportUnitTestCase(String name)
+  {
+    super(name);
+  }
+   
+  public void setUp()
+  {
+    haServiceMBeanSupportTester_ = new HAServiceMBeanSupportTester();
+  }
+
+  
+  public void tearDown() 
+  {
+    haServiceMBeanSupportTester_ = null;
+  }
+
+
+  /**
+   * 
+   * messages should be sent out to both remote and local listeners.
+   *
+   */
+  public void testSendNotificationBroadcastsToClusterAndLocally()
+  {
+    Notification notification = new Notification("test.notification", "some:name=tester", 1);
+    haServiceMBeanSupportTester_.sendNotification( notification );
+
+    assertEquals("sendNotificationToLocalListeners() was not handed the original notification", 
+      haServiceMBeanSupportTester_.__invokationStack__.pop(), notification );
+
+    assertEquals("method not invoked as expected",
+      haServiceMBeanSupportTester_.__invokationStack__.pop(), "sendNotificationToLocalListeners");      
+
+    assertEquals("sendNotificationRemote() was not handed the original notification", 
+      haServiceMBeanSupportTester_.__invokationStack__.pop(), notification );
+    
+    assertEquals("method not invoked as expected",
+      haServiceMBeanSupportTester_.__invokationStack__.pop(), "sendNotificationRemote");      
+  }
+
+  /**
+   * 
+   * Even if the message cannot be sent out to the cluster,
+   * it should still be delivered to local listeners.
+   *
+   */
+  public void testSendNotificationAfterClusterFailureContinueWithLocal()
+  {
+    haServiceMBeanSupportTester_.__shouldSendNotificationRemoteFail__ = true;
+
+    Notification notification = new Notification("test.notification", "some:name=tester", 1);
+    haServiceMBeanSupportTester_.sendNotification( notification );
+    
+    assertEquals("sendNotificationToLocalListeners() was not handed the original notification", 
+    haServiceMBeanSupportTester_.__invokationStack__.pop(), notification );
+
+    assertEquals("method not invoked as expected",
+      haServiceMBeanSupportTester_.__invokationStack__.pop(), "sendNotificationToLocalListeners");      
+  }
+  
+  public void testSendLifecycleNotifications()
+  {
+     Notification notification = new AttributeChangeNotification(
+           haServiceMBeanSupportTester_,
+           1, System.currentTimeMillis(), "test",
+           "State", "java.lang.Integer",
+           new Integer(0), new Integer(1)
+           );
+     
+     haServiceMBeanSupportTester_.setSendRemoteLifecycleNotifications(false);
+     
+     haServiceMBeanSupportTester_.sendNotification( notification );
+     
+     assertEquals("sendNotificationToLocalListeners() was handed the original notification", 
+                 haServiceMBeanSupportTester_.__invokationStack__.pop(), notification );
+
+     assertEquals("method invoked as expected",
+       haServiceMBeanSupportTester_.__invokationStack__.pop(), "sendNotificationToLocalListeners");      
+
+     try
+     {
+        haServiceMBeanSupportTester_.__invokationStack__.pop();
+        fail("sendNotificationRemote() was not handed the original notification");
+     }
+     catch (EmptyStackException good) {}
+     
+     haServiceMBeanSupportTester_.setSendRemoteLifecycleNotifications(true);
+     haServiceMBeanSupportTester_.setSendLocalLifecycleNotifications(false);
+     
+     haServiceMBeanSupportTester_.sendNotification( notification );     
+
+     assertEquals("sendNotificationRemote() was handed the original notification", 
+       haServiceMBeanSupportTester_.__invokationStack__.pop(), notification );
+     
+     assertEquals("method invoked as expected",
+       haServiceMBeanSupportTester_.__invokationStack__.pop(), "sendNotificationRemote");
+     
+     try
+     {
+        haServiceMBeanSupportTester_.__invokationStack__.pop();
+        fail("sendNotificationToLocalListeners() was not handed the original notification");
+     }
+     catch (EmptyStackException good) {}
+  }
+  
+  public void testServiceHAName() throws Exception
+  {
+     assertEquals("Default name correct", HAServiceMBeanSupportTester.SERVICE_NAME, 
+                   haServiceMBeanSupportTester_.getServiceHAName());
+     
+     haServiceMBeanSupportTester_.setServiceHAName("Test");
+     
+     assertEquals("Specified name correct", "Test", 
+           haServiceMBeanSupportTester_.getServiceHAName());
+  }
+
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAServiceMBeanSupportUnitTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonControllerUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonControllerUnitTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonControllerUnitTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,154 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.jboss.test.cluster.hasingleton.HASingletonControllerTester;
+
+/**
+ * HASingletonController tests
+ * 
+ * @author  Ivelin Ivanov <ivelin at jboss.org>
+ * @version $Revision$
+ */
+public class HASingletonControllerUnitTestCase extends TestCase
+{
+   private HASingletonControllerTester singletonControllerTester = null;
+
+   public HASingletonControllerUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public void setUp()
+   {
+      singletonControllerTester = new HASingletonControllerTester();
+   }
+
+
+   public void tearDown()
+   {
+      singletonControllerTester = null;
+   }
+
+   public void testSetValidTargetName() throws Exception
+   {
+      ObjectName someSingletonService = new ObjectName("jboss:service=HASingletonMBeanExample");
+      singletonControllerTester.setTargetName(someSingletonService);
+
+      assertEquals("setTargetName() failed", singletonControllerTester.getTargetName(), someSingletonService);
+   }
+
+   public void testSetTargetStartMethod()
+   {
+      String someMethod = "startTheSingleton";
+      singletonControllerTester.setTargetStartMethod(someMethod);
+
+      assertEquals("setTargetStartMethod() failed", singletonControllerTester.getTargetStartMethod(), someMethod);
+   }
+
+   public void testSetTargetStartMethodArgument()
+   {
+       String someArgument = "aStartValue";
+       singletonControllerTester.setTargetStartMethodArgument(someArgument);
+  
+       assertEquals("setTargetStartMethodArgument() failed", singletonControllerTester.getTargetStartMethodArgument(), someArgument);
+   }
+
+   public void testSetTargetStopMethodArgument()
+   {
+      String someArgument = "aSopValue";
+      singletonControllerTester.setTargetStopMethodArgument(someArgument);
+  
+      assertEquals("setTargetStopMethodArgument() failed", singletonControllerTester.getTargetStopMethodArgument(), someArgument);
+   } 
+
+   /* HASingletonController can now start without a target/method set.
+    * We can use the produced notifications to start/stop other services
+    * by setting a dependency on a Barrier mbean, see JBAS-2626
+   public void testSetNullOrBlankStartTargetName()
+   {
+      String someMethod = "";
+      singletonControllerTester.setTargetStartMethod(someMethod);
+
+      assertEquals("setTargetStartMethod() failed to set default value", singletonControllerTester.getTargetStartMethod(), "startSingleton");
+
+      someMethod = null;
+      singletonControllerTester.setTargetStartMethod(someMethod);
+
+      assertEquals("setTargetStartMethod() failed to set default value", singletonControllerTester.getTargetStartMethod(), "startSingleton");
+   }
+   */
+
+   public void testSetTargetStopMethod()
+   {
+      String someMethod = "stopTheSingleton";
+      singletonControllerTester.setTargetStopMethod(someMethod);
+
+      assertEquals("setTargetStartMethod() failed", singletonControllerTester.getTargetStopMethod(), someMethod);
+   }
+
+   /* HASingletonController can now start without a target/method set.
+    * We can use the produced notifications to start/stop other services
+    * by setting a dependency on a Barrier mbean, see JBAS-2626
+   public void testSetNullOrBlankStopTargetName()
+   {
+      String someMethod = "";
+      singletonControllerTester.setTargetStopMethod(someMethod);
+
+      assertEquals("setTargetStartMethod() failed to set default value", singletonControllerTester.getTargetStopMethod(), "stopSingleton");
+
+      someMethod = null;
+      singletonControllerTester.setTargetStopMethod(someMethod);
+
+      assertEquals("setTargetStartMethod() failed to set default value", singletonControllerTester.getTargetStopMethod(), "stopSingleton");
+   }
+   */
+
+   public void testStartSingleton() throws Exception
+   {
+      ObjectName serviceName = new ObjectName("jboss:service=HASingletonMBeanExample");
+      singletonControllerTester.setTargetName(serviceName);
+      singletonControllerTester.setTargetStartMethod("startTheSingleton");
+
+      singletonControllerTester.startSingleton();
+
+      assertEquals("method not invoked as expected",
+         singletonControllerTester.__invokationStack__.pop(), "invokeMBeanMethod:jboss:service=HASingletonMBeanExample.startTheSingleton");
+   }
+
+   public void testStopSingleton() throws Exception
+   {
+      ObjectName serviceName = new ObjectName("jboss:service=HASingletonMBeanExample");
+      singletonControllerTester.setTargetName(serviceName);
+      singletonControllerTester.setTargetStopMethod("stopTheSingleton");
+
+      singletonControllerTester.stopSingleton();
+
+      assertEquals("method not invoked as expected",
+         singletonControllerTester.__invokationStack__.pop(), "invokeMBeanMethod:jboss:service=HASingletonMBeanExample.stopTheSingleton");
+   }
+
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonControllerUnitTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonElectionPolicyTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonElectionPolicyTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonElectionPolicyTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import javax.management.ObjectName;
+
+import junit.framework.Test;
+
+import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
+import org.jboss.test.JBossClusteredTestCase;
+
+/**
+ * Unit tests for HASingletonElectionPolicy.
+ * The testing deployment is under resources/ha/electionpolicy. 
+ *
+ * @author <a href="mailto:Alex.Fu at novell.com">Alex Fu</a>
+ * @author Brian Stansberry
+ * @version $Revision$
+ *
+ */
+public class HASingletonElectionPolicyTestCase extends JBossClusteredTestCase 
+{
+   public HASingletonElectionPolicyTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public static Test suite() throws Exception
+   {
+      // Refer to jboss-service.xml under resources/ha/electionpolicy
+      return getDeploySetup(HASingletonElectionPolicyTestCase.class, "ha-electionpolicy-beans.xml");
+   }
+   
+   public void testElectionPolicy() throws Exception
+   {
+      // Get MBeanServerConnections
+      RMIAdaptor[] adaptors = this.getAdaptors();
+      int size = adaptors.length;
+      assertTrue(size == 2);   // cluster size must be 2 for 3rd policy test
+      
+      // First policy is to elect the oldest node (position = 0)
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonMBeanExample_1");
+         
+         Boolean n1 = (Boolean)adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean)adaptors[size - 1].getAttribute(mbean, "MasterNode");
+         
+         assertEquals(Boolean.TRUE, n1);
+         assertEquals(Boolean.FALSE, n2);
+      }
+      
+      // Second policy is the youngest (position = -1)
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonMBeanExample_2");
+         
+         Boolean n1 = (Boolean)adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean)adaptors[size - 1].getAttribute(mbean, "MasterNode");
+         
+         assertEquals(Boolean.FALSE, n1);
+         assertEquals(Boolean.TRUE, n2);
+      }
+      
+      // 3rd policy is the 2nd oldest (position = 1)
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonMBeanExample_3");
+         
+         Boolean n1 = (Boolean)adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean)adaptors[1].getAttribute(mbean, "MasterNode");
+         
+         assertEquals(Boolean.FALSE, n1);
+         assertEquals(Boolean.TRUE, n2);
+      }
+      
+      // 4th policy is not set, default is oldest
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonMBeanExample_4");
+         
+         Boolean n1 = (Boolean)adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean)adaptors[size - 1].getAttribute(mbean, "MasterNode");
+         
+         assertEquals(Boolean.TRUE, n1);
+         assertEquals(Boolean.FALSE, n2);
+      }
+      
+      return;
+   }
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonElectionPolicyTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonSupportUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonSupportUnitTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonSupportUnitTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,150 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.test.cluster.defaultcfg.test;
+ 
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.jboss.test.cluster.hasingleton.HASingletonSupportTester;
+
+
+public class HASingletonSupportUnitTestCase extends TestCase
+{
+
+  private HASingletonSupportTester singletonSupportTester = null;
+
+  public HASingletonSupportUnitTestCase(String testCaseName)
+  {
+    super(testCaseName);
+  }
+
+
+  public void setUp()
+  {
+    singletonSupportTester = new HASingletonSupportTester();
+  }
+  
+  public void tearDown() 
+  {
+    singletonSupportTester = null;
+  }
+  
+  public void testStartService() throws Exception
+  {
+    singletonSupportTester.start();
+
+    // test that the correct start sequence was followed correctly  
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "registerDRMListener");  
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "registerRPCHandler");  
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "setupPartition");  
+      
+  }
+
+  public void testStopService() throws Exception
+  {
+    singletonSupportTester.start();
+    singletonSupportTester.stop();
+
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "unregisterRPCHandler");  
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "unregisterDRMListener");  
+    
+  }
+  
+  public void testBecomeMasterNode() throws Exception
+  {
+    singletonSupportTester.start();
+    
+    // register DRM Listener is expected to call back
+    singletonSupportTester.__isDRMMasterReplica__ = true;
+    singletonSupportTester.partitionTopologyChanged( new ArrayList(2), 1);
+
+    // test whether it was elected    
+    assertTrue("expected to become master", singletonSupportTester.isMasterNode());
+    
+    // test whether the election sequence was followed correctly
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "startSingleton");  
+    //assertEquals("method not invoked as expected",
+    //  singletonSupportTester.__invokationStack__.pop(), "callMethodOnCluster:_stopOldMaster");  
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "makeThisNodeMaster");      
+  }
+  
+  public void testBecomeSlaveNodeWithAnotherMaster() throws Exception
+  {
+    singletonSupportTester.start();
+    
+    boolean savedIsMasterNode = singletonSupportTester.isMasterNode();
+    
+    // register DRM Listener is expected to call back
+    singletonSupportTester.__isDRMMasterReplica__ = false;
+    singletonSupportTester.partitionTopologyChanged(new ArrayList(2), 1);
+    
+    // this call back should not change the master/slave status
+    assertEquals("expected to be still in old master/slave state", singletonSupportTester.isMasterNode(), savedIsMasterNode );
+    
+    // the new master is expected to call back
+    singletonSupportTester._stopOldMaster();
+    
+    if (savedIsMasterNode)
+    {
+      assertEquals("this node was the old master, but method not invoked as expected",
+        singletonSupportTester.__invokationStack__.pop(), "stopSingleton");  
+    }
+      
+    // now it should be slave
+    assertTrue("expected to be slave", !singletonSupportTester.isMasterNode());
+            
+  }
+
+  public void testStopOnlyNode() throws Exception
+  {
+    singletonSupportTester.start();
+    
+    // register DRM Listener is expected to call back
+    singletonSupportTester.__isDRMMasterReplica__ = true;
+    singletonSupportTester.partitionTopologyChanged( new ArrayList(2), 1);
+
+    // test whether it was elected for master    
+    assertTrue("expected to become master", singletonSupportTester.isMasterNode());
+    
+    singletonSupportTester.stop();
+    
+    // register DRM Listener is expected to call back
+    singletonSupportTester.__isDRMMasterReplica__ = false;
+    // since the only node (this one) in the partition is now removed, the replicants list should be empty 
+    singletonSupportTester.partitionTopologyChanged(new ArrayList(0), 1);
+    
+    assertTrue("expected to have made a call to _stopOldMater(), thus become slave", !singletonSupportTester.isMasterNode() );
+    
+    assertEquals("method not invoked as expected",
+      singletonSupportTester.__invokationStack__.pop(), "stopSingleton");  
+      
+  }
+  
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonSupportUnitTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/PartitionRestartUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/PartitionRestartUnitTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/PartitionRestartUnitTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,143 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.util.Properties;
+
+import javax.management.ObjectName;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import junit.framework.Test;
+
+import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
+import org.jboss.test.JBossClusteredTestCase;
+import org.jboss.test.cluster.ejb2.basic.interfaces.NodeAnswer;
+import org.jboss.test.cluster.ejb2.basic.interfaces.StatefulSession;
+import org.jboss.test.testbean.interfaces.StatefulSessionHome;
+
+/**
+ * Tests that a restart of ClusterPartition works properly.
+ * 
+ * @author <a href="mailto://brian.stansberry@jboss.com">Brian Stansberry</a>
+ * @version $Revision$
+ */
+public class PartitionRestartUnitTestCase extends JBossClusteredTestCase
+{
+   /**
+    * Create a new PartitionRestartUnitTestCase.
+    * 
+    * @param name
+    */
+   public PartitionRestartUnitTestCase(String name)
+   {
+      super(name);
+   }         
+
+   public static Test suite() throws Exception
+   {
+      Test t1 = JBossClusteredTestCase.getDeploySetup(PartitionRestartUnitTestCase.class, "partition-restart-beans.xml, partition-restart.jar");
+      return t1;
+   }   
+   
+   public void testStatefulBeanFailover() 
+   throws Exception
+   {       
+      getLog().debug("testStatefulBeanFailover");
+      
+      RMIAdaptor[] adaptors = this.getAdaptors(); 
+      
+      String[] urls = getNamingURLs();
+      Properties env = new Properties();
+      env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+         "org.jnp.interfaces.NamingContextFactory");
+      env.setProperty(Context.PROVIDER_URL, urls[0]);
+      Context ctx = new InitialContext(env);
+      getLog().debug("OK");
+      
+      getLog().debug("");
+      getLog().debug("Looking up the home nextgen.StatefulSession...");
+      StatefulSessionHome  statefulSessionHome =
+      (StatefulSessionHome) ctx.lookup("nextgen_StatefulSession");
+      if (statefulSessionHome!= null ) getLog().debug("ok");
+         getLog().debug("Calling create on StatefulSessionHome...");
+      StatefulSession statefulSession =
+         (StatefulSession)statefulSessionHome.create("Bupple-Dupple");
+      assertTrue("statefulSessionHome.create() != null", statefulSession != null);
+      getLog().debug("ok");
+      
+      NodeAnswer node1 = statefulSession.getNodeState ();
+      getLog ().debug (node1);
+      
+      // Now we switch to the other node, simulating a failure on node 1
+      //
+      System.setProperty ("JBossCluster-DoFail", "once");
+      NodeAnswer node2 = statefulSession.getNodeState ();      
+      getLog ().debug (node2);
+      
+      assertTrue ("Failover has occured", !node1.nodeId.equals (node2.nodeId));
+      
+      assertTrue ("Value is identical on replicated node", 
+                  "Bupple-Dupple".equals (node1.answer) &&
+                  node1.answer.equals (node2.answer) );
+
+      // Stop and restart the ClusterPartition on node1
+      restartPartition(adaptors[0]);
+      
+      // Let the cluster stabilize
+      sleep(2000);
+      
+      // we change our name to see if it replicates to node 1
+      //
+      statefulSession.setName ("Changed");
+      
+      // now we travel back to node 1
+      System.setProperty ("JBossCluster-DoFail", "once");
+      node1 = statefulSession.getNodeState ();
+      getLog ().debug (node1);
+      
+      assertTrue ("Failover has occured", !node1.nodeId.equals (node2.nodeId));
+      
+      assertTrue ("Value is identical on replicated node", "Changed".equals (node1.answer) );      
+      
+      statefulSession.remove();
+      getLog().debug("ok");
+   }
+   
+   
+   protected void restartPartition(RMIAdaptor adaptor) throws Exception
+   {
+      ObjectName partition = new ObjectName("jboss:service=RestartPartition");
+      
+      Object[] params = new Object[0];
+      String[] types = new String[0];
+      adaptor.invoke(partition, "stop", params, types);
+      
+      sleep(2000);
+      
+      adaptor.invoke(partition, "start", params, types);
+      
+      sleep(2000);
+   }
+
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/PartitionRestartUnitTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/RPCTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/RPCTestCase.java	                        (rev 0)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/RPCTestCase.java	2007-07-24 03:27:28 UTC (rev 64237)
@@ -0,0 +1,316 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2007, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.util.ArrayList;
+import javax.management.ObjectName;
+
+import junit.framework.Test;
+
+import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
+import org.jboss.jmx.adaptor.rmi.RMIAdaptorExt;
+import org.jboss.test.JBossClusteredTestCase;
+import org.jboss.test.cluster.hapartition.rpc.Person;
+import org.jboss.test.cluster.hapartition.rpc.PersonQuery;
+
+/** Tests of clustered RPC calls
+ *
+ * @author Jerry Gauthier
+ * @version $Revision$
+ */
+public class RPCTestCase extends JBossClusteredTestCase
+{
+   // must match service names in rpc-tests.sar
+   private static final String RPC_SERVICE = "jboss.test:service=RPCTestCase";
+   private static final String RPC_ONENODE_SERVICE = "jboss.test:service=RPCOneNodeTestCase";
+   private static final String RPC_CLASSLOADER_SERVICE = "jboss.test:service=RPCClassLoaderTestCase";
+   private static final String RPC_ONENODE_CLASSLOADER_SERVICE = "jboss.test:service=RPCOneNodeClassLoaderTestCase";
+   
+   public static Test suite() throws Exception
+   {
+      Test t1 = getDeploySetup(RPCTestCase.class, "rpc-tests.sar, rpc-cl-tests.sar");
+      return t1;
+   }
+
+   public RPCTestCase(String name)
+   {
+      super(name);
+   }
+
+   public void testMethodOnCluster() throws Exception
+   {
+      log.debug("+++ testMethodOnCluster");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server0 = (RMIAdaptorExt) adaptors[0];
+      ObjectName rpcService = new ObjectName(RPC_SERVICE);
+
+      Object obj0 = server0.invoke(rpcService, "runRetrieveAll", null, null);
+      assertNotNull("expected ArrayList as result type, got null", obj0);
+      assertTrue( "expected ArrayList as result type, got " +obj0.getClass().getName(), obj0 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj0;
+      
+      // there should be two Person responses, the attributes should differ
+      assertEquals("Result should contain two responses; ", 2, responses.size());      
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+      }
+      Person person0 = (Person)responses.get(0);
+      Person person1 = (Person)responses.get(1);
+      assertFalse("expected different person names, got " + person0.getName(),
+                  person0.getName().equals(person1.getName()));
+
+   }
+   
+   public void testParmMethodOnCluster() throws Exception
+   {
+      log.debug("+++ testParmMethodOnCluster");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server1 = (RMIAdaptorExt) adaptors[1];
+      ObjectName rpcService = new ObjectName(RPC_SERVICE);
+      
+      // try using a custom class as parameter
+      String employer = "WidgetsRUs";
+      PersonQuery query = new PersonQuery();
+      query.setEmployer(employer);
+      Object[] parms = new Object[]{query};
+      String[] types = new String[]{PersonQuery.class.getName()};
+      
+      Object obj1 = server1.invoke(rpcService, "runRetrieveQuery", parms, types);
+      assertNotNull("expected ArrayList as result type, got null", obj1);
+      assertTrue( "expected ArrayList as result type, got " +obj1.getClass().getName(), obj1 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj1;
+      
+      // there should be two responses, a Person and a null value
+      assertEquals("Result should contain two responses; ", 2, responses.size());
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         if (response != null)
+         {
+            assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+            String respEmpl = ((Person)response).getEmployer();
+            assertTrue("expected " + employer + " as selected response value, got " + respEmpl,
+                        (employer.equalsIgnoreCase(respEmpl)));
+         }
+      }
+
+   }
+   
+   public void testAsynchMethodOnCluster() throws Exception
+   {
+      log.debug("+++ testAsynchMethodOnCluster");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server0 = (RMIAdaptorExt) adaptors[0];
+      RMIAdaptorExt server1 = (RMIAdaptorExt) adaptors[1];
+      ObjectName rpcService = new ObjectName(RPC_SERVICE);
+      
+      // this will set the 'notified' attribute to true for all Person objects in RPCUser
+      server0.invoke(rpcService, "runNotifyAllAsynch", null, null);
+      Thread.sleep(5000);
+      
+      // confirm the attribute has been set successfully on each node
+      Object obj1 = server1.invoke(rpcService, "runRetrieveAll", null, null);
+      assertNotNull("expected ArrayList as result type, got null", obj1);
+      assertTrue( "expected ArrayList as result type, got " +obj1.getClass().getName(), obj1 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj1;
+      
+      // there should be two Person responses, the 'notified' attribute should be true
+      assertEquals("Result should contain two responses; ", 2, responses.size());      
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+         Person person = (Person)response;
+         assertTrue("expected true as response value, got false for " + person.getName(),
+                     (person.getNotified() == true));
+         
+      }
+   }
+   
+   public void testMethodOnCoordinatorNode() throws Exception
+   {
+      log.debug("+++ testMethodOnCoordinatorNode");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server0 = (RMIAdaptorExt) adaptors[0];
+      ObjectName rpcService = new ObjectName(RPC_SERVICE);
+      
+      Object obj0 = server0.invoke(rpcService, "runRetrieveFromCoordinator", null, null);
+      assertNotNull("expected ArrayList as result type, got null", obj0);
+      assertTrue( "expected ArrayList as result type, got " +obj0.getClass().getName(), obj0 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj0;
+
+      // there should be one Person response
+      assertEquals("Result should contain one response; ", 1, responses.size());  
+      Object response = responses.get(0);
+      if (response instanceof Exception)
+         fail("received exception response: " + ((Exception)response).toString());
+      assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+
+      String employer = "WidgetsRUs";
+      String respEmpl = ((Person)response).getEmployer();
+      assertTrue("expected " + employer + " as selected response value, got " + respEmpl,
+                  (employer.equalsIgnoreCase(respEmpl)));
+   }
+   
+   public void testMethodOnOneNode() throws Exception
+   {
+      log.debug("+++ testMethodOnOneNode");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server0 = (RMIAdaptorExt) adaptors[0];
+      ObjectName rpcService = new ObjectName(RPC_ONENODE_SERVICE);
+
+      Object obj0 = server0.invoke(rpcService, "runRetrieveAll", null, null);
+      assertNotNull("expected ArrayList as result type, got null", obj0);
+      assertTrue( "expected ArrayList as result type, got " +obj0.getClass().getName(), obj0 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj0;
+      
+      // there should be one response as the service is only registered on one node
+      assertEquals("Result should contain one response; ", 1, responses.size());      
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+      }
+
+   }
+   
+   public void testClassLoaderParmMethodOnOneNode() throws Exception
+   {
+      log.debug("+++ testClassLoaderParmMethodOnOneNode");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server1 = (RMIAdaptorExt) adaptors[1];
+      ObjectName rpcService = new ObjectName(RPC_ONENODE_CLASSLOADER_SERVICE);
+      
+      // try using a custom class as parameter
+      String employer = "WidgetsRUs";
+      PersonQuery query = new PersonQuery();
+      query.setEmployer(employer);
+      Object[] parms = new Object[]{query};
+      String[] types = new String[]{PersonQuery.class.getName()};
+      
+      Object obj1 = server1.invoke(rpcService, "runRetrieveQuery", parms, types);
+      assertNotNull("expected ArrayList as result type, got null", obj1);
+      assertTrue( "expected ArrayList as result type, got " +obj1.getClass().getName(), obj1 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj1;
+      
+      // there should be one response as the service is only registered on one node
+      assertEquals("Result should contain one response; ", 1, responses.size());
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         if (response != null)
+         {
+            assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+            String respEmpl = ((Person)response).getEmployer();
+            assertTrue("expected " + employer + " as selected response value, got " + respEmpl,
+                        (employer.equalsIgnoreCase(respEmpl)));
+         }
+      }
+
+   }
+   
+   public void testClassLoaderParmMethodOnCluster() throws Exception
+   {
+      log.debug("+++ testClassLoaderParmMethodOnCluster");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server1 = (RMIAdaptorExt) adaptors[1];
+      ObjectName rpcService = new ObjectName(RPC_CLASSLOADER_SERVICE);
+      
+      // try using a custom class as parameter
+      String employer = "WidgetsRUs";
+      PersonQuery query = new PersonQuery();
+      query.setEmployer(employer);
+      Object[] parms = new Object[]{query};
+      String[] types = new String[]{PersonQuery.class.getName()};
+      
+      Object obj1 = server1.invoke(rpcService, "runRetrieveQuery", parms, types);
+      assertNotNull("expected ArrayList as result type, got null", obj1);
+      assertTrue( "expected ArrayList as result type, got " +obj1.getClass().getName(), obj1 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj1;
+      
+      // there should be two responses, a Person and a null value
+      assertEquals("Result should contain two responses; ", 2, responses.size());
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         if (response != null)
+         {
+            assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+            String respEmpl = ((Person)response).getEmployer();
+            assertTrue("expected " + employer + " as selected response value, got " + respEmpl,
+                        (employer.equalsIgnoreCase(respEmpl)));
+         }
+      }
+
+   }
+   
+   public void testClassLoaderMethodOnCluster() throws Exception
+   {
+      log.debug("+++ testClassLoaderMethodOnCluster");
+      
+      RMIAdaptor[] adaptors = getAdaptors();
+      RMIAdaptorExt server0 = (RMIAdaptorExt) adaptors[0];
+      ObjectName rpcService = new ObjectName(RPC_CLASSLOADER_SERVICE);
+
+      Object obj0 = server0.invoke(rpcService, "runRetrieveAll", null, null);
+      assertNotNull("expected ArrayList as result type, got null", obj0);
+      assertTrue( "expected ArrayList as result type, got " +obj0.getClass().getName(), obj0 instanceof ArrayList);
+      ArrayList responses = (ArrayList)obj0;
+      
+      // there should be two Person responses, the attributes should differ
+      assertEquals("Result should contain two responses; ", 2, responses.size());      
+      for (int i = 0; i < responses.size(); i++)
+      {
+         Object response = responses.get(i);
+         if (response instanceof Exception)
+            fail("received exception response: " + ((Exception)response).toString());
+         assertTrue("expected Person as response type, got " +response.getClass().getName(), response instanceof Person);
+      }
+      Person person0 = (Person)responses.get(0);
+      Person person1 = (Person)responses.get(1);
+      assertFalse("expected different person names, got " + person0.getName(),
+                  person0.getName().equals(person1.getName()));
+
+   }
+
+}


Property changes on: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/RPCTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native




More information about the jboss-cvs-commits mailing list