/*
* 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.ejb.lifecycle.test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import junit.framework.Protectable;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import org.jboss.ejb.MessageDrivenContainer;
import org.jboss.logging.Logger;
import org.jboss.system.ServiceControllerMBean;
import org.jboss.test.JBossTestCase;
import org.jboss.test.util.jms.JMSDestinationsUtil;
/**
* Base TestCase for lifecycle tests. This test overrides the run method of the JUnit test
* to execute a external test case, restart a service and run the external test case again.
*
* @author <a href="mailto:emuckenh@redhat.com">Emanuel Muckenhuber</a>
* @version $Revision: 103773 $
*/
public abstract class AbstractLifeCycleTestWrapper extends JBossTestCase
{
/** The service controller objectName. */
private static final ObjectName serviceController = ServiceControllerMBean.OBJECT_NAME;
/** The logger. */
protected static final Logger log = Logger.getLogger(AbstractLifeCycleTestWrapper.class);
public AbstractLifeCycleTestWrapper(String name)
{
super(name);
}
/**
* Get the package which should be deployed.
*
* @return the deploy package
*/
protected abstract String getPackage();
/**
* The tests to execute.
*
* @return the tests.
*/
protected abstract Enumeration<TestCase> getTests();
/**
* Restart a service.
*
* @param name the service name
* @throws Exception
*/
protected void restart(String name) throws Exception
{
restart(new String[] { name });
}
/**
* Restart more services.
*
* @param names the service names
* @throws Exception
*/
protected void restart(String... names) throws Exception
{
for(String restartName : names)
{
ObjectName objectName = new ObjectName(restartName);
restart(objectName);
}
}
/**
* Restart the container. This calls stop, destroy, create and start
* over the ServiceController.
*
* @param name the objectName
* @throws Exception
*/
protected void restart(ObjectName name) throws Exception
{
log.debug("restarting service: " + name);
Object[] args = { name };
String[] sig = { ObjectName.class.getName() };
invoke(serviceController, "stop", args, sig);
invoke(serviceController, "destroy", args, sig);
invoke(serviceController, "create", args, sig);
invoke(serviceController, "start", args, sig);
}
/**
* Get the JNDI name of a MDB bean. This is needed as the jndi name
* is basically something like "local/" + ejbName + '@' + System.identityHashCode(ejbName)
*
* @param name the partial jndi name
* @return the jndi name of the MDB bean
* @throws Exception
*/
protected String getMDBName(String name) throws Exception
{
Set<ObjectInstance> set = getServer().queryMBeans(new ObjectName("jboss.j2ee:service=EJB,*"), null);
for(ObjectInstance i : set)
{
if(i.getClassName().equals(MessageDrivenContainer.class.getName()))
{
if( i.getObjectName().getKeyProperty("plugin") == null )
{
if(i.getObjectName().getKeyProperty("binding") == null)
{
String jndi = i.getObjectName().getKeyProperty("jndiName");
if(jndi != null && jndi.startsWith(name))
{
return jndi;
}
}
}
}
}
return null;
}
/**
* Deploy a deployment.
*
* @throws Exception
*/
protected void deploy() throws Exception
{
super.setUp();
try
{
JMSDestinationsUtil.setupBasicDestinations();
redeploy(getPackage());
}
catch(Exception e)
{
undeploy(getPackage());
throw e;
}
}
/**
* Undeploy a deployment.
*
* @throws Exception
*/
protected void undeploy() throws Exception
{
undeploy(getPackage());
JMSDestinationsUtil.destroyDestinations();
}
/**
* Override the JUnit run test to execute external tests,
* restart the service and run the test again.
* FIXME this is a hack.
*
* @param result the JUNIT TestResult.
*/
@Override
public void run(TestResult result)
{
try
{
// deploy
deploy();
// get the external tests
Enumeration<TestCase> e = getTests();
while(e.hasMoreElements())
{
TestCase t = e.nextElement();
// run the external test
result.runProtected(this, getProctectable(t));
}
// run the test case as usual
super.run(result);
//
e = getTests();
while(e.hasMoreElements())
{
TestCase t = e.nextElement();
// run the external test again
result.runProtected(this, getProctectable(t));
}
}
catch(Exception e)
{
result.addError(this, e);
}
finally
{
try
{
// undeploy
undeploy();
}
catch(Exception e)
{
result.addError(this, e);
}
}
}
protected Enumeration<TestCase> getTestCases(Class<? extends TestCase> testClass)
{
return getTestCases(testClass, null);
}
@SuppressWarnings("unchecked")
protected Enumeration<TestCase> getTestCases(Class<? extends TestCase> testClass, Collection<String> excludes)
{
if(testClass == null ) return Collections.enumeration(Collections.EMPTY_SET);
Enumeration<Test> testCases = new TestSuite(testClass).tests();
if(excludes == null || excludes.isEmpty()) return Collections.enumeration(Collections.EMPTY_SET);
List<TestCase> filtered = new ArrayList<TestCase>();
while(testCases.hasMoreElements())
{
Test t = testCases.nextElement();
if (t instanceof TestCase)
{
TestCase tc = (TestCase)t;
if(!excludes.contains(tc.getName()))
filtered.add(tc);
}
}
return Collections.enumeration(filtered);
}
/**
* Helper to wrap a test for JUnit.
*
* @param test the Test
* @return a Protectable
*/
private Protectable getProctectable(final TestCase test)
{
return new Protectable() {
public void protect() throws Throwable {
test.runBare();
}
};
}
}