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