/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
package org.jboss.soa.esb.listeners.gateway;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.List;
import junit.framework.JUnit4TestAdapter;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.couriers.MockCourier;
import org.jboss.internal.soa.esb.couriers.MockCourierFactory;
import org.jboss.internal.soa.esb.services.registry.MockRegistry;
import org.jboss.internal.soa.esb.util.embedded.EmbeddableException;
import org.jboss.internal.soa.esb.util.embedded.ftp.FtpTestUtil;
import org.jboss.internal.soa.esb.util.embedded.ftp.NoConfigFileFtpServer;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.couriers.CourierException;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.listeners.ListenerTagNames;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleException;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.schedule.SchedulingException;
import org.jboss.soa.esb.services.registry.RegistryException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Unit test for RemoteGatewayListener that uses an embedded ftp server
* Tests the RemoteGatewayListener with the default RemoteFileSystemStrategy.
*
* @author Daniel Bevenius
*
*/
public class RemoteGatewayListenerUnitTest
{
private static Logger log = Logger.getLogger( RemoteGatewayListenerUnitTest.class );
/* EmbeddedFtp Server */
protected static NoConfigFileFtpServer ftpServer;
/* Instance of class under test */
protected static RemoteGatewayListener gatewayListener;
/*
* ConfigTree configuration. This is a field so that test methods
* can override the default settings created by createConfigTree()
*/
protected static ConfigTree configTree;
/* name of the remote ftp input directory */
protected static String remoteInputDirName;
/* name of the remote ftp upload directory */
protected static String remoteUploadDirName;
/* name of the remote ftp error directory */
protected static String remoteErrorDirName;
protected static final String SERVICE_CATEGORY = "RemoteGWListenerTest";
protected static final String SERVICE_NAME = SERVICE_CATEGORY;
private static final String INPUT_SUFFIX = ".txt";
private static final String WORK_SUFFIX = ".esbwork";
protected static final String POST_SUFFIX = ".done";
private static final String POST_ERROR_SUFFIX = ".error";
private static final String POST_DEL = "false";
private static final String RENAMED_SUFFIX = ".renamed";
protected static final String TEST_FILE_CONTENT = RemoteGatewayListenerUnitTest.class.getName() + " junit ftp test";
protected File testFile;
protected File renamedFile;
@BeforeClass
public static void classSetup() throws EmbeddableException, ConfigurationException, GatewayException, RegistryException, MalformedURLException, MessageDeliverException {
MockCourierFactory.install();
MockRegistry.install();
MockRegistry.register(RemoteGatewayListenerUnitTest.SERVICE_CATEGORY, RemoteGatewayListenerUnitTest.SERVICE_NAME, new MockCourier(true));
ftpServer = createFtpServer();
ftpServer.start();
createWorkDirectories();
configTree = createConfigTree();
createRemoteGatewayListener( configTree );
}
@AfterClass
public static void classCleanup() throws EmbeddableException, ConfigurationException, GatewayException, RegistryException, MalformedURLException
{
MockRegistry.uninstall();
MockCourierFactory.uninstall();
}
protected static void createWorkDirectories()
{
remoteInputDirName = "/" + ftpServer.getLocalInputDir().getName();
remoteUploadDirName = "/" + ftpServer.getLocalUploadDir().getName();
remoteErrorDirName = "/" + ftpServer.getLocalErrorDir().getName();
}
protected static void createRemoteGatewayListener( ConfigTree configTree )
throws ConfigurationException, RegistryException, GatewayException {
gatewayListener = new RemoteGatewayListener( configTree );
}
public static NoConfigFileFtpServer createFtpServer()
{
ftpServer = new NoConfigFileFtpServer();
ftpServer.setPort( 2221 );
return ftpServer;
}
@AfterClass
public static void classTearDown()
{
try
{
ftpServer.stop();
}
catch ( Exception e )
{
log.warn ( e.getMessage() );
}
if ( !FtpTestUtil.deleteDir( ftpServer.getFtpServerDir() ) )
{
log.warn( "Could not delete " + ftpServer.getFtpServerDir() ) ;
}
}
@Before
public void setUp()
{
testFile = FtpTestUtil.createTestFile( ftpServer.getLocalInputDir(), getClass().getName() + INPUT_SUFFIX , TEST_FILE_CONTENT );
}
@After
public void tearDown()
{
FtpTestUtil.deleteFile( testFile );
FtpTestUtil.deleteFile( renamedFile );
}
/**
* Test with the following configuration:
* inputDir="/input"
* postDir="/upload"
*/
@Test //( timeout=3000 )
public void doRun_PostDir_Different_From_InputDir() throws ManagedLifecycleException, ConfigurationException, GatewayException, RegistryException, InterruptedException, SchedulingException
{
setAbsoluteInputDir();
setAbsolutePostDirToUploadDir();
boolean getCourierReturnValue = true;
RemoteGatewayListenerMock mock = createAndStartListener ( configTree, getCourierReturnValue );
File done = ftpServer.getLocalUploadDir();
String doneFileName = testFile.getName() + POST_SUFFIX;
try {
mock.onSchedule();
File processedFile = new File ( done, doneFileName );
try
{
assertTrue ( processedFile.exists() );
}
finally
{
FtpTestUtil.deleteFile( processedFile );
}
} finally {
mock.stop();
mock.destroy();
}
}
/**
* Test with the following configuration:
* inputDir="/input"
* postDir="/input"
*/
@Test ( timeout=3000 )
public void doRun_PostDir_Same_As_InputDir() throws ManagedLifecycleException, ConfigurationException, GatewayException, RegistryException, InterruptedException, SchedulingException
{
setAbsoluteInputDir();
setAbsolutePostDirToInputDir();
boolean getCourierReturnValue = true;
RemoteGatewayListenerMock mock = createAndStartListener ( configTree, getCourierReturnValue );
File inputDir = ftpServer.getLocalInputDir();
String doneFileName = testFile.getName() + POST_SUFFIX;
try {
mock.onSchedule();
File processedFile = new File ( inputDir, doneFileName );
try
{
assertTrue ( processedFile.exists() );
}
finally
{
FtpTestUtil.deleteFile( processedFile );
}
} finally {
mock.stop();
mock.destroy();
}
}
/**
* This test will assert that the work file is renamed into the error directory.
* Test with the following configuration:
* postDir="/input"
* errorDir="/error"
*
* Note. when this test runs a stacktrace will be displayed. This is expected.
*/
@Test ( timeout = 2000 )
public void doRun_Negative() throws ManagedLifecycleException, ConfigurationException, GatewayException, RegistryException, InterruptedException, SchedulingException
{
setAbsoluteInputDir();
setAbsoluteErrorDir();
boolean getCourierReturnValue = false;
log.error( "The following exceptions are expected: " );
RemoteGatewayListenerMock mock = createAndStartListener ( configTree, getCourierReturnValue );
try {
File errorDir = ftpServer.getLocalErrorDir();
String errorFileName = testFile.getName() + POST_ERROR_SUFFIX;
mock.onSchedule();
File errorFile = new File ( errorDir, errorFileName );
try
{
assertTrue ( errorFile.exists() );
}
finally
{
FtpTestUtil.deleteFile( errorFile );
}
} finally {
mock.stop();
mock.destroy();
}
}
@Test
public void renameFile_In_Same_Directory() throws GatewayException
{
File from = createAbsoluteFromFile();
File to = createAbsoluteToFile();
gatewayListener.renameFile( from, to );
renamedFile = new File ( ftpServer.getLocalInputDir(), to.getName() );
assertFileRemoved( testFile );
assertFileExists( renamedFile );
}
@Test
public void renameFile_In_Different_Directory() throws GatewayException
{
File from = createAbsoluteFromFile();
File to = createAbsoluteToFileUploadDir();
gatewayListener.renameFile( from, to );
renamedFile = new File ( ftpServer.getLocalUploadDir(), to.getName() );
assertFileRemoved( testFile );
assertFileExists( renamedFile );
}
@Test
public void deleteFile() throws GatewayException
{
File remoteFile = createAbsoluteFromFile();
gatewayListener.deleteFile( remoteFile );
assertFalse( "Remote file was not deleted", testFile.exists() );
}
@Test
public void getFileListFromRemoteDir() throws GatewayException
{
File[] fileListFromRemoteDir = gatewayListener.getFileList();
assertNotNull ( fileListFromRemoteDir );
assertTrue ( fileListFromRemoteDir.length > 0 );
List<File> fileList = Arrays.asList( fileListFromRemoteDir );
assertTrue( "The test file was not included in the List! " , fileList.contains( new File ( testFile.getName() ) ));
}
@Test
public void getFileContents() throws GatewayException
{
File remoteFileName = createAbsoluteFromFile();
byte[] fileContents = gatewayListener.getFileContents( remoteFileName );
assertEquals( TEST_FILE_CONTENT, new String ( fileContents ) );
}
/*
* Will create a configTree that looks like the following:
* <junitRemoteGatewayListenerTest
* URL="ftp://anonymous:letMeIn@localhost:2221/input"
* errorDelete="false"
* errorDir="/error"
* errorSuffix=".error"
* gatewayClass="org.jboss.soa.esb.listeners.gateway.RemoteGatewayListener"
* inputSuffix=".txt"
* maxThreads="1"
* passive="false"
* pollLatencySeconds="5"
* postDelete="false"
* postDir="/upload"
* postSuffix=".done"
* service-description="Gateway for SIFO"
* target-service-category="RemoteGWListenerTest"
* target-service-name="RemoteGWListenerTest"
* workSuffix=".esbwork"
* />
*/
public static ConfigTree createConfigTree()
{
ConfigTree configTree = new ConfigTree( "junitRemoteGatewayListenerTest" );
configTree.setAttribute( ListenerTagNames.TARGET_SERVICE_CATEGORY_TAG, SERVICE_CATEGORY );
configTree.setAttribute( ListenerTagNames.TARGET_SERVICE_NAME_TAG, SERVICE_NAME );
try
{
configTree.setAttribute( ListenerTagNames.URL_TAG, ftpServer.getURL().toString() );
}
catch (MalformedURLException e)
{
fail ( e.getMessage() );
}
/* input attributes */
configTree.setAttribute( ListenerTagNames.FILE_INPUT_DIR_TAG, remoteInputDirName );
configTree.setAttribute( ListenerTagNames.FILE_INPUT_SFX_TAG, INPUT_SUFFIX );
configTree.setAttribute( ListenerTagNames.FILE_WORK_SFX_TAG, WORK_SUFFIX );
/* post attributes */
configTree.setAttribute( ListenerTagNames.FILE_POST_DIR_TAG, remoteUploadDirName );
configTree.setAttribute( ListenerTagNames.FILE_POST_SFX_TAG, POST_SUFFIX);
configTree.setAttribute( ListenerTagNames.FILE_POST_DEL_TAG, POST_DEL);
/* post error attributes */
configTree.setAttribute( ListenerTagNames.FILE_ERROR_DIR_TAG, remoteErrorDirName );
configTree.setAttribute( ListenerTagNames.FILE_ERROR_SFX_TAG, POST_ERROR_SUFFIX);
// Do not allow the background scheduler to fire before we run the tests.
// We should really be allowing it to fire so that we can test the normal operation.
configTree.setAttribute( ListenerTagNames.SCHEDULE_ID_REF, "idref") ;
configTree.setAttribute( ListenerTagNames.SCHEDULE_SIMPLE_FREQUENCY, "1000000000") ;
configTree.setAttribute( ListenerTagNames.SCHEDULE_SIMPLE_EXEC, "0") ;
return configTree;
}
protected void waitForFile( File inDir, String fileNameToWaitfor ) throws InterruptedException
{
boolean done = false;
while( !done )
{
for( String fileName : inDir.list() )
{
log.debug( fileName );
if ( fileName.equals( fileNameToWaitfor ) )
{
done = true;
break;
}
else
Thread.sleep( 1000 );
}
}
}
/**
* Creates a RemoteGatewayListenerMock instance with the passed in arguments, and then starts
* the RemoteGatewayListener's doRun() method in a new Thread.
*
* @param configTree The configTree to use to configure the RemoteGatewayListenerMock object
* @param returnValueForCourier the return value for the getCourier method of the RemoteGatewayListenerMock object
* @return RemoteGatewayListenerMock Mock impl of a RemoteGatewayListener.
*/
private RemoteGatewayListenerMock createAndStartListener ( ConfigTree configTree, boolean returnValueForCourier ) throws ConfigurationException, GatewayException, RegistryException, ManagedLifecycleException
{
final RemoteGatewayListenerMock mock = new RemoteGatewayListenerMock( configTree );
mock.initialise();
mock.start();
if(returnValueForCourier) {
MockCourierFactory.courierException = null;
} else {
MockCourierFactory.courierException = new CourierException("Test generated mock exception.");
}
return mock;
}
protected static void assertFileRemoved( File file)
{
assertFalse( "The file was not removed from the filesystem", file.exists() );
}
protected static void assertFileExists( File file )
{
assertTrue( "The file was not renamed to the upload directory.", file.exists() );
}
protected void setAbsoluteInputDir()
{
configTree.setAttribute( ListenerTagNames.FILE_INPUT_DIR_TAG, remoteInputDirName );
}
protected void setAbsolutePostDirToInputDir()
{
configTree.setAttribute( ListenerTagNames.FILE_POST_DIR_TAG, remoteInputDirName );
}
protected void setAbsolutePostDirToUploadDir()
{
configTree.setAttribute( ListenerTagNames.FILE_POST_DIR_TAG, remoteUploadDirName );
}
private void setAbsoluteErrorDir()
{
configTree.setAttribute( ListenerTagNames.FILE_ERROR_DIR_TAG, remoteErrorDirName );
}
protected File createAbsoluteFromFile()
{
return new File ( remoteInputDirName + "/" + testFile.getName() );
}
protected File createAbsoluteToFile()
{
return new File ( remoteInputDirName + "/" + testFile.getName() + RENAMED_SUFFIX );
}
private File createAbsoluteToFileUploadDir()
{
return new File ( remoteUploadDirName + "/" + testFile.getName() + RENAMED_SUFFIX );
}
/**
* Just here to get Ant to find annotated test.
*/
public static junit.framework.Test suite()
{
return new JUnit4TestAdapter( RemoteGatewayListenerUnitTest.class);
}
/**
* Mock impl of RemoteGatewayListener.
*/
class RemoteGatewayListenerMock extends RemoteGatewayListener
{
private boolean finishedOneRun;
/**
* Sole constructor
*
* @param configTree configTree used to configure this RemoteGatewayListener
*
*/
public RemoteGatewayListenerMock ( ConfigTree configTree) throws ConfigurationException, GatewayException, RegistryException {
super ( configTree );
}
public boolean hasFinishedOneRun()
{
return finishedOneRun;
}
}
}