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

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Mar 5 15:32:20 EST 2008


Author: galder.zamarreno at jboss.com
Date: 2008-03-05 15:32:20 -0500 (Wed, 05 Mar 2008)
New Revision: 70451

Modified:
   trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/UnifiedInvokerHaUnitTestCase.java
   trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java
   trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java
Log:
[JBAS-4815] Added a thread safety test to check whether the chosen and used target are the same when multiple threads call the same proxy concurrently. Simplified remoting mock objects to make them behave closer to the production code.

Modified: trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/UnifiedInvokerHaUnitTestCase.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/UnifiedInvokerHaUnitTestCase.java	2008-03-05 20:30:09 UTC (rev 70450)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/UnifiedInvokerHaUnitTestCase.java	2008-03-05 20:32:20 UTC (rev 70451)
@@ -34,7 +34,7 @@
 import org.jboss.test.cluster.invokerha.AbstractInvokerHa;
 import org.jboss.test.cluster.invokerha.InvokerHaInfrastructure;
 import org.jboss.test.cluster.invokerha.InvokerHaInfrastructure.InvokerHaFactory;
-import org.jboss.test.cluster.invokerha.UnifiedInvokerHaMockUtils.MockClient;
+import org.jboss.test.cluster.invokerha.InvokerHaInfrastructure.TraceRoundRobin;
 import org.jboss.test.cluster.invokerha.UnifiedInvokerHaMockUtils.MockInvokerLocator;
 import org.jboss.test.cluster.invokerha.UnifiedInvokerHaMockUtils.MockUnifiedInvokerHA;
 
@@ -60,6 +60,11 @@
       super.tearDown();
    }
    
+   public void testProxyThreadSafety() throws Throwable
+   {
+      performConcurrentCalls(50, 50, TraceRoundRobin.class);
+   }   
+   
    /** Classes **/
    
    /**
@@ -85,8 +90,7 @@
       public InvokerHA createInvokerHaServer(String serverName, int serverNumber)
       {
          MockUnifiedInvokerHA invoker = new MockUnifiedInvokerHA(getInvokerTypeName() + "-" + serverName + "-" + serverNumber);
-         MockClient client = new MockClient(invoker);
-         MockInvokerLocator locator = new MockInvokerLocator("127.0.0.1", serverNumber, client);
+         MockInvokerLocator locator = new MockInvokerLocator("127.0.0.1", serverNumber, invoker);
          invoker.setLocator(locator);
          
          return invoker;          

Modified: trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java	2008-03-05 20:30:09 UTC (rev 70450)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java	2008-03-05 20:32:20 UTC (rev 70451)
@@ -22,6 +22,13 @@
 package org.jboss.test.cluster.invokerha;
 
 import java.rmi.server.UID;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import javax.transaction.Transaction;
 
@@ -36,6 +43,7 @@
 import org.jboss.test.cluster.invokerha.InvokerHaInfrastructure.TraceRoundRobin;
 import org.jboss.test.cluster.invokerha.InvokerHaTransactionalMockUtils.MockTransaction;
 
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 /**
@@ -65,6 +73,8 @@
    {
       super.setUp();
       
+      log.info(getName());
+      
       invokerHaFactory = factory; 
       
       transactionalMockUtils = new InvokerHaTransactionalMockUtils();
@@ -186,6 +196,36 @@
       }
    }
    
+   protected void performConcurrentCalls(int numberThreads, 
+         int numberCallsPerThread, Class<? extends LoadBalancePolicy> policyClass) throws Exception
+   {
+      ExecutorService executor = Executors.newCachedThreadPool();
+      CyclicBarrier barrier = new CyclicBarrier(numberThreads + 1);
+      List<Future<Void>> futures = new ArrayList<Future<Void>>();
+      
+      log.debug("create proxies");
+      createNewProxies(0, policyClass, true);
+      for (int i = 0; i < numberThreads; i++)
+      {
+         log.debug("schedule execution");
+         Future<Void> future = executor.submit(new InvokerProxyBatch(barrier, numberCallsPerThread, policyClass));
+         futures.add(future);
+      }
+      barrier.await(); // wait for all threads to be ready
+      barrier.await(); // wait for all threads to finish
+      
+      log.debug("all threads finished, let's shutdown the executor and check whether any exceptions were reported");
+      
+      for (Future<Void> future : futures)
+      {
+         future.get();
+      }
+      
+      executor.shutdown();
+      
+      log.debug("no exceptions reported, good :)");
+   }
+     
    protected Object assertSuccessfulPostConditions(Invocation inv, Object prevChosenTarget, Transaction tx, Class<? extends LoadBalancePolicy> policyClass)
    {
       assertEquals(0, inv.getAsIsValue("FAILOVER_COUNTER"));
@@ -272,4 +312,88 @@
    {
       return checkFirstAvailable(chosenTarget, prevChosenTarget);
    }   
+
+   /** Classes **/
+   
+   public class InvokerProxyBatch implements Callable<Void>
+   {
+      private final CyclicBarrier barrier;
+      
+      private final int numberCallsPerThread;
+      
+      private final Class<? extends LoadBalancePolicy> policyClass;
+      
+      public InvokerProxyBatch(CyclicBarrier ciclycBarrier, int numberCalls, Class<? extends LoadBalancePolicy> policy)
+      {
+         barrier = ciclycBarrier;
+         numberCallsPerThread = numberCalls;
+         policyClass = policy;
+      }
+
+      public Void call() throws Exception
+      {
+         try
+         {
+            log.debug("wait for all executions paths to be ready to perform calls");
+            barrier.await();
+            
+            log.debug("perform invoker proxy calls");
+            performThreadSafeCalls(numberCallsPerThread, policyClass);
+         }
+         catch(AssertionFailedError afe)
+         {
+            logAndThrow("Assertion failed in thread: " + Thread.currentThread().getName(), afe);
+         }
+         finally
+         {
+            log.debug("wait for all execution paths to finish");
+            barrier.await();
+         }
+         
+         return null;
+      }
+      
+      protected void performThreadSafeCalls(int numberPairCalls, Class<? extends LoadBalancePolicy> policyClass) throws Exception
+      {
+         Invocation inv;
+         
+         for (int i = 0; i < numberPairCalls; i++)
+         {
+            /* create invocation to date time teller */
+            inv = infrastructure.createDateTimeTellerInvocation(null, null);
+            /* invoke on proxy passing the invocation */
+            log.debug(timeTellerProxy.invoke(inv));
+            /* assert post conditions after invocation */
+            assertThreadSafePostConditions(inv, timeTellerProxy);
+            
+            /* create invocation to system time teller */
+            inv = infrastructure.createSystemTimeTellerInvocation(null, null);
+            /* invoke on proxy passing the invocation */
+            log.debug(systemTimeProxy.invoke(inv));
+            /* assert post conditions after invocation */
+            assertThreadSafePostConditions(inv, systemTimeProxy);
+         }
+      }
+
+      protected void assertThreadSafePostConditions(Invocation inv, Invoker invoker)
+      {
+         assertEquals(0, inv.getAsIsValue("FAILOVER_COUNTER"));
+         Object chosenTarget = inv.getTransientValue(invokerHaFactory.getChosenTargetKey());
+         assertNotNull(chosenTarget);
+         
+         /* NOTE: currently, the following assertion is only valid for unified 
+          * invokers, do not call from thread safety tests related to other 
+          * invokers */
+         
+         /* assert that target chosen by load balance policy and target to which 
+          * invocation was directed is the same */      
+         assertEquals(chosenTarget, inv.getTransientValue("TEST_USED_TARGET"));
+      } 
+      
+      private void logAndThrow(String message, Throwable t) throws Exception
+      {
+         log.error(message, t);
+         throw new Exception(message, t);
+      }
+   }
 }

Modified: trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java
===================================================================
--- trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java	2008-03-05 20:30:09 UTC (rev 70450)
+++ trunk/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java	2008-03-05 20:32:20 UTC (rev 70451)
@@ -39,7 +39,6 @@
 import org.jboss.remoting.ConnectionFailedException;
 import org.jboss.remoting.InvocationRequest;
 import org.jboss.remoting.InvokerLocator;
-import org.jboss.remoting.ServerInvoker;
 import org.jboss.remoting.callback.InvokerCallbackHandler;
 import org.jboss.remoting.marshal.Marshaller;
 import org.jboss.remoting.marshal.UnMarshaller;
@@ -125,7 +124,7 @@
       @Override
       protected Client createClient(InvokerLocator locator, String subSystem) throws Exception
       {
-         return ((MockInvokerLocator)locator).getClient();
+         return new MockClient(locator);
       }
 
       @Override
@@ -139,6 +138,11 @@
          
          super.putIfExistsTransactionTarget(invocation, tpc);
       }
+      
+      public InvokerLocator getLocator()
+      {
+         return super.getLocator();
+      }
    }
 
    public static class MockInvokerLocator extends InvokerLocator
@@ -146,24 +150,23 @@
       /** The serialVersionUID */
       private static final long serialVersionUID = 8641387521254685628L;
       
-      /* client that will be returned when locator is initialised */
-      private MockClient client;
-      
-      public MockInvokerLocator(String host, int port, MockClient client)
+      private MockUnifiedInvokerHA invoker;
+
+      public MockInvokerLocator(String host, int port, MockUnifiedInvokerHA invoker)
       {
          super("unittest", host, port, "mock", null);
-         this.client = client;
-      }
-
-      public MockClient getClient()
+         this.invoker = invoker;
+      }      
+      
+      public MockUnifiedInvokerHA getInvoker()
       {
-         return client;
+         return invoker;
       }
-
+      
       @Override
       public String toString()
       {
-         return super.toString() + ",[client=" + client + "]";
+         return super.toString() + ",[invoker=" + invoker + "]";
       }
 
       @Override
@@ -171,20 +174,18 @@
       {
          /* reimplemented equals to avoid lingering static family cluster info 
           * references being valid in latter tests */
-         return super.equals(obj) && client.equals(((MockInvokerLocator)obj).getClient());
+         return super.equals(obj) && invoker.equals(((MockInvokerLocator)obj).getInvoker());
       }
    }
 
    public static class MockClient extends Client
    {
-      /** underlying invoker target */
-      private MockUnifiedInvokerHA invoker;
-
-      public MockClient(MockUnifiedInvokerHA invoker)
+      public MockClient(InvokerLocator locator) throws Exception
       {
-         this.invoker = invoker;
+         super(locator);
+         setInvoker(new MockClientInvoker(locator));
       }
-
+      
       @Override
       public void connect() throws Exception
       {
@@ -192,14 +193,11 @@
       }
 
       @Override
-      public ClientInvoker getInvoker()
-      {
-         return new MockClientInvoker(invoker.getLocator());
-      }
-
-      @Override
       public Object invoke(Object param, Map metadata) throws Throwable
       {
+         Invocation inv = (Invocation) param;
+         inv.getTransientPayload().put("TEST_USED_TARGET", this.getInvoker().getLocator());
+         
          /* Down the call stack in Remoting's Client.invoke, marshaller is 
           * called which via org.jboss.invocation.unified.marshall.InvocationMarshaller 
           * sets the transaction progagation context.
@@ -210,9 +208,10 @@
           * Not ideal, as I try avoiding production code in UTs as much as 
           * possible, but makes the mock implementation a lot simpler.
           */
-         Invocation inv = (Invocation) param;
          MarshalledInvocation marshInv = new MarshalledInvocation(inv);
          marshInv.setTransactionPropagationContext(getTransactionPropagationContext());
+
+         MockUnifiedInvokerHA invoker = ((MockInvokerLocator)getInvoker().getLocator()).getInvoker();
          
          return invoker.invoke(new InvocationRequest("", "", marshInv,
                metadata, null, null));
@@ -227,11 +226,11 @@
       @Override
       public String toString()
       {
-         return invoker.toString();
+         return ((MockInvokerLocator)getInvoker().getLocator()).getInvoker().toString();
       }
    }
    
-   public static class MockClientInvoker implements ClientInvoker
+   static class MockClientInvoker implements ClientInvoker
    {
       private InvokerLocator locator;
       




More information about the jboss-cvs-commits mailing list