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