Package org.jboss.test.timer.test

Source Code of org.jboss.test.timer.test.BasicTimerUnitTestCase

/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, 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.timer.test;

import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import javax.ejb.EJBHome;
import javax.ejb.NoSuchObjectLocalException;
import javax.jms.Message;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.login.LoginContext;

import junit.framework.Test;
import junit.framework.TestSuite;
import org.jboss.test.JBossTestCase;
import org.jboss.test.JBossTestSetup;
import org.jboss.test.util.AppCallbackHandler;
import org.jboss.test.util.jms.JMSDestinationsUtil;
import org.jboss.test.timer.interfaces.TimerEntity;
import org.jboss.test.timer.interfaces.TimerEntityHome;
import org.jboss.test.timer.interfaces.TimerSFSB;
import org.jboss.test.timer.interfaces.TimerSFSBHome;
import org.jboss.test.timer.interfaces.TimerSLSBHome;
import org.jboss.test.timer.interfaces.TimerSLSB;

/**
* Simple unit tests for the EJB Timer service
*/
public class BasicTimerUnitTestCase extends JBossTestCase
{

   private static final String EJB_TIMER_XAR = "ejb-timer.ear";

   private static final int SHORT_PERIOD = 1 * 1000; // 1s
   private static final int LONG_PERIOD = 20 * 1000; // 20s
   private LoginContext lc;

   /**
    * Setup the test suite.
    */
   public static Test suite() throws Exception
   {
      TestSuite suite = new TestSuite();

      suite.addTest(new JBossTestSetup(new TestSuite(BasicTimerUnitTestCase.class))
      {
         protected void setUp() throws Exception
         {
            super.setUp();
            JMSDestinationsUtil.setupBasicDestinations();
            deploy (EJB_TIMER_XAR);
         }
         protected void tearDown() throws Exception
         {
            super.tearDown();
            undeploy (EJB_TIMER_XAR);
            JMSDestinationsUtil.destroyDestinations();
         }
      });

      return suite;
   }

   /**
    * Constructor for the BasicTimerUnitTest object
    */
   public BasicTimerUnitTestCase(String pName)
   {
      super(pName);
   }

   public void tearDown()
   {
   }

   /**
    * Test that a Stafeful Session Bean cannot access a Timer Service
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testStatefulSessionBeanTimer()
      throws Exception
   {
      TimerSFSBHome lHome = (TimerSFSBHome) getEJBHome(TimerSFSBHome.JNDI_NAME);
      TimerSFSB lBean = lHome.create();
      try
      {
         lBean.checkTimerService();
         fail("Stateful Session Bean is not allowed to get a Timer Service");
      }
      catch (RemoteException re)
      {
         Throwable lCause = re.detail;
         if (lCause instanceof ServerException)
         {
            lCause = ((ServerException) lCause).detail;
            if (lCause instanceof IllegalStateException)
            {
               // This exception is expected -> ignore
            }
            else
            {
               throw re;
            }
         }
      }
   }

   /**
    * Test that a repetitive Stafeless Session Bean Timer
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testStatelessSessionBeanTimer()
      throws Exception
   {
      TimerSLSBHome home = (TimerSLSBHome) getEJBHome(TimerSLSBHome.JNDI_NAME);
      TimerSLSB bean = home.create();
      byte[] handle = bean.startTimer(SHORT_PERIOD);
      Thread.sleep(12 * SHORT_PERIOD + SHORT_PERIOD);
      int count = bean.getTimeoutCount(handle);
      bean.stopTimer(handle);
      assertTrue("Timeout was expected to be called at least 10 times but was "
         + "only called: " + count + " times",
         count >= 10);
      Thread.sleep(5 * SHORT_PERIOD);
      int count2 = bean.getTimeoutCount(handle);
      assertTrue("After the timer was stopped no timeout should happen but "
         + "it was called " + count2 + " more times",
         count2 == 0);
      bean.remove();
   }

   /**
    * Test that a repetitive Stateless Session Bean Timer with a retry.
    * NOTE: This test was added to test JIRA issue JBAS-1926.
    * Since the same timer mechanism is used (with respects to what this test actualy tests)
    * with entity and message beans, testing on those would probably be redundant, so a test
    * is only run on stateless session bean.
    *
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testStatelessSessionBeanTimerRetry()
      throws Exception
   {
      log.info("testStatelessSessionBeanTimerRetry(): start");
      TimerSLSBHome home = (TimerSLSBHome) getEJBHome(TimerSLSBHome.JNDI_NAME);
      TimerSLSB bean = home.create();

      // We need to make sure that the next timer interval occurs
      // while the retry timeout is STILL running in order to test JBAS-1926
      final long retryMs = bean.getRetryTimeoutPeriod();
      log.info("testStatelessSessionBeanTimerRetry():GOT RETRY TIME:" + retryMs);
      assertFalse("Failed to get valid retry timeout!", retryMs == -1);
      final HashMap info = new HashMap();
      info.put(TimerSLSB.INFO_EXEC_FAIL_COUNT,new Integer(1)); // fail only once
      // RE: JIRA Issue JBAS-1926
      // This is the amount of time the task will take to execute
      // This is intentionlly more than the time of the interval
      // so that the we can be sure that the interval will fire again
      // WHILE the retry is still in progress.
      final int taskTime = SHORT_PERIOD * 2;
      info.put(TimerSLSB.INFO_TASK_RUNTIME,new Integer(taskTime)); // the time is takes to execute the task

      final byte[] handle = bean.startTimer(SHORT_PERIOD,info);
      // Wait for 1 SHORT_PERIOD for the first firing
      // Another retryMs for the amount of time it takes for the retry to happen
      // and finally the amount of time that it takes to execute the task and 200ms to be safe.
      Thread.sleep(SHORT_PERIOD  + retryMs + taskTime + 200);
      int count = bean.getTimeoutCount(handle);
      bean.stopTimer(handle);
      assertEquals("Timeout was called too many times. Should have been once for the initial" +
            ", and once for the retry during the time allotted.",2,count);

      bean.remove();
   }
  

   /**
    * Test that a single Stafeless Session Bean Timer
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testStatelessSessionBeanSingleTimer()
      throws Exception
   {
      TimerSLSBHome home = (TimerSLSBHome) getEJBHome(TimerSLSBHome.JNDI_NAME);
      TimerSLSB bean = home.create();
      byte[] handle = bean.startSingleTimer(SHORT_PERIOD);
      Thread.sleep(5 * SHORT_PERIOD);
      int lCount = bean.getTimeoutCount(handle);
      assertTrue("Timeout was expected to be called only once but was called: "
         + lCount + " times",
         lCount == 1);
      try
      {
         bean.stopTimer(handle);
         fail("A single timer should expire after the first event and therefore this "
            + "has to throw an NoSuchObjectLocalException");
      }
      catch (RemoteException re)
      {
         Throwable lCause = re.detail;
         if (lCause instanceof ServerException)
         {
            lCause = ((ServerException) lCause).detail;
            if (lCause instanceof NoSuchObjectLocalException)
            {
               // This exception is expected -> ignore
            }
            else
            {
               throw re;
            }
         }
      }

      // Test for the case where a transaction fails, the time should be retried once
      // This test assumes the FixedRetryPolicy is left at the default of 200ms.
      // The "fail-once" data in the timer will be used by the bean to fail the
      // transaction once, to make sure that it is automatically retried.
      log.info("testStatelessSessionBeanSingleTimer(): Testing retry on timer.");
      final HashMap info = new HashMap(1);
      info.put(TimerSLSB.INFO_EXEC_FAIL_COUNT,new Integer(1));
      handle = bean.startSingleTimer(SHORT_PERIOD,info);
      Thread.sleep(5 * SHORT_PERIOD);
      assertEquals("Timeout was expected to be called twice, once inititially, one once for the retry.",
               2,bean.getTimeoutCount(handle));


   }

   /**
    * Test that a repetitive Entity Bean Timer
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testEntityBeanTimer()
      throws Exception
   {
      TimerEntityHome home = (TimerEntityHome) getEJBHome(TimerEntityHome.JNDI_NAME);
      TimerEntity entity = home.create(new Integer(111));
      entity.startTimer(SHORT_PERIOD);
      Thread.sleep(12 * SHORT_PERIOD);
      entity.stopTimer();
      int lCount = entity.getTimeoutCount();
      assertTrue("Timeout was expected to be called at least 10 times but was "
         + "only called: " + lCount + " times",
         lCount >= 10);
      Thread.sleep(5 * SHORT_PERIOD);
      int lCount2 = entity.getTimeoutCount();
      assertTrue("After the timer was stopped no timeout should happen but "
         + "it was called " + (lCount2 - lCount) + " more times",
         lCount == lCount2);
      entity.remove();
   }

   /**
    * Test that a single Entity Bean Timer
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testEntityBeanSingleTimer()
      throws Exception
   {
      TimerEntityHome home = (TimerEntityHome) getEJBHome(TimerEntityHome.JNDI_NAME);
      TimerEntity entity = home.create(new Integer(222));
      entity.startSingleTimer(SHORT_PERIOD);
      Thread.sleep(5 * SHORT_PERIOD);
      int lCount = entity.getTimeoutCount();
      assertTrue("Timeout was expected to be called only once but was called: "
         + lCount + " times",
         lCount == 1);
      try
      {
         entity.stopTimer();
         fail("A single timer should expire after the first event and therefore this "
            + "has to throw an NoSuchObjectLocalException");
      }
      catch (RemoteException re)
      {
         Throwable lCause = re.detail;
         if (lCause instanceof ServerException)
         {
            lCause = ((ServerException) lCause).detail;
            if (lCause instanceof NoSuchObjectLocalException)
            {
               // This exception is expected -> ignore
            }
            else
            {
               throw re;
            }
         }
      }
      entity.remove();
   }

   /** Test an mdb that creates a timer for each onMessage
    * @throws Exception
    */
   public void testMDBTimer() throws Exception
   {
      log.info("+++ testMDBTimer");
      InitialContext ctx = new InitialContext();
      QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");

      QueueConnection queConn = null;
      QueueSession session = null;
      QueueSender sender = null;
      QueueReceiver receiver = null;

      try
      {
         queConn = factory.createQueueConnection();
         queConn.start();

         Queue queueA = (Queue) ctx.lookup("queue/A");
         Queue queueB = (Queue) ctx.lookup("queue/B");
        
         session = queConn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
         sender = session.createSender(queueA);
         receiver = session.createReceiver(queueB);

         while (receiver.receive(1000) != null)
         {
            // Empty the queue
         }

         TextMessage message = session.createTextMessage();
         message.setText("testMDBTimer");
         message.setIntProperty("UNIQUE_ID", 123456789);
         message.setJMSReplyTo(queueB);
         sender.send(message);

         // Get the initial onMessage ack
         Message reply = receiver.receive(30000);
         log.info("onMessage reply: " + reply);
         assertTrue("onMessage reply != null", reply != null);

         if (log.isDebugEnabled())
         {
            log.debug("Properties");
            Enumeration e = reply.getPropertyNames();
            while (e.hasMoreElements())
            {
               log.debug(e.nextElement());
            }
         }

         int id = reply.getIntProperty("UNIQUE_ID");
         log.debug("id=" + id);
         assertTrue("onMessage reply.id = 123456789", id == 123456789);

         // Get the initial timer reply
         reply = receiver.receive(30000);
         log.info("ejbTimeout reply: " + reply);
         assertTrue("ejbTimeout reply != null", reply != null);

         if (log.isDebugEnabled())
         {
            log.debug("Properties");
            Enumeration e = reply.getPropertyNames();
            while (e.hasMoreElements())
            {
               log.debug(e.nextElement());
            }
         }

         id = reply.getIntProperty("UNIQUE_ID");
         log.debug("id=" + id);
         assertTrue("onMessage reply.id = 123456789", id == 123456789);
      }
      finally
      {
         if (receiver != null)
         {
            try
            {
               receiver.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
         if (sender != null)
         {
            try
            {
               sender.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
         if (session != null)
         {
            try
            {
               session.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
         if (queConn != null)
         {
            try
            {
               queConn.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
      }
   }

   /** Test an mdb that creates a timer in its ejbCreate method
    * @throws Exception
    */
   public void testOnCreateMDBTimer() throws Exception
   {
      log.info("+++ testOnCreateMDBTimer");
      InitialContext ctx = new InitialContext();
      QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");

      QueueConnection queConn = null;
      QueueSession session = null;
      QueueSender sender = null;
      QueueReceiver receiver = null;

      try
      {
         queConn = factory.createQueueConnection();
         queConn.start();

         Queue queueA = (Queue) ctx.lookup("queue/C");
         Queue queueB = (Queue) ctx.lookup("queue/D");

         session = queConn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
         sender = session.createSender(queueA);
         receiver = session.createReceiver(queueB);

         while (receiver.receive(1000) != null)
         {
            // Empty the queue
         }

         TextMessage message = session.createTextMessage();
         message.setText("testOnCreateMDBTimer");
         message.setIntProperty("UNIQUE_ID", 123456788);
         message.setJMSReplyTo(queueB);
         sender.send(message);

         // Get the initial onMessage ack
         Message reply = receiver.receive(15000);
         log.info("onMessage reply: " + reply);
         assertTrue("onMessage reply != null", reply != null);
         int id = reply.getIntProperty("UNIQUE_ID");
         assertTrue("onMessage reply.id = 123456788", id == 123456788);

         // Get the 10 ejbCreate timer replys
         for(int n = 0; n < 10; n ++)
         {
            reply = receiver.receive(15000);
            log.info("ejbTimeout reply: " + reply);
            assertTrue("ejbTimeout reply != null", reply != null);
            id = reply.getIntProperty("UNIQUE_ID");
            assertTrue("onMessage reply.id = 123456788", id == 123456788);
            long elapsed = reply.getLongProperty("Elapsed");
            log.info("Elapsed: "+elapsed);
         }
      }
      finally
      {
         if (receiver != null)
         {
            try
            {
               receiver.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
         if (sender != null)
         {
            try
            {
               sender.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
         if (session != null)
         {
            try
            {
               session.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
         if (queConn != null)
         {
            try
            {
               queConn.close();
            } catch (JMSException ignore)
            {
               //
            }
         }
      }
   }

   /**
    * Test with a repetitive timer the timer interface
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testTimerImplementation()
      throws Exception
   {
      TimerSLSBHome home = (TimerSLSBHome) getEJBHome(TimerSLSBHome.JNDI_NAME);
      TimerSLSB bean = home.create();
      byte[] handle = bean.startTimer(LONG_PERIOD);
      Date lNextEvent = bean.getNextTimeout(handle);
      long lUntilNextEvent = lNextEvent.getTime() - new Date().getTime();
      Thread.sleep(SHORT_PERIOD);
      long lTimeRemaining = bean.getTimeRemaining(handle);
      Object info = bean.getInfo(handle);
      assertTrue("Date of the next event must be greater than 0", lUntilNextEvent > 0);
      assertTrue("Period until next event must be greater than 0", lTimeRemaining > 0);
      assertTrue("Period until next event must be smaller than time until next even because it "
         + "it is called later", lUntilNextEvent > lTimeRemaining);
      assertTrue("Info("+info+") must be 'TimerSLSBean.startTimer'",
         "TimerSLSBean.startTimer".equals(info));
      assertTrue("Must be able to get a handle", handle != null);
      bean.stopTimer(handle);
   }

   /**
    * Test that a session that does not implement TimedObject cannot obtain
    * the TimerService from its EJBContext
    *
    * @throws Exception Unexpected Exception indicating an error
    */
   public void testBadStatelessSessionBeanTimer()
      throws Exception
   {
      TimerSLSBHome home = (TimerSLSBHome) getEJBHome("ejb/test/timer/NoTimedObjectBean");
      TimerSLSB bean = home.create();
      try
      {
         bean.startTimer(SHORT_PERIOD);
         fail("Was able to call NoTimedObjectBean.startTimer");
      }
      catch(RemoteException e)
      {
         log.info("Saw exception as expected", e);
      }
      bean.remove();
   }

   private EJBHome getEJBHome(String pJNDIName)
      throws NamingException
   {
      InitialContext lContext = new InitialContext();
      return (EJBHome) lContext.lookup(pJNDIName);
   }

   private void login() throws Exception
   {
      lc = null;
      String username = "jduke";
      char[] password = "theduke".toCharArray();
      AppCallbackHandler handler = new AppCallbackHandler(username, password);
      log.debug("Creating LoginContext(ejb-timers)");
      lc = new LoginContext("ejb-timers", handler);
      lc.login();
      log.debug("Created LoginContext, subject="+lc.getSubject());
   }
   private void logout() throws Exception
   {
      if( lc != null )
      {
         lc.logout();
         lc = null;
      }
   }
}
TOP

Related Classes of org.jboss.test.timer.test.BasicTimerUnitTestCase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.