v2.5

git-svn-id: svn://svn.code.sf.net/p/mockftpserver/code@274 531de8e6-9941-0410-b38b-9a92acbe0330
diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/AbstractCommandHandlerTestCase.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/AbstractCommandHandlerTestCase.java
new file mode 100644
index 0000000..6694c0f
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/AbstractCommandHandlerTestCase.java
@@ -0,0 +1,230 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.MockControl;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.text.MessageFormat;

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Abstract superclass for CommandHandler tests

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public abstract class AbstractCommandHandlerTestCase extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(AbstractCommandHandlerTestCase.class);

+

+    // Some common test constants

+    protected static final String DIR1 = "dir1";

+    protected static final String DIR2 = "dir2";

+    protected static final String FILENAME1 = "sample1.txt";

+    protected static final String FILENAME2 = "sample2.txt";

+

+    protected Session session;

+    protected ResourceBundle replyTextBundle;

+

+    /**

+     * Test the handleCommand() method, when one or more parameter is missing or invalid

+     *

+     * @param commandHandler - the CommandHandler to test

+     * @param commandName    - the name for the Command

+     * @param parameters     - the Command parameters

+     */

+    protected void testHandleCommand_InvalidParameters(AbstractTrackingCommandHandler commandHandler,

+                                                       String commandName, String[] parameters) throws Exception {

+        Command command = new Command(commandName, parameters);

+        session.sendReply(ReplyCodes.COMMAND_SYNTAX_ERROR, replyTextFor(ReplyCodes.COMMAND_SYNTAX_ERROR));

+        replay(session);

+

+        commandHandler.handleCommand(command, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Verify that the CommandHandler contains the specified number of invocation records

+     *

+     * @param commandHandler - the CommandHandler

+     * @param expected       - the expected number of invocations

+     */

+    protected void verifyNumberOfInvocations(InvocationHistory commandHandler, int expected) {

+        assertEquals("number of invocations", expected, commandHandler.numberOfInvocations());

+    }

+

+    /**

+     * Verify that the InvocationRecord contains no data elements

+     *

+     * @param invocationRecord - the InvocationRecord

+     */

+    protected void verifyNoDataElements(InvocationRecord invocationRecord) {

+        LOG.info("Verifying: " + invocationRecord);

+        assertEquals("number of data elements", 0, invocationRecord.keySet().size());

+    }

+

+    /**

+     * Verify that the InvocationRecord contains exactly one data element, with the specified key

+     * and value.

+     *

+     * @param invocationRecord - the InvocationRecord

+     * @param key              - the expected key

+     * @param value            - the expected value

+     */

+    protected void verifyOneDataElement(InvocationRecord invocationRecord, String key, Object value) {

+        LOG.info("Verifying: " + invocationRecord);

+        assertEquals("number of data elements", 1, invocationRecord.keySet().size());

+        assertEqualsAllTypes("value:" + value, value, invocationRecord.getObject(key));

+    }

+

+    /**

+     * Verify that the InvocationRecord contains exactly two data element, with the specified keys

+     * and values.

+     *

+     * @param invocationRecord - the InvocationRecord

+     * @param key1             - the expected key1

+     * @param value1           - the expected value1

+     * @param key2             - the expected key2

+     * @param value2-          the expected value2

+     */

+    protected void verifyTwoDataElements(InvocationRecord invocationRecord, String key1, Object value1,

+                                         String key2, Object value2) {

+

+        LOG.info("Verifying: " + invocationRecord);

+        assertEquals("number of data elements", 2, invocationRecord.keySet().size());

+        assertEqualsAllTypes("value1:" + value1, value1, invocationRecord.getObject(key1));

+        assertEqualsAllTypes("value2:" + value2, value2, invocationRecord.getObject(key2));

+    }

+

+    /**

+     * Assert that the actual is equal to the expected, using arrays equality comparison if

+     * necessary

+     *

+     * @param message  - the message, used if the comparison fails

+     * @param expected - the expected value

+     * @param actual   - the actual value

+     */

+    private void assertEqualsAllTypes(String message, Object expected, Object actual) {

+

+        if (expected instanceof byte[] || actual instanceof byte[]) {

+            assertEquals(message, (byte[]) expected, (byte[]) actual);

+        } else if (expected instanceof Object[] || actual instanceof Object[]) {

+            assertEquals(message, (Object[]) expected, (Object[]) actual);

+        } else {

+            assertEquals(message, expected, actual);

+        }

+    }

+

+    /**

+     * Perform setup before each test

+     *

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        session = (Session) createMock(Session.class);

+        control(session).setDefaultMatcher(MockControl.ARRAY_MATCHER);

+        control(session).expectAndDefaultReturn(session.getClientHost(), DEFAULT_HOST);

+

+        replyTextBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][]{

+                        {"150", replyTextFor(150)},

+                        {"200", replyTextFor(200)},

+                        {"211", replyTextWithParameterFor(211)},

+                        {"213", replyTextWithParameterFor(213)},

+                        {"214", replyTextWithParameterFor(214)},

+                        {"215", replyTextWithParameterFor(215)},

+                        {"220", replyTextFor(220)},

+                        {"221", replyTextFor(221)},

+                        {"226", replyTextFor(226)},

+                        {"226.WithFilename", replyTextWithParameterFor("226.WithFilename")},

+                        {"227", replyTextWithParameterFor(227)},

+                        {"229", replyTextWithParameterFor(229)},

+                        {"230", replyTextFor(230)},

+                        {"250", replyTextFor(250)},

+                        {"257", replyTextWithParameterFor(257)},

+                        {"331", replyTextFor(331)},

+                        {"350", replyTextFor(350)},

+                        {"501", replyTextFor(501)},

+                        {"502", replyTextFor(502)},

+                };

+            }

+        };

+    }

+

+    /**

+     * Return the test-specific reply text for the specified reply code

+     *

+     * @param replyCode - the reply code

+     * @return the reply text for the specified reply code

+     */

+    protected String replyTextFor(int replyCode) {

+        return "Reply for " + replyCode;

+    }

+

+    /**

+     * Return the test-specific parameterized reply text for the specified reply code

+     *

+     * @param replyCode - the reply code

+     * @return the reply text for the specified reply code

+     */

+    protected String replyTextWithParameterFor(int replyCode) {

+        return "Reply for " + replyCode + ":{0}";

+    }

+

+    /**

+     * Return the test-specific parameterized reply text for the specified messageKey

+     *

+     * @param messageKey - the messageKey

+     * @return the reply text for the specified messageKey

+     */

+    protected String replyTextWithParameterFor(String messageKey) {

+        return "Reply for " + messageKey + ":{0}";

+    }

+

+    /**

+     * Return the test-specific reply text for the specified reply code and message parameter

+     *

+     * @param replyCode - the reply code

+     * @param parameter - the message parameter value

+     * @return the reply text for the specified reply code

+     */

+    protected String formattedReplyTextFor(int replyCode, Object parameter) {

+        return MessageFormat.format(replyTextWithParameterFor(replyCode), objArray(parameter));

+    }

+

+    /**

+     * Return the test-specific reply text for the specified message key and message parameter

+     *

+     * @param messageKey - the messageKey

+     * @param parameter  - the message parameter value

+     * @return the reply text for the specified message key and parameter

+     */

+    protected String formattedReplyTextFor(String messageKey, Object parameter) {

+        return MessageFormat.format(replyTextWithParameterFor(messageKey), objArray(parameter));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/CommandTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/CommandTest.java
new file mode 100644
index 0000000..9182046
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/CommandTest.java
@@ -0,0 +1,186 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.CommandSyntaxException;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.List;

+

+/**

+ * Tests for the Command class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class CommandTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(CommandTest.class);

+

+    /**

+     * Test the Command(String,String[]) constructor

+     */

+    public void testConstructor() {

+        final String[] PARAMETERS = array("123");

+        Command command = new Command("abc", PARAMETERS);

+        assertEquals("name", "abc", command.getName());

+        assertEquals("parameters", PARAMETERS, command.getParameters());

+    }

+

+    /**

+     * Test the Command(String,List) constructor

+     */

+    public void testConstructor_List() {

+        final List PARAMETERS_LIST = list("123");

+        final String[] PARAMETERS_ARRAY = array("123");

+        Command command = new Command("abc", PARAMETERS_LIST);

+        assertEquals("name", "abc", command.getName());

+        assertEquals("parameters String[]", PARAMETERS_ARRAY, command.getParameters());

+    }

+

+    /**

+     * Test the Constructor method, passing in a null name

+     */

+    public void testConstructor_NullName() {

+        try {

+            new Command(null, EMPTY);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the Constructor method, passing in a null parameters

+     */

+    public void testConstructor_NullParameters() {

+        try {

+            new Command("OK", (String[]) null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the normalizeName() method

+     */

+    public void testNormalizeName() {

+        assertEquals("XXX", "XXX", Command.normalizeName("XXX"));

+        assertEquals("xxx", "XXX", Command.normalizeName("xxx"));

+        assertEquals("Xxx", "XXX", Command.normalizeName("Xxx"));

+    }

+

+    /**

+     * Test the getRequiredParameter method

+     */

+    public void testGetRequiredParameter() {

+        Command command = new Command("abc", array("123", "456"));

+        assertEquals("123", "123", command.getRequiredParameter(0));

+        assertEquals("456", "456", command.getRequiredParameter(1));

+    }

+

+    /**

+     * Test the getRequiredParameter method, when the index is not valid

+     */

+    public void testGetRequiredParameter_IndexNotValid() {

+        Command command = new Command("abc", array("123", "456"));

+        try {

+            command.getRequiredParameter(2);

+            fail("Expected CommandSyntaxException");

+        }

+        catch (CommandSyntaxException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the getOptionalString method

+     */

+    public void testGetOptionalString() {

+        Command command = new Command("abc", array("123", "456"));

+        assertEquals("123", "123", command.getOptionalString(0));

+        assertEquals("456", "456", command.getOptionalString(1));

+        assertEquals("null", null, command.getOptionalString(2));

+    }

+

+    /**

+     * Test the getParameter method

+     */

+    public void testGetParameter() {

+        Command command = new Command("abc", array("123", "456"));

+        assertEquals("123", "123", command.getParameter(0));

+        assertEquals("456", "456", command.getParameter(1));

+        assertEquals("null", null, command.getParameter(2));

+    }

+

+    /**

+     * Test that a Command object is immutable, changing the original parameters passed in to the constructor

+     */

+    public void testImmutable_ChangeOriginalParameters() {

+        final String[] PARAMETERS = {"a", "b", "c"};

+        final Command COMMAND = new Command("command", PARAMETERS);

+        PARAMETERS[2] = "xxx";

+        assertEquals("parameters", COMMAND.getParameters(), new String[]{"a", "b", "c"});

+    }

+

+    /**

+     * Test that a Command object is immutable, changing the parameters returned from getParameters

+     */

+    public void testImmutable_ChangeRetrievedParameters() {

+        final String[] PARAMETERS = {"a", "b", "c"};

+        final Command COMMAND = new Command("command", PARAMETERS);

+        String[] parameters = COMMAND.getParameters();

+        parameters[2] = "xxx";

+        assertEquals("parameters", PARAMETERS, COMMAND.getParameters());

+    }

+

+    /**

+     * Test the equals() method, and tests the hasCode() method implicitly

+     *

+     * @throws Exception

+     */

+    public void testEquals() throws Exception {

+        final Command COMMAND1 = new Command("a", EMPTY);

+        final Command COMMAND2 = new Command("a", EMPTY);

+        final Command COMMAND3 = new Command("b", array("1"));

+        final Command COMMAND4 = new Command("b", array("2"));

+        final Command COMMAND5 = new Command("c", array("1"));

+        _testEquals(COMMAND1, null, false);

+        _testEquals(COMMAND1, COMMAND1, true);

+        _testEquals(COMMAND1, COMMAND2, true);

+        _testEquals(COMMAND1, COMMAND3, false);

+        _testEquals(COMMAND3, COMMAND4, false);

+        _testEquals(COMMAND3, COMMAND5, false);

+    }

+

+    /**

+     * Test that command1 equals command2 if and only if expectedEqual is true

+     *

+     * @param command1      - the first command

+     * @param command2      - the second command

+     * @param expectedEqual - true if command1 is expected to equal command2

+     */

+    private void _testEquals(Command command1, Command command2, boolean expectedEqual) {

+        assertEquals(command1.toString() + " and " + command2, expectedEqual, command1.equals(command2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/ConnectCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/ConnectCommandHandlerTest.java
new file mode 100644
index 0000000..127b403
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/ConnectCommandHandlerTest.java
@@ -0,0 +1,48 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+/**

+ * Tests for the ConnectCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class ConnectCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private ConnectCommandHandler commandHandler;

+    private Command command1;

+

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.CONNECT_OK, replyTextFor(ReplyCodes.CONNECT_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new ConnectCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.CONNECT, EMPTY);

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/InvocationRecordTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/InvocationRecordTest.java
new file mode 100644
index 0000000..026a7e2
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/InvocationRecordTest.java
@@ -0,0 +1,226 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.Date;

+import java.util.HashSet;

+import java.util.Set;

+

+/**

+ * Tests for InvocationRecord

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class InvocationRecordTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(InvocationRecordTest.class);

+    private static final Command COMMAND = new Command("command", EMPTY);

+    private static final String KEY1 = "key1";

+    private static final String KEY2 = "key2";

+    private static final String STRING = "abc123";

+    private static final Integer INT = new Integer(77);

+

+    private InvocationRecord invocationRecord;

+

+    /**

+     * Test the Constructor

+     */

+    public void testConstructor() {

+        final Command COMMAND = new Command("ABC", EMPTY);

+        long beforeTime = System.currentTimeMillis();

+        InvocationRecord commandInvocation = new InvocationRecord(COMMAND, DEFAULT_HOST);

+        long afterTime = System.currentTimeMillis();

+        LOG.info(commandInvocation.toString());

+        assertEquals("Command", COMMAND, commandInvocation.getCommand());

+        assertTrue("time", commandInvocation.getTime().getTime() >= beforeTime

+                && commandInvocation.getTime().getTime() <= afterTime);

+        assertEquals("host", DEFAULT_HOST, commandInvocation.getClientHost());

+    }

+

+    /**

+     * Test the set() method, passing in a null key

+     */

+    public void testSet_NullKey() {

+        try {

+            invocationRecord.set(null, STRING);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the set() method, passing in a null value

+     */

+    public void testSet_NullValue() {

+        invocationRecord.set(KEY1, null);

+        assertNull(KEY1, invocationRecord.getObject(KEY1));

+    }

+

+    /**

+     * Test the containsKey() method

+     */

+    public void testContainsKey() {

+        invocationRecord.set(KEY1, STRING);

+        assertTrue(KEY1, invocationRecord.containsKey(KEY1));

+        assertFalse(KEY2, invocationRecord.containsKey(KEY2));

+    }

+

+    /**

+     * Test the containsKey() method, passing in a null key

+     */

+    public void testContainsKey_Null() {

+        try {

+            invocationRecord.containsKey(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the getString() method

+     */

+    public void testGetString() {

+        assertNull("undefined", invocationRecord.getString("UNDEFINED"));

+        invocationRecord.set(KEY1, STRING);

+        assertEquals(KEY1, STRING, invocationRecord.getString(KEY1));

+    }

+

+    /**

+     * Test the getString() method, passing in a null key

+     */

+    public void testGetString_Null() {

+        try {

+            invocationRecord.getString(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the getString() method, when the value for the key is not a String

+     */

+    public void testGetString_NotAString() {

+

+        invocationRecord.set(KEY1, INT);

+        try {

+            invocationRecord.getString(KEY1);

+            fail("Expected ClassCastException");

+        }

+        catch (ClassCastException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the getObject() method

+     */

+    public void testGetObject() {

+        assertNull("undefined", invocationRecord.getObject("UNDEFINED"));

+        invocationRecord.set(KEY1, STRING);

+        assertEquals(KEY1, STRING, invocationRecord.getObject(KEY1));

+    }

+

+    /**

+     * Test the keySet() method

+     */

+    public void testKeySet() {

+        Set set = new HashSet();

+        assertEquals("empty", set, invocationRecord.keySet());

+        invocationRecord.set(KEY1, STRING);

+        invocationRecord.set(KEY2, STRING);

+        set.add(KEY1);

+        set.add(KEY2);

+        assertEquals("2", set, invocationRecord.keySet());

+    }

+

+    /**

+     * Test that the keySet() return value does not allow breaking immutability   

+     */

+    public void testKeySet_Immutability() {

+        Set keySet = invocationRecord.keySet();

+        try {

+            keySet.add("abc");

+            fail("Expected UnsupportedOperationException");

+        }

+        catch (UnsupportedOperationException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the getObject() method, passing in a null key

+     */

+    public void testGetObject_Null() {

+        try {

+            invocationRecord.getObject(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the lock() method 

+     */

+    public void testLock() {

+        assertFalse("locked - before", invocationRecord.isLocked());

+        invocationRecord.set(KEY1, STRING);

+        invocationRecord.lock();

+        assertTrue("locked - after", invocationRecord.isLocked());

+        try {

+            invocationRecord.set(KEY2, "abc");

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test that the getTime() return value does not break immutability   

+     */

+    public void testGetTime_Immutability() {

+        

+        Date timestamp = invocationRecord.getTime();

+        long timeInMillis = timestamp.getTime();

+        timestamp.setTime(12345L);

+        assertEquals("time", timeInMillis, invocationRecord.getTime().getTime());

+    }

+    

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        invocationRecord = new InvocationRecord(COMMAND, DEFAULT_HOST);

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/ReplyTextBundleUtilTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/ReplyTextBundleUtilTest.java
new file mode 100644
index 0000000..edb6384
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/ReplyTextBundleUtilTest.java
@@ -0,0 +1,104 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for the ReplyTextBundleUtil class.

+ * 

+ * @version $Revision$ - $Date$

+ *

+ * @author Chris Mair

+ */

+public final class ReplyTextBundleUtilTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(ReplyTextBundleUtilTest.class);

+    

+    private ResourceBundle resourceBundle1;

+    private ResourceBundle resourceBundle2;

+    

+    /**

+     * Test the setReplyTextBundleIfAppropriate() method, when the CommandHandler implements 

+     * the ResourceBundleAware interface, and the replyTextBundle has not yet been set. 

+     */

+    public void testSetReplyTextBundleIfAppropriate_ReplyTextBundleAware_NotSetYet() {

+        AbstractTrackingCommandHandler commandHandler = new StaticReplyCommandHandler();

+        ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(commandHandler, resourceBundle1);

+        assertSame(resourceBundle1, commandHandler.getReplyTextBundle());

+    }

+

+    /**

+     * Test the setReplyTextBundleIfAppropriate() method, when the CommandHandler implements 

+     * the ResourceBundleAware interface, and the replyTextBundle has already been set. 

+     */

+    public void testSetReplyTextBundleIfAppropriate_ReplyTextBundleAware_AlreadySet() {

+        AbstractTrackingCommandHandler commandHandler = new StaticReplyCommandHandler();

+        commandHandler.setReplyTextBundle(resourceBundle2);

+        ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(commandHandler, resourceBundle1);

+        assertSame(resourceBundle2, commandHandler.getReplyTextBundle());

+    }

+

+    /**

+     * Test the setReplyTextBundleIfAppropriate() method, when the CommandHandler does not 

+     * implement the ResourceBundleAware interface. 

+     */

+    public void testSetReplyTextBundleIfAppropriate_NotReplyTextBundleAware() {

+        CommandHandler commandHandler = (CommandHandler) createMock(CommandHandler.class);

+        replay(commandHandler);

+        ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(commandHandler, resourceBundle1);

+        verify(commandHandler);         // expect no method calls

+    }

+    

+    /**

+     * Test the setReplyTextBundleIfAppropriate() method, when the CommandHandler is null. 

+     */

+    public void testSetReplyTextBundleIfAppropriate_NullCommandHandler() {

+        try {

+            ReplyTextBundleUtil.setReplyTextBundleIfAppropriate(null, resourceBundle1);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        resourceBundle1 = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return null;

+            }

+        };

+

+        resourceBundle2 = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][] { { "a", "b" } };

+            }

+        };

+    }

+    

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/SimpleCompositeCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/SimpleCompositeCommandHandlerTest.java
new file mode 100644
index 0000000..6635afa
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/SimpleCompositeCommandHandlerTest.java
@@ -0,0 +1,269 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ArrayList;

+import java.util.List;

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for SimpleCompositeCommandHandler

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public class SimpleCompositeCommandHandlerTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(SimpleCompositeCommandHandlerTest.class);

+    

+    private SimpleCompositeCommandHandler simpleCompositeCommandHandler;

+    private Session session;

+    private Command command;

+    private CommandHandler commandHandler1;

+    private CommandHandler commandHandler2;

+    private CommandHandler commandHandler3;

+    

+    /**

+     * Test the handleCommand() method 

+     */

+    public void testHandleCommand_OneHandler_OneInvocation() throws Exception {

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        

+        commandHandler1.handleCommand(command, session);

+        replay(commandHandler1);

+        

+        simpleCompositeCommandHandler.handleCommand(command, session);

+        verify(commandHandler1);

+    }

+    

+    /**

+     * Test the handleCommand() method, with two CommandHandler defined, but with multiple invocation 

+     */

+    public void testHandleCommand_TwoHandlers() throws Exception {

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler2);

+        

+        commandHandler1.handleCommand(command, session);

+        commandHandler2.handleCommand(command, session);

+        replayAll();

+        

+        simpleCompositeCommandHandler.handleCommand(command, session);

+        simpleCompositeCommandHandler.handleCommand(command, session);

+        verifyAll();

+    }

+    

+    /**

+     * Test the handleCommand() method, with three CommandHandler defined, and multiple invocation 

+     */

+    public void testHandleCommand_ThreeHandlers() throws Exception {

+        

+        List list = new ArrayList();

+        list.add(commandHandler1);

+        list.add(commandHandler2);

+        list.add(commandHandler3);

+        simpleCompositeCommandHandler.setCommandHandlers(list);

+        

+        commandHandler1.handleCommand(command, session);

+        commandHandler2.handleCommand(command, session);

+        commandHandler3.handleCommand(command, session);

+        replayAll();

+        

+        simpleCompositeCommandHandler.handleCommand(command, session);

+        simpleCompositeCommandHandler.handleCommand(command, session);

+        simpleCompositeCommandHandler.handleCommand(command, session);

+        verifyAll();

+    }

+    

+    /**

+     * Test the handleCommand() method, with a single CommandHandler defined, but too many invocations 

+     */

+    public void testHandleCommand_OneHandler_TooManyInvocations() throws Exception {

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        

+        commandHandler1.handleCommand(command, session);

+        replay(commandHandler1);

+        

+        simpleCompositeCommandHandler.handleCommand(command, session);

+

+        // Second invocation throws an exception

+        try {

+            simpleCompositeCommandHandler.handleCommand(command, session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the handleCommand_NoHandlersDefined() method 

+     */

+    public void testHandleCommand_NoHandlersDefined() throws Exception {

+        try {

+            simpleCompositeCommandHandler.handleCommand(command, session);

+            fail("Expected AssertFailedException");

+        }

+        catch(AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the handleCommand(Command,Session) method, passing in a null Command

+     */

+    public void testHandleCommand_NullCommand() throws Exception {

+        try {

+            simpleCompositeCommandHandler.handleCommand(null, session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the handleCommand(Command,Session) method, passing in a null Session

+     */

+    public void testHandleCommand_NullSession() throws Exception {

+        try {

+            simpleCompositeCommandHandler.handleCommand(command, null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the addCommandHandler(CommandHandler) method, passing in a null CommandHandler

+     */

+    public void testAddCommandHandler_NullCommandHandler() throws Exception {

+        try {

+            simpleCompositeCommandHandler.addCommandHandler(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the setCommandHandlers(List) method, passing in a null

+     */

+    public void testSetCommandHandlers_Null() throws Exception {

+        try {

+            simpleCompositeCommandHandler.setCommandHandlers(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the getCommandHandler(int) method, passing in an index for which no CommandHandler is defined

+     */

+    public void testGetCommandHandler_UndefinedIndex() throws Exception {

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        try {

+            simpleCompositeCommandHandler.getCommandHandler(1);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the getCommandHandler(int) method

+     */

+    public void testGetCommandHandler() throws Exception {

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler2);

+        assertSame("index 0", commandHandler1, simpleCompositeCommandHandler.getCommandHandler(0));

+        assertSame("index 1", commandHandler2, simpleCompositeCommandHandler.getCommandHandler(1));

+    }

+    

+    /**

+     * Test the getCommandHandler(int) method, passing in a negative index

+     */

+    public void testGetCommandHandler_NegativeIndex() throws Exception {

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        try {

+            simpleCompositeCommandHandler.getCommandHandler(-1);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the getReplyTextBundle() method

+     */

+    public void testGetReplyTextBundle() {

+        assertNull(simpleCompositeCommandHandler.getReplyTextBundle());

+    }

+    

+    /**

+     * Test the setReplyTextBundle() method

+     */

+    public void testSetReplyTextBundle() {

+        

+        AbstractTrackingCommandHandler replyTextBundleAwareCommandHandler1 = new StaticReplyCommandHandler();

+        AbstractTrackingCommandHandler replyTextBundleAwareCommandHandler2 = new StaticReplyCommandHandler();

+        simpleCompositeCommandHandler.addCommandHandler(replyTextBundleAwareCommandHandler1);

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        simpleCompositeCommandHandler.addCommandHandler(replyTextBundleAwareCommandHandler2);

+        

+        ResourceBundle resourceBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return null;

+            }

+        };

+        

+        simpleCompositeCommandHandler.setReplyTextBundle(resourceBundle);

+        assertSame("1", resourceBundle, replyTextBundleAwareCommandHandler1.getReplyTextBundle());

+        assertSame("2", resourceBundle, replyTextBundleAwareCommandHandler1.getReplyTextBundle());

+    }

+    

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+    

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        simpleCompositeCommandHandler = new SimpleCompositeCommandHandler();

+        session = (Session) createMock(Session.class);

+        command = new Command("cmd", EMPTY);

+        commandHandler1 = (CommandHandler) createMock(CommandHandler.class);

+        commandHandler2 = (CommandHandler) createMock(CommandHandler.class);

+        commandHandler3 = (CommandHandler) createMock(CommandHandler.class);

+    }

+    

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/StaticReplyCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/StaticReplyCommandHandlerTest.java
new file mode 100644
index 0000000..634f182
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/StaticReplyCommandHandlerTest.java
@@ -0,0 +1,140 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.util.AssertFailedException;

+

+/**

+ * Tests for the StaticReplyCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class StaticReplyCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(StaticReplyCommandHandlerTest.class);

+    private static final int REPLY_CODE = 999;

+    private static final String REPLY_TEXT = "some text 123";

+    private static final Command COMMAND = new Command("ANY", EMPTY);

+    

+    private StaticReplyCommandHandler commandHandler;

+    

+    /**

+     * Test the constructor that takes a replyCode, passing in a null

+     */

+    public void testConstructor_String_InvalidReplyCode() {

+        try {

+            new StaticReplyCommandHandler(-1);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the constructor that takes a replyCode and replyText, passing in a null replyCode

+     */

+    public void testConstructor_StringString_InvalidReplyCode() {

+        try {

+            new StaticReplyCommandHandler(-99, "text");

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the setReplyCode() method, passing in a null

+     */

+    public void testSetReplyCode_Invalid() {

+        try {

+            commandHandler.setReplyCode(-1);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the handleCommand() method when the replyText attribute has not been set.

+     * So, use whatever replyText has been configured in the replyCodeMapping

+     * @throws Exception

+     */

+    public void testHandleCommand_ReplyTextNotSet() throws Exception {

+        commandHandler.setReplyCode(250);

+        

+        session.sendReply(250, replyTextFor(250));

+        replay(session);

+        

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+    

+    /**

+     * Test the handleCommand() method, when the replyCode and replyText are both set

+     * @throws Exception

+     */

+    public void testHandleCommand_SetReplyText() throws Exception {

+        commandHandler.setReplyCode(REPLY_CODE);

+        commandHandler.setReplyText(REPLY_TEXT);

+        

+        session.sendReply(REPLY_CODE, REPLY_TEXT);

+        replay(session);

+        

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+    

+    /**

+     * Test the handleCommand() method when the replyCode attribute has not been set

+     * @throws Exception

+     */

+    public void testHandleCommand_ReplyCodeNotSet() throws Exception {

+

+        try {

+            commandHandler.handleCommand(COMMAND, session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+    

+    /**

+     * @see AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new StaticReplyCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+    

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/UnsupportedCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/UnsupportedCommandHandlerTest.java
new file mode 100644
index 0000000..cd6d84a
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/UnsupportedCommandHandlerTest.java
@@ -0,0 +1,48 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+/**

+ * Tests for the UnsupportedCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class UnsupportedCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private UnsupportedCommandHandler commandHandler;

+    private Command command1;

+

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.COMMAND_NOT_SUPPORTED, replyTextFor(ReplyCodes.COMMAND_NOT_SUPPORTED));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new UnsupportedCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command("XXXX", EMPTY);

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractCommandHandlerTest.java
new file mode 100644
index 0000000..f356c88
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractCommandHandlerTest.java
@@ -0,0 +1,126 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.MockControl;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.stub.command.AbstractStubCommandHandler;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for the AbstractCommandHandler class. The class name is prefixed with an

+ * underscore so that it is not filtered out by Maven's Surefire test plugin.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class _AbstractCommandHandlerTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(_AbstractTrackingCommandHandlerTest.class);

+    private static final int REPLY_CODE1 = 777;

+    private static final int REPLY_CODE2 = 888;

+    private static final String REPLY_TEXT1 = "reply1 ... abcdef";

+    private static final String REPLY_TEXT2 = "abc {0} def";

+    private static final String MESSAGE_KEY = "key.123";

+    private static final String MESSAGE_TEXT = "message.123";

+

+    private AbstractCommandHandler commandHandler;

+

+    /**

+     * Test the quotes utility method

+     */

+    public void testQuotes() {

+        assertEquals("abc", "\"abc\"", AbstractStubCommandHandler.quotes("abc"));

+        assertEquals("<empty>", "\"\"", AbstractStubCommandHandler.quotes(""));

+    }

+

+    /**

+     * Test the quotes utility method, passing in a null

+     */

+    public void testQuotes_Null() {

+        try {

+            AbstractStubCommandHandler.quotes(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the assertValidReplyCode() method

+     */

+    public void testAssertValidReplyCode() {

+        // These are valid, so expect no exceptions

+        commandHandler.assertValidReplyCode(1);

+        commandHandler.assertValidReplyCode(100);

+

+        // These are invalid

+        testAssertValidReplyCodeWithInvalid(0);

+        testAssertValidReplyCodeWithInvalid(-1);

+    }

+

+    /**

+     * Test the assertValidReplyCode() method , passing in an invalid replyCode value

+     *

+     * @param invalidReplyCode - a reply code that is expected to be invalid

+     */

+    private void testAssertValidReplyCodeWithInvalid(int invalidReplyCode) {

+        try {

+            commandHandler.assertValidReplyCode(invalidReplyCode);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        Session session = (Session) createMock(Session.class);

+        control(session).setDefaultMatcher(MockControl.ARRAY_MATCHER);

+        commandHandler = new AbstractCommandHandler() {

+            public void handleCommand(Command command, Session session) throws Exception {

+            }

+        };

+        ResourceBundle replyTextBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][]{

+                        {Integer.toString(REPLY_CODE1), REPLY_TEXT1},

+                        {Integer.toString(REPLY_CODE2), REPLY_TEXT2},

+                        {MESSAGE_KEY, MESSAGE_TEXT}

+                };

+            }

+        };

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractStaticReplyCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractStaticReplyCommandHandlerTest.java
new file mode 100644
index 0000000..c4a8e50
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractStaticReplyCommandHandlerTest.java
@@ -0,0 +1,158 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.MockControl;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for the AbstractStaticReplyCommandHandler class. The class name is prefixed with an underscore

+ * so that it is not filtered out by Maven's Surefire test plugin.

+ *

+ * @version $Revision$ - $Date$

+ *

+ * @author Chris Mair

+ */

+public final class _AbstractStaticReplyCommandHandlerTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(_AbstractStaticReplyCommandHandlerTest.class);

+    private static final int REPLY_CODE1 = 777;

+    private static final int REPLY_CODE2 = 888;

+    private static final String REPLY_TEXT1 = "reply1 ... abcdef";

+    private static final String REPLY_TEXT2 = "abc {0} def";

+    private static final String REPLY_TEXT2_FORMATTED = "abc 123 def";

+    private static final String MESSAGE_KEY = "key.123";

+    private static final String MESSAGE_TEXT = "message.123";

+    private static final String OVERRIDE_REPLY_TEXT = "overridden reply ... abcdef";

+    private static final Object ARG = "123";

+

+    private AbstractStaticReplyCommandHandler commandHandler;

+    private Session session;

+

+    /**

+     * Test the sendReply(Session) method

+     */

+    public void testSendReply() {

+        session.sendReply(REPLY_CODE1, REPLY_TEXT1);

+        replay(session);

+

+        commandHandler.setReplyCode(REPLY_CODE1);

+        commandHandler.sendReply(session);

+        verify(session);

+    }

+

+    /**

+     * Test the sendReply(Session) method, when the replyText has been set

+     */

+    public void testSendReply_SetReplyText() {

+        session.sendReply(REPLY_CODE1, OVERRIDE_REPLY_TEXT);

+        replay(session);

+

+        commandHandler.setReplyCode(REPLY_CODE1);

+        commandHandler.setReplyText(OVERRIDE_REPLY_TEXT);

+        commandHandler.sendReply(session);

+        verify(session);

+    }

+

+    /**

+     * Test the sendReply(Session) method, when the replyMessageKey has been set

+     */

+    public void testSendReply_SetReplyMessageKey() {

+        session.sendReply(REPLY_CODE1, REPLY_TEXT2);

+        replay(session);

+

+        commandHandler.setReplyCode(REPLY_CODE1);

+        commandHandler.setReplyMessageKey(Integer.toString(REPLY_CODE2));

+        commandHandler.sendReply(session);

+        verify(session);

+    }

+

+    /**

+     * Test the sendReply(Session) method, when the replyCode has not been set

+     */

+    public void testSendReply_ReplyCodeNotSet() {

+        try {

+            commandHandler.sendReply(session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the sendReply(Session,Object) method

+     */

+    public void testSendReply_MessageParameter() {

+        session.sendReply(REPLY_CODE2, REPLY_TEXT2);

+        session.sendReply(REPLY_CODE2, REPLY_TEXT2_FORMATTED);

+        replay(session);

+

+        commandHandler.setReplyCode(REPLY_CODE2);

+        commandHandler.sendReply(session);

+        commandHandler.sendReply(session, ARG);

+        verify(session);

+    }

+

+    /**

+     * Test the setReplyCode() method, passing in an invalid value

+     */

+    public void testSetReplyCode_Invalid() {

+        try {

+            commandHandler.setReplyCode(0);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        session = (Session) createMock(Session.class);

+        control(session).setDefaultMatcher(MockControl.ARRAY_MATCHER);

+        commandHandler = new AbstractStaticReplyCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws Exception {

+            }

+        };

+        ResourceBundle replyTextBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][]{

+                        {Integer.toString(REPLY_CODE1), REPLY_TEXT1},

+                        {Integer.toString(REPLY_CODE2), REPLY_TEXT2},

+                        {MESSAGE_KEY, MESSAGE_TEXT}

+                };

+            }

+        };

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractTrackingCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractTrackingCommandHandlerTest.java
new file mode 100644
index 0000000..5cc98f2
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/command/_AbstractTrackingCommandHandlerTest.java
@@ -0,0 +1,222 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.MockControl;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for the AbstractTrackingCommandHandler class. The class name is prefixed with an

+ * underscore so that it is not filtered out by Maven's Surefire test plugin.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class _AbstractTrackingCommandHandlerTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(_AbstractTrackingCommandHandlerTest.class);

+    private static final String COMMAND_NAME = "abc";

+    private static final Object ARG = "123";

+    private static final Object[] ARGS = {ARG};

+    private static final Command COMMAND = new Command(COMMAND_NAME, EMPTY);

+    private static final Command COMMAND_WITH_ARGS = new Command(COMMAND_NAME, EMPTY);

+    private static final int REPLY_CODE1 = 777;

+    private static final int REPLY_CODE2 = 888;

+    private static final int REPLY_CODE3 = 999;

+    private static final String REPLY_TEXT1 = "reply1 ... abcdef";

+    private static final String REPLY_TEXT2 = "abc {0} def";

+    private static final String REPLY_TEXT2_FORMATTED = "abc 123 def";

+    private static final String OVERRIDE_REPLY_TEXT = "overridden reply ... abcdef";

+    private static final String MESSAGE_KEY = "key.123";

+    private static final String MESSAGE_TEXT = "message.123";

+

+    private AbstractTrackingCommandHandler commandHandler;

+    private Session session;

+

+    /**

+     * Test the handleCommand(Command,Session) method

+     */

+    public void testHandleCommand() throws Exception {

+        assertEquals("before", 0, commandHandler.numberOfInvocations());

+        commandHandler.handleCommand(COMMAND, session);

+        assertEquals("after", 1, commandHandler.numberOfInvocations());

+        assertTrue("locked", commandHandler.getInvocation(0).isLocked());

+    }

+

+    /**

+     * Test the handleCommand(Command,Session) method, passing in a null Command

+     */

+    public void testHandleCommand_NullCommand() throws Exception {

+        try {

+            commandHandler.handleCommand(null, session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the handleCommand(Command,Session) method, passing in a null Session

+     */

+    public void testHandleCommand_NullSession() throws Exception {

+        try {

+            commandHandler.handleCommand(COMMAND, null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the numberOfInvocations(), addInvocationRecord() and clearInvocationRecord() methods

+     */

+    public void testInvocationHistory() throws Exception {

+        control(session).expectAndDefaultReturn(session.getClientHost(), DEFAULT_HOST);

+        replay(session);

+

+        assertEquals("none", 0, commandHandler.numberOfInvocations());

+        commandHandler.handleCommand(COMMAND, session);

+        assertEquals("1", 1, commandHandler.numberOfInvocations());

+        commandHandler.handleCommand(COMMAND, session);

+        assertEquals("2", 2, commandHandler.numberOfInvocations());

+        commandHandler.clearInvocations();

+        assertEquals("cleared", 0, commandHandler.numberOfInvocations());

+    }

+

+    /**

+     * Test the getInvocation() method

+     *

+     * @throws Exception

+     */

+    public void testGetInvocation() throws Exception {

+        control(session).expectAndDefaultReturn(session.getClientHost(), DEFAULT_HOST);

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        commandHandler.handleCommand(COMMAND_WITH_ARGS, session);

+        assertSame("1", COMMAND, commandHandler.getInvocation(0).getCommand());

+        assertSame("2", COMMAND_WITH_ARGS, commandHandler.getInvocation(1).getCommand());

+    }

+

+    /**

+     * Test the getInvocation() method, passing in an invalid index

+     */

+    public void testGetInvocation_IndexOutOfBounds() throws Exception {

+        commandHandler.handleCommand(COMMAND, session);

+        try {

+            commandHandler.getInvocation(2);

+            fail("Expected IndexOutOfBoundsException");

+        }

+        catch (IndexOutOfBoundsException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the sendReply() method, when no message arguments are specified

+     */

+    public void testSendReply() {

+        session.sendReply(REPLY_CODE1, REPLY_TEXT1);

+        session.sendReply(REPLY_CODE1, MESSAGE_TEXT);

+        session.sendReply(REPLY_CODE1, OVERRIDE_REPLY_TEXT);

+        session.sendReply(REPLY_CODE3, null);

+        replay(session);

+

+        commandHandler.sendReply(session, REPLY_CODE1, null, null, null);

+        commandHandler.sendReply(session, REPLY_CODE1, MESSAGE_KEY, null, null);

+        commandHandler.sendReply(session, REPLY_CODE1, MESSAGE_KEY, OVERRIDE_REPLY_TEXT, null);

+        commandHandler.sendReply(session, REPLY_CODE3, null, null, null);

+

+        verify(session);

+    }

+

+    /**

+     * Test the sendReply() method, passing in message arguments

+     */

+    public void testSendReply_WithMessageArguments() {

+        session.sendReply(REPLY_CODE1, REPLY_TEXT2_FORMATTED);

+        replay(session);

+

+        commandHandler.sendReply(session, REPLY_CODE1, null, REPLY_TEXT2, ARGS);

+

+        verify(session);

+    }

+

+    /**

+     * Test the sendReply() method, passing in a null Session

+     */

+    public void testSendReply_NullSession() {

+        try {

+            commandHandler.sendReply(null, REPLY_CODE1, REPLY_TEXT1, null, null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the sendReply() method, passing in an invalid replyCode

+     */

+    public void testSendReply_InvalidReplyCode() {

+        try {

+            commandHandler.sendReply(session, 0, REPLY_TEXT1, null, null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        session = (Session) createMock(Session.class);

+        control(session).setDefaultMatcher(MockControl.ARRAY_MATCHER);

+        commandHandler = new AbstractTrackingCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws Exception {

+            }

+        };

+        ResourceBundle replyTextBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][]{

+                        {Integer.toString(REPLY_CODE1), REPLY_TEXT1},

+                        {Integer.toString(REPLY_CODE2), REPLY_TEXT2},

+                        {MESSAGE_KEY, MESSAGE_TEXT}

+                };

+            }

+        };

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/server/AbstractFtpServerTestCase.java b/tags/2.5/src/test/java/org/mockftpserver/core/server/AbstractFtpServerTestCase.java
new file mode 100644
index 0000000..70e6f9a
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/server/AbstractFtpServerTestCase.java
@@ -0,0 +1,175 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.server;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.CommandHandler;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.session.DefaultSession;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.net.Socket;

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * Abstract superclass for tests of AbstractFtpServer subclasses.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public abstract class AbstractFtpServerTestCase extends AbstractTestCase {

+

+    protected Logger LOG = LoggerFactory.getLogger(getClass());

+

+    protected AbstractFtpServer ftpServer;

+    private CommandHandler commandHandler;

+    private CommandHandler commandHandler2;

+

+    /**

+     * Test the setCommandHandlers() method

+     */

+    public void testSetCommandHandlers() {

+        Map mapping = new HashMap();

+        mapping.put("AAA", commandHandler);

+        mapping.put("BBB", commandHandler2);

+

+        ftpServer.setCommandHandlers(mapping);

+        assertSame("commandHandler1", commandHandler, ftpServer.getCommandHandler("AAA"));

+        assertSame("commandHandler2", commandHandler2, ftpServer.getCommandHandler("BBB"));

+

+        verifyCommandHandlerInitialized(commandHandler);

+        verifyCommandHandlerInitialized(commandHandler2);

+

+        // Make sure default CommandHandlers are still set

+        assertTrue("ConnectCommandHandler", ftpServer.getCommandHandler(CommandNames.CONNECT) != null);

+    }

+

+    /**

+     * Test the setCommandHandlers() method, when the Map is null

+     */

+    public void testSetCommandHandlers_Null() {

+        try {

+            ftpServer.setCommandHandlers(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setCommandHandler() method

+     */

+    public void testSetCommandHandler() {

+        ftpServer.setCommandHandler("ZZZ", commandHandler2);

+        assertSame("commandHandler", commandHandler2, ftpServer.getCommandHandler("ZZZ"));

+        verifyCommandHandlerInitialized(commandHandler2);

+    }

+

+    /**

+     * Test the setCommandHandler() method, when the commandName is null

+     */

+    public void testSetCommandHandler_NullCommandName() {

+        CommandHandler commandHandler = (CommandHandler) createMock(CommandHandler.class);

+        try {

+            ftpServer.setCommandHandler(null, commandHandler);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setCommandHandler() method, when the commandHandler is null

+     */

+    public void testSetCommandHandler_NullCommandHandler() {

+        try {

+            ftpServer.setCommandHandler("ZZZ", null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    public void testSetServerControlPort() {

+        assertEquals("default", 21, ftpServer.getServerControlPort());

+        ftpServer.setServerControlPort(99);

+        assertEquals("99", 99, ftpServer.getServerControlPort());

+    }

+

+    /**

+     * Test the setCommandHandler() and getCommandHandler() methods for commands in lower case or mixed case

+     */

+    public void testLowerCaseOrMixedCaseCommandNames() {

+        ftpServer.setCommandHandler("XXX", commandHandler);

+        assertSame("ZZZ", commandHandler, ftpServer.getCommandHandler("XXX"));

+        assertSame("Zzz", commandHandler, ftpServer.getCommandHandler("Xxx"));

+        assertSame("zzz", commandHandler, ftpServer.getCommandHandler("xxx"));

+

+        ftpServer.setCommandHandler("YyY", commandHandler);

+        assertSame("ZZZ", commandHandler, ftpServer.getCommandHandler("YYY"));

+        assertSame("Zzz", commandHandler, ftpServer.getCommandHandler("Yyy"));

+        assertSame("zzz", commandHandler, ftpServer.getCommandHandler("yyy"));

+

+        ftpServer.setCommandHandler("zzz", commandHandler);

+        assertSame("ZZZ", commandHandler, ftpServer.getCommandHandler("ZZZ"));

+        assertSame("Zzz", commandHandler, ftpServer.getCommandHandler("zzZ"));

+        assertSame("zzz", commandHandler, ftpServer.getCommandHandler("zzz"));

+    }

+

+    /**

+     * Test calling stop() for a server that was never started.

+     */

+    public void testStopWithoutStart() {

+        ftpServer.stop();

+    }

+

+    public void testCreateSession() {

+        assertEquals(ftpServer.createSession(new Socket()).getClass(), DefaultSession.class);

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        ftpServer = createFtpServer();

+

+        commandHandler = createCommandHandler();

+        commandHandler2 = createCommandHandler();

+    }

+

+    //-------------------------------------------------------------------------

+    // Abstract method declarations

+    //-------------------------------------------------------------------------

+

+    protected abstract AbstractFtpServer createFtpServer();

+

+    protected abstract CommandHandler createCommandHandler();

+

+    protected abstract void verifyCommandHandlerInitialized(CommandHandler commandHandler);

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/server/AbstractFtpServer_StartTestCase.java b/tags/2.5/src/test/java/org/mockftpserver/core/server/AbstractFtpServer_StartTestCase.java
new file mode 100644
index 0000000..cc5b346
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/server/AbstractFtpServer_StartTestCase.java
@@ -0,0 +1,87 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.server;

+

+import org.apache.commons.net.ftp.FTPClient;

+import org.mockftpserver.test.*;

+import org.mockftpserver.test.AbstractTestCase;

+

+/**

+ * Abstract superclass for tests of AbstractFtpServer subclasses that require the server thread to be started.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public abstract class AbstractFtpServer_StartTestCase extends AbstractTestCase {

+

+    private static final String SERVER = "localhost";

+

+    private AbstractFtpServer ftpServer;

+

+    /**

+     * Test the start() and stop() methods. Start the server and then stop it immediately.

+     */

+    public void testStartAndStop() throws Exception {

+        ftpServer.setServerControlPort(PortTestUtil.getFtpServerControlPort());

+        assertEquals("started - before", false, ftpServer.isStarted());

+

+        ftpServer.start();

+        Thread.sleep(200L);     // give it some time to get started

+        assertEquals("started - after start()", true, ftpServer.isStarted());

+        assertEquals("shutdown - after start()", false, ftpServer.isShutdown());

+

+        ftpServer.stop();

+

+        assertEquals("shutdown - after stop()", true, ftpServer.isShutdown());

+    }

+

+    /**

+     * Test setting a non-default port number for the StubFtpServer control connection socket.

+     */

+    public void testCustomServerControlPort() throws Exception {

+        final int SERVER_CONTROL_PORT = 9187;

+

+        ftpServer.setServerControlPort(SERVER_CONTROL_PORT);

+        ftpServer.start();

+

+        try {

+            FTPClient ftpClient = new FTPClient();

+            ftpClient.connect(SERVER, SERVER_CONTROL_PORT);

+        }

+        finally {

+            ftpServer.stop();

+        }

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        ftpServer = createFtpServer();

+    }

+

+    //-------------------------------------------------------------------------

+    // Abstract method declarations

+    //-------------------------------------------------------------------------

+

+    protected abstract AbstractFtpServer createFtpServer();

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/session/DefaultSessionTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/session/DefaultSessionTest.java
new file mode 100644
index 0000000..5763e5e
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/session/DefaultSessionTest.java
@@ -0,0 +1,482 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.session;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.MockFtpServerException;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.socket.StubServerSocket;

+import org.mockftpserver.core.socket.StubServerSocketFactory;

+import org.mockftpserver.core.socket.StubSocket;

+import org.mockftpserver.core.socket.StubSocketFactory;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.io.ByteArrayInputStream;

+import java.io.ByteArrayOutputStream;

+import java.io.IOException;

+import java.io.InputStream;

+import java.net.InetAddress;

+import java.net.SocketTimeoutException;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * Tests for the DefaultSession class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class DefaultSessionTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(DefaultSessionTest.class);

+    private static final String DATA = "sample data 123";

+    private static final int PORT = 197;

+    private static final String NAME1 = "name1";

+    private static final String NAME2 = "name2";

+    private static final Object VALUE = "value";

+

+    private DefaultSession session;

+    private ByteArrayOutputStream outputStream;

+    private Map commandHandlerMap;

+    private StubSocket stubSocket;

+    private InetAddress clientHost;

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        commandHandlerMap = new HashMap();

+        outputStream = new ByteArrayOutputStream();

+        session = createDefaultSession("");

+        clientHost = InetAddress.getLocalHost();

+    }

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#tearDown()

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+    }

+

+    /**

+     * Test the Constructor when the control socket is null

+     */

+    public void testConstructor_NullControlSocket() {

+        try {

+            new DefaultSession(null, commandHandlerMap);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the Constructor when the command handler Map is null

+     */

+    public void testConstructor_NullCommandHandlerMap() {

+        try {

+            new DefaultSession(stubSocket, null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setClientDataPort() method

+     */

+    public void testSetClientDataPort() {

+        StubSocket stubSocket = createTestSocket("");

+        StubSocketFactory stubSocketFactory = new StubSocketFactory(stubSocket);

+        session.socketFactory = stubSocketFactory;

+        session.setClientDataPort(PORT);

+        session.setClientDataHost(clientHost);

+        session.openDataConnection();

+        assertEquals("data port", PORT, stubSocketFactory.requestedDataPort);

+    }

+

+    /**

+     * Test the setClientDataPort() method after the session was in passive data mode

+     */

+    public void testSetClientDataPort_AfterPassiveConnectionMode() throws IOException {

+        StubServerSocket stubServerSocket = new StubServerSocket(PORT);

+        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);

+        session.serverSocketFactory = stubServerSocketFactory;

+

+        session.switchToPassiveMode();

+        assertFalse("server socket closed", stubServerSocket.isClosed());

+        assertNotNull("passiveModeDataSocket", session.passiveModeDataSocket);

+        session.setClientDataPort(PORT);

+

+        // Make sure that any passive mode connection info is cleared out

+        assertTrue("server socket closed", stubServerSocket.isClosed());

+        assertNull("passiveModeDataSocket should be null", session.passiveModeDataSocket);

+    }

+

+    /**

+     * Test the setClientHost() method

+     */

+    public void testSetClientHost() throws Exception {

+        StubSocket stubSocket = createTestSocket("");

+        StubSocketFactory stubSocketFactory = new StubSocketFactory(stubSocket);

+        session.socketFactory = stubSocketFactory;

+        session.setClientDataHost(clientHost);

+        session.openDataConnection();

+        assertEquals("client host", clientHost, stubSocketFactory.requestedHost);

+    }

+

+    /**

+     * Test the openDataConnection(), setClientDataPort() and setClientDataHost() methods

+     */

+    public void testOpenDataConnection() {

+        StubSocket stubSocket = createTestSocket("");

+        StubSocketFactory stubSocketFactory = new StubSocketFactory(stubSocket);

+        session.socketFactory = stubSocketFactory;

+

+        // Use default client data port

+        session.setClientDataHost(clientHost);

+        session.openDataConnection();

+        assertEquals("data port", DefaultSession.DEFAULT_CLIENT_DATA_PORT, stubSocketFactory.requestedDataPort);

+        assertEquals("client host", clientHost, stubSocketFactory.requestedHost);

+

+        // Set client data port explicitly

+        session.setClientDataPort(PORT);

+        session.setClientDataHost(clientHost);

+        session.openDataConnection();

+        assertEquals("data port", PORT, stubSocketFactory.requestedDataPort);

+        assertEquals("client host", clientHost, stubSocketFactory.requestedHost);

+    }

+

+    /**

+     * Test the OpenDataConnection method, when in passive mode and no incoming connection is

+     * initiated

+     */

+    public void testOpenDataConnection_PassiveMode_NoConnection() throws IOException {

+

+        StubServerSocket stubServerSocket = new StubServerSocket(PORT);

+        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);

+        session.serverSocketFactory = stubServerSocketFactory;

+

+        session.switchToPassiveMode();

+

+        try {

+            session.openDataConnection();

+            fail("Expected MockFtpServerException");

+        }

+        catch (MockFtpServerException expected) {

+            LOG.info("Expected: " + expected);

+            assertSame("cause", SocketTimeoutException.class, expected.getCause().getClass());

+        }

+    }

+

+    /**

+     * Test the OpenDataConnection method, when the clientHost has not been set

+     */

+    public void testOpenDataConnection_NullClientHost() {

+        try {

+            session.openDataConnection();

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the readData() method

+     */

+    public void testReadData() {

+        StubSocket stubSocket = createTestSocket(DATA);

+        session.socketFactory = new StubSocketFactory(stubSocket);

+        session.setClientDataHost(clientHost);

+

+        session.openDataConnection();

+        byte[] data = session.readData();

+        LOG.info("data=[" + new String(data) + "]");

+        assertEquals("data", DATA.getBytes(), data);

+    }

+

+    /**

+     * Test the readData() method after switching to passive mode

+     */

+    public void testReadData_PassiveMode() throws IOException {

+        StubSocket stubSocket = createTestSocket(DATA);

+        StubServerSocket stubServerSocket = new StubServerSocket(PORT, stubSocket);

+        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);

+        session.serverSocketFactory = stubServerSocketFactory;

+

+        session.switchToPassiveMode();

+        session.openDataConnection();

+        byte[] data = session.readData();

+        LOG.info("data=[" + new String(data) + "]");

+        assertEquals("data", DATA.getBytes(), data);

+    }

+

+    /**

+     * Test the readData(int) method

+     */

+    public void testReadData_NumBytes() {

+        final int NUM_BYTES = 5;

+        final String EXPECTED_DATA = DATA.substring(0, NUM_BYTES);

+        StubSocket stubSocket = createTestSocket(DATA);

+        session.socketFactory = new StubSocketFactory(stubSocket);

+        session.setClientDataHost(clientHost);

+

+        session.openDataConnection();

+        byte[] data = session.readData(NUM_BYTES);

+        LOG.info("data=[" + new String(data) + "]");

+        assertEquals("data", EXPECTED_DATA.getBytes(), data);

+    }

+

+    public void testReadData_NumBytes_AskForMoreBytesThanThereAre() {

+        StubSocket stubSocket = createTestSocket(DATA);

+        session.socketFactory = new StubSocketFactory(stubSocket);

+        session.setClientDataHost(clientHost);

+

+        session.openDataConnection();

+        byte[] data = session.readData(10000);

+        LOG.info("data=[" + new String(data) + "]");

+        assertEquals("data", DATA.getBytes(), data);

+    }

+

+    /**

+     * Test the closeDataConnection() method

+     */

+    public void testCloseDataConnection() {

+        StubSocket stubSocket = createTestSocket(DATA);

+        session.socketFactory = new StubSocketFactory(stubSocket);

+

+        session.setClientDataHost(clientHost);

+        session.openDataConnection();

+        session.closeDataConnection();

+        assertTrue("client data socket should be closed", stubSocket.isClosed());

+    }

+

+    /**

+     * Test the switchToPassiveMode() method

+     */

+    public void testSwitchToPassiveMode() throws IOException {

+        StubServerSocket stubServerSocket = new StubServerSocket(PORT);

+        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);

+        session.serverSocketFactory = stubServerSocketFactory;

+

+        assertNull("passiveModeDataSocket starts out null", session.passiveModeDataSocket);

+        int port = session.switchToPassiveMode();

+        assertSame("passiveModeDataSocket", stubServerSocket, session.passiveModeDataSocket);

+        assertEquals("port", PORT, port);

+    }

+

+    /**

+     * Test the getServerHost() method

+     */

+    public void testGetServerHost() {

+        assertEquals("host", DEFAULT_HOST, session.getServerHost());

+    }

+

+    /**

+     * Test the getClientHost() method when the session is not yet started

+     */

+    public void testGetClientHost_NotRunning() {

+        assertNull("null", session.getClientHost());

+    }

+

+    /**

+     * Test the parseCommand() method

+     */

+    public void testParseCommand() {

+        Command command = session.parseCommand("LIST");

+        assertEquals("command name", "LIST", command.getName());

+        assertEquals("command parameters", EMPTY, command.getParameters());

+

+        command = session.parseCommand("USER user123");

+        assertEquals("command name", "USER", command.getName());

+        assertEquals("command parameters", array("user123"), command.getParameters());

+

+        command = session.parseCommand("PORT 127,0,0,1,17,37");

+        assertEquals("command name", "PORT", command.getName());

+        assertEquals("command parameters", new String[] { "127", "0", "0", "1", "17", "37" }, command

+                .getParameters());

+    }

+

+    /**

+     * Test the parseCommand() method, passing in an empty command String

+     */

+    public void testParseCommand_EmptyCommandString() {

+        try {

+            session.parseCommand("");

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the sendData() method, as well as the openDataConnection() and closeDataConnection()

+     */

+    public void testSendData() {

+        StubSocket stubSocket = createTestSocket("1234567890 abcdef");

+        session.socketFactory = new StubSocketFactory(stubSocket);

+

+        session.setClientDataHost(clientHost);

+        session.openDataConnection();

+        session.sendData(DATA.getBytes(), DATA.length());

+        LOG.info("output=[" + outputStream.toString() + "]");

+        assertEquals("output", DATA, outputStream.toString());

+    }

+

+    /**

+     * Test the SendData() method, passing in a null byte[]

+     */

+    public void testSendData_Null() {

+

+        try {

+            session.sendData(null, 1);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the SendReply(int,String) method, passing in an invalid reply code

+     */

+    public void testSendReply_InvalidReplyCode() {

+

+        try {

+            session.sendReply(-66, "text");

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the getAttribute() and setAttribute() methods 

+     */

+    public void testGetAndSetAttribute() {

+        assertNull("name does not exist yet", session.getAttribute(NAME1));

+        session.setAttribute(NAME1, VALUE);

+        session.setAttribute(NAME2, null);

+        assertEquals("NAME1", VALUE, session.getAttribute(NAME1));

+        assertNull("NAME2", session.getAttribute(NAME2));

+        assertNull("no such name", session.getAttribute("noSuchName"));

+    }

+    

+    /**

+     * Test the getAttribute() method, passing in a null name

+     */

+    public void testGetAttribute_Null() {

+        try {

+            session.getAttribute(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the setAttribute() method, passing in a null name

+     */

+    public void testSetAttribute_NullName() {

+        try {

+            session.setAttribute(null, VALUE);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the removeAttribute() 

+     */

+    public void testRemoveAttribute() {

+        session.removeAttribute("noSuchName");      // do nothing

+        session.setAttribute(NAME1, VALUE);

+        session.removeAttribute(NAME1);

+        assertNull("NAME1", session.getAttribute(NAME1));

+    }

+    

+    /**

+     * Test the removeAttribute() method, passing in a null name

+     */

+    public void testRemoveAttribute_Null() {

+        try {

+            session.removeAttribute(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Test the getAttributeNames() 

+     */

+    public void testGetAttributeNames() {

+        assertEquals("No names yet", Collections.EMPTY_SET, session.getAttributeNames());

+        session.setAttribute(NAME1, VALUE);

+        assertEquals("1", Collections.singleton(NAME1), session.getAttributeNames());

+        session.setAttribute(NAME2, VALUE);

+        assertEquals("2", set(NAME1, NAME2), session.getAttributeNames());

+    }

+    

+    // -------------------------------------------------------------------------

+    // Internal Helper Methods

+    // -------------------------------------------------------------------------

+

+    /**

+     * Create and return a DefaultSession object that reads from an InputStream with the specified

+     * contents and writes to the predefined outputStrean ByteArrayOutputStream. Also, save the

+     * StubSocket being used in the stubSocket attribute.

+     * 

+     * @param inputStreamContents - the contents of the input stream

+     * @return the DefaultSession

+     */

+    private DefaultSession createDefaultSession(String inputStreamContents) {

+        stubSocket = createTestSocket(inputStreamContents);

+        return new DefaultSession(stubSocket, commandHandlerMap);

+    }

+

+    /**

+     * Create and return a StubSocket that reads from an InputStream with the specified contents and

+     * writes to the predefined outputStrean ByteArrayOutputStream.

+     * 

+     * @param inputStreamContents - the contents of the input stream

+     * @return the StubSocket

+     */

+    private StubSocket createTestSocket(String inputStreamContents) {

+        InputStream inputStream = new ByteArrayInputStream(inputStreamContents.getBytes());

+        StubSocket stubSocket = new StubSocket(inputStream, outputStream);

+        stubSocket._setLocalAddress(DEFAULT_HOST);

+        return stubSocket;

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/session/DefaultSession_RunTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/session/DefaultSession_RunTest.java
new file mode 100644
index 0000000..5c64877
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/session/DefaultSession_RunTest.java
@@ -0,0 +1,244 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.session;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandHandler;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ConnectCommandHandler;

+import org.mockftpserver.core.command.InvocationRecord;

+import org.mockftpserver.core.socket.StubSocket;

+import org.mockftpserver.stub.command.AbstractStubCommandHandler;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.io.*;

+import java.util.HashMap;

+import java.util.ListResourceBundle;

+import java.util.Map;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for the DefaultSession class that require the session (thread) to be running/active.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class DefaultSession_RunTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(DefaultSession_RunTest.class);

+    private static final Command COMMAND = new Command("USER", EMPTY);

+    private static final int REPLY_CODE = 100;

+    private static final String REPLY_TEXT = "sample text description";

+

+    private DefaultSession session;

+    private ByteArrayOutputStream outputStream;

+    private Map commandHandlerMap;

+    private StubSocket stubSocket;

+    private boolean commandHandled = false;

+    private String commandToRegister = COMMAND.getName();

+

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandlerMap = new HashMap();

+        outputStream = new ByteArrayOutputStream();

+    }

+

+    public void testInvocationOfCommandHandler() throws Exception {

+        AbstractStubCommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session cmdSession, InvocationRecord invocationRecord) {

+                assertEquals("command", COMMAND, command);

+                assertSame("session", session, cmdSession);

+                assertEquals("InvocationRecord: command", COMMAND, invocationRecord.getCommand());

+                assertEquals("InvocationRecord: clientHost", DEFAULT_HOST, invocationRecord.getClientHost());

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, "");

+    }

+

+    public void testClose() throws Exception {

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                session.close();

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, "");

+        assertFalse("socket should not be closed", stubSocket.isClosed());

+    }

+

+    public void testClose_WithoutCommand() throws Exception {

+        PipedOutputStream pipedOutputStream = new PipedOutputStream();

+        PipedInputStream inputStream = new PipedInputStream(pipedOutputStream);

+        stubSocket = new StubSocket(DEFAULT_HOST, inputStream, outputStream);

+        session = new DefaultSession(stubSocket, commandHandlerMap);

+

+        initializeConnectCommandHandler();

+

+        Thread thread = new Thread(session);

+        thread.start();

+        Thread.sleep(1000L);

+

+        session.close();

+        thread.join();

+    }

+

+    public void testGetClientHost() throws Exception {

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, "");

+        LOG.info("clientHost=" + session.getClientHost());

+        assertEquals("clientHost", DEFAULT_HOST, session.getClientHost());

+    }

+

+    public void testSendReply_NullReplyText() throws Exception {

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                session.sendReply(REPLY_CODE, null);

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, Integer.toString(REPLY_CODE));

+    }

+

+    public void testSendReply_TrimReplyText() throws Exception {

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                session.sendReply(REPLY_CODE, " " + REPLY_TEXT + " ");

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, REPLY_CODE + " " + REPLY_TEXT);

+    }

+

+    public void testSendReply_MultiLineText() throws Exception {

+        final String MULTILINE_REPLY_TEXT = "abc\ndef\nghi\njkl";

+        final String FORMATTED_MULTILINE_REPLY_TEXT = "123-abc\ndef\nghi\n123 jkl";

+

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                session.sendReply(123, MULTILINE_REPLY_TEXT);

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, FORMATTED_MULTILINE_REPLY_TEXT);

+    }

+

+    public void testSendReply_ReplyText() throws Exception {

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                session.sendReply(REPLY_CODE, REPLY_TEXT);

+                commandHandled = true;

+            }

+        };

+        runCommandAndVerifyOutput(commandHandler, REPLY_CODE + " " + REPLY_TEXT);

+    }

+

+    public void testUnrecognizedCommand() throws Exception {

+        // Register a handler for unsupported commands

+        CommandHandler commandHandler = new AbstractStubCommandHandler() {

+            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {

+                session.sendReply(502, "Unsupported");

+                commandHandled = true;

+            }

+        };

+        // Register the UNSUPPORTED command handler instead of the command that will be sent. So when we

+        // send the regular command, it will trigger the handling for unsupported/unrecognized commands.

+        commandToRegister = CommandNames.UNSUPPORTED;

+        runCommandAndVerifyOutput(commandHandler, "502 Unsupported");

+    }

+

+    // -------------------------------------------------------------------------

+    // Internal Helper Methods

+    // -------------------------------------------------------------------------

+

+    /**

+     * Create and return a DefaultSession and define the specified CommandHandler. Also, save the

+     * StubSocket being used in the stubSocket attribute.

+     *

+     * @param commandHandler - define this CommandHandler within the commandHandlerMap

+     * @return the DefaultSession

+     */

+    private DefaultSession createDefaultSession(CommandHandler commandHandler) {

+        stubSocket = createTestSocket(COMMAND.getName());

+        commandHandlerMap.put(commandToRegister, commandHandler);

+        initializeConnectCommandHandler();

+        return new DefaultSession(stubSocket, commandHandlerMap);

+    }

+

+    private void initializeConnectCommandHandler() {

+        ConnectCommandHandler connectCommandHandler = new ConnectCommandHandler();

+

+        ResourceBundle replyTextBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][]{

+                        {"220", "Reply for 220"},

+                };

+            }

+        };

+        connectCommandHandler.setReplyTextBundle(replyTextBundle);

+        commandHandlerMap.put(CommandNames.CONNECT, connectCommandHandler);

+    }

+

+    /**

+     * Create and return a StubSocket that reads from an InputStream with the specified contents and

+     * writes to the predefined outputStrean ByteArrayOutputStream.

+     *

+     * @param inputStreamContents - the contents of the input stream

+     * @return the StubSocket

+     */

+    private StubSocket createTestSocket(String inputStreamContents) {

+        InputStream inputStream = new ByteArrayInputStream(inputStreamContents.getBytes());

+        return new StubSocket(DEFAULT_HOST, inputStream, outputStream);

+    }

+

+    /**

+     * Run the command represented by the CommandHandler and verify that the session output from the

+     * control socket contains the expected output text.

+     *

+     * @param commandHandler - the CommandHandler to invoke

+     * @param expectedOutput - the text expected within the session output

+     * @throws InterruptedException - if the thread sleep is interrupted

+     */

+    private void runCommandAndVerifyOutput(CommandHandler commandHandler, String expectedOutput)

+            throws InterruptedException {

+        session = createDefaultSession(commandHandler);

+

+        Thread thread = new Thread(session);

+        thread.start();

+

+        for (int i = 0; !commandHandled && i < 10; i++) {

+            Thread.sleep(50L);

+        }

+

+        session.close();

+        thread.join();

+

+        assertEquals("commandHandled", true, commandHandled);

+

+        String output = outputStream.toString();

+        LOG.info("output=[" + output.trim() + "]");

+        assertTrue("line ends with \\r\\n",

+                output.charAt(output.length() - 2) == '\r' && output.charAt(output.length() - 1) == '\n');

+        assertTrue("output: expected [" + expectedOutput + "]", output.indexOf(expectedOutput) != -1);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubServerSocket.java b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubServerSocket.java
new file mode 100644
index 0000000..e3a9686
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubServerSocket.java
@@ -0,0 +1,74 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.socket;

+

+import java.io.IOException;

+import java.net.ServerSocket;

+import java.net.Socket;

+import java.net.SocketTimeoutException;

+

+/**

+ * Test (fake) subclass of ServerSocket that performs no network access and allows setting the 

+ * Socket returned by accept(), and the local port for the ServerSocket.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public class StubServerSocket extends ServerSocket {

+    private int localPort;

+    private Socket socket;

+

+    /**

+     * Construct a new instance with the specified local port.

+     * @param localPort - the local port to be returned from getLocalPort()

+     * @throws IOException

+     */

+    public StubServerSocket(int localPort) throws IOException {

+        this(localPort, null);

+    }

+

+    /**

+     * Construct a new instance with specified local port and accept() socket. 

+     * @param localPort - the local port to be returned from getLocalPort()

+     * @param socket - the socket to be returned from accept(); if null, then accept() throws SocketTimeoutException. 

+     * @throws IOException

+     */

+    public StubServerSocket(int localPort, Socket socket) throws IOException {

+        super(0);

+        this.localPort = localPort;

+        this.socket = socket;

+    }

+    

+    /**

+     * Return the predefined local port 

+     * @see java.net.ServerSocket#getLocalPort()

+     */

+    public int getLocalPort() {

+        return localPort;

+    }

+    

+    /**

+     * If a socket was specified on the constructor, then return that; otherwise, throw a SocketTimeoutException. 

+     * @see java.net.ServerSocket#accept()

+     */

+    public Socket accept() throws IOException {

+        if (socket != null) {

+            return socket;

+        }

+        throw new SocketTimeoutException();

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubServerSocketFactory.java b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubServerSocketFactory.java
new file mode 100644
index 0000000..c58caa4
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubServerSocketFactory.java
@@ -0,0 +1,48 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.socket;

+

+import java.io.IOException;

+import java.net.ServerSocket;

+

+/**

+ * Test-only implementation of ServerSocketFactory. It always returns the predefined

+ * ServerSocket instance specified on the constructor.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public class StubServerSocketFactory implements ServerSocketFactory {

+    private StubServerSocket stubServerSocket;

+

+    /**

+     * Construct a new factory instance that always returns the specified

+     * ServerSocket instance. 

+     * @param serverSocket - the ServerSocket instance to be returned by this factory

+     */

+    public StubServerSocketFactory(StubServerSocket serverSocket) {

+        this.stubServerSocket = serverSocket;

+    }

+

+    /**

+     * Return the predefined ServerSocket instance.

+     * @see org.mockftpserver.core.socket.ServerSocketFactory#createServerSocket(int)

+     */

+    public ServerSocket createServerSocket(int port) throws IOException {

+        return stubServerSocket;

+    }

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubSocket.java b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubSocket.java
new file mode 100644
index 0000000..3816bf0
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubSocket.java
@@ -0,0 +1,101 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.socket;

+

+import java.io.IOException;

+import java.io.InputStream;

+import java.io.OutputStream;

+import java.net.InetAddress;

+import java.net.Socket;

+

+/**

+ * Test (fake) subclass of Socket that performs no network access and allows setting the 

+ * inputStream and OutputStream for the socket.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class StubSocket extends Socket {

+

+    private InetAddress inetAddress;

+    private InetAddress localAddress;

+    private InputStream inputStream;

+    private OutputStream outputStream;

+    

+    /**

+     * Construct a new instance using the specified InputStream and OutputStream

+     * @param inputStream - the InputStream to use

+     * @param outputStream - the OutputStream to use

+     */

+    public StubSocket(InputStream inputStream, OutputStream outputStream) {

+        this(null, inputStream, outputStream);

+    }

+    

+    /**

+     * Construct a new instance using the specified host, InputStream and OutputStream

+     * @param inetAddress - the InetAddress for this socket

+     * @param inputStream - the InputStream to use

+     * @param outputStream - the OutputStream to use

+     */

+    public StubSocket(InetAddress inetAddress, InputStream inputStream, OutputStream outputStream) {

+        this.inetAddress = inetAddress;

+        this.inputStream = inputStream;

+        this.outputStream = outputStream;

+    }

+    

+    /**

+     * Override the superclass implementation. If the local inetAddress is not null, 

+     * return that. Otherwise return super.getInetAddress().

+     * @see java.net.Socket#getInetAddress()

+     */

+    public InetAddress getInetAddress() {

+        return (inetAddress != null) ? inetAddress : super.getInetAddress();

+    }

+    

+    /**

+     * Override the superclass implementation. If the local localAddress is not

+     * null, return that. Otherwise return super.getLocalAddress();

+     * @see java.net.Socket#getLocalAddress()

+     */

+    public InetAddress getLocalAddress() {

+        return (localAddress != null) ? localAddress : super.getLocalAddress();

+    }

+    

+    /**

+     * Override the superclass implementation to provide the predefined InputStream

+     * @see java.net.Socket#getInputStream()

+     */

+    public InputStream getInputStream() throws IOException {

+        return inputStream;

+    }

+    

+    /**

+     * Override the superclass implementation to provide the predefined OutputStream

+     * @see java.net.Socket#getOutputStream()

+     */

+    public OutputStream getOutputStream() throws IOException {

+        return outputStream;

+    }

+    

+    //-------------------------------------------------------------------------

+    // Test-specific helper methods

+    //-------------------------------------------------------------------------

+

+    public void _setLocalAddress(InetAddress localAddress) {

+        this.localAddress = localAddress;

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubSocketFactory.java b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubSocketFactory.java
new file mode 100644
index 0000000..724399c
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/socket/StubSocketFactory.java
@@ -0,0 +1,53 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.socket;

+

+import java.io.IOException;

+import java.net.InetAddress;

+import java.net.Socket;

+

+/**

+ * Test-only implementation of SocketFactory. It always returns the predefined

+ * StubSocket instance specified on the constructor. It allows direct access to the

+ * requested host address and port number.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public class StubSocketFactory implements SocketFactory {

+    private StubSocket stubSocket;

+    public int requestedDataPort;

+    public InetAddress requestedHost;

+

+    /**

+     * Create a new instance that always returns the specified StubSocket instance.

+     * @param stubSocket - the StubSocket to be returned by this factory

+     */

+    public StubSocketFactory(StubSocket stubSocket) {

+        this.stubSocket = stubSocket;

+    }

+

+    /**

+     * Return the predefined StubSocket instance

+     * @see org.mockftpserver.core.socket.SocketFactory#createSocket(java.net.InetAddress, int)

+     */

+    public Socket createSocket(InetAddress host, int port) throws IOException {

+        this.requestedHost = host;

+        this.requestedDataPort = port;

+        return stubSocket;

+    }

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/core/util/AssertTest.java b/tags/2.5/src/test/java/org/mockftpserver/core/util/AssertTest.java
new file mode 100644
index 0000000..0cdf72f
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/core/util/AssertTest.java
@@ -0,0 +1,229 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.core.util;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * Tests for the Assert class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public class AssertTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(AssertTest.class);

+

+    /**

+     * This interface defines a generic closure (a generic wrapper for a block of code).

+     */

+    private static interface ExceptionClosure {

+        /**

+         * Execute arbitrary logic that can throw any type of Exception

+         *

+         * @throws Exception

+         */

+        public void execute() throws Exception;

+    }

+

+

+    private static final String MESSAGE = "exception message";

+

+    /**

+     * Test the assertNull() method

+     */

+    public void testAssertNull() {

+

+        Assert.isNull(null, MESSAGE);

+

+        try {

+            Assert.isNull("OK", MESSAGE);

+            fail("Expected IllegalArumentException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+            assertExceptionMessageContains(expected, MESSAGE);

+        }

+    }

+

+

+    /**

+     * Test the assertNotNull() method

+     */

+    public void testAssertNotNull() {

+

+        Assert.notNull("OK", MESSAGE);

+

+        try {

+            Assert.notNull(null, MESSAGE);

+            fail("Expected IllegalArumentException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+            assertExceptionMessageContains(expected, MESSAGE);

+        }

+    }

+

+    /**

+     * Test the assertTrue() method

+     */

+    public void testAssertTrue() throws Exception {

+

+        Assert.isTrue(true, MESSAGE);

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.isTrue(false, MESSAGE);

+            }

+        });

+    }

+

+    /**

+     * Test the assertFalse() method

+     */

+    public void testAssertFalse() throws Exception {

+

+        Assert.isFalse(false, MESSAGE);

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.isFalse(true, MESSAGE);

+            }

+        });

+    }

+

+    /**

+     * Test the assertNotEmpty(Collection,String) method

+     */

+    public void testAssertNotNullOrEmpty_Collection() throws Exception {

+

+        final Collection COLLECTION = Collections.singletonList("item");

+        Assert.notNullOrEmpty(COLLECTION, MESSAGE);

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty((Collection) null, MESSAGE);

+            }

+        });

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty(new ArrayList(), MESSAGE);

+            }

+        });

+    }

+

+    /**

+     * Test the assertNotEmpty(Map,String) method

+     */

+    public void testAssertNotNullOrEmpty_Map() throws Exception {

+

+        final Map MAP = Collections.singletonMap("key", "value");

+        Assert.notNullOrEmpty(MAP, MESSAGE);

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty((Map) null, MESSAGE);

+            }

+        });

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty(new HashMap(), MESSAGE);

+            }

+        });

+    }

+

+    /**

+     * Test the assertNotEmpty(Objecct[],String) method

+     */

+    public void testAssertNotNullOrEmpty_array() throws Exception {

+

+        final Object[] ARRAY = {"1", "2"};

+        Assert.notNullOrEmpty(ARRAY, MESSAGE);

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty((Object[]) null, MESSAGE);

+            }

+        });

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty(new String[]{}, MESSAGE);

+            }

+        });

+    }

+

+    /**

+     * Test the assertNotEmpty(String,String) method

+     */

+    public void testAssertNotNullOrEmpty_String() throws Exception {

+

+        Assert.notNullOrEmpty("OK", MESSAGE);

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty((String) null, MESSAGE);

+            }

+        });

+

+        verifyThrowsAssertFailedException(true, new ExceptionClosure() {

+            public void execute() throws Exception {

+                Assert.notNullOrEmpty("", MESSAGE);

+            }

+        });

+    }

+

+    //-------------------------------------------------------------------------

+    // Helper Methods

+    //-------------------------------------------------------------------------

+

+    private void assertExceptionMessageContains(Throwable exception, String text) {

+        String message = exception.getMessage();

+        assertTrue("Exception message [" + message + "] does not contain [" + text + "]", message.indexOf(text) != -1);

+    }

+

+    /**

+     * Verify that execution of the ExceptionClosure (code block) results in an

+     * AssertFailedException being thrown with the constant MESSAGE as its message.

+     *

+     * @param closure - the ExceptionClosure encapsulating the code to execute

+     */

+    private void verifyThrowsAssertFailedException(boolean checkMessage, ExceptionClosure closure)

+            throws Exception {

+

+        try {

+            closure.execute();

+            fail("Expected IllegalArumentException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+            if (checkMessage) {

+                assertExceptionMessageContains(expected, MESSAGE);

+            }

+		}

+	}

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/fake/example/RemoteFileTest.java b/tags/2.5/src/test/java/org/mockftpserver/fake/example/RemoteFileTest.java
new file mode 100644
index 0000000..8c7e5ea
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/fake/example/RemoteFileTest.java
@@ -0,0 +1,81 @@
+/*

+ * Copyright 2008 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.fake.example;

+

+import org.mockftpserver.fake.FakeFtpServer;

+import org.mockftpserver.fake.UserAccount;

+import org.mockftpserver.fake.filesystem.FileEntry;

+import org.mockftpserver.fake.filesystem.FileSystem;

+import org.mockftpserver.fake.filesystem.UnixFakeFileSystem;

+import org.mockftpserver.stub.example.RemoteFile;

+import org.mockftpserver.test.*;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.io.IOException;

+

+/**

+ * Example test using FakeFtpServer, with programmatic configuration.

+ */

+public class RemoteFileTest extends AbstractTestCase implements IntegrationTest {

+

+    private static final String HOME_DIR = "/";

+    private static final String FILE = "/dir/sample.txt";

+    private static final String CONTENTS = "abcdef 1234567890";

+

+    private RemoteFile remoteFile;

+    private FakeFtpServer fakeFtpServer;

+

+    public void testReadFile() throws Exception {

+        String contents = remoteFile.readFile(FILE);

+        assertEquals("contents", CONTENTS, contents);

+    }

+

+    public void testReadFileThrowsException() {

+        try {

+            remoteFile.readFile("NoSuchFile.txt");

+            fail("Expected IOException");

+        }

+        catch (IOException expected) {

+            // Expected this

+        }

+    }

+

+    protected void setUp() throws Exception {

+        super.setUp();

+        fakeFtpServer = new FakeFtpServer();

+        fakeFtpServer.setServerControlPort(0);  // use any free port

+

+        FileSystem fileSystem = new UnixFakeFileSystem();

+        fileSystem.add(new FileEntry(FILE, CONTENTS));

+        fakeFtpServer.setFileSystem(fileSystem);

+

+        UserAccount userAccount = new UserAccount(RemoteFile.USERNAME, RemoteFile.PASSWORD, HOME_DIR);

+        fakeFtpServer.addUserAccount(userAccount);

+

+        fakeFtpServer.start();

+        int port = fakeFtpServer.getServerControlPort();

+

+        remoteFile = new RemoteFile();

+        remoteFile.setServer("localhost");

+        remoteFile.setPort(port);

+    }

+

+    protected void tearDown() throws Exception {

+        super.tearDown();

+        fakeFtpServer.stop();

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/fake/example/SimpleUnixFakeFtpServerTest.java b/tags/2.5/src/test/java/org/mockftpserver/fake/example/SimpleUnixFakeFtpServerTest.java
new file mode 100644
index 0000000..5f04957
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/fake/example/SimpleUnixFakeFtpServerTest.java
@@ -0,0 +1,49 @@
+/*

+ * Copyright 2008 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.fake.example;

+

+import org.mockftpserver.fake.FakeFtpServer;

+import org.mockftpserver.fake.UserAccount;

+import org.mockftpserver.fake.filesystem.DirectoryEntry;

+import org.mockftpserver.fake.filesystem.FileEntry;

+import org.mockftpserver.fake.filesystem.FileSystem;

+import org.mockftpserver.fake.filesystem.UnixFakeFileSystem;

+import org.mockftpserver.test.AbstractTestCase;

+import org.mockftpserver.test.IntegrationTest;

+

+/**

+ * Example code illustrating how to programmatically configure a FakeFtpServer with a (simulated) Unix

+ * filesystem.

+ */

+public class SimpleUnixFakeFtpServerTest extends AbstractTestCase implements IntegrationTest {

+

+    public void testConfigureAndStart() throws Exception {

+        FakeFtpServer fakeFtpServer = new FakeFtpServer();

+        fakeFtpServer.setServerControlPort(9981);

+        fakeFtpServer.addUserAccount(new UserAccount("user", "password", "c:\\data"));

+

+        FileSystem fileSystem = new UnixFakeFileSystem();

+        fileSystem.add(new DirectoryEntry("/data"));

+        fileSystem.add(new FileEntry("/data/file1.txt", "abcdef 1234567890"));

+        fileSystem.add(new FileEntry("/data/run.exe"));

+        fakeFtpServer.setFileSystem(fileSystem);

+

+        fakeFtpServer.start();

+

+        fakeFtpServer.stop();

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/fake/example/SimpleWindowsFakeFtpServerTest.java b/tags/2.5/src/test/java/org/mockftpserver/fake/example/SimpleWindowsFakeFtpServerTest.java
new file mode 100644
index 0000000..e1a595f
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/fake/example/SimpleWindowsFakeFtpServerTest.java
@@ -0,0 +1,49 @@
+/*

+ * Copyright 2008 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.fake.example;

+

+import org.mockftpserver.fake.FakeFtpServer;

+import org.mockftpserver.fake.UserAccount;

+import org.mockftpserver.fake.filesystem.DirectoryEntry;

+import org.mockftpserver.fake.filesystem.FileEntry;

+import org.mockftpserver.fake.filesystem.FileSystem;

+import org.mockftpserver.fake.filesystem.WindowsFakeFileSystem;

+import org.mockftpserver.test.*;

+import org.mockftpserver.test.AbstractTestCase;

+

+/**

+ * Example code illustrating how to programmatically configure a FakeFtpServer with a (simulated) Windows

+ * filesystem.

+ */

+public class SimpleWindowsFakeFtpServerTest extends AbstractTestCase implements IntegrationTest {

+

+    public void testConfigureAndStart() throws Exception {

+        FakeFtpServer fakeFtpServer = new FakeFtpServer();

+        fakeFtpServer.setServerControlPort(9981);

+        fakeFtpServer.addUserAccount(new UserAccount("user", "password", "c:\\data"));

+

+        FileSystem fileSystem = new WindowsFakeFileSystem();

+        fileSystem.add(new DirectoryEntry("c:\\data"));

+        fileSystem.add(new FileEntry("c:\\data\\file1.txt", "abcdef 1234567890"));

+        fileSystem.add(new FileEntry("c:\\data\\run.exe"));

+        fakeFtpServer.setFileSystem(fileSystem);

+

+        fakeFtpServer.start();

+

+        fakeFtpServer.stop();

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/fake/example/WindowsFakeFileSystemPermissionsTest.java b/tags/2.5/src/test/java/org/mockftpserver/fake/example/WindowsFakeFileSystemPermissionsTest.java
new file mode 100644
index 0000000..54630d9
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/fake/example/WindowsFakeFileSystemPermissionsTest.java
@@ -0,0 +1,76 @@
+/*

+ * Copyright 2008 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.fake.example;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.fake.FakeFtpServer;

+import org.mockftpserver.fake.filesystem.DirectoryEntry;

+import org.mockftpserver.fake.filesystem.FileEntry;

+import org.mockftpserver.fake.filesystem.FileSystem;

+import org.mockftpserver.fake.filesystem.Permissions;

+import org.mockftpserver.fake.filesystem.WindowsFakeFileSystem;

+import org.mockftpserver.test.*;

+import org.mockftpserver.test.AbstractTestCase;

+

+/**

+ * Example code illustrating how to programmatically configure a FakeFtpServer with a (simulated) Windows

+ * filesystem, and including file/directory permissions.

+ */

+public class WindowsFakeFileSystemPermissionsTest extends AbstractTestCase implements IntegrationTest {

+

+    private static final Logger LOG = LoggerFactory.getLogger(WindowsFakeFileSystemPermissionsTest.class);

+

+    public void testFilesystemWithPermissions() throws Exception {

+

+        final String USER1 = "joe";

+        final String USER2 = "mary";

+        final String GROUP = "dev";

+        final String CONTENTS = "abcdef 1234567890";

+

+        FileSystem fileSystem = new WindowsFakeFileSystem();

+        DirectoryEntry directoryEntry1 = new DirectoryEntry("c:\\");

+        directoryEntry1.setPermissions(new Permissions("rwxrwx---"));

+        directoryEntry1.setOwner(USER1);

+        directoryEntry1.setGroup(GROUP);

+

+        DirectoryEntry directoryEntry2 = new DirectoryEntry("c:\\data");

+        directoryEntry2.setPermissions(Permissions.ALL);

+        directoryEntry2.setOwner(USER1);

+        directoryEntry2.setGroup(GROUP);

+

+        FileEntry fileEntry1 = new FileEntry("c:\\data\\file1.txt", CONTENTS);

+        fileEntry1.setPermissionsFromString("rw-rw-rw-");

+        fileEntry1.setOwner(USER1);

+        fileEntry1.setGroup(GROUP);

+

+        FileEntry fileEntry2 = new FileEntry("c:\\data\\run.exe");

+        fileEntry2.setPermissionsFromString("rwxrwx---");

+        fileEntry2.setOwner(USER2);

+        fileEntry2.setGroup(GROUP);

+

+        fileSystem.add(directoryEntry1);

+        fileSystem.add(directoryEntry2);

+        fileSystem.add(fileEntry1);

+        fileSystem.add(fileEntry2);

+

+        FakeFtpServer fakeFtpServer = new FakeFtpServer();

+        fakeFtpServer.setFileSystem(fileSystem);

+

+        LOG.info(fileSystem.toString());

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServerIntegrationTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServerIntegrationTest.java
new file mode 100644
index 0000000..2949a14
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServerIntegrationTest.java
@@ -0,0 +1,591 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub;

+

+import org.apache.commons.net.ftp.FTP;

+import org.apache.commons.net.ftp.FTPClient;

+import org.apache.commons.net.ftp.FTPFile;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.CommandHandler;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.InvocationRecord;

+import org.mockftpserver.core.command.SimpleCompositeCommandHandler;

+import org.mockftpserver.core.command.StaticReplyCommandHandler;

+import org.mockftpserver.stub.command.*;

+import org.mockftpserver.test.*;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.io.ByteArrayInputStream;

+import java.io.ByteArrayOutputStream;

+import java.io.IOException;

+

+/**

+ * Tests for StubFtpServer using the Apache Jakarta Commons Net FTP client.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class StubFtpServerIntegrationTest extends AbstractTestCase implements IntegrationTest {

+

+    private static final Logger LOG = LoggerFactory.getLogger(StubFtpServerIntegrationTest.class);

+    private static final String SERVER = "localhost";

+    private static final String USERNAME = "user123";

+    private static final String PASSWORD = "password";

+    private static final String FILENAME = "abc.txt";

+    private static final String ASCII_CONTENTS = "abcdef\tghijklmnopqr";

+    private static final byte[] BINARY_CONTENTS = new byte[256];

+

+    private StubFtpServer stubFtpServer;

+    private FTPClient ftpClient;

+    private RetrCommandHandler retrCommandHandler;

+    private StorCommandHandler storCommandHandler;

+

+    //-------------------------------------------------------------------------

+    // Tests

+    //-------------------------------------------------------------------------

+

+    public void testLogin() throws Exception {

+        // Connect

+        LOG.info("Conecting to " + SERVER);

+        ftpClientConnect();

+        verifyReplyCode("connect", 220);

+

+        // Login

+        String userAndPassword = USERNAME + "/" + PASSWORD;

+        LOG.info("Logging in as " + userAndPassword);

+        boolean success = ftpClient.login(USERNAME, PASSWORD);

+        assertTrue("Unable to login with " + userAndPassword, success);

+        verifyReplyCode("login with " + userAndPassword, 230);

+

+        assertTrue("isStarted", stubFtpServer.isStarted());

+        assertFalse("isShutdown", stubFtpServer.isShutdown());

+

+        // Quit

+        LOG.info("Quit");

+        ftpClient.quit();

+        verifyReplyCode("quit", 221);

+    }

+

+    public void testAcct() throws Exception {

+        ftpClientConnect();

+

+        // ACCT

+        int replyCode = ftpClient.acct("123456");

+        assertEquals("acct", 230, replyCode);

+    }

+

+    /**

+     * Test the stop() method when no session has ever been started

+     */

+    public void testStop_NoSessionEverStarted() throws Exception {

+        LOG.info("Testing a stop() when no session has ever been started");

+    }

+

+    public void testHelp() throws Exception {

+        // Modify HELP CommandHandler to return a predefined help message

+        final String HELP = "help message";

+        HelpCommandHandler helpCommandHandler = (HelpCommandHandler) stubFtpServer.getCommandHandler(CommandNames.HELP);

+        helpCommandHandler.setHelpMessage(HELP);

+

+        ftpClientConnect();

+

+        // HELP

+        String help = ftpClient.listHelp();

+        assertTrue("Wrong response", help.indexOf(HELP) != -1);

+        verifyReplyCode("listHelp", 214);

+    }

+

+    /**

+     * Test the LIST and SYST commands.

+     */

+    public void testList() throws Exception {

+        ftpClientConnect();

+

+        // Set directory listing

+        ListCommandHandler listCommandHandler = (ListCommandHandler) stubFtpServer.getCommandHandler(CommandNames.LIST);

+        listCommandHandler.setDirectoryListing("11-09-01 12:30PM  406348 File2350.log\n"

+                + "11-01-01 1:30PM <DIR>  archive");

+

+        // LIST

+        FTPFile[] files = ftpClient.listFiles();

+        assertEquals("number of files", 2, files.length);

+        verifyFTPFile(files[0], FTPFile.FILE_TYPE, "File2350.log", 406348L);

+        verifyFTPFile(files[1], FTPFile.DIRECTORY_TYPE, "archive", 0L);

+        verifyReplyCode("list", 226);

+    }

+

+    /**

+     * Test the LIST, PASV and SYST commands, transferring a directory listing in passive mode

+     */

+    public void testList_PassiveMode() throws Exception {

+        ftpClientConnect();

+

+        ftpClient.enterLocalPassiveMode();

+

+        // Set directory listing

+        ListCommandHandler listCommandHandler = (ListCommandHandler) stubFtpServer.getCommandHandler(CommandNames.LIST);

+        listCommandHandler.setDirectoryListing("11-09-01 12:30PM  406348 File2350.log");

+

+        // LIST

+        FTPFile[] files = ftpClient.listFiles();

+        assertEquals("number of files", 1, files.length);

+        verifyReplyCode("list", 226);

+    }

+

+    public void testNlst() throws Exception {

+        ftpClientConnect();

+

+        // Set directory listing

+        NlstCommandHandler nlstCommandHandler = (NlstCommandHandler) stubFtpServer.getCommandHandler(CommandNames.NLST);

+        nlstCommandHandler.setDirectoryListing("File1.txt\nfile2.data");

+

+        // NLST

+        String[] filenames = ftpClient.listNames();

+        assertEquals("number of files", 2, filenames.length);

+        assertEquals(filenames[0], "File1.txt");

+        assertEquals(filenames[1], "file2.data");

+        verifyReplyCode("listNames", 226);

+    }

+

+    /**

+     * Test printing the current working directory (PWD)

+     */

+    public void testPwd() throws Exception {

+        // Modify PWD CommandHandler to return a predefined directory

+        final String DIR = "some/dir";

+        PwdCommandHandler pwdCommandHandler = (PwdCommandHandler) stubFtpServer.getCommandHandler(CommandNames.PWD);

+        pwdCommandHandler.setDirectory(DIR);

+

+        ftpClientConnect();

+

+        // PWD

+        String dir = ftpClient.printWorkingDirectory();

+        assertEquals("Unable to PWD", DIR, dir);

+        verifyReplyCode("printWorkingDirectory", 257);

+    }

+

+    public void testStat() throws Exception {

+        // Modify Stat CommandHandler to return predefined text

+        final String STATUS = "some information 123";

+        StatCommandHandler statCommandHandler = (StatCommandHandler) stubFtpServer.getCommandHandler(CommandNames.STAT);

+        statCommandHandler.setStatus(STATUS);

+

+        ftpClientConnect();

+

+        // STAT

+        String status = ftpClient.getStatus();

+        assertEquals("STAT reply", "211 " + STATUS + ".", status.trim());

+        verifyReplyCode("getStatus", 211);

+    }

+

+    /**

+     * Test getting the status (STAT), when the reply text contains multiple lines

+     */

+    public void testStat_MultilineReplyText() throws Exception {

+        // Modify Stat CommandHandler to return predefined text

+        final String STATUS = "System name: abc.def\nVersion 3.5.7\nNumber of failed logins: 2";

+        final String FORMATTED_REPLY_STATUS = "211-System name: abc.def\r\nVersion 3.5.7\r\n211 Number of failed logins: 2.";

+        StatCommandHandler statCommandHandler = (StatCommandHandler) stubFtpServer.getCommandHandler(CommandNames.STAT);

+        statCommandHandler.setStatus(STATUS);

+

+        ftpClientConnect();

+

+        // STAT

+        String status = ftpClient.getStatus();

+        assertEquals("STAT reply", FORMATTED_REPLY_STATUS, status.trim());

+        verifyReplyCode("getStatus", 211);

+    }

+

+    public void testSyst() throws Exception {

+        ftpClientConnect();

+

+        // SYST

+        assertEquals("getSystemName()", "\"WINDOWS\" system type.", ftpClient.getSystemName());

+        verifyReplyCode("syst", 215);

+    }

+

+    public void testCwd() throws Exception {

+        // Connect

+        LOG.info("Conecting to " + SERVER);

+        ftpClientConnect();

+        verifyReplyCode("connect", 220);

+

+        // CWD

+        boolean success = ftpClient.changeWorkingDirectory("dir1/dir2");

+        assertTrue("Unable to CWD", success);

+        verifyReplyCode("changeWorkingDirectory", 250);

+    }

+

+    /**

+     * Test changing the current working directory (CWD), when it causes a remote error

+     */

+    public void testCwd_Error() throws Exception {

+        // Override CWD CommandHandler to return error reply code

+        final int REPLY_CODE = 500;

+        StaticReplyCommandHandler cwdCommandHandler = new StaticReplyCommandHandler(REPLY_CODE);

+        stubFtpServer.setCommandHandler("CWD", cwdCommandHandler);

+

+        ftpClientConnect();

+

+        // CWD

+        boolean success = ftpClient.changeWorkingDirectory("dir1/dir2");

+        assertFalse("Expected failure", success);

+        verifyReplyCode("changeWorkingDirectory", REPLY_CODE);

+    }

+

+    public void testCdup() throws Exception {

+        ftpClientConnect();

+

+        // CDUP

+        boolean success = ftpClient.changeToParentDirectory();

+        assertTrue("Unable to CDUP", success);

+        verifyReplyCode("changeToParentDirectory", 200);

+    }

+

+    public void testDele() throws Exception {

+        ftpClientConnect();

+

+        // DELE

+        boolean success = ftpClient.deleteFile(FILENAME);

+        assertTrue("Unable to DELE", success);

+        verifyReplyCode("deleteFile", 250);

+    }

+

+    public void testEprt() throws Exception {

+        LOG.info("Skipping...");

+//        ftpClientConnect();

+//        ftpClient.sendCommand("EPRT", "|2|1080::8:800:200C:417A|5282|");

+//        verifyReplyCode("EPRT", 200);

+    }

+

+    public void testEpsv() throws Exception {

+        ftpClientConnect();

+        ftpClient.sendCommand("EPSV");

+        verifyReplyCode("EPSV", 229);

+    }

+    

+    public void testFeat_UseStaticReplyCommandHandler() throws IOException {

+        // The FEAT command is not supported out of the box

+        final String FEAT_TEXT = "Extensions supported:\n" +

+                "MLST size*;create;modify*;perm;media-type\n" +

+                "SIZE\n" +

+                "COMPRESSION\n" +

+                "END";

+        StaticReplyCommandHandler featCommandHandler = new StaticReplyCommandHandler(211, FEAT_TEXT);

+        stubFtpServer.setCommandHandler("FEAT", featCommandHandler);

+

+        ftpClientConnect();

+        assertEquals(ftpClient.sendCommand("FEAT"), 211);

+        LOG.info(ftpClient.getReplyString());

+    }

+

+    public void testMkd() throws Exception {

+        ftpClientConnect();

+

+        // MKD

+        boolean success = ftpClient.makeDirectory("dir1/dir2");

+        assertTrue("Unable to CWD", success);

+        verifyReplyCode("makeDirectory", 257);

+    }

+

+    public void testNoop() throws Exception {

+        ftpClientConnect();

+

+        // NOOP

+        boolean success = ftpClient.sendNoOp();

+        assertTrue("Unable to NOOP", success);

+        verifyReplyCode("NOOP", 200);

+    }

+

+    public void testRest() throws Exception {

+        ftpClientConnect();

+

+        // REST

+        int replyCode = ftpClient.rest("marker");

+        assertEquals("Unable to REST", 350, replyCode);

+    }

+

+    public void testRmd() throws Exception {

+        ftpClientConnect();

+

+        // RMD

+        boolean success = ftpClient.removeDirectory("dir1/dir2");

+        assertTrue("Unable to RMD", success);

+        verifyReplyCode("removeDirectory", 250);

+    }

+

+    public void testRename() throws Exception {

+        ftpClientConnect();

+

+        // Rename (RNFR, RNTO)

+        boolean success = ftpClient.rename(FILENAME, "new_" + FILENAME);

+        assertTrue("Unable to RENAME", success);

+        verifyReplyCode("rename", 250);

+    }

+

+    public void testAllo() throws Exception {

+        ftpClientConnect();

+

+        // ALLO

+        assertTrue("ALLO", ftpClient.allocate(1024));

+        assertTrue("ALLO with recordSize", ftpClient.allocate(1024, 64));

+    }

+

+    /**

+     * Test GET and PUT of ASCII files

+     */

+    public void testTransferAsciiFile() throws Exception {

+        retrCommandHandler.setFileContents(ASCII_CONTENTS);

+

+        ftpClientConnect();

+

+        // Get File

+        LOG.info("Get File for remotePath [" + FILENAME + "]");

+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

+        assertTrue(ftpClient.retrieveFile(FILENAME, outputStream));

+        LOG.info("File contents=[" + outputStream.toString());

+        assertEquals("File contents", ASCII_CONTENTS, outputStream.toString());

+

+        // Put File

+        LOG.info("Put File for local path [" + FILENAME + "]");

+        ByteArrayInputStream inputStream = new ByteArrayInputStream(ASCII_CONTENTS.getBytes());

+        assertTrue(ftpClient.storeFile(FILENAME, inputStream));

+        InvocationRecord invocationRecord = storCommandHandler.getInvocation(0);

+        byte[] contents = (byte[]) invocationRecord.getObject(StorCommandHandler.FILE_CONTENTS_KEY);

+        LOG.info("File contents=[" + contents + "]");

+        assertEquals("File contents", ASCII_CONTENTS.getBytes(), contents);

+    }

+

+    /**

+     * Test GET and PUT of binary files

+     */

+    public void testTransferBinaryFiles() throws Exception {

+        retrCommandHandler.setFileContents(BINARY_CONTENTS);

+

+        ftpClientConnect();

+        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

+

+        // Get File

+        LOG.info("Get File for remotePath [" + FILENAME + "]");

+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

+        assertTrue("GET", ftpClient.retrieveFile(FILENAME, outputStream));

+        LOG.info("GET File length=" + outputStream.size());

+        assertEquals("File contents", BINARY_CONTENTS, outputStream.toByteArray());

+

+        // Put File

+        LOG.info("Put File for local path [" + FILENAME + "]");

+        ByteArrayInputStream inputStream = new ByteArrayInputStream(BINARY_CONTENTS);

+        assertTrue("PUT", ftpClient.storeFile(FILENAME, inputStream));

+        InvocationRecord invocationRecord = storCommandHandler.getInvocation(0);

+        byte[] contents = (byte[]) invocationRecord.getObject(StorCommandHandler.FILE_CONTENTS_KEY);

+        LOG.info("PUT File length=" + contents.length);

+        assertEquals("File contents", BINARY_CONTENTS, contents);

+    }

+

+    public void testStou() throws Exception {

+        StouCommandHandler stouCommandHandler = (StouCommandHandler) stubFtpServer.getCommandHandler(CommandNames.STOU);

+        stouCommandHandler.setFilename(FILENAME);

+

+        ftpClientConnect();

+

+        // Stor a File (STOU)

+        ByteArrayInputStream inputStream = new ByteArrayInputStream(ASCII_CONTENTS.getBytes());

+        assertTrue(ftpClient.storeUniqueFile(FILENAME, inputStream));

+        InvocationRecord invocationRecord = stouCommandHandler.getInvocation(0);

+        byte[] contents = (byte[]) invocationRecord.getObject(StorCommandHandler.FILE_CONTENTS_KEY);

+        LOG.info("File contents=[" + contents + "]");

+        assertEquals("File contents", ASCII_CONTENTS.getBytes(), contents);

+    }

+

+    public void testAppe() throws Exception {

+        AppeCommandHandler appeCommandHandler = (AppeCommandHandler) stubFtpServer.getCommandHandler(CommandNames.APPE);

+

+        ftpClientConnect();

+

+        // Append a File (APPE)

+        ByteArrayInputStream inputStream = new ByteArrayInputStream(ASCII_CONTENTS.getBytes());

+        assertTrue(ftpClient.appendFile(FILENAME, inputStream));

+        InvocationRecord invocationRecord = appeCommandHandler.getInvocation(0);

+        byte[] contents = (byte[]) invocationRecord.getObject(AppeCommandHandler.FILE_CONTENTS_KEY);

+        LOG.info("File contents=[" + contents + "]");

+        assertEquals("File contents", ASCII_CONTENTS.getBytes(), contents);

+    }

+

+    public void testAbor() throws Exception {

+        ftpClientConnect();

+

+        // ABOR

+        assertTrue("ABOR", ftpClient.abort());

+    }

+

+    public void testPasv() throws Exception {

+        ftpClientConnect();

+

+        // PASV

+        ftpClient.enterLocalPassiveMode();

+        // no reply code; the PASV command is sent only when the data connection is opened 

+    }

+

+    public void testMode() throws Exception {

+        ftpClientConnect();

+

+        // MODE

+        boolean success = ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);

+        assertTrue("Unable to MODE", success);

+        verifyReplyCode("setFileTransferMode", 200);

+    }

+

+    public void testStru() throws Exception {

+        ftpClientConnect();

+

+        // STRU

+        boolean success = ftpClient.setFileStructure(FTP.FILE_STRUCTURE);

+        assertTrue("Unable to STRU", success);

+        verifyReplyCode("setFileStructure", 200);

+    }

+

+    public void testSimpleCompositeCommandHandler() throws Exception {

+        // Replace CWD CommandHandler with a SimpleCompositeCommandHandler

+        CommandHandler commandHandler1 = new StaticReplyCommandHandler(500);

+        CommandHandler commandHandler2 = new CwdCommandHandler();

+        SimpleCompositeCommandHandler simpleCompositeCommandHandler = new SimpleCompositeCommandHandler();

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler1);

+        simpleCompositeCommandHandler.addCommandHandler(commandHandler2);

+        stubFtpServer.setCommandHandler("CWD", simpleCompositeCommandHandler);

+

+        // Connect

+        ftpClientConnect();

+

+        // CWD

+        assertFalse("first", ftpClient.changeWorkingDirectory("dir1/dir2"));

+        assertTrue("first", ftpClient.changeWorkingDirectory("dir1/dir2"));

+    }

+

+    public void testSite() throws Exception {

+        ftpClientConnect();

+

+        // SITE

+        int replyCode = ftpClient.site("parameters,1,2,3");

+        assertEquals("SITE", 200, replyCode);

+    }

+

+    public void testSmnt() throws Exception {

+        ftpClientConnect();

+

+        // SMNT

+        assertTrue("SMNT", ftpClient.structureMount("dir1/dir2"));

+        verifyReplyCode("structureMount", 250);

+    }

+

+    public void testRein() throws Exception {

+        ftpClientConnect();

+

+        // REIN

+        assertEquals("REIN", 220, ftpClient.rein());

+    }

+

+    /**

+     * Test that command names in lowercase or mixed upper/lower case are accepted

+     */

+    public void testCommandNamesInLowerOrMixedCase() throws Exception {

+        ftpClientConnect();

+

+        assertEquals("rein", 220, ftpClient.sendCommand("rein"));

+        assertEquals("rEIn", 220, ftpClient.sendCommand("rEIn"));

+        assertEquals("reiN", 220, ftpClient.sendCommand("reiN"));

+        assertEquals("Rein", 220, ftpClient.sendCommand("Rein"));

+    }

+

+    public void testUnrecognizedCommand() throws Exception {

+        ftpClientConnect();

+

+        assertEquals("Unrecognized:XXXX", 502, ftpClient.sendCommand("XXXX"));

+    }

+

+    // -------------------------------------------------------------------------

+    // Test setup and tear-down

+    // -------------------------------------------------------------------------

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        for (int i = 0; i < BINARY_CONTENTS.length; i++) {

+            BINARY_CONTENTS[i] = (byte) i;

+        }

+

+        stubFtpServer = new StubFtpServer();

+        stubFtpServer.setServerControlPort(PortTestUtil.getFtpServerControlPort());

+        stubFtpServer.start();

+        ftpClient = new FTPClient();

+        retrCommandHandler = (RetrCommandHandler) stubFtpServer.getCommandHandler(CommandNames.RETR);

+        storCommandHandler = (StorCommandHandler) stubFtpServer.getCommandHandler(CommandNames.STOR);

+    }

+

+    /**

+     * Perform cleanup after each test

+     *

+     * @see org.mockftpserver.test.AbstractTestCase#tearDown()

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+        stubFtpServer.stop();

+    }

+

+    // -------------------------------------------------------------------------

+    // Internal Helper Methods

+    // -------------------------------------------------------------------------

+

+    /**

+     * Connect to the server from the FTPClient

+     */

+    private void ftpClientConnect() throws IOException {

+        ftpClient.connect(SERVER, PortTestUtil.getFtpServerControlPort());

+    }

+

+    /**

+     * Assert that the FtpClient reply code is equal to the expected value

+     *

+     * @param operation         - the description of the operation performed; used in the error message

+     * @param expectedReplyCode - the expected FtpClient reply code

+     */

+    private void verifyReplyCode(String operation, int expectedReplyCode) {

+        int replyCode = ftpClient.getReplyCode();

+        LOG.info("Reply: operation=\"" + operation + "\" replyCode=" + replyCode);

+        assertEquals("Unexpected replyCode for " + operation, expectedReplyCode, replyCode);

+    }

+

+    /**

+     * Verify that the FTPFile has the specified properties

+     *

+     * @param ftpFile - the FTPFile to verify

+     * @param type    - the expected file type

+     * @param name    - the expected file name

+     * @param size    - the expected file size (will be zero for a directory)

+     */

+    private void verifyFTPFile(FTPFile ftpFile, int type, String name, long size) {

+        LOG.info(ftpFile.toString());

+        assertEquals("type: " + ftpFile, type, ftpFile.getType());

+        assertEquals("name: " + ftpFile, name, ftpFile.getName());

+        assertEquals("size: " + ftpFile, size, ftpFile.getSize());

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServerTest.java
new file mode 100644
index 0000000..797d806
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServerTest.java
@@ -0,0 +1,122 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub;

+

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandHandler;

+import org.mockftpserver.core.command.InvocationRecord;

+import org.mockftpserver.core.server.*;

+import org.mockftpserver.core.server.AbstractFtpServerTestCase;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.stub.command.AbstractStubCommandHandler;

+import org.mockftpserver.stub.command.CwdCommandHandler;

+

+import java.util.ResourceBundle;

+

+/**

+ * Unit tests for StubFtpServer. Also see {@link StubFtpServer_StartTest}

+ * and {@link StubFtpServerIntegrationTest}.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class StubFtpServerTest extends AbstractFtpServerTestCase {

+

+    private StubFtpServer stubFtpServer;

+    private AbstractStubCommandHandler commandHandler;

+    private CommandHandler commandHandler_NoReplyTextBundle;

+

+    //-------------------------------------------------------------------------

+    // Extra tests  (Standard tests defined in superclass)

+    //-------------------------------------------------------------------------

+

+    /**

+     * Test the setCommandHandler() method, for a CommandHandler that does not implement ResourceBundleAware

+     */

+    public void testSetCommandHandler_NotReplyTextBundleAware() {

+        stubFtpServer.setCommandHandler("ZZZ", commandHandler_NoReplyTextBundle);

+        assertSame("commandHandler", commandHandler_NoReplyTextBundle, stubFtpServer.getCommandHandler("ZZZ"));

+    }

+

+    /**

+     * Test the setCommandHandler() method, for a CommandHandler that implements ReplyTextBundleAware,

+     * and whose replyTextBundle attribute is null.

+     */

+    public void testSetCommandHandler_NullReplyTextBundle() {

+        stubFtpServer.setCommandHandler("ZZZ", commandHandler);

+        assertSame("commandHandler", commandHandler, stubFtpServer.getCommandHandler("ZZZ"));

+        assertSame("replyTextBundle", stubFtpServer.getReplyTextBundle(), commandHandler.getReplyTextBundle());

+    }

+

+    /**

+     * Test setReplyTextBaseName() method

+     */

+    public void testSetReplyTextBaseName() {

+        stubFtpServer.setReplyTextBaseName("SampleReplyText");

+        CwdCommandHandler commandHandler = new CwdCommandHandler();

+

+        // The resource bundle is passed along to new CommandHandlers (if they don't already have one) 

+        stubFtpServer.setCommandHandler("CWD", commandHandler);

+        ResourceBundle resourceBundle = commandHandler.getReplyTextBundle();

+        assertEquals("110", "Testing123", resourceBundle.getString("110"));

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        stubFtpServer = (StubFtpServer) ftpServer;

+

+        // Create a CommandHandler instance that also implements ResourceBundleAware

+        commandHandler = new AbstractStubCommandHandler() {

+            protected void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws Exception {

+            }

+        };

+

+        // Create a CommandHandler instance that does NOT implement ResourceBundleAware

+        commandHandler_NoReplyTextBundle = new CommandHandler() {

+            public void handleCommand(Command command, Session session) throws Exception {

+            }

+        };

+    }

+

+    //-------------------------------------------------------------------------

+    // Abstract method implementations

+    //-------------------------------------------------------------------------

+

+    protected AbstractFtpServer createFtpServer() {

+        return new StubFtpServer();

+    }

+

+    protected CommandHandler createCommandHandler() {

+        return new AbstractStubCommandHandler() {

+            protected void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws Exception {

+            }

+        };

+    }

+

+    protected void verifyCommandHandlerInitialized(CommandHandler commandHandler) {

+        AbstractStubCommandHandler stubCommandHandler = (AbstractStubCommandHandler) commandHandler;

+        assertSame("replyTextBundle", stubFtpServer.getReplyTextBundle(), stubCommandHandler.getReplyTextBundle());

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServer_MultipleClientsIntegrationTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServer_MultipleClientsIntegrationTest.java
new file mode 100644
index 0000000..87ad2dd
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServer_MultipleClientsIntegrationTest.java
@@ -0,0 +1,137 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub;

+

+import org.apache.commons.net.ftp.FTPClient;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.InvocationRecord;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.stub.command.AbstractStubCommandHandler;

+import org.mockftpserver.test.AbstractTestCase;

+import org.mockftpserver.test.IntegrationTest;

+import org.mockftpserver.test.PortTestUtil;

+

+/**

+ * StubFtpServer tests for multiple FTP clients using the Apache Jakarta Commons Net FTP client.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class StubFtpServer_MultipleClientsIntegrationTest extends AbstractTestCase implements

+        IntegrationTest {

+

+    private static final Logger LOG = LoggerFactory.getLogger(StubFtpServer_MultipleClientsIntegrationTest.class);

+    private static final String SERVER = "localhost";

+

+    // Custom CommandHandler for PWD so that we can verify unique session-specific responses.

+    // Send back the hashCode for the Session as the reply text.

+    private static class CustomPwdCommandHandler extends AbstractStubCommandHandler {

+        protected void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws Exception {

+            String replyText = quotes(Integer.toString(session.hashCode()));

+            sendReply(session, 257, null, replyText, null);

+        }

+    }

+    

+    private StubFtpServer stubFtpServer;

+    private FTPClient ftpClient1;

+    private FTPClient ftpClient2;

+    private FTPClient ftpClient3;

+

+    /**

+     * Test that multiple simultaneous clients can connect and establish sessions. 

+     */

+    public void testMultipleClients() throws Exception {

+

+        // Connect from client 1

+        LOG.info("connect() to ftpClient1");

+        ftpClient1.connect(SERVER, PortTestUtil.getFtpServerControlPort());

+        String sessionId1 = ftpClient1.printWorkingDirectory();

+        LOG.info("PWD(1) reply =[" + sessionId1 + "]");

+

+        // Connect from client 2

+        LOG.info("connect() to ftpClient2");

+        ftpClient2.connect(SERVER, PortTestUtil.getFtpServerControlPort());

+        String sessionId2 = ftpClient2.printWorkingDirectory();

+        LOG.info("PWD(2) reply =[" + sessionId2 + "]");

+

+        // Connect from client 3

+        LOG.info("connect() to ftpClient3");

+        ftpClient3.connect(SERVER, PortTestUtil.getFtpServerControlPort());

+        String sessionId3 = ftpClient3.printWorkingDirectory();

+        LOG.info("PWD(3) reply =[" + sessionId3 + "]");

+        

+        // Make sure all session ids are unique

+        assertNotSame("sessionId1 vs sessionId2", sessionId1, sessionId2);

+        assertNotSame("sessionId2 vs sessionId3", sessionId2, sessionId3);

+        assertNotSame("sessionId1 vs sessionId3", sessionId1, sessionId3);

+

+        // Now make sure that the replies from the existing sessions remain consistent

+        assertEquals("reply from session1", sessionId1, ftpClient1.printWorkingDirectory());

+        assertEquals("reply from session2", sessionId2, ftpClient2.printWorkingDirectory());

+        assertEquals("reply from session3", sessionId3, ftpClient3.printWorkingDirectory());

+    }

+    

+    // -------------------------------------------------------------------------

+    // Test setup and tear-down

+    // -------------------------------------------------------------------------

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+

+        stubFtpServer = new StubFtpServer();

+        stubFtpServer.setServerControlPort(PortTestUtil.getFtpServerControlPort());

+        stubFtpServer.setCommandHandler(CommandNames.PWD, new CustomPwdCommandHandler());

+        stubFtpServer.start();

+        

+        ftpClient1 = new FTPClient();

+        ftpClient2 = new FTPClient();

+        ftpClient3 = new FTPClient();

+        

+        ftpClient1.setDefaultTimeout(1000);

+        ftpClient2.setDefaultTimeout(1000);

+        ftpClient3.setDefaultTimeout(1000);

+    }

+

+    /**

+     * Perform cleanup after each test

+     * @see org.mockftpserver.test.AbstractTestCase#tearDown()

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+

+        LOG.info("Cleaning up...");

+        if (ftpClient1.isConnected()) {

+            ftpClient1.disconnect();

+        }

+        if (ftpClient2.isConnected()) {

+            ftpClient2.disconnect();

+        }

+        if (ftpClient3.isConnected()) {

+            ftpClient3.disconnect();

+        }

+

+        stubFtpServer.stop();

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServer_StartTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServer_StartTest.java
new file mode 100644
index 0000000..e67b289
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/StubFtpServer_StartTest.java
@@ -0,0 +1,37 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub;

+

+import org.mockftpserver.core.server.AbstractFtpServer;

+import org.mockftpserver.core.server.AbstractFtpServer_StartTestCase;

+

+/**

+ * Tests for StubFtpServer that require the StubFtpServer thread to be started.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class StubFtpServer_StartTest extends AbstractFtpServer_StartTestCase {

+

+    //-------------------------------------------------------------------------

+    // Abstract method implementations

+    //-------------------------------------------------------------------------

+

+    protected AbstractFtpServer createFtpServer() {

+        return new StubFtpServer();

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/AborCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AborCommandHandlerTest.java
new file mode 100644
index 0000000..6aab009
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AborCommandHandlerTest.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the AborCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class AborCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private AborCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        final Command COMMAND = new Command(CommandNames.ABOR, EMPTY);

+

+        session.sendReply(ReplyCodes.ABOR_OK, replyTextFor(ReplyCodes.ABOR_OK));

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new AborCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/AcctCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AcctCommandHandlerTest.java
new file mode 100644
index 0000000..0960f97
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AcctCommandHandlerTest.java
@@ -0,0 +1,75 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the AcctCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class AcctCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String ACCOUNT1 = "account1";

+    private static final String ACCOUNT2 = "account2";

+

+    private AcctCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.ACCT_OK, replyTextFor(ReplyCodes.ACCT_OK));

+        session.sendReply(ReplyCodes.ACCT_OK, replyTextFor(ReplyCodes.ACCT_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), AcctCommandHandler.ACCOUNT_KEY, ACCOUNT1);

+        verifyOneDataElement(commandHandler.getInvocation(1), AcctCommandHandler.ACCOUNT_KEY, ACCOUNT2);

+    }

+    

+    /**

+     * Test the handleCommand() method, when no password parameter has been specified

+     */

+    public void testHandleCommand_MissingPasswordParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.ACCT, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new AcctCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.ACCT, array(ACCOUNT1));

+        command2 = new Command(CommandNames.ACCT, array(ACCOUNT2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/AlloCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AlloCommandHandlerTest.java
new file mode 100644
index 0000000..3d555b0
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AlloCommandHandlerTest.java
@@ -0,0 +1,123 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.util.AssertFailedException;

+

+/**

+ * Tests for the AlloCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class AlloCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(AlloCommandHandlerTest.class);

+    private static final int BYTES1 = 64;

+    private static final int BYTES2 = 555;

+    private static final int RECORD_SIZE = 77;

+

+    private AlloCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.ALLO_OK, replyTextFor(ReplyCodes.ALLO_OK));

+        session.sendReply(ReplyCodes.ALLO_OK, replyTextFor(ReplyCodes.ALLO_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), AlloCommandHandler.NUMBER_OF_BYTES_KEY, new Integer(

+                BYTES1));

+        verifyTwoDataElements(commandHandler.getInvocation(1), AlloCommandHandler.NUMBER_OF_BYTES_KEY, new Integer(

+                BYTES2), AlloCommandHandler.RECORD_SIZE_KEY, new Integer(RECORD_SIZE));

+    }

+

+    /**

+     * Test the handleCommand() method, when no numberOfBytes parameter has been specified

+     */

+    public void testHandleCommand_MissingNumberOfBytesParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.ALLO, EMPTY);

+    }

+

+    /**

+     * Test the handleCommand() method, when the recordSize delimiter ("R") parameter is specified,

+     * but is not followed by the recordSize value.

+     */

+    public void testHandleCommand_RecordSizeDelimiterWithoutValue() throws Exception {

+        try {

+            commandHandler.handleCommand(new Command(CommandNames.ALLO, array("123 R ")), session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the handleCommand() method, when a non-numeric numberOfBytes parameter has been

+     * specified

+     */

+    public void testHandleCommand_InvalidNumberOfBytesParameter() throws Exception {

+        try {

+            commandHandler.handleCommand(new Command(CommandNames.ALLO, array("xx")), session);

+            fail("Expected NumberFormatException");

+        }

+        catch (NumberFormatException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the handleCommand() method, when a non-numeric recordSize parameter has been specified

+     */

+    public void testHandleCommand_InvalidRecordSizeParameter() throws Exception {

+        try {

+            commandHandler.handleCommand(new Command(CommandNames.ALLO, array("123 R xx")), session);

+            fail("Expected NumberFormatException");

+        }

+        catch (NumberFormatException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new AlloCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.ALLO, array(Integer.toString(BYTES1)));

+        command2 = new Command(CommandNames.ALLO, array(Integer.toString(BYTES2) + " R " + Integer.toString(RECORD_SIZE)));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/AppeCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AppeCommandHandlerTest.java
new file mode 100644
index 0000000..8b288d4
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/AppeCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the AppeCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class AppeCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private AppeCommandHandler commandHandler;

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new AppeCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+    /**

+     * Test the handleCommand() method, as well as the getFileContents() and clearFileContents() methods

+     */

+    public void testHandleCommand() throws Exception {

+        final String DATA = "ABC";

+

+        session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+        session.openDataConnection();

+        session.readData();

+        control(session).setReturnValue(DATA.getBytes());

+        session.closeDataConnection();

+        session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_FINAL_OK));

+        replay(session);

+

+        Command command = new Command(CommandNames.APPE, array(FILENAME1));

+        commandHandler.handleCommand(command, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyTwoDataElements(commandHandler.getInvocation(0), AppeCommandHandler.PATHNAME_KEY, FILENAME1,

+                AppeCommandHandler.FILE_CONTENTS_KEY, DATA.getBytes());

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.APPE, EMPTY);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/CdupCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/CdupCommandHandlerTest.java
new file mode 100644
index 0000000..ea449dd
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/CdupCommandHandlerTest.java
@@ -0,0 +1,65 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the CdupCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class CdupCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private CdupCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand(Command,Session) method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.CDUP_OK, replyTextFor(ReplyCodes.CDUP_OK));

+        session.sendReply(ReplyCodes.CDUP_OK, replyTextFor(ReplyCodes.CDUP_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+        verifyNoDataElements(commandHandler.getInvocation(1));

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new CdupCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.CDUP, EMPTY);

+        command2 = new Command(CommandNames.CDUP, EMPTY);

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/CwdCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/CwdCommandHandlerTest.java
new file mode 100644
index 0000000..1ca9707
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/CwdCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the CwdCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class CwdCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private CwdCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand(Command,Session) method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.CWD_OK, replyTextFor(ReplyCodes.CWD_OK));

+        session.sendReply(ReplyCodes.CWD_OK, replyTextFor(ReplyCodes.CWD_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), CwdCommandHandler.PATHNAME_KEY, DIR1);

+        verifyOneDataElement(commandHandler.getInvocation(1), CwdCommandHandler.PATHNAME_KEY, DIR2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.CWD, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new CwdCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.CWD, array(DIR1));

+        command2 = new Command(CommandNames.CWD, array(DIR2));

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/DeleCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/DeleCommandHandlerTest.java
new file mode 100644
index 0000000..f7fcad0
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/DeleCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the DeleCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class DeleCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private DeleCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand(Command,Session) method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.DELE_OK, replyTextFor(ReplyCodes.DELE_OK));

+        session.sendReply(ReplyCodes.DELE_OK, replyTextFor(ReplyCodes.DELE_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), DeleCommandHandler.PATHNAME_KEY, FILENAME1);

+        verifyOneDataElement(commandHandler.getInvocation(1), DeleCommandHandler.PATHNAME_KEY, FILENAME2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.DELE, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new DeleCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.DELE, array(FILENAME1));

+        command2 = new Command(CommandNames.DELE, array(FILENAME2));

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/EprtCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/EprtCommandHandlerTest.java
new file mode 100644
index 0000000..632fa59
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/EprtCommandHandlerTest.java
@@ -0,0 +1,89 @@
+/*

+ * Copyright 2009 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+import java.net.InetAddress;

+

+/**

+ * Tests for the EprtCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class EprtCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String[] PARAMETERS_INSUFFICIENT = EMPTY;

+    private static final String[] PARAMETERS_IPV4 = {"|1|132.235.1.2|6275|"};

+    private static final InetAddress HOST_IPV4 = inetAddress("132.235.1.2");

+    private static final String[] PARAMETERS_IPV6 = {"|2|1080::8:800:200C:417A|6275|"};

+    private static final InetAddress HOST_IPV6 = inetAddress("1080::8:800:200C:417A");

+    private static final int PORT = 6275;

+

+    private EprtCommandHandler commandHandler;

+

+    public void testHandleCommand_IPv4() throws Exception {

+        final Command COMMAND = new Command(CommandNames.EPRT, PARAMETERS_IPV4);

+

+        session.setClientDataPort(PORT);

+        session.setClientDataHost(HOST_IPV4);

+        session.sendReply(ReplyCodes.EPRT_OK, replyTextFor(ReplyCodes.EPRT_OK));

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyTwoDataElements(commandHandler.getInvocation(0),

+                PortCommandHandler.HOST_KEY, HOST_IPV4,

+                PortCommandHandler.PORT_KEY, new Integer(PORT));

+    }

+

+    public void testHandleCommand_IPv6() throws Exception {

+        final Command COMMAND = new Command(CommandNames.EPRT, PARAMETERS_IPV6);

+

+        session.setClientDataPort(PORT);

+        session.setClientDataHost(HOST_IPV6);

+        session.sendReply(ReplyCodes.EPRT_OK, replyTextFor(ReplyCodes.EPRT_OK));

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyTwoDataElements(commandHandler.getInvocation(0),

+                PortCommandHandler.HOST_KEY, HOST_IPV6,

+                PortCommandHandler.PORT_KEY, new Integer(PORT));

+    }

+

+    public void testHandleCommand_MissingRequiredParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.EPRT, PARAMETERS_INSUFFICIENT);

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new EprtCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/EpsvCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/EpsvCommandHandlerTest.java
new file mode 100644
index 0000000..e995a8f
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/EpsvCommandHandlerTest.java
@@ -0,0 +1,67 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+import java.net.InetAddress;

+

+/**

+ * Tests for the EpsvCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class EpsvCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final InetAddress SERVER = inetAddress("1080::8:800:200C:417A");

+    private static final int PORT = 6275;

+

+    private EpsvCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        session.switchToPassiveMode();

+        control(session).setReturnValue(PORT);

+        session.getServerHost();

+        control(session).setReturnValue(SERVER);

+        session.sendReply(ReplyCodes.EPSV_OK, formattedReplyTextFor(ReplyCodes.EPSV_OK, Integer.toString(PORT)));

+        replay(session);

+

+        final Command COMMAND = new Command(CommandNames.EPSV, EMPTY);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new EpsvCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}
\ No newline at end of file
diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/FileRetrCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/FileRetrCommandHandlerTest.java
new file mode 100644
index 0000000..2e02f6e
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/FileRetrCommandHandlerTest.java
@@ -0,0 +1,179 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.ArgumentsMatcher;

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.util.AssertFailedException;

+

+import java.util.Arrays;

+

+/**

+ * Tests for the FileRetrCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class FileRetrCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(FileRetrCommandHandlerTest.class);

+    private static final byte BYTE1 = (byte) 7;

+    private static final byte BYTE2 = (byte) 21;

+

+    private FileRetrCommandHandler commandHandler;

+

+    /**

+     * Test the constructor that takes a String, passing in a null

+     */

+    public void testConstructor_String_Null() {

+        try {

+            new FileRetrCommandHandler(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setFile(String) method, passing in a null

+     */

+    public void testSetFile_Null() {

+        try {

+            commandHandler.setFile(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the handleCommand(Command,Session) method. Create a temporary (binary) file, and

+     * make sure its contents are written back

+     *

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+

+        final byte[] BUFFER = new byte[FileRetrCommandHandler.BUFFER_SIZE];

+        Arrays.fill(BUFFER, BYTE1);

+

+        session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+        session.openDataConnection();

+

+        ArgumentsMatcher matcher = new ArgumentsMatcher() {

+            int counter = -1;   // will increment for each invocation

+

+            public boolean matches(Object[] expected, Object[] actual) {

+                counter++;

+                byte[] buffer = (byte[]) actual[0];

+                int expectedLength = ((Integer) expected[1]).intValue();

+                int actualLength = ((Integer) actual[1]).intValue();

+                LOG.info("invocation #" + counter + " expected=" + expectedLength + " actualLength=" + actualLength);

+                if (counter < 5) {

+                    assertEquals("buffer for invocation #" + counter, BUFFER, buffer);

+                } else {

+                    // TODO Got two invocations here; only expected one

+                    //assertEquals("length for invocation #" + counter, expectedLength, actualLength);

+                    assertEquals("buffer[0]", BYTE2, buffer[0]);

+                    assertEquals("buffer[1]", BYTE2, buffer[1]);

+                    assertEquals("buffer[2]", BYTE2, buffer[2]);

+                }

+                return true;

+            }

+

+            public String toString(Object[] args) {

+                return args[0].getClass().getName() + " " + args[1].toString();

+            }

+        };

+

+        session.sendData(BUFFER, 512);

+        control(session).setMatcher(matcher);

+        session.sendData(BUFFER, 512);

+        session.sendData(BUFFER, 512);

+        session.sendData(BUFFER, 512);

+        session.sendData(BUFFER, 512);

+        session.sendData(BUFFER, 3);

+

+        session.closeDataConnection();

+        session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_FINAL_OK));

+        replay(session);

+

+        commandHandler.setFile("Sample.jpg");

+        Command command = new Command(CommandNames.RETR, array(FILENAME1));

+        commandHandler.handleCommand(command, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyOneDataElement(commandHandler.getInvocation(0), FileRetrCommandHandler.PATHNAME_KEY, FILENAME1);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        commandHandler.setFile("abc.txt");      // this property must be set

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.RETR, EMPTY);

+    }

+

+    /**

+     * Test the HandleCommand method, when the file property has not been set

+     */

+    public void testHandleCommand_FileNotSet() throws Exception {

+        try {

+            commandHandler.handleCommand(new Command(CommandNames.RETR, EMPTY), session);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new FileRetrCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+//    /**

+//     * Create a sample binary file; 5 buffers full plus 3 extra bytes

+//     */

+//    private void createSampleFile() {

+//        final String FILE_PATH = "test/org.mockftpserver/command/Sample.jpg";

+//        final byte[] BUFFER = new byte[FileRetrCommandHandler.BUFFER_SIZE];

+//        Arrays.fill(BUFFER, BYTE1);

+//

+//        File file = new File(FILE_PATH);

+//        FileOutputStream out = new FileOutputStream(file);

+//        for (int i = 0; i < 5; i++) {

+//            out.write(BUFFER);

+//        }

+//        Arrays.fill(BUFFER, BYTE2);

+//        out.write(BUFFER, 0, 3);

+//        out.close();

+//        LOG.info("Created temporary file [" + FILE_PATH + "]: length=" + file.length());

+//    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/HelpCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/HelpCommandHandlerTest.java
new file mode 100644
index 0000000..3605fdb
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/HelpCommandHandlerTest.java
@@ -0,0 +1,69 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the HelpCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class HelpCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private HelpCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        final String RESPONSE_DATA = "help for ABC...";

+        commandHandler.setHelpMessage(RESPONSE_DATA);

+

+        session.sendReply(ReplyCodes.HELP_OK, formattedReplyTextFor(ReplyCodes.HELP_OK, RESPONSE_DATA));

+        session.sendReply(ReplyCodes.HELP_OK, formattedReplyTextFor(ReplyCodes.HELP_OK, RESPONSE_DATA));

+        replay(session);

+

+        final Command COMMAND1 = new Command(CommandNames.HELP, EMPTY);

+        final Command COMMAND2 = new Command(CommandNames.HELP, array("abc"));

+

+        commandHandler.handleCommand(COMMAND1, session);

+        commandHandler.handleCommand(COMMAND2, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), HelpCommandHandler.COMMAND_NAME_KEY, null);

+        verifyOneDataElement(commandHandler.getInvocation(1), HelpCommandHandler.COMMAND_NAME_KEY, "abc");

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new HelpCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/ListCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/ListCommandHandlerTest.java
new file mode 100644
index 0000000..7301798
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/ListCommandHandlerTest.java
@@ -0,0 +1,75 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.easymock.MockControl;

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the ListCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class ListCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private ListCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     *

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        final String DIR_LISTING = " directory listing\nabc.txt\ndef.log\n";

+        final String DIR_LISTING_TRIMMED = DIR_LISTING.trim();

+        ((ListCommandHandler) commandHandler).setDirectoryListing(DIR_LISTING);

+

+        for (int i = 0; i < 2; i++) {

+            session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+            session.openDataConnection();

+            byte[] bytes = DIR_LISTING_TRIMMED.getBytes();

+            session.sendData(bytes, bytes.length);

+            control(session).setMatcher(MockControl.ARRAY_MATCHER);

+            session.closeDataConnection();

+            session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_FINAL_OK));

+        }

+        replay(session);

+

+        Command command1 = new Command(CommandNames.LIST, array(DIR1));

+        Command command2 = new Command(CommandNames.LIST, EMPTY);

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), ListCommandHandler.PATHNAME_KEY, DIR1);

+        verifyOneDataElement(commandHandler.getInvocation(1), ListCommandHandler.PATHNAME_KEY, null);

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new ListCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/MkdCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/MkdCommandHandlerTest.java
new file mode 100644
index 0000000..acb432c
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/MkdCommandHandlerTest.java
@@ -0,0 +1,73 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the MkdCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class MkdCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private MkdCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.MKD_OK, formattedReplyTextFor(ReplyCodes.MKD_OK, DIR1));

+        session.sendReply(ReplyCodes.MKD_OK, formattedReplyTextFor(ReplyCodes.MKD_OK, DIR2));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), MkdCommandHandler.PATHNAME_KEY, DIR1);

+        verifyOneDataElement(commandHandler.getInvocation(1), MkdCommandHandler.PATHNAME_KEY, DIR2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.MKD, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new MkdCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.MKD, array(DIR1));

+        command2 = new Command(CommandNames.MKD, array(DIR2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/ModeCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/ModeCommandHandlerTest.java
new file mode 100644
index 0000000..bc38036
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/ModeCommandHandlerTest.java
@@ -0,0 +1,75 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the ModeCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class ModeCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String CODE1 = "S";

+    private static final String CODE2 = "B";

+

+    private ModeCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.MODE_OK, replyTextFor(ReplyCodes.MODE_OK));

+        session.sendReply(ReplyCodes.MODE_OK, replyTextFor(ReplyCodes.MODE_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), ModeCommandHandler.MODE_KEY, CODE1);

+        verifyOneDataElement(commandHandler.getInvocation(1), ModeCommandHandler.MODE_KEY, CODE2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.MODE, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new ModeCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.MODE, array(CODE1));

+        command2 = new Command(CommandNames.MODE, array(CODE2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/NlstCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/NlstCommandHandlerTest.java
new file mode 100644
index 0000000..3cc6b3c
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/NlstCommandHandlerTest.java
@@ -0,0 +1,75 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.easymock.MockControl;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the NlstCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class NlstCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private NlstCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        final String DIR_LISTING = " directory listing\nabc.txt\ndef.log\n";

+        final String DIR_LISTING_TRIMMED = DIR_LISTING.trim();

+        ((NlstCommandHandler) commandHandler).setDirectoryListing(DIR_LISTING);

+

+        for (int i = 0; i < 2; i++) {

+            session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+            session.openDataConnection();

+            byte[] bytes = DIR_LISTING_TRIMMED.getBytes();

+            session.sendData(bytes, bytes.length);

+            control(session).setMatcher(MockControl.ARRAY_MATCHER);

+            session.closeDataConnection();

+            session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_FINAL_OK));

+        }

+        replay(session);

+

+        Command command1 = new Command(CommandNames.LIST, array(DIR1));

+        Command command2 = new Command(CommandNames.LIST, EMPTY);

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), NlstCommandHandler.PATHNAME_KEY, DIR1);

+        verifyOneDataElement(commandHandler.getInvocation(1), NlstCommandHandler.PATHNAME_KEY, null);

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new NlstCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/NoopCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/NoopCommandHandlerTest.java
new file mode 100644
index 0000000..65422bf
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/NoopCommandHandlerTest.java
@@ -0,0 +1,61 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the NoopCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class NoopCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private NoopCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        final Command COMMAND = new Command(CommandNames.NOOP, EMPTY);

+

+        session.sendReply(ReplyCodes.NOOP_OK, replyTextFor(ReplyCodes.NOOP_OK));

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new NoopCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/PassCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PassCommandHandlerTest.java
new file mode 100644
index 0000000..750d259
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PassCommandHandlerTest.java
@@ -0,0 +1,76 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the PassCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class PassCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String PASSWORD1 = "password1";

+    private static final String PASSWORD2 = "password2";

+

+    private PassCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.PASS_OK, replyTextFor(ReplyCodes.PASS_OK));

+        session.sendReply(ReplyCodes.PASS_OK, replyTextFor(ReplyCodes.PASS_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), PassCommandHandler.PASSWORD_KEY, PASSWORD1);

+        verifyOneDataElement(commandHandler.getInvocation(1), PassCommandHandler.PASSWORD_KEY, PASSWORD2);

+    }

+    

+    /**

+     * Test the handleCommand() method, when no password parameter has been specified

+     */

+    public void testHandleCommand_MissingPasswordParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.PASS, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new PassCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.PASS, array(PASSWORD1));

+        command2 = new Command(CommandNames.PASS, array(PASSWORD2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/PasvCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PasvCommandHandlerTest.java
new file mode 100644
index 0000000..82ee289
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PasvCommandHandlerTest.java
@@ -0,0 +1,73 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+import java.net.InetAddress;

+

+/**

+ * Tests for the PasvCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class PasvCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(PasvCommandHandlerTest.class);

+    private static final int PORT = (23 << 8) + 77;

+

+    private PasvCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        final InetAddress SERVER = inetAddress("192.168.0.2");

+        session.switchToPassiveMode();

+        control(session).setReturnValue(PORT);

+        session.getServerHost();

+        control(session).setReturnValue(SERVER);

+        session.sendReply(ReplyCodes.PASV_OK, formattedReplyTextFor(227, "(192,168,0,2,23,77)"));

+        replay(session);

+

+        final Command COMMAND = new Command(CommandNames.PASV, EMPTY);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new PasvCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/PortCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PortCommandHandlerTest.java
new file mode 100644
index 0000000..6f5f4e0
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PortCommandHandlerTest.java
@@ -0,0 +1,78 @@
+/*

+ * Copyright 2008 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+import java.net.InetAddress;

+

+/**

+ * Tests for the PortCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class PortCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String[] PARAMETERS = new String[]{"11", "22", "33", "44", "1", "206"};

+    private static final String[] PARAMETERS_INSUFFICIENT = new String[]{"7", "29", "99", "11", "77"};

+    private static final int PORT = (1 << 8) + 206;

+    private static final InetAddress HOST = inetAddress("11.22.33.44");

+

+    private PortCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        final Command COMMAND = new Command(CommandNames.PORT, PARAMETERS);

+

+        session.setClientDataPort(PORT);

+        session.setClientDataHost(HOST);

+        session.sendReply(ReplyCodes.PORT_OK, replyTextFor(ReplyCodes.PORT_OK));

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyTwoDataElements(commandHandler.getInvocation(0),

+                PortCommandHandler.HOST_KEY, HOST,

+                PortCommandHandler.PORT_KEY, new Integer(PORT));

+    }

+

+    /**

+     * Test the handleCommand() method, when not enough parameters have been specified

+     */

+    public void testHandleCommand_InsufficientParameters() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.PORT, PARAMETERS_INSUFFICIENT);

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new PortCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/PwdCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PwdCommandHandlerTest.java
new file mode 100644
index 0000000..92d8cd4
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/PwdCommandHandlerTest.java
@@ -0,0 +1,65 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the PwdCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class PwdCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private PwdCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        final String RESPONSE_DATA = "current dir 1";

+        commandHandler.setDirectory(RESPONSE_DATA);

+

+        session.sendReply(ReplyCodes.PWD_OK, formattedReplyTextFor(ReplyCodes.PWD_OK, "\"" + RESPONSE_DATA + "\""));

+        replay(session);

+

+        final Command COMMAND = new Command(CommandNames.PWD, EMPTY);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new PwdCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/QuitCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/QuitCommandHandlerTest.java
new file mode 100644
index 0000000..8392dcc
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/QuitCommandHandlerTest.java
@@ -0,0 +1,60 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the QuitCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class QuitCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private QuitCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        final Command COMMAND = new Command(CommandNames.QUIT, EMPTY);

+

+        session.sendReply(ReplyCodes.QUIT_OK, replyTextFor(ReplyCodes.QUIT_OK));

+        session.close();

+        replay(session);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new QuitCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/ReinCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/ReinCommandHandlerTest.java
new file mode 100644
index 0000000..9fd6501
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/ReinCommandHandlerTest.java
@@ -0,0 +1,65 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the ReinCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class ReinCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private ReinCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand(Command,Session) method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.REIN_OK, replyTextFor(ReplyCodes.REIN_OK));

+        session.sendReply(ReplyCodes.REIN_OK, replyTextFor(ReplyCodes.REIN_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+        verifyNoDataElements(commandHandler.getInvocation(1));

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new ReinCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.REIN, EMPTY);

+        command2 = new Command(CommandNames.REIN, EMPTY);

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/RestCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RestCommandHandlerTest.java
new file mode 100644
index 0000000..09d378c
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RestCommandHandlerTest.java
@@ -0,0 +1,78 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the RestCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class RestCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String MARKER1 = "marker1";

+    private static final String MARKER2 = "marker2";

+    

+    private RestCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.REST_OK, replyTextFor(ReplyCodes.REST_OK));

+        session.sendReply(ReplyCodes.REST_OK, replyTextFor(ReplyCodes.REST_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), RestCommandHandler.MARKER_KEY, MARKER1);

+        verifyOneDataElement(commandHandler.getInvocation(1), RestCommandHandler.MARKER_KEY, MARKER2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no marker parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.REST, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new RestCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.REST, array(MARKER1));

+        command2 = new Command(CommandNames.REST, array(MARKER2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/RetrCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RetrCommandHandlerTest.java
new file mode 100644
index 0000000..c3e6c2d
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RetrCommandHandlerTest.java
@@ -0,0 +1,134 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.MockControl;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+import org.mockftpserver.core.util.AssertFailedException;

+

+/**

+ * Tests for the RetrCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class RetrCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(RetrCommandHandlerTest.class);

+

+    private RetrCommandHandler commandHandler;

+

+    /**

+     * Test the constructor that takes a String, passing in a null

+     */

+    public void testConstructor_String_Null() {

+        try {

+            new RetrCommandHandler((String) null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the constructor that takes a byte[], passing in a null

+     */

+    public void testConstructor_ByteArray_Null() {

+        try {

+            new RetrCommandHandler((byte[]) null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setFileContents(String) method, passing in a null

+     */

+    public void testSetFileContents_String_Null() {

+        try {

+            commandHandler.setFileContents((String) null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setFileContents(byte[]) method, passing in a null

+     */

+    public void testSetFileContents_ByteArray_Null() {

+        try {

+            commandHandler.setFileContents((byte[]) null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the handleCommand() method

+     *

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        final String FILE_CONTENTS = "abc_123 456";

+        commandHandler.setFileContents(FILE_CONTENTS);

+

+        session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+        session.openDataConnection();

+        session.sendData(FILE_CONTENTS.getBytes(), FILE_CONTENTS.length());

+        control(session).setMatcher(MockControl.ARRAY_MATCHER);

+        session.closeDataConnection();

+        session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_FINAL_OK));

+        replay(session);

+

+        Command command = new Command(CommandNames.RETR, array(FILENAME1));

+        commandHandler.handleCommand(command, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyOneDataElement(commandHandler.getInvocation(0), RetrCommandHandler.PATHNAME_KEY, FILENAME1);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.RETR, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new RetrCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/RmdCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RmdCommandHandlerTest.java
new file mode 100644
index 0000000..a549514
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RmdCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the RmdCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class RmdCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private RmdCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.RMD_OK, replyTextFor(ReplyCodes.RMD_OK));

+        session.sendReply(ReplyCodes.RMD_OK, replyTextFor(ReplyCodes.RMD_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), RmdCommandHandler.PATHNAME_KEY, DIR1);

+        verifyOneDataElement(commandHandler.getInvocation(1), RmdCommandHandler.PATHNAME_KEY, DIR2);

+    }

+    

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.RMD, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new RmdCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.RMD, array(DIR1));

+        command2 = new Command(CommandNames.RMD, array(DIR2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/RnfrCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RnfrCommandHandlerTest.java
new file mode 100644
index 0000000..f494dd5
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RnfrCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the RnfrCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class RnfrCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private RnfrCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.RNFR_OK, replyTextFor(ReplyCodes.RNFR_OK));

+        session.sendReply(ReplyCodes.RNFR_OK, replyTextFor(ReplyCodes.RNFR_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), RnfrCommandHandler.PATHNAME_KEY, FILENAME1);

+        verifyOneDataElement(commandHandler.getInvocation(1), RnfrCommandHandler.PATHNAME_KEY, FILENAME2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.RNFR, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new RnfrCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.RNFR, array(FILENAME1));

+        command2 = new Command(CommandNames.RNFR, array(FILENAME2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/RntoCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RntoCommandHandlerTest.java
new file mode 100644
index 0000000..12217d1
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/RntoCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the RntoCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class RntoCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private RntoCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.RNTO_OK, replyTextFor(ReplyCodes.RNTO_OK));

+        session.sendReply(ReplyCodes.RNTO_OK, replyTextFor(ReplyCodes.RNTO_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), RntoCommandHandler.PATHNAME_KEY, FILENAME1);

+        verifyOneDataElement(commandHandler.getInvocation(1), RntoCommandHandler.PATHNAME_KEY, FILENAME2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.RNTO, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new RntoCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.RNTO, array(FILENAME1));

+        command2 = new Command(CommandNames.RNTO, array(FILENAME2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/SiteCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/SiteCommandHandlerTest.java
new file mode 100644
index 0000000..6351cd5
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/SiteCommandHandlerTest.java
@@ -0,0 +1,73 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the SiteCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class SiteCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String PARAMETERS1 = "abc def";

+    private static final String PARAMETERS2 = "abc,23,def";

+    

+    private SiteCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand(Command,Session) method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.SITE_OK, replyTextFor(ReplyCodes.SITE_OK));

+        session.sendReply(ReplyCodes.SITE_OK, replyTextFor(ReplyCodes.SITE_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), SiteCommandHandler.PARAMETERS_KEY, PARAMETERS1);

+        verifyOneDataElement(commandHandler.getInvocation(1), SiteCommandHandler.PARAMETERS_KEY, PARAMETERS2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no "parameters" parameter has been specified

+     */

+    public void testHandleCommand_MissingParameters() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.SITE, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new SiteCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.SITE, array(PARAMETERS1));

+        command2 = new Command(CommandNames.SITE, array(PARAMETERS2));

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/SmntCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/SmntCommandHandlerTest.java
new file mode 100644
index 0000000..65cea91
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/SmntCommandHandlerTest.java
@@ -0,0 +1,70 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the SmntCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class SmntCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private SmntCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+    

+    /**

+     * Test the handleCommand(Command,Session) method

+     * @throws Exception

+     */

+    public void testHandleCommand() throws Exception {

+        session.sendReply(ReplyCodes.SMNT_OK, replyTextFor(ReplyCodes.SMNT_OK));

+        session.sendReply(ReplyCodes.SMNT_OK, replyTextFor(ReplyCodes.SMNT_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), SmntCommandHandler.PATHNAME_KEY, DIR1);

+        verifyOneDataElement(commandHandler.getInvocation(1), SmntCommandHandler.PATHNAME_KEY, DIR2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.SMNT, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new SmntCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.SMNT, array(DIR1));

+        command2 = new Command(CommandNames.SMNT, array(DIR2));

+    }

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/StatCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StatCommandHandlerTest.java
new file mode 100644
index 0000000..5596685
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StatCommandHandlerTest.java
@@ -0,0 +1,101 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the StatCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class StatCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String RESPONSE_DATA = "status info 123.456";

+    private static final String PATHNAME = "dir/file";

+

+    private StatCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter is specified

+     */

+    public void testHandleCommand_NoPathname() throws Exception {

+

+        session.sendReply(ReplyCodes.STAT_SYSTEM_OK, formattedReplyTextFor(ReplyCodes.STAT_SYSTEM_OK, RESPONSE_DATA));

+        replay(session);

+

+        final Command COMMAND = new Command(CommandNames.STAT, EMPTY);

+        commandHandler.setStatus(RESPONSE_DATA);

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyOneDataElement(commandHandler.getInvocation(0), StatCommandHandler.PATHNAME_KEY, null);

+    }

+

+    /**

+     * Test the handleCommand() method, specifying a pathname parameter

+     * @throws Exception

+     */

+    public void testHandleCommand_Pathname() throws Exception {

+

+        session.sendReply(ReplyCodes.STAT_FILE_OK, formattedReplyTextFor(ReplyCodes.STAT_FILE_OK, RESPONSE_DATA));

+        replay(session);

+

+        final Command COMMAND = new Command(CommandNames.STAT, array(PATHNAME));

+

+        commandHandler.setStatus(RESPONSE_DATA);

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyOneDataElement(commandHandler.getInvocation(0), StatCommandHandler.PATHNAME_KEY, PATHNAME);

+    }

+

+    /**

+     * Test the handleCommand() method, when the replyCode is explicitly set

+     */

+    public void testHandleCommand_OverrideReplyCode() throws Exception {

+

+        session.sendReply(200, replyTextFor(200));

+        replay(session);

+

+        final Command COMMAND = new Command(CommandNames.STAT, EMPTY);

+        commandHandler.setStatus(RESPONSE_DATA);

+        commandHandler.setReplyCode(200);

+        commandHandler.handleCommand(COMMAND, session);

+

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyOneDataElement(commandHandler.getInvocation(0), StatCommandHandler.PATHNAME_KEY, null);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new StatCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/StorCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StorCommandHandlerTest.java
new file mode 100644
index 0000000..8f9c51f
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StorCommandHandlerTest.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the StorCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class StorCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private StorCommandHandler commandHandler;

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new StorCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+    /**

+     * Test the handleCommand() method, as well as the getFileContents() and clearFileContents() methods

+     */

+    public void testHandleCommand() throws Exception {

+        final String DATA = "ABC";

+

+        session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+        session.openDataConnection();

+        session.readData();

+        control(session).setReturnValue(DATA.getBytes());

+        session.closeDataConnection();

+        session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_FINAL_OK));

+        replay(session);

+

+        Command command = new Command(CommandNames.STOR, array(FILENAME1));

+        commandHandler.handleCommand(command, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyTwoDataElements(commandHandler.getInvocation(0), StorCommandHandler.PATHNAME_KEY, FILENAME1,

+                StorCommandHandler.FILE_CONTENTS_KEY, DATA.getBytes());

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.STOR, EMPTY);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/StouCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StouCommandHandlerTest.java
new file mode 100644
index 0000000..4aeef23
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StouCommandHandlerTest.java
@@ -0,0 +1,68 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the StouCommandHandler class

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public final class StouCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private StouCommandHandler commandHandler;

+

+    /**

+     * Perform initialization before each test

+     *

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new StouCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+    /**

+     * Test the handleCommand() method, as well as the getFileContents() and clearFileContents() methods

+     */

+    public void testHandleCommand() throws Exception {

+        final String DATA = "ABC";

+        final String FILENAME = "abc.txt";

+

+        session.sendReply(ReplyCodes.TRANSFER_DATA_INITIAL_OK, replyTextFor(ReplyCodes.TRANSFER_DATA_INITIAL_OK));

+        session.openDataConnection();

+        session.readData();

+        control(session).setReturnValue(DATA.getBytes());

+        session.closeDataConnection();

+        session.sendReply(ReplyCodes.TRANSFER_DATA_FINAL_OK, formattedReplyTextFor("226.WithFilename", FILENAME));

+        replay(session);

+

+        Command command = new Command(CommandNames.STOU, array(FILENAME1));

+        commandHandler.setFilename(FILENAME);

+        commandHandler.handleCommand(command, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyOneDataElement(commandHandler.getInvocation(0), StouCommandHandler.FILE_CONTENTS_KEY, DATA.getBytes());

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/StruCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StruCommandHandlerTest.java
new file mode 100644
index 0000000..2c5ba1e
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/StruCommandHandlerTest.java
@@ -0,0 +1,75 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the StruCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class StruCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String CODE1 = "F";

+    private static final String CODE2 = "R";

+

+    private StruCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.STRU_OK, replyTextFor(ReplyCodes.STRU_OK));

+        session.sendReply(ReplyCodes.STRU_OK, replyTextFor(ReplyCodes.STRU_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), StruCommandHandler.FILE_STRUCTURE_KEY, CODE1);

+        verifyOneDataElement(commandHandler.getInvocation(1), StruCommandHandler.FILE_STRUCTURE_KEY, CODE2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no pathname parameter has been specified

+     */

+    public void testHandleCommand_MissingPathnameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.STRU, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new StruCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        command1 = new Command(CommandNames.STRU, array(CODE1));

+        command2 = new Command(CommandNames.STRU, array(CODE2));

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/SystCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/SystCommandHandlerTest.java
new file mode 100644
index 0000000..e7991c0
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/SystCommandHandlerTest.java
@@ -0,0 +1,80 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.util.AssertFailedException;

+

+/**

+ * Tests for the SystCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class SystCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(SystCommandHandlerTest.class);

+    

+    private SystCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        final String SYSTEM_NAME = "UNIX";

+        commandHandler.setSystemName(SYSTEM_NAME);

+

+        session.sendReply(ReplyCodes.SYST_OK, formattedReplyTextFor(ReplyCodes.SYST_OK, "\"" + SYSTEM_NAME + "\""));

+        replay(session);

+        

+        final Command COMMAND = new Command(CommandNames.SYST, EMPTY);

+

+        commandHandler.handleCommand(COMMAND, session);

+        verify(session);

+        

+        verifyNumberOfInvocations(commandHandler, 1);

+        verifyNoDataElements(commandHandler.getInvocation(0));

+    }

+    

+    /**

+     * Test the SetSystemName method, passing in a null

+     */

+    public void testSetSystemName_Null() {

+        try {

+            commandHandler.setSystemName(null);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+    

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new SystCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/TypeCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/TypeCommandHandlerTest.java
new file mode 100644
index 0000000..3a1e0f2
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/TypeCommandHandlerTest.java
@@ -0,0 +1,75 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.ReplyCodes;

+

+/**

+ * Tests for the TypeCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class TypeCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private TypeCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+        final Command COMMAND1 = new Command("TYPE", array("A"));

+        final Command COMMAND2 = new Command("TYPE", array("B"));

+        final Command COMMAND3 = new Command("TYPE", array("L", "8"));

+

+        session.sendReply(ReplyCodes.TYPE_OK, replyTextFor(ReplyCodes.TYPE_OK));

+        session.sendReply(ReplyCodes.TYPE_OK, replyTextFor(ReplyCodes.TYPE_OK));

+        session.sendReply(ReplyCodes.TYPE_OK, replyTextFor(ReplyCodes.TYPE_OK));

+        replay(session);

+        

+        commandHandler.handleCommand(COMMAND1, session);

+        commandHandler.handleCommand(COMMAND2, session);

+        commandHandler.handleCommand(COMMAND3, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 3);

+        verifyOneDataElement(commandHandler.getInvocation(0), TypeCommandHandler.TYPE_INFO_KEY, new String[] {"A", null});

+        verifyOneDataElement(commandHandler.getInvocation(1), TypeCommandHandler.TYPE_INFO_KEY, new String[] {"B", null});

+        verifyOneDataElement(commandHandler.getInvocation(2), TypeCommandHandler.TYPE_INFO_KEY, new String[] {"L", "8"});

+    }

+    

+    /**

+     * Test the handleCommand() method, when no type parameter has been specified

+     */

+    public void testHandleCommand_MissingTypeParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.TYPE, EMPTY);

+    }

+

+    /**

+     * Perform initialization before each test

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new TypeCommandHandler();

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/UserCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/UserCommandHandlerTest.java
new file mode 100644
index 0000000..f63b847
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/UserCommandHandlerTest.java
@@ -0,0 +1,85 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.mockftpserver.core.command.*;

+import org.mockftpserver.core.command.AbstractCommandHandlerTestCase;

+

+/**

+ * Tests for the UserCommandHandler class

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class UserCommandHandlerTest extends AbstractCommandHandlerTestCase {

+

+    private static final String USERNAME1 = "user1";

+    private static final String USERNAME2 = "user2";

+

+    private UserCommandHandler commandHandler;

+    private Command command1;

+    private Command command2;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(ReplyCodes.USER_NEED_PASSWORD_OK, replyTextFor(ReplyCodes.USER_NEED_PASSWORD_OK));

+        session.sendReply(ReplyCodes.USER_LOGGED_IN_OK, replyTextFor(ReplyCodes.USER_LOGGED_IN_OK));

+        replay(session);

+

+        commandHandler.handleCommand(command1, session);

+        commandHandler.setPasswordRequired(false);

+        commandHandler.handleCommand(command2, session);

+        verify(session);

+

+        verifyNumberOfInvocations(commandHandler, 2);

+        verifyOneDataElement(commandHandler.getInvocation(0), UserCommandHandler.USERNAME_KEY, USERNAME1);

+        verifyOneDataElement(commandHandler.getInvocation(1), UserCommandHandler.USERNAME_KEY, USERNAME2);

+    }

+

+    /**

+     * Test the handleCommand() method, when no username parameter has been specified

+     */

+    public void testHandleCommand_MissingUsernameParameter() throws Exception {

+        testHandleCommand_InvalidParameters(commandHandler, CommandNames.USER, EMPTY);

+    }

+

+    /**

+     * Test the setPasswordRequired() and isPasswordRequired() methods 

+     */

+    public void testSetPasswordRequired() {

+        assertTrue("initial state", commandHandler.isPasswordRequired());

+        commandHandler.setPasswordRequired(false);

+        assertFalse("after set false", commandHandler.isPasswordRequired());

+    }

+    

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.core.command.AbstractCommandHandlerTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        commandHandler = new UserCommandHandler();

+        command1 = new Command(CommandNames.USER, array(USERNAME1));

+        command2 = new Command(CommandNames.USER, array(USERNAME2));

+        commandHandler.setReplyTextBundle(replyTextBundle);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/command/_AbstractStubDataCommandHandlerTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/command/_AbstractStubDataCommandHandlerTest.java
new file mode 100644
index 0000000..0d2e979
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/command/_AbstractStubDataCommandHandlerTest.java
@@ -0,0 +1,177 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.command;

+

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.core.command.Command;

+import org.mockftpserver.core.command.InvocationRecord;

+import org.mockftpserver.core.session.Session;

+import org.mockftpserver.core.util.AssertFailedException;

+import org.mockftpserver.test.AbstractTestCase;

+

+import java.util.ListResourceBundle;

+import java.util.ResourceBundle;

+

+/**

+ * Tests for AbstractStubDataCommandHandler. The class name is prefixed with an underscore

+ * so that it is not filtered out by Maven's Surefire test plugin.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class _AbstractStubDataCommandHandlerTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(_AbstractStubDataCommandHandlerTest.class);

+    private static final Command COMMAND = new Command("command", EMPTY);

+    private static final InvocationRecord INVOCATION_RECORD = new InvocationRecord(COMMAND, DEFAULT_HOST);

+

+    private static final String REPLY_TEXT150 = "reply 150 ... abcdef";

+    private static final String REPLY_TEXT226 = "reply 226 ... abcdef";

+    private static final String REPLY_TEXT222 = "reply 222 ... abcdef";

+    private static final String REPLY_TEXT333 = "reply 333 ... abcdef";

+    private static final String REPLY_TEXT444 = "reply 444 ... abcdef";

+    

+    private Session session;

+    private ResourceBundle replyTextBundle;

+    private AbstractStubDataCommandHandler commandHandler;

+

+    /**

+     * Test the handleCommand() method

+     */

+    public void testHandleCommand() throws Exception {

+

+        session.sendReply(150, REPLY_TEXT150);

+        session.openDataConnection();

+        session.sendReply(222, REPLY_TEXT222);

+        session.sendReply(333, REPLY_TEXT333);

+        session.sendReply(444, REPLY_TEXT444);

+        session.closeDataConnection();

+        session.sendReply(226, REPLY_TEXT226);

+        replay(session);

+        

+        // Define CommandHandler test subclass

+        commandHandler = new AbstractStubDataCommandHandler() {

+            protected void beforeProcessData(Command c, Session s, InvocationRecord ir) {

+                verifyParameters(c, s, ir);

+                // Send unique reply code so that we can verify proper method invocation and ordering

+                session.sendReply(222, REPLY_TEXT222);

+            }

+

+            protected void processData(Command c, Session s, InvocationRecord ir) {

+                verifyParameters(c, s, ir);

+                // Send unique reply code so that we can verify proper method invocation and ordering

+                session.sendReply(333, REPLY_TEXT333);

+            }

+

+            protected void afterProcessData(Command c, Session s, InvocationRecord ir) {

+                verifyParameters(c, s, ir);

+                // Send unique reply code so that we can verify proper method invocation and ordering

+                session.sendReply(444, REPLY_TEXT444);

+            }

+

+            private void verifyParameters(Command c, Session s, InvocationRecord ir) {

+                assertSame("command", COMMAND, c);

+                assertSame("session", session, s);

+                assertSame("invocationRecord", INVOCATION_RECORD, ir);

+            }

+        };

+

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        commandHandler.handleCommand(COMMAND, session, INVOCATION_RECORD);

+        

+        verify(session);

+    }

+

+    /**

+     * Test the handleCommand() method, overriding the initial reply code and text

+     */

+    public void testHandleCommand_OverrideInitialReplyCodeAndText() throws Exception {

+

+        final int OVERRIDE_REPLY_CODE = 333;

+        final String OVERRIDE_REPLY_TEXT = "reply text";

+        

+        session.sendReply(OVERRIDE_REPLY_CODE, OVERRIDE_REPLY_TEXT);

+        session.openDataConnection();

+        session.closeDataConnection();

+        session.sendReply(226, REPLY_TEXT226);

+        replay(session);

+        

+        commandHandler.setPreliminaryReplyCode(OVERRIDE_REPLY_CODE);

+        commandHandler.setPreliminaryReplyText(OVERRIDE_REPLY_TEXT);

+        commandHandler.setReplyTextBundle(replyTextBundle);

+        commandHandler.handleCommand(COMMAND, session, INVOCATION_RECORD);

+        

+        verify(session);

+    }

+

+    /**

+     * Test the setPreliminaryReplyCode() method, passing in an invalid value 

+     */

+    public void testSetPreliminaryReplyCode_Invalid() {

+        try {

+            commandHandler.setPreliminaryReplyCode(0);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    /**

+     * Test the setFinalReplyCode() method, passing in an invalid value 

+     */

+    public void testSetFinalReplyCode_Invalid() {

+        try {

+            commandHandler.setFinalReplyCode(0);

+            fail("Expected AssertFailedException");

+        }

+        catch (AssertFailedException expected) {

+            LOG.info("Expected: " + expected);

+        }

+    }

+

+    //-------------------------------------------------------------------------

+    // Test setup

+    //-------------------------------------------------------------------------

+    

+    /**

+     * Perform initialization before each test

+     * 

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        session = (Session) createMock(Session.class);

+        replyTextBundle = new ListResourceBundle() {

+            protected Object[][] getContents() {

+                return new Object[][] { 

+                        { Integer.toString(150), REPLY_TEXT150 }, 

+                        { Integer.toString(222), REPLY_TEXT222 }, 

+                        { Integer.toString(226), REPLY_TEXT226 }, 

+                        { Integer.toString(333), REPLY_TEXT333 }, 

+                        { Integer.toString(444), REPLY_TEXT444 }, 

+                };

+            }

+        };

+        commandHandler = new AbstractStubDataCommandHandler() {

+            protected void processData(Command c, Session s, InvocationRecord ir) {

+            }

+        };

+    }

+    

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/example/FtpWorkingDirectory.java b/tags/2.5/src/test/java/org/mockftpserver/stub/example/FtpWorkingDirectory.java
new file mode 100644
index 0000000..dab841f
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/example/FtpWorkingDirectory.java
@@ -0,0 +1,63 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.example;

+

+import org.apache.commons.net.ftp.FTPClient;

+

+import java.io.IOException;

+import java.net.SocketException;

+

+/**

+ * Simple FTP client code example.

+ * 

+ * @version $Revision$ - $Date$

+ *

+ * @author Chris Mair

+ */

+public class FtpWorkingDirectory {

+

+    private String server;

+    private int port;

+

+    /**

+     * Return the current working directory for the FTP account on the server

+     * @return the current working directory

+     * @throws SocketException

+     * @throws IOException

+     */

+    public String getWorkingDirectory() throws SocketException, IOException {

+        FTPClient ftpClient = new FTPClient();

+        ftpClient.connect(server, port);

+        return ftpClient.printWorkingDirectory();

+    }

+

+    /**

+     * Set the hostname of the FTP server

+     * @param server - the hostname of the FTP server

+     */

+    public void setServer(String server) {

+        this.server = server;

+    }

+    

+    /**

+     * Set the port number for the FTP server

+     * @param port - the port number

+     */

+    public void setPort(int port) {

+        this.port = port;

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/example/FtpWorkingDirectoryTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/example/FtpWorkingDirectoryTest.java
new file mode 100644
index 0000000..b3a7d47
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/example/FtpWorkingDirectoryTest.java
@@ -0,0 +1,70 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.example;

+

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.stub.StubFtpServer;

+import org.mockftpserver.stub.command.PwdCommandHandler;

+import org.mockftpserver.test.AbstractTestCase;

+import org.mockftpserver.test.IntegrationTest;

+

+/**

+ * Example test using StubFtpServer, with programmatic configuration.

+ */

+public class FtpWorkingDirectoryTest extends AbstractTestCase implements IntegrationTest {

+

+    private static final int PORT = 9981;

+    private FtpWorkingDirectory ftpWorkingDirectory;

+    private StubFtpServer stubFtpServer;

+    

+    /**

+     * Test FtpWorkingDirectory getWorkingDirectory() method 

+     */

+    public void testGetWorkingDirectory() throws Exception {

+        

+        // Replace the existing (default) CommandHandler; customize returned directory pathname

+        final String DIR = "some/dir";

+        PwdCommandHandler pwdCommandHandler = new PwdCommandHandler();

+        pwdCommandHandler.setDirectory(DIR);

+        stubFtpServer.setCommandHandler(CommandNames.PWD, pwdCommandHandler);

+        

+        stubFtpServer.start();

+        

+        String workingDir = ftpWorkingDirectory.getWorkingDirectory();

+

+        assertEquals("workingDirectory", DIR, workingDir);

+    }

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        ftpWorkingDirectory = new FtpWorkingDirectory();

+        ftpWorkingDirectory.setPort(PORT);

+        stubFtpServer = new StubFtpServer();

+        stubFtpServer.setServerControlPort(PORT);

+    }

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#tearDown()

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+        stubFtpServer.stop();

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/example/RemoteFile.java b/tags/2.5/src/test/java/org/mockftpserver/stub/example/RemoteFile.java
new file mode 100644
index 0000000..833cf56
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/example/RemoteFile.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.example;

+

+import org.apache.commons.net.ftp.FTPClient;

+

+import java.io.ByteArrayOutputStream;

+import java.io.IOException;

+

+/**

+ * Simple FTP client code example.

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public class RemoteFile {

+

+    public static final String USERNAME = "user";

+    public static final String PASSWORD = "password";

+

+    private String server;

+    private int port;

+

+    public String readFile(String filename) throws IOException {

+

+        FTPClient ftpClient = new FTPClient();

+        ftpClient.connect(server, port);

+        ftpClient.login(USERNAME, PASSWORD);

+

+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

+        boolean success = ftpClient.retrieveFile(filename, outputStream);

+        ftpClient.disconnect();

+

+        if (!success) {

+            throw new IOException("Retrieve file failed: " + filename);

+        }

+        return outputStream.toString();

+    }

+

+    /**

+     * Set the hostname of the FTP server

+     *

+     * @param server - the hostname of the FTP server

+     */

+    public void setServer(String server) {

+        this.server = server;

+    }

+

+    /**

+     * Set the port number for the FTP server

+     *

+     * @param port - the port number

+     */

+    public void setPort(int port) {

+        this.port = port;

+    }

+

+    // Other methods ...

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/example/RemoteFileTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/example/RemoteFileTest.java
new file mode 100644
index 0000000..e7e5769
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/example/RemoteFileTest.java
@@ -0,0 +1,104 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.example;

+

+import org.mockftpserver.core.command.CommandNames;

+import org.mockftpserver.core.command.InvocationRecord;

+import org.mockftpserver.stub.StubFtpServer;

+import org.mockftpserver.stub.command.RetrCommandHandler;

+import org.mockftpserver.test.AbstractTestCase;

+import org.mockftpserver.test.IntegrationTest;

+

+import java.io.IOException;

+

+/**

+ * Example test using StubFtpServer, with programmatic configuration.

+ */

+public class RemoteFileTest extends AbstractTestCase implements IntegrationTest {

+

+    private static final int PORT = 9981;

+    private static final String FILENAME = "dir/sample.txt";

+

+    private RemoteFile remoteFile;

+    private StubFtpServer stubFtpServer;

+    

+    /**

+     * Test readFile() method 

+     */

+    public void testReadFile() throws Exception {

+

+        final String CONTENTS = "abcdef 1234567890";

+

+        // Replace the default RETR CommandHandler; customize returned file contents

+        RetrCommandHandler retrCommandHandler = new RetrCommandHandler();

+        retrCommandHandler.setFileContents(CONTENTS);

+        stubFtpServer.setCommandHandler(CommandNames.RETR, retrCommandHandler);

+        

+        stubFtpServer.start();

+        

+        String contents = remoteFile.readFile(FILENAME);

+

+        // Verify returned file contents

+        assertEquals("contents", CONTENTS, contents);

+        

+        // Verify the submitted filename

+        InvocationRecord invocationRecord = retrCommandHandler.getInvocation(0);

+        String filename = invocationRecord.getString(RetrCommandHandler.PATHNAME_KEY);

+        assertEquals("filename", FILENAME, filename);

+    }

+

+    /**

+     * Test the readFile() method when the FTP transfer fails (returns a non-success reply code) 

+     */

+    public void testReadFileThrowsException() {

+

+        // Replace the default RETR CommandHandler; return failure reply code

+        RetrCommandHandler retrCommandHandler = new RetrCommandHandler();

+        retrCommandHandler.setFinalReplyCode(550);

+        stubFtpServer.setCommandHandler(CommandNames.RETR, retrCommandHandler);

+        

+        stubFtpServer.start();

+

+        try {

+            remoteFile.readFile(FILENAME);

+            fail("Expected IOException");

+        }

+        catch (IOException expected) {

+            // Expected this

+        }

+    }

+    

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        remoteFile = new RemoteFile();

+        remoteFile.setServer("localhost");

+        remoteFile.setPort(PORT);

+        stubFtpServer = new StubFtpServer();

+        stubFtpServer.setServerControlPort(PORT);

+    }

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#tearDown()

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+        stubFtpServer.stop();

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/stub/example/SpringConfigurationTest.java b/tags/2.5/src/test/java/org/mockftpserver/stub/example/SpringConfigurationTest.java
new file mode 100644
index 0000000..acb10c1
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/stub/example/SpringConfigurationTest.java
@@ -0,0 +1,89 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.stub.example;

+

+import org.apache.commons.net.ftp.FTPClient;

+import org.apache.commons.net.ftp.FTPFile;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.mockftpserver.stub.StubFtpServer;

+import org.mockftpserver.test.AbstractTestCase;

+import org.springframework.context.ApplicationContext;

+import org.springframework.context.support.ClassPathXmlApplicationContext;

+

+import java.io.ByteArrayOutputStream;

+

+/**

+ * Example test for StubFtpServer, using the Spring Framework ({@link http://www.springframework.org/}) 

+ * for configuration.

+ */

+public class SpringConfigurationTest extends AbstractTestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(SpringConfigurationTest.class);

+    private static final String SERVER = "localhost";

+    private static final int PORT = 9981;

+

+    private StubFtpServer stubFtpServer;

+    private FTPClient ftpClient;

+    

+    /**

+     * Test starting the StubFtpServer configured within the example Spring configuration file 

+     */

+    public void testStubFtpServer() throws Exception {

+        stubFtpServer.start();

+        

+        ftpClient.connect(SERVER, PORT);

+

+        // PWD

+        String dir = ftpClient.printWorkingDirectory();

+        assertEquals("PWD", "foo/bar", dir);

+        

+        // LIST

+        FTPFile[] files = ftpClient.listFiles();

+        LOG.info("FTPFile[0]=" + files[0]);

+        LOG.info("FTPFile[1]=" + files[1]);

+        assertEquals("number of files from LIST", 2, files.length);

+        

+        // DELE

+        assertFalse("DELE", ftpClient.deleteFile("AnyFile.txt"));

+        

+        // RETR

+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

+        assertTrue(ftpClient.retrieveFile("SomeFile.txt", outputStream));

+        LOG.info("File contents=[" + outputStream.toString() + "]");

+    }

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#setUp()

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+        

+        ApplicationContext context = new ClassPathXmlApplicationContext("stubftpserver-beans.xml");

+        stubFtpServer = (StubFtpServer) context.getBean("stubFtpServer");

+

+        ftpClient = new FTPClient();

+    }

+

+    /**

+     * @see org.mockftpserver.test.AbstractTestCase#tearDown()

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+        stubFtpServer.stop();

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/test/AbstractTestCase.java b/tags/2.5/src/test/java/org/mockftpserver/test/AbstractTestCase.java
new file mode 100644
index 0000000..a3e5110
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/test/AbstractTestCase.java
@@ -0,0 +1,369 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.test;

+

+import junit.framework.TestCase;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+import org.easymock.MockControl;

+import org.mockftpserver.core.MockFtpServerException;

+import org.mockftpserver.core.util.Assert;

+import org.mockftpserver.core.util.AssertFailedException;

+

+import java.io.File;

+import java.net.InetAddress;

+import java.net.UnknownHostException;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+import java.util.Set;

+

+/**

+ * Abstract superclass for all project test classes

+ *

+ * @author Chris Mair

+ * @version $Revision$ - $Date$

+ */

+public abstract class AbstractTestCase extends TestCase {

+

+    private static final Logger LOG = LoggerFactory.getLogger(AbstractTestCase.class);

+    protected static final List EMPTY_LIST = Collections.EMPTY_LIST;

+    protected static final String[] EMPTY = new String[0];

+    protected static final InetAddress DEFAULT_HOST = inetAddress(null);

+

+    /**

+     * Constructor

+     */

+    public AbstractTestCase() {

+        super();

+    }

+

+    //-------------------------------------------------------------------------

+    // Manage EasyMock Control objects under the covers, and provide a syntax

+    // somewhat similar to EasyMock 2.2 for createMock, verify and replay.

+    //-------------------------------------------------------------------------

+

+    private Map mocks = new HashMap();

+

+    /**

+     * Create a new mock for the specified interface. Keep track of the associated control object

+     * under the covers to support the associated  method.

+     *

+     * @param interfaceToMock - the Class of the interface to be mocked

+     * @return the new mock

+     */

+    protected Object createMock(Class interfaceToMock) {

+        MockControl control = MockControl.createControl(interfaceToMock);

+        Object mock = control.getMock();

+        mocks.put(mock, control);

+        return mock;

+    }

+

+    /**

+     * Put the mock object into replay mode

+     *

+     * @param mock - the mock to set in replay mode

+     * @throws AssertFailedException - if mock is null

+     * @throws AssertFailedException - if mock is not a mock object created using {@link #createMock(Class)}

+     */

+    protected void replay(Object mock) {

+        control(mock).replay();

+    }

+

+    /**

+     * Put all mocks created with createMock() into replay mode.

+     */

+    protected void replayAll() {

+        for (Iterator iter = mocks.keySet().iterator(); iter.hasNext();) {

+            Object mock = iter.next();

+            replay(mock);

+        }

+    }

+

+    /**

+     * Verify the mock object

+     *

+     * @param mock - the mock to verify

+     * @throws AssertFailedException - if mock is null

+     * @throws AssertFailedException - if mock is not a mock object created using {@link #createMock(Class)}

+     */

+    protected void verify(Object mock) {

+        control(mock).verify();

+    }

+

+    /**

+     * Verify all mocks created with createMock() into replay mode.

+     */

+    protected void verifyAll() {

+        for (Iterator iter = mocks.keySet().iterator(); iter.hasNext();) {

+            Object mock = iter.next();

+            verify(mock);

+        }

+    }

+

+    /**

+     * Return the mock control associated with the mock

+     *

+     * @param mock - the mock

+     * @return the associated MockControl

+     * @throws AssertFailedException - if mock is null

+     * @throws AssertFailedException - if mock is not a mock object created using {@link #createMock(Class)}

+     */

+    protected MockControl control(Object mock) {

+        Assert.notNull(mock, "mock");

+        MockControl control = (MockControl) mocks.get(mock);

+        Assert.notNull(control, "control");

+        return control;

+    }

+

+    //-------------------------------------------------------------------------

+    // Other Helper Methods

+    //-------------------------------------------------------------------------

+

+    /**

+     * Assert that the two objects are not equal

+     *

+     * @param object1 - the first object

+     * @param object2 - the second object

+     */

+    protected void assertNotEquals(String message, Object object1, Object object2) {

+        assertFalse(message, object1.equals(object2));

+    }

+

+    /**

+     * Assert that the two byte arrays have the same length and content

+     *

+     * @param array1 - the first array

+     * @param array2 - the second array

+     */

+    protected void assertEquals(String message, byte[] array1, byte[] array2) {

+        assertTrue("Arrays not equal: " + message, Arrays.equals(array1, array2));

+    }

+

+    /**

+     * Assert that the two Object arrays have the same length and content

+     *

+     * @param array1 - the first array

+     * @param array2 - the second array

+     */

+    protected void assertEquals(String message, Object[] array1, Object[] array2) {

+        assertTrue("Arrays not equal: " + message, Arrays.equals(array1, array2));

+    }

+

+    /**

+     * Create and return a one-element Object[] containing the specified Object

+     *

+     * @param o - the object

+     * @return the Object array, of length 1, containing o

+     */

+    protected static Object[] objArray(Object o) {

+        return new Object[]{o};

+    }

+

+    /**

+     * Create and return a one-element String[] containing the specified String

+     *

+     * @param s - the String

+     * @return the String array, of length 1, containing s

+     */

+    protected static String[] array(String s) {

+        return new String[]{s};

+    }

+

+    /**

+     * Create and return a two-element String[] containing the specified Strings

+     *

+     * @param s1 - the first String

+     * @param s2 - the second String

+     * @return the String array, of length 2, containing s1 and s2

+     */

+    protected static String[] array(String s1, String s2) {

+        return new String[]{s1, s2};

+    }

+

+    /**

+     * Create a new InetAddress from the specified host String, using the

+     * {@link InetAddress#getByName(String)} method, wrapping any checked

+     * exception within a unchecked MockFtpServerException.

+     *

+     * @param host

+     * @return an InetAddress for the specified host

+     * @throws MockFtpServerException - if an UnknownHostException is thrown

+     */

+    protected static InetAddress inetAddress(String host) {

+        try {

+            return InetAddress.getByName(host);

+        }

+        catch (UnknownHostException e) {

+            throw new MockFtpServerException(e);

+        }

+    }

+

+    /**

+     * Create and return a List containing the Objects passed as arguments to this method

+     *

+     * @param e1- the first element to add

+     * @param e2- the second element to add

+     * @return the List containing the specified elements

+     */

+    protected static List list(Object e1, Object e2) {

+        List list = new ArrayList();

+        list.add(e1);

+        list.add(e2);

+        return list;

+    }

+

+    /**

+     * Create and return a List containing the single Object passed as an argument to this method

+     *

+     * @param element- the element to add

+     * @return the List containing the specified element

+     */

+    protected static List list(Object element) {

+        return Collections.singletonList(element);

+    }

+

+    /**

+     * Create and return a Set containing the Objects passed as arguments to this method

+     *

+     * @param e1 - the first element to add

+     * @param e2 - the second element to add

+     * @return the Set containing the specified elements

+     */

+    protected static Set set(Object e1, Object e2) {

+        Set set = new HashSet();

+        set.add(e1);

+        set.add(e2);

+        return set;

+    }

+

+    /**

+     * Create and return a Set containing the Objects passed as arguments to this method

+     *

+     * @param e1 - the first element to add

+     * @param e2 - the second element to add

+     * @param e3 - the third element to add

+     * @return the Set containing the specified elements

+     */

+    protected static Set set(Object e1, Object e2, Object e3) {

+        Set set = set(e1, e2);

+        set.add(e3);

+        return set;

+    }

+

+    /**

+     * Override the default test run behavior to write out the current test name

+     * and handle Errors and Exceptions in a standard way.

+     *

+     * @see junit.framework.TestCase#runBare()

+     */

+    public void runBare() throws Throwable {

+

+        LoggingUtil loggingUtil = null;

+        try {

+            loggingUtil = LoggingUtil.getTestCaseLogger(this);

+            loggingUtil.logStartOfTest();

+            super.runBare();

+        }

+        catch (Exception e) {

+            handleException(e);

+        }

+        catch (Error e) {

+            handleError(e);

+        }

+        finally {

+            if (loggingUtil != null) {

+                loggingUtil.logEndOfTest();

+            }

+        }

+    }

+

+    /**

+     * Setup before each test.

+     */

+    protected void setUp() throws Exception {

+        super.setUp();

+    }

+

+    /**

+     * Cleanup after each test.

+     */

+    protected void tearDown() throws Exception {

+        super.tearDown();

+    }

+

+    //-----------------------------------------------------------

+    // Private Internal Methods

+    //-----------------------------------------------------------

+

+    /**

+     * Handle an exception

+     *

+     * @param e the Exception

+     * @throws Exception

+     */

+    private void handleException(Exception e) throws Exception {

+

+        LOG.error("EXCEPTION: ", e);

+        throw e;

+    }

+

+    /**

+     * Handle an Error

+     *

+     * @param e the Error

+     * @throws Exception

+     */

+    private void handleError(Error e) throws Exception {

+        LOG.error("ERROR: ", e);

+        throw e;

+    }

+

+    //-------------------------------------------------------------------------

+    // Helper methods

+    //-------------------------------------------------------------------------

+

+    /**

+     * Delete the named file if it exists

+     *

+     * @param filename - the full pathname of the file

+     */

+    protected void deleteFile(String filename) {

+        File keyFile = new File(filename);

+        boolean deleted = keyFile.delete();

+        LOG.info("Deleted [" + filename + "]: " + deleted);

+    }

+

+    //-------------------------------------------------------------------------

+    // Common validation helper methods

+    //-------------------------------------------------------------------------

+

+    /**

+     * Verify that the named file exists

+     *

+     * @param filename - the full pathname of the file

+     */

+    protected void verifyFileExists(String filename) {

+        File keyFile = new File(filename);

+        assertTrue("File does not exist [" + filename + "]", keyFile.exists());

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/test/IntegrationTest.java b/tags/2.5/src/test/java/org/mockftpserver/test/IntegrationTest.java
new file mode 100644
index 0000000..0f6e3ae
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/test/IntegrationTest.java
@@ -0,0 +1,27 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.test;

+

+/**

+ * Marker interface for integration test

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public interface IntegrationTest {

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/test/LoggingUtil.java b/tags/2.5/src/test/java/org/mockftpserver/test/LoggingUtil.java
new file mode 100644
index 0000000..d7347ca
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/test/LoggingUtil.java
@@ -0,0 +1,147 @@
+/*

+ * Copyright 2007 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.mockftpserver.test;

+

+import junit.framework.TestCase;

+import junit.framework.TestSuite;

+

+/**

+ * Provides facilities to log the start and end of a test run.

+ * 

+ * May want to refactor this and create two subclasses: TestCaseLogger

+ * and TestSuiteLogger.

+ * 

+ * @version $Revision$ - $Date$

+ * 

+ * @author Chris Mair

+ */

+public final class LoggingUtil {

+

+    private static final String TEST_CASE_SEPARATOR = "---------------";

+    private static final String TEST_SUITE_SEPARATOR = "####################";

+

+    private String testTitle;

+    private String separator;

+    private long startTime; 

+

+    

+    //-------------------------------------------------------------------------

+    // General-purpose API to log messages

+    //-------------------------------------------------------------------------

+    

+    /**

+     * Log the specified message from the caller object.

+     * @param caller the calling object

+     * @param message the message to log

+     */

+    public static void log(Object caller, Object message) {

+        

+        String classNameNoPackage = getClassName(caller);

+        String messageStr = (message==null) ? "null" : message.toString();

+        String formattedMessage = "[" + classNameNoPackage + "] " + messageStr;

+        writeLogMessage(formattedMessage);

+    }

+    

+    

+    //-------------------------------------------------------------------------

+    // Factory Methods to get instance for TestCase or TestSuite

+    //-------------------------------------------------------------------------

+    

+    /**

+     * Return a LoggingUtil instance suitable for logging TestCase start and end

+     * @param testCase the TestCase

+     * @return a LoggingUtil

+     */

+    public static LoggingUtil getTestCaseLogger(TestCase testCase) {

+        

+        String title = getClassName(testCase) + "." + testCase.getName();

+        return new LoggingUtil(title, TEST_CASE_SEPARATOR);

+    }

+

+

+    /**

+     * Return a LoggingUtil instance suitable for logging TestSuite start and end

+     * @param testSuite the TestSuite

+     * @return a LoggingUtil

+     */

+    public static LoggingUtil getTestSuiteLogger(TestSuite testCase) {

+        

+        String title = "SUITE " + getClassName(testCase);

+        return new LoggingUtil(title, TEST_SUITE_SEPARATOR);

+    }

+

+

+    /**

+     * Constructor. Private to force access through the factory method(s) 

+     */

+    private LoggingUtil(String title, String separator) {

+        this.startTime = System.currentTimeMillis();

+        this.testTitle = title;

+        this.separator = separator;

+    }

+

+

+    /**

+     * Write out the the name of the test class and test name to the log

+     */

+    public void logStartOfTest() {

+        

+        writeLogMessage(separator + " [ START: " + testTitle + " ] " + separator);

+    }

+

+

+    /**

+     * Write out the the name of the test class and test name to the log

+     */

+    public void logEndOfTest() {

+        

+        long elapsedTime = System.currentTimeMillis() - startTime;

+        writeLogMessage(separator + " [ END: " 

+            + testTitle

+            + "   Time=" + elapsedTime

+            + "ms ] "+ separator + "\n");

+    }

+

+

+    /**

+     * Return the name of the class for the specified object, stripping off the package name

+     * @return the name of the class, stripping off the package name

+     */

+    private static String getClassName(Object object) {

+        

+        // If it's already a class, then use as is

+        Class theClass = (object instanceof Class) ? ((Class)object) : object.getClass();

+        String className =  theClass.getName();

+        

+        int index = className.lastIndexOf(".");

+        if (index != -1) {

+            className = className.substring(index+1);

+        }

+        return className;

+    }

+

+

+    /**

+     * Write the specified message out to the log

+     * @param message the message to write

+     */

+    private static void writeLogMessage(String message) {

+        // Don't want to use Trace -- it requires initialization of the system configuration

+        //Trace.trace(message);

+        System.out.println(message);

+    }

+

+}

diff --git a/tags/2.5/src/test/java/org/mockftpserver/test/PortTestUtil.java b/tags/2.5/src/test/java/org/mockftpserver/test/PortTestUtil.java
new file mode 100644
index 0000000..72017bf
--- /dev/null
+++ b/tags/2.5/src/test/java/org/mockftpserver/test/PortTestUtil.java
@@ -0,0 +1,43 @@
+/*

+ * Copyright 2008 the original author or authors.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.mockftpserver.test;

+

+/**

+ * Contains static test utility method to determine FTP server port number to use for tests  

+ * 

+ * @version $Revision$ - $Date$

+ *

+ * @author Chris Mair

+ */

+public final class PortTestUtil {

+

+    private static final int DEFAULT_SERVER_CONTROL_PORT = 21;

+    private static final String FTP_SERVER_PORT_PROPERTY = "ftp.server.port";

+    

+    /**

+     * Return the port number to use for the FTP server control port. If the "ftp.server.port"

+     * system property is defined, then use that value (converted to an integer), otherwise

+     * return the default port number of 21.

+     * 

+     * @return the port number to use for the FTP server control port

+     */

+    public static int getFtpServerControlPort() {

+        String systemProperty = System.getProperty(FTP_SERVER_PORT_PROPERTY);

+        return (systemProperty == null) ? DEFAULT_SERVER_CONTROL_PORT : Integer.parseInt(systemProperty);

+    }

+    

+}