Home | History | Annotate | Download | only in session
      1 /*
      2  * Copyright 2007 the original author or authors.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package org.mockftpserver.core.session;
     17 
     18 import java.io.ByteArrayInputStream;
     19 import java.io.ByteArrayOutputStream;
     20 import java.io.IOException;
     21 import java.io.InputStream;
     22 import java.util.HashMap;
     23 import java.util.ListResourceBundle;
     24 import java.util.Map;
     25 import java.util.ResourceBundle;
     26 
     27 
     28 import org.apache.log4j.Logger;
     29 import org.mockftpserver.core.command.Command;
     30 import org.mockftpserver.core.command.CommandHandler;
     31 import org.mockftpserver.core.command.CommandNames;
     32 import org.mockftpserver.core.command.InvocationRecord;
     33 import org.mockftpserver.core.session.DefaultSession;
     34 import org.mockftpserver.core.session.Session;
     35 import org.mockftpserver.core.socket.StubSocket;
     36 import org.mockftpserver.stub.command.AbstractStubCommandHandler;
     37 import org.mockftpserver.stub.command.ConnectCommandHandler;
     38 import org.mockftpserver.test.AbstractTest;
     39 
     40 /**
     41  * Tests for the DefaultSession class that require the session (thread) to be running/active.
     42  *
     43  * @version $Revision$ - $Date$
     44  *
     45  * @author Chris Mair
     46  */
     47 public final class DefaultSession_RunTest extends AbstractTest {
     48 
     49     private static final Logger LOG = Logger.getLogger(DefaultSession_RunTest.class);
     50     private static final Command COMMAND = new Command("USER", EMPTY);
     51     private static final int REPLY_CODE = 100;
     52     private static final String REPLY_TEXT = "sample text description";
     53 
     54     private DefaultSession session;
     55     private ByteArrayOutputStream outputStream;
     56     private Map commandHandlerMap;
     57     private StubSocket stubSocket;
     58     private boolean commandHandled = false;
     59 
     60     /**
     61      * Perform initialization before each test
     62      *
     63      * @see org.mockftpserver.test.AbstractTest#setUp()
     64      */
     65     protected void setUp() throws Exception {
     66         super.setUp();
     67         commandHandlerMap = new HashMap();
     68         outputStream = new ByteArrayOutputStream();
     69     }
     70 
     71     /**
     72      * Test that the CommandHandler is properly initialized and passed the expected parameters
     73      */
     74     public void testInvocationOfCommandHandler() throws Exception {
     75         AbstractStubCommandHandler commandHandler = new AbstractStubCommandHandler() {
     76             public void handleCommand(Command command, Session cmdSession, InvocationRecord invocationRecord) {
     77                 assertEquals("command", COMMAND, command);
     78                 assertSame("session", session, cmdSession);
     79                 assertEquals("InvocationRecord: command", COMMAND, invocationRecord.getCommand());
     80                 assertEquals("InvocationRecord: clientHost", DEFAULT_HOST, invocationRecord.getClientHost());
     81                 commandHandled = true;
     82             }
     83         };
     84         runCommandAndVerifyOutput(commandHandler, "");
     85     }
     86 
     87     /**
     88      * Test the close() method
     89      *
     90      * @throws IOException
     91      */
     92     public void testClose() throws Exception {
     93         CommandHandler commandHandler = new AbstractStubCommandHandler() {
     94             public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
     95                 session.close();
     96                 commandHandled = true;
     97             }
     98         };
     99         runCommandAndVerifyOutput(commandHandler, "");
    100         assertFalse("socket should not be closed", stubSocket.isClosed());
    101     }
    102 
    103     /**
    104      * Test the getClientHost() method
    105      *
    106      * @throws IOException
    107      */
    108     public void testGetClientHost() throws Exception {
    109         CommandHandler commandHandler = new AbstractStubCommandHandler() {
    110             public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
    111                 commandHandled = true;
    112             }
    113         };
    114         runCommandAndVerifyOutput(commandHandler, "");
    115         LOG.info("clientHost=" + session.getClientHost());
    116         assertEquals("clientHost", DEFAULT_HOST, session.getClientHost());
    117     }
    118 
    119     /**
    120      * Test the sendReply() method, when the specified reply text is null
    121      */
    122     public void testSendReply_NullReplyText() throws Exception {
    123         CommandHandler commandHandler = new AbstractStubCommandHandler() {
    124             public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
    125                 session.sendReply(REPLY_CODE, null);
    126                 commandHandled = true;
    127             }
    128         };
    129         runCommandAndVerifyOutput(commandHandler, Integer.toString(REPLY_CODE));
    130     }
    131 
    132     /**
    133      * Test the sendReply() method, verifying that extra extra whitespace is trimmed from the reply text
    134      */
    135     public void testSendReply_TrimReplyText() throws Exception {
    136         CommandHandler commandHandler = new AbstractStubCommandHandler() {
    137             public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
    138                 session.sendReply(REPLY_CODE, " " + REPLY_TEXT + " ");
    139                 commandHandled = true;
    140             }
    141         };
    142         runCommandAndVerifyOutput(commandHandler, REPLY_CODE + " " + REPLY_TEXT);
    143     }
    144 
    145     /**
    146      * Test the sendReply() method, when the text contains multiple lines
    147      */
    148     public void testSendReply_MultiLineText() throws Exception {
    149         final String MULTILINE_REPLY_TEXT = "abc\ndef\nghi\njkl";
    150         final String FORMATTED_MULTILINE_REPLY_TEXT = "123-abc\ndef\nghi\n123 jkl";
    151 
    152         CommandHandler commandHandler = new AbstractStubCommandHandler() {
    153             public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
    154                 session.sendReply(123, MULTILINE_REPLY_TEXT);
    155                 commandHandled = true;
    156             }
    157         };
    158         runCommandAndVerifyOutput(commandHandler, FORMATTED_MULTILINE_REPLY_TEXT);
    159     }
    160 
    161     /**
    162      * Test the sendReply() method when the reply code has associated reply text
    163      */
    164     public void testSendReply_ReplyText() throws Exception {
    165         CommandHandler commandHandler = new AbstractStubCommandHandler() {
    166             public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
    167                 session.sendReply(REPLY_CODE, REPLY_TEXT);
    168                 commandHandled = true;
    169             }
    170         };
    171         runCommandAndVerifyOutput(commandHandler, REPLY_CODE + " " + REPLY_TEXT);
    172     }
    173 
    174     // -------------------------------------------------------------------------
    175     // Internal Helper Methods
    176     // -------------------------------------------------------------------------
    177 
    178     /**
    179      * Create and return a DefaultSession object that reads from an InputStream with the specified
    180      * contents and writes to the predefined outputStrean ByteArrayOutputStream. Also, save the
    181      * StubSocket being used in the stubSocket attribute.
    182      *
    183      * @param inputStreamContents - the contents of the input stream
    184      * @return the DefaultSession
    185      */
    186     private DefaultSession createDefaultSession(CommandHandler commandHandler) {
    187         stubSocket = createTestSocket(COMMAND.getName());
    188         commandHandlerMap.put(COMMAND.getName(), commandHandler);
    189 
    190         ConnectCommandHandler connectCommandHandler = new ConnectCommandHandler();
    191 
    192         ResourceBundle replyTextBundle = new ListResourceBundle() {
    193             protected Object[][] getContents() {
    194                 return new Object[][] {
    195                         { "220", "Reply for 220" },
    196                 };
    197             }
    198         };
    199         connectCommandHandler.setReplyTextBundle(replyTextBundle);
    200         commandHandlerMap.put(CommandNames.CONNECT, connectCommandHandler);
    201 
    202         return new DefaultSession(stubSocket, commandHandlerMap);
    203     }
    204 
    205     /**
    206      * Create and return a StubSocket that reads from an InputStream with the specified contents and
    207      * writes to the predefined outputStrean ByteArrayOutputStream.
    208      *
    209      * @param inputStreamContents - the contents of the input stream
    210      * @return the StubSocket
    211      */
    212     private StubSocket createTestSocket(String inputStreamContents) {
    213         InputStream inputStream = new ByteArrayInputStream(inputStreamContents.getBytes());
    214         return new StubSocket(DEFAULT_HOST, inputStream, outputStream);
    215     }
    216 
    217     /**
    218      * Run the command represented by the CommandHandler and verify that the session output from the
    219      * control socket contains the expected output text.
    220      *
    221      * @param commandHandler - the CommandHandler to invoke
    222      * @param expectedOutput - the text expected within the session output
    223      * @throws InterruptedException
    224      */
    225     private void runCommandAndVerifyOutput(CommandHandler commandHandler, String expectedOutput)
    226             throws InterruptedException {
    227         session = createDefaultSession(commandHandler);
    228 
    229         Thread thread = new Thread(session);
    230         thread.start();
    231 
    232         for (int i = 0; !commandHandled && i < 10; i++) {
    233             Thread.sleep(50L);
    234         }
    235 
    236         session.close();
    237         thread.join();
    238 
    239         assertEquals("commandHandled", true, commandHandled);
    240 
    241         String output = outputStream.toString();
    242         LOG.info("output=[" + output.trim() + "]");
    243         assertTrue("line ends with \\r\\n",
    244                 output.charAt(output.length()-2) == '\r' && output.charAt(output.length()-1) == '\n');
    245         assertTrue("output: expected [" + expectedOutput + "]", output.indexOf(expectedOutput) != -1);
    246     }
    247 
    248 }
    249