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