/* | |
* 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); | |
} | |
} |