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