DefaultSessionTest.java revision bda3441225e0607b5ced8b538123fd7c7a417910
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 */
16package org.mockftpserver.core.session;
17
18import org.apache.log4j.Logger;
19import org.mockftpserver.core.MockFtpServerException;
20import org.mockftpserver.core.command.Command;
21import org.mockftpserver.core.socket.StubServerSocket;
22import org.mockftpserver.core.socket.StubServerSocketFactory;
23import org.mockftpserver.core.socket.StubSocket;
24import org.mockftpserver.core.socket.StubSocketFactory;
25import org.mockftpserver.core.util.AssertFailedException;
26import org.mockftpserver.test.AbstractTestCase;
27
28import java.io.ByteArrayInputStream;
29import java.io.ByteArrayOutputStream;
30import java.io.IOException;
31import java.io.InputStream;
32import java.net.InetAddress;
33import java.net.SocketTimeoutException;
34import java.util.Collections;
35import java.util.HashMap;
36import java.util.Map;
37
38/**
39 * Tests for the DefaultSession class
40 *
41 * @version $Revision$ - $Date$
42 *
43 * @author Chris Mair
44 */
45public final class DefaultSessionTest extends AbstractTestCase {
46
47    private static final Logger LOG = Logger.getLogger(DefaultSessionTest.class);
48    private static final String DATA = "sample data 123";
49    private static final int PORT = 197;
50    private static final String NAME1 = "name1";
51    private static final String NAME2 = "name2";
52    private static final Object VALUE = "value";
53
54    private DefaultSession session;
55    private ByteArrayOutputStream outputStream;
56    private Map commandHandlerMap;
57    private StubSocket stubSocket;
58    private InetAddress clientHost;
59
60    /**
61     * Perform initialization before each test
62     *
63     * @see org.mockftpserver.test.AbstractTestCase#setUp()
64     */
65    protected void setUp() throws Exception {
66        super.setUp();
67
68        commandHandlerMap = new HashMap();
69        outputStream = new ByteArrayOutputStream();
70        session = createDefaultSession("");
71        clientHost = InetAddress.getLocalHost();
72    }
73
74    /**
75     * @see org.mockftpserver.test.AbstractTestCase#tearDown()
76     */
77    protected void tearDown() throws Exception {
78        super.tearDown();
79    }
80
81    /**
82     * Test the Constructor when the control socket is null
83     */
84    public void testConstructor_NullControlSocket() {
85        try {
86            new DefaultSession(null, commandHandlerMap);
87            fail("Expected AssertFailedException");
88        }
89        catch (AssertFailedException expected) {
90            LOG.info("Expected: " + expected);
91        }
92    }
93
94    /**
95     * Test the Constructor when the command handler Map is null
96     */
97    public void testConstructor_NullCommandHandlerMap() {
98        try {
99            new DefaultSession(stubSocket, null);
100            fail("Expected AssertFailedException");
101        }
102        catch (AssertFailedException expected) {
103            LOG.info("Expected: " + expected);
104        }
105    }
106
107    /**
108     * Test the setClientDataPort() method
109     */
110    public void testSetClientDataPort() {
111        StubSocket stubSocket = createTestSocket("");
112        StubSocketFactory stubSocketFactory = new StubSocketFactory(stubSocket);
113        session.socketFactory = stubSocketFactory;
114        session.setClientDataPort(PORT);
115        session.setClientDataHost(clientHost);
116        session.openDataConnection();
117        assertEquals("data port", PORT, stubSocketFactory.requestedDataPort);
118    }
119
120    /**
121     * Test the setClientDataPort() method after the session was in passive data mode
122     */
123    public void testSetClientDataPort_AfterPassiveConnectionMode() throws IOException {
124        StubServerSocket stubServerSocket = new StubServerSocket(PORT);
125        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);
126        session.serverSocketFactory = stubServerSocketFactory;
127
128        session.switchToPassiveMode();
129        assertFalse("server socket closed", stubServerSocket.isClosed());
130        assertNotNull("passiveModeDataSocket", session.passiveModeDataSocket);
131        session.setClientDataPort(PORT);
132
133        // Make sure that any passive mode connection info is cleared out
134        assertTrue("server socket closed", stubServerSocket.isClosed());
135        assertNull("passiveModeDataSocket should be null", session.passiveModeDataSocket);
136    }
137
138    /**
139     * Test the setClientHost() method
140     */
141    public void testSetClientHost() throws Exception {
142        StubSocket stubSocket = createTestSocket("");
143        StubSocketFactory stubSocketFactory = new StubSocketFactory(stubSocket);
144        session.socketFactory = stubSocketFactory;
145        session.setClientDataHost(clientHost);
146        session.openDataConnection();
147        assertEquals("client host", clientHost, stubSocketFactory.requestedHost);
148    }
149
150    /**
151     * Test the openDataConnection(), setClientDataPort() and setClientDataHost() methods
152     */
153    public void testOpenDataConnection() {
154        StubSocket stubSocket = createTestSocket("");
155        StubSocketFactory stubSocketFactory = new StubSocketFactory(stubSocket);
156        session.socketFactory = stubSocketFactory;
157
158        // Use default client data port
159        session.setClientDataHost(clientHost);
160        session.openDataConnection();
161        assertEquals("data port", DefaultSession.DEFAULT_CLIENT_DATA_PORT, stubSocketFactory.requestedDataPort);
162        assertEquals("client host", clientHost, stubSocketFactory.requestedHost);
163
164        // Set client data port explicitly
165        session.setClientDataPort(PORT);
166        session.setClientDataHost(clientHost);
167        session.openDataConnection();
168        assertEquals("data port", PORT, stubSocketFactory.requestedDataPort);
169        assertEquals("client host", clientHost, stubSocketFactory.requestedHost);
170    }
171
172    /**
173     * Test the OpenDataConnection method, when in passive mode and no incoming connection is
174     * initiated
175     */
176    public void testOpenDataConnection_PassiveMode_NoConnection() throws IOException {
177
178        StubServerSocket stubServerSocket = new StubServerSocket(PORT);
179        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);
180        session.serverSocketFactory = stubServerSocketFactory;
181
182        session.switchToPassiveMode();
183
184        try {
185            session.openDataConnection();
186            fail("Expected MockFtpServerException");
187        }
188        catch (MockFtpServerException expected) {
189            LOG.info("Expected: " + expected);
190            assertSame("cause", SocketTimeoutException.class, expected.getCause().getClass());
191        }
192    }
193
194    /**
195     * Test the OpenDataConnection method, when the clientHost has not been set
196     */
197    public void testOpenDataConnection_NullClientHost() {
198        try {
199            session.openDataConnection();
200            fail("Expected AssertFailedException");
201        }
202        catch (AssertFailedException expected) {
203            LOG.info("Expected: " + expected);
204        }
205    }
206
207    /**
208     * Test the readData() method
209     */
210    public void testReadData() {
211        StubSocket stubSocket = createTestSocket(DATA);
212        session.socketFactory = new StubSocketFactory(stubSocket);
213        session.setClientDataHost(clientHost);
214
215        session.openDataConnection();
216        byte[] data = session.readData();
217        LOG.info("data=[" + new String(data) + "]");
218        assertEquals("data", DATA.getBytes(), data);
219    }
220
221    /**
222     * Test the readData() method after switching to passive mode
223     */
224    public void testReadData_PassiveMode() throws IOException {
225        StubSocket stubSocket = createTestSocket(DATA);
226        StubServerSocket stubServerSocket = new StubServerSocket(PORT, stubSocket);
227        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);
228        session.serverSocketFactory = stubServerSocketFactory;
229
230        session.switchToPassiveMode();
231        session.openDataConnection();
232        byte[] data = session.readData();
233        LOG.info("data=[" + new String(data) + "]");
234        assertEquals("data", DATA.getBytes(), data);
235    }
236
237    /**
238     * Test the readData(int) method
239     */
240    public void testReadData_NumBytes() {
241        final int NUM_BYTES = 5;
242        final String EXPECTED_DATA = DATA.substring(0, NUM_BYTES);
243        StubSocket stubSocket = createTestSocket(DATA);
244        session.socketFactory = new StubSocketFactory(stubSocket);
245        session.setClientDataHost(clientHost);
246
247        session.openDataConnection();
248        byte[] data = session.readData(NUM_BYTES);
249        LOG.info("data=[" + new String(data) + "]");
250        assertEquals("data", EXPECTED_DATA.getBytes(), data);
251    }
252
253    public void testReadData_NumBytes_AskForMoreBytesThanThereAre() {
254        StubSocket stubSocket = createTestSocket(DATA);
255        session.socketFactory = new StubSocketFactory(stubSocket);
256        session.setClientDataHost(clientHost);
257
258        session.openDataConnection();
259        byte[] data = session.readData(10000);
260        LOG.info("data=[" + new String(data) + "]");
261        assertEquals("data", DATA.getBytes(), data);
262    }
263
264    /**
265     * Test the closeDataConnection() method
266     */
267    public void testCloseDataConnection() {
268        StubSocket stubSocket = createTestSocket(DATA);
269        session.socketFactory = new StubSocketFactory(stubSocket);
270
271        session.setClientDataHost(clientHost);
272        session.openDataConnection();
273        session.closeDataConnection();
274        assertTrue("client data socket should be closed", stubSocket.isClosed());
275    }
276
277    /**
278     * Test the switchToPassiveMode() method
279     */
280    public void testSwitchToPassiveMode() throws IOException {
281        StubServerSocket stubServerSocket = new StubServerSocket(PORT);
282        StubServerSocketFactory stubServerSocketFactory = new StubServerSocketFactory(stubServerSocket);
283        session.serverSocketFactory = stubServerSocketFactory;
284
285        assertNull("passiveModeDataSocket starts out null", session.passiveModeDataSocket);
286        int port = session.switchToPassiveMode();
287        assertSame("passiveModeDataSocket", stubServerSocket, session.passiveModeDataSocket);
288        assertEquals("port", PORT, port);
289    }
290
291    /**
292     * Test the getServerHost() method
293     */
294    public void testGetServerHost() {
295        assertEquals("host", DEFAULT_HOST, session.getServerHost());
296    }
297
298    /**
299     * Test the getClientHost() method when the session is not yet started
300     */
301    public void testGetClientHost_NotRunning() {
302        assertNull("null", session.getClientHost());
303    }
304
305    /**
306     * Test the parseCommand() method
307     */
308    public void testParseCommand() {
309        Command command = session.parseCommand("LIST");
310        assertEquals("command name", "LIST", command.getName());
311        assertEquals("command parameters", EMPTY, command.getParameters());
312
313        command = session.parseCommand("USER user123");
314        assertEquals("command name", "USER", command.getName());
315        assertEquals("command parameters", array("user123"), command.getParameters());
316
317        command = session.parseCommand("PORT 127,0,0,1,17,37");
318        assertEquals("command name", "PORT", command.getName());
319        assertEquals("command parameters", new String[] { "127", "0", "0", "1", "17", "37" }, command
320                .getParameters());
321    }
322
323    /**
324     * Test the parseCommand() method, passing in an empty command String
325     */
326    public void testParseCommand_EmptyCommandString() {
327        try {
328            session.parseCommand("");
329            fail("Expected AssertFailedException");
330        }
331        catch (AssertFailedException expected) {
332            LOG.info("Expected: " + expected);
333        }
334    }
335
336    /**
337     * Test the sendData() method, as well as the openDataConnection() and closeDataConnection()
338     */
339    public void testSendData() {
340        StubSocket stubSocket = createTestSocket("1234567890 abcdef");
341        session.socketFactory = new StubSocketFactory(stubSocket);
342
343        session.setClientDataHost(clientHost);
344        session.openDataConnection();
345        session.sendData(DATA.getBytes(), DATA.length());
346        LOG.info("output=[" + outputStream.toString() + "]");
347        assertEquals("output", DATA, outputStream.toString());
348    }
349
350    /**
351     * Test the SendData() method, passing in a null byte[]
352     */
353    public void testSendData_Null() {
354
355        try {
356            session.sendData(null, 1);
357            fail("Expected AssertFailedException");
358        }
359        catch (AssertFailedException expected) {
360            LOG.info("Expected: " + expected);
361        }
362    }
363
364    /**
365     * Test the SendReply(int,String) method, passing in an invalid reply code
366     */
367    public void testSendReply_InvalidReplyCode() {
368
369        try {
370            session.sendReply(-66, "text");
371            fail("Expected AssertFailedException");
372        }
373        catch (AssertFailedException expected) {
374            LOG.info("Expected: " + expected);
375        }
376    }
377
378    /**
379     * Test the getAttribute() and setAttribute() methods
380     */
381    public void testGetAndSetAttribute() {
382        assertNull("name does not exist yet", session.getAttribute(NAME1));
383        session.setAttribute(NAME1, VALUE);
384        session.setAttribute(NAME2, null);
385        assertEquals("NAME1", VALUE, session.getAttribute(NAME1));
386        assertNull("NAME2", session.getAttribute(NAME2));
387        assertNull("no such name", session.getAttribute("noSuchName"));
388    }
389
390    /**
391     * Test the getAttribute() method, passing in a null name
392     */
393    public void testGetAttribute_Null() {
394        try {
395            session.getAttribute(null);
396            fail("Expected AssertFailedException");
397        }
398        catch (AssertFailedException expected) {
399            LOG.info("Expected: " + expected);
400        }
401    }
402
403    /**
404     * Test the setAttribute() method, passing in a null name
405     */
406    public void testSetAttribute_NullName() {
407        try {
408            session.setAttribute(null, VALUE);
409            fail("Expected AssertFailedException");
410        }
411        catch (AssertFailedException expected) {
412            LOG.info("Expected: " + expected);
413        }
414    }
415
416    /**
417     * Test the removeAttribute()
418     */
419    public void testRemoveAttribute() {
420        session.removeAttribute("noSuchName");      // do nothing
421        session.setAttribute(NAME1, VALUE);
422        session.removeAttribute(NAME1);
423        assertNull("NAME1", session.getAttribute(NAME1));
424    }
425
426    /**
427     * Test the removeAttribute() method, passing in a null name
428     */
429    public void testRemoveAttribute_Null() {
430        try {
431            session.removeAttribute(null);
432            fail("Expected AssertFailedException");
433        }
434        catch (AssertFailedException expected) {
435            LOG.info("Expected: " + expected);
436        }
437    }
438
439    /**
440     * Test the getAttributeNames()
441     */
442    public void testGetAttributeNames() {
443        assertEquals("No names yet", Collections.EMPTY_SET, session.getAttributeNames());
444        session.setAttribute(NAME1, VALUE);
445        assertEquals("1", Collections.singleton(NAME1), session.getAttributeNames());
446        session.setAttribute(NAME2, VALUE);
447        assertEquals("2", set(NAME1, NAME2), session.getAttributeNames());
448    }
449
450    // -------------------------------------------------------------------------
451    // Internal Helper Methods
452    // -------------------------------------------------------------------------
453
454    /**
455     * Create and return a DefaultSession object that reads from an InputStream with the specified
456     * contents and writes to the predefined outputStrean ByteArrayOutputStream. Also, save the
457     * StubSocket being used in the stubSocket attribute.
458     *
459     * @param inputStreamContents - the contents of the input stream
460     * @return the DefaultSession
461     */
462    private DefaultSession createDefaultSession(String inputStreamContents) {
463        stubSocket = createTestSocket(inputStreamContents);
464        return new DefaultSession(stubSocket, commandHandlerMap);
465    }
466
467    /**
468     * Create and return a StubSocket that reads from an InputStream with the specified contents and
469     * writes to the predefined outputStrean ByteArrayOutputStream.
470     *
471     * @param inputStreamContents - the contents of the input stream
472     * @return the StubSocket
473     */
474    private StubSocket createTestSocket(String inputStreamContents) {
475        InputStream inputStream = new ByteArrayInputStream(inputStreamContents.getBytes());
476        StubSocket stubSocket = new StubSocket(inputStream, outputStream);
477        stubSocket._setLocalAddress(DEFAULT_HOST);
478        return stubSocket;
479    }
480
481}
482