1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.nio.tests.java.nio.channels; 19 20import java.io.IOException; 21import java.io.InputStream; 22import java.io.OutputStream; 23import java.net.InetSocketAddress; 24import java.net.ServerSocket; 25import java.net.Socket; 26import java.nio.ByteBuffer; 27import java.nio.channels.AsynchronousCloseException; 28import java.nio.channels.ClosedChannelException; 29import java.nio.channels.IllegalBlockingModeException; 30import java.nio.channels.NotYetBoundException; 31import java.nio.channels.SelectionKey; 32import java.nio.channels.ServerSocketChannel; 33import java.nio.channels.SocketChannel; 34import java.nio.channels.spi.SelectorProvider; 35 36import junit.framework.TestCase; 37import tests.support.Support_PortManager; 38 39/* 40 * test for ServerSocketChannel 41 */ 42public class ServerSocketChannelTest extends TestCase { 43 44 private static final int CAPACITY_NORMAL = 200; 45 46 private static final int CAPACITY_64KB = 65536; 47 48 private static final int TIME_UNIT = 200; 49 50 private InetSocketAddress localAddr1; 51 52 private ServerSocketChannel serverChannel; 53 54 private SocketChannel clientChannel; 55 56 protected void setUp() throws Exception { 57 super.setUp(); 58 this.localAddr1 = new InetSocketAddress( 59 "127.0.0.1", Support_PortManager 60 .getNextPort()); 61 this.serverChannel = ServerSocketChannel.open(); 62 this.clientChannel = SocketChannel.open(); 63 } 64 65 protected void tearDown() throws Exception { 66 if (null != this.serverChannel) { 67 try { 68 this.serverChannel.close(); 69 } catch (Exception e) { 70 //ignore 71 } 72 73 } 74 if (null != this.clientChannel) { 75 try { 76 this.clientChannel.close(); 77 } catch (Exception e) { 78 //ignore 79 } 80 } 81 super.tearDown(); 82 } 83 84 // ------------------------------------------------------------------- 85 // Test for methods in abstract class. 86 // ------------------------------------------------------------------- 87 88 /* 89 * Test method for 'java.nio.channels.ServerSocketChannel.validOps()' 90 */ 91 public void testValidOps() { 92 MockServerSocketChannel testMSChnlnull = new MockServerSocketChannel( 93 null); 94 MockServerSocketChannel testMSChnl = new MockServerSocketChannel( 95 SelectorProvider.provider()); 96 assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps()); 97 assertEquals(SelectionKey.OP_ACCEPT, testMSChnl.validOps()); 98 assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnull.validOps()); 99 100 } 101 102 /* 103 * Test method for 'java.nio.channels.ServerSocketChannel.open()' 104 */ 105 public void testOpen() { 106 MockServerSocketChannel testMSChnl = new MockServerSocketChannel(null); 107 MockServerSocketChannel testMSChnlnotnull = new MockServerSocketChannel( 108 SelectorProvider.provider()); 109 assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnotnull.validOps()); 110 assertNull(testMSChnl.provider()); 111 assertNotNull(testMSChnlnotnull.provider()); 112 assertNotNull(this.serverChannel.provider()); 113 assertEquals(testMSChnlnotnull.provider(), this.serverChannel 114 .provider()); 115 } 116 117 // ------------------------------------------------------------------- 118 // Test for socket() 119 // ------------------------------------------------------------------- 120 121 /* 122 * Test method for 'java.nio.channels.ServerSocketChannel.socket()' 123 */ 124 public void testSocket_Block_BeforeClose() throws Exception { 125 assertTrue(this.serverChannel.isOpen()); 126 assertTrue(this.serverChannel.isBlocking()); 127 ServerSocket s1 = this.serverChannel.socket(); 128 assertFalse(s1.isClosed()); 129 assertSocketNotAccepted(s1); 130 ServerSocket s2 = this.serverChannel.socket(); 131 // same 132 assertSame(s1, s2); 133 134 // socket close makes the channel close 135 s1.close(); 136 assertFalse(this.serverChannel.isOpen()); 137 138 } 139 140 public void testSocket_NonBlock_BeforeClose() throws Exception { 141 assertTrue(this.serverChannel.isOpen()); 142 this.serverChannel.configureBlocking(false); 143 ServerSocket s1 = this.serverChannel.socket(); 144 assertFalse(s1.isClosed()); 145 assertSocketNotAccepted(s1); 146 ServerSocket s2 = this.serverChannel.socket(); 147 // same 148 assertSame(s1, s2); 149 150 // socket close makes the channel close 151 s1.close(); 152 assertFalse(this.serverChannel.isOpen()); 153 154 } 155 156 public void testSocket_Block_Closed() throws Exception { 157 this.serverChannel.close(); 158 assertFalse(this.serverChannel.isOpen()); 159 assertTrue(this.serverChannel.isBlocking()); 160 ServerSocket s1 = this.serverChannel.socket(); 161 assertTrue(s1.isClosed()); 162 assertSocketNotAccepted(s1); 163 ServerSocket s2 = this.serverChannel.socket(); 164 // same 165 assertSame(s1, s2); 166 } 167 168 public void testSocket_NonBlock_Closed() throws Exception { 169 this.serverChannel.configureBlocking(false); 170 this.serverChannel.close(); 171 assertFalse(this.serverChannel.isBlocking()); 172 assertFalse(this.serverChannel.isOpen()); 173 ServerSocket s1 = this.serverChannel.socket(); 174 assertTrue(s1.isClosed()); 175 assertSocketNotAccepted(s1); 176 ServerSocket s2 = this.serverChannel.socket(); 177 // same 178 assertSame(s1, s2); 179 } 180 181 private void assertSocketNotAccepted(ServerSocket s) throws IOException { 182 assertFalse(s.isBound()); 183 assertNull(s.getInetAddress()); 184 assertEquals(-1, s.getLocalPort()); 185 assertNull(s.getLocalSocketAddress()); 186 try { 187 assertEquals(0, s.getSoTimeout()); 188 } catch (IOException expected) { 189 // Android doesn't cache the timeout, so the getsockopt(2) fails and throws. 190 } 191 } 192 193 public void testChannelBasicStatus() { 194 ServerSocket gotSocket = this.serverChannel.socket(); 195 assertFalse(gotSocket.isClosed()); 196 assertTrue(this.serverChannel.isBlocking()); 197 assertFalse(this.serverChannel.isRegistered()); 198 assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps()); 199 assertEquals(SelectorProvider.provider(), this.serverChannel.provider()); 200 } 201 202 // ------------------------------------------------------------------- 203 // Test for accept() 204 // ------------------------------------------------------------------- 205 206 /* 207 * Test method for 'java.nio.channels.ServerSocketChannel.accept()' 208 */ 209 210 public void testAccept_Block_NotYetBound() throws IOException { 211 assertTrue(this.serverChannel.isOpen()); 212 assertTrue(this.serverChannel.isBlocking()); 213 try { 214 this.serverChannel.accept(); 215 fail("Should throw NotYetBoundException"); 216 } catch (NotYetBoundException e) { 217 // correct 218 } 219 } 220 221 public void testAccept_NonBlock_NotYetBound() throws IOException { 222 assertTrue(this.serverChannel.isOpen()); 223 this.serverChannel.configureBlocking(false); 224 try { 225 this.serverChannel.accept(); 226 fail("Should throw NotYetBoundException"); 227 } catch (NotYetBoundException e) { 228 // correct 229 } 230 } 231 232 public void testAccept_ClosedChannel() throws Exception { 233 this.serverChannel.close(); 234 assertFalse(this.serverChannel.isOpen()); 235 try { 236 this.serverChannel.accept(); 237 fail("Should throw ClosedChannelException"); 238 } catch (ClosedChannelException e) { 239 // OK. 240 } 241 } 242 243 public void testAccept_Block_NoConnect() throws IOException { 244 assertTrue(this.serverChannel.isBlocking()); 245 ServerSocket gotSocket = this.serverChannel.socket(); 246 gotSocket.bind(localAddr1); 247 // blocking mode , will block and wait for ever... 248 // so must close the server channel with another thread. 249 new Thread() { 250 public void run() { 251 try { 252 Thread.sleep(TIME_UNIT); 253 ServerSocketChannelTest.this.serverChannel.close(); 254 } catch (Exception e) { 255 fail("Fail to close the server channel because of" 256 + e.getClass().getName()); 257 } 258 } 259 }.start(); 260 try { 261 this.serverChannel.accept(); 262 fail("Should throw a AsynchronousCloseException"); 263 } catch (AsynchronousCloseException e) { 264 // OK. 265 } 266 } 267 268 public void testAccept_NonBlock_NoConnect() throws IOException { 269 ServerSocket gotSocket = this.serverChannel.socket(); 270 gotSocket.bind(localAddr1); 271 this.serverChannel.configureBlocking(false); 272 // non-blocking mode , will immediately return 273 assertNull(this.serverChannel.accept()); 274 } 275 276 /** 277 * @tests ServerSocketChannel#accept().socket() 278 */ 279 public void test_read_Blocking_RealData() throws IOException { 280 serverChannel.socket().bind(localAddr1); 281 ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL); 282 283 for (int i = 0; i < CAPACITY_NORMAL; i++) { 284 buf.put((byte) i); 285 } 286 clientChannel.connect(localAddr1); 287 Socket serverSocket = serverChannel.accept().socket(); 288 InputStream in = serverSocket.getInputStream(); 289 buf.flip(); 290 clientChannel.write(buf); 291 clientChannel.close(); 292 assertReadResult(in,CAPACITY_NORMAL); 293 } 294 295 /** 296 * Asserts read content. The read content should contain <code>size</code> 297 * bytes, and the value should be a sequence from 0 to size-1 298 * ([0,1,...size-1]). Otherwise, the method throws Exception. 299 * 300 */ 301 private void assertReadResult(InputStream in, int size) throws IOException{ 302 byte[] readContent = new byte[size + 1]; 303 int count = 0; 304 int total = 0; 305 while ((count = in.read(readContent, total, size + 1 - total)) != -1) { 306 total = total + count; 307 } 308 assertEquals(size, total); 309 for (int i = 0; i < size; i++) { 310 assertEquals((byte) i, readContent[i]); 311 } 312 } 313 314 /** 315 * @tests ServerSocketChannel#accept().socket() 316 */ 317 public void test_read_NonBlocking_RealData() throws Exception { 318 serverChannel.configureBlocking(false); 319 serverChannel.socket().bind(localAddr1); 320 ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL); 321 for (int i = 0; i < CAPACITY_NORMAL; i++) { 322 buf.put((byte) i); 323 } 324 buf.flip(); 325 clientChannel.connect(localAddr1); 326 Socket serverSocket = serverChannel.accept().socket(); 327 InputStream in = serverSocket.getInputStream(); 328 clientChannel.write(buf); 329 clientChannel.close(); 330 assertReadResult(in,CAPACITY_NORMAL); 331 } 332 333 /** 334 * @tests ServerSocketChannel#accept().socket() 335 */ 336 public void test_write_Blocking_RealData() throws IOException { 337 assertTrue(serverChannel.isBlocking()); 338 ServerSocket serverSocket = serverChannel.socket(); 339 serverSocket.bind(localAddr1); 340 341 byte[] writeContent = new byte[CAPACITY_NORMAL]; 342 for (int i = 0; i < writeContent.length; i++) { 343 writeContent[i] = (byte) i; 344 } 345 clientChannel.connect(localAddr1); 346 Socket socket = serverChannel.accept().socket(); 347 OutputStream out = socket.getOutputStream(); 348 out.write(writeContent); 349 out.flush(); 350 socket.close(); 351 assertWriteResult(CAPACITY_NORMAL); 352 } 353 354 355 /** 356 * @tests ServerSocketChannel#accept().socket() 357 */ 358 public void test_write_NonBlocking_RealData() throws Exception { 359 serverChannel.configureBlocking(false); 360 ServerSocket serverSocket = serverChannel.socket(); 361 serverSocket.bind(localAddr1); 362 363 byte[] writeContent = new byte[CAPACITY_NORMAL]; 364 for (int i = 0; i < CAPACITY_NORMAL; i++) { 365 writeContent[i] = (byte) i; 366 } 367 clientChannel.connect(localAddr1); 368 Socket clientSocket = serverChannel.accept().socket(); 369 OutputStream out = clientSocket.getOutputStream(); 370 out.write(writeContent); 371 clientSocket.close(); 372 assertWriteResult(CAPACITY_NORMAL); 373 } 374 375 /** 376 * @throws InterruptedException 377 * @tests ServerSocketChannel#accept().socket() 378 */ 379 public void test_read_LByteBuffer_Blocking_ReadWriteRealLargeData() 380 throws IOException, InterruptedException { 381 serverChannel.socket().bind(localAddr1); 382 ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB); 383 for (int i = 0; i < CAPACITY_64KB; i++) { 384 buf.put((byte) i); 385 } 386 buf.flip(); 387 clientChannel.connect(localAddr1); 388 WriteChannelThread writeThread = new WriteChannelThread(clientChannel, buf); 389 writeThread.start(); 390 Socket socket = serverChannel.accept().socket(); 391 InputStream in = socket.getInputStream(); 392 assertReadResult(in,CAPACITY_64KB); 393 writeThread.join(); 394 // check if the thread threw any exceptions 395 if (writeThread.exception != null) { 396 throw writeThread.exception; 397 } 398 } 399 400 class WriteChannelThread extends Thread { 401 SocketChannel channel; 402 ByteBuffer buffer; 403 IOException exception; 404 405 public WriteChannelThread(SocketChannel channel, ByteBuffer buffer) { 406 this.channel = channel; 407 this.buffer = buffer; 408 } 409 410 public void run() { 411 try { 412 channel.write(buffer); 413 channel.close(); 414 } catch (IOException e) { 415 exception = e; 416 } 417 } 418 } 419 420 /** 421 * @tests ServerSocketChannel#accept().socket() 422 */ 423 public void test_read_LByteBuffer_NonBlocking_ReadWriteRealLargeData() 424 throws Exception { 425 serverChannel.configureBlocking(false); 426 serverChannel.socket().bind(localAddr1); 427 ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB); 428 for (int i = 0; i < CAPACITY_64KB; i++) { 429 buf.put((byte) i); 430 } 431 buf.flip(); 432 clientChannel.connect(localAddr1); 433 WriteChannelThread writeThread = new WriteChannelThread(clientChannel, buf); 434 writeThread.start(); 435 Socket socket = serverChannel.accept().socket(); 436 InputStream in = socket.getInputStream(); 437 assertReadResult(in,CAPACITY_64KB); 438 writeThread.join(); 439 // check if the thread threw any exceptions 440 if (writeThread.exception != null) { 441 throw writeThread.exception; 442 } 443 } 444 445 /** 446 * @tests ServerSocketChannel#accept().socket() 447 */ 448 public void test_write_LByteBuffer_NonBlocking_ReadWriteRealLargeData() 449 throws Exception { 450 serverChannel.configureBlocking(false); 451 serverChannel.socket().bind(localAddr1); 452 byte[] writeContent = new byte[CAPACITY_64KB]; 453 for (int i = 0; i < writeContent.length; i++) { 454 writeContent[i] = (byte) i; 455 } 456 clientChannel.connect(localAddr1); 457 Socket socket = serverChannel.accept().socket(); 458 WriteSocketThread writeThread = new WriteSocketThread(socket, writeContent); 459 writeThread.start(); 460 assertWriteResult(CAPACITY_64KB); 461 writeThread.join(); 462 // check if the thread threw any exceptions 463 if (writeThread.exception != null) { 464 throw writeThread.exception; 465 } 466 } 467 468 class WriteSocketThread extends Thread { 469 Socket socket; 470 byte[] buffer; 471 IOException exception; 472 473 public WriteSocketThread(Socket socket, byte[] buffer) { 474 this.socket = socket; 475 this.buffer = buffer; 476 } 477 478 public void run() { 479 try { 480 OutputStream out = socket.getOutputStream(); 481 out.write(buffer); 482 socket.close(); 483 } catch (IOException e) { 484 exception = e; 485 } 486 } 487 } 488 489 /** 490 * @tests ServerSocketChannel#accept().socket() 491 */ 492 public void test_write_LByteBuffer_Blocking_ReadWriteRealLargeData() 493 throws Exception { 494 serverChannel.socket().bind(localAddr1); 495 byte[] writeContent = new byte[CAPACITY_64KB]; 496 for (int i = 0; i < writeContent.length; i++) { 497 writeContent[i] = (byte) i; 498 } 499 clientChannel.connect(localAddr1); 500 Socket socket = serverChannel.accept().socket(); 501 WriteSocketThread writeThread = new WriteSocketThread(socket, writeContent); 502 writeThread.start(); 503 assertWriteResult(CAPACITY_64KB); 504 writeThread.join(); 505 // check if the thread threw any exceptions 506 if (writeThread.exception != null) { 507 throw writeThread.exception; 508 } 509 } 510 511 /** 512 * Uses SocketChannel.read(ByteBuffer) to verify write result. 513 */ 514 private void assertWriteResult(int size) throws IOException{ 515 ByteBuffer buf = ByteBuffer.allocate(size + 1); 516 int count = 0; 517 int total = 0; 518 long beginTime = System.currentTimeMillis(); 519 while ((count = clientChannel.read(buf)) != -1) { 520 total = total + count; 521 // 10s timeout to avoid dead loop 522 if (System.currentTimeMillis() - beginTime > 10000){ 523 break; 524 } 525 } 526 assertEquals(total, size); 527 buf.flip(); 528 for (int i = 0; i < count; i++) { 529 assertEquals((byte) i, buf.get(i)); 530 } 531 } 532 533 /** 534 * @tests ServerSocketChannel#socket().getSoTimeout() 535 */ 536 public void test_accept_SOTIMEOUT() throws IOException { 537 // regression test for Harmony-707 538 final int SO_TIMEOUT = 10; 539 ServerSocketChannel sc = ServerSocketChannel.open(); 540 try { 541 ServerSocket ss = sc.socket(); 542 ss.bind(localAddr1); 543 sc.configureBlocking(false); 544 ss.setSoTimeout(SO_TIMEOUT); 545 SocketChannel client = sc.accept(); 546 // non blocking mode, returns null since there are no pending connections. 547 assertNull(client); 548 int soTimeout = ss.getSoTimeout(); 549 // Harmony fails here. 550 assertEquals(SO_TIMEOUT, soTimeout); 551 } finally { 552 sc.close(); 553 } 554 } 555 556 /** 557 * @tests ServerSocket#socket().accept() 558 */ 559 public void test_socket_accept_Blocking_NotBound() throws IOException { 560 // regression test for Harmony-748 561 ServerSocket gotSocket = serverChannel.socket(); 562 serverChannel.configureBlocking(true); 563 try { 564 gotSocket.accept(); 565 fail("Should throw an IllegalBlockingModeException"); 566 } catch (IllegalBlockingModeException e) { 567 // expected 568 } 569 serverChannel.close(); 570 try { 571 gotSocket.accept(); 572 fail("Should throw an IllegalBlockingModeException"); 573 } catch (IllegalBlockingModeException e) { 574 // expected 575 } 576 } 577 578 /** 579 * @tests ServerSocket#socket().accept() 580 */ 581 public void test_socket_accept_Nonblocking_NotBound() throws IOException { 582 // regression test for Harmony-748 583 ServerSocket gotSocket = serverChannel.socket(); 584 serverChannel.configureBlocking(false); 585 try { 586 gotSocket.accept(); 587 fail("Should throw an IllegalBlockingModeException"); 588 } catch (IllegalBlockingModeException e) { 589 // expected 590 } 591 serverChannel.close(); 592 try { 593 gotSocket.accept(); 594 fail("Should throw an IllegalBlockingModeException"); 595 } catch (IllegalBlockingModeException e) { 596 // expected 597 } 598 } 599 600 /** 601 * @tests ServerSocket#socket().accept() 602 */ 603 public void test_socket_accept_Nonblocking_Bound() throws IOException { 604 // regression test for Harmony-748 605 serverChannel.configureBlocking(false); 606 ServerSocket gotSocket = serverChannel.socket(); 607 gotSocket.bind(localAddr1); 608 try { 609 gotSocket.accept(); 610 fail("Should throw an IllegalBlockingModeException"); 611 } catch (IllegalBlockingModeException e) { 612 // expected 613 } 614 serverChannel.close(); 615 try { 616 gotSocket.accept(); 617 fail("Should throw a ClosedChannelException"); 618 } catch (ClosedChannelException e) { 619 // expected 620 } 621 } 622 623 /** 624 * @tests ServerSocket#socket().accept() 625 */ 626 public void test_socket_accept_Blocking_Bound() throws IOException { 627 // regression test for Harmony-748 628 serverChannel.configureBlocking(true); 629 ServerSocket gotSocket = serverChannel.socket(); 630 gotSocket.bind(localAddr1); 631 serverChannel.close(); 632 try { 633 gotSocket.accept(); 634 fail("Should throw a ClosedChannelException"); 635 } catch (ClosedChannelException e) { 636 // expected 637 } 638 } 639 /** 640 * Regression test for HARMONY-4961 641 */ 642 public void test_socket_getLocalPort() throws IOException { 643 serverChannel.socket().bind(localAddr1); 644 clientChannel.connect(localAddr1); 645 SocketChannel myChannel = serverChannel.accept(); 646 int port = myChannel.socket().getLocalPort(); 647 assertEquals(localAddr1.getPort(), port); 648 myChannel.close(); 649 clientChannel.close(); 650 serverChannel.close(); 651 } 652 653 /** 654 * Regression test for HARMONY-6375 655 */ 656 public void test_accept_configureBlocking() throws Exception { 657 InetSocketAddress localAddr = new InetSocketAddress("localhost", 0); 658 serverChannel.socket().bind(localAddr); 659 660 // configure the channel non-blocking 661 // when it is accepting in main thread 662 new Thread() { 663 public void run() { 664 try { 665 Thread.sleep(TIME_UNIT); 666 serverChannel.configureBlocking(false); 667 serverChannel.close(); 668 } catch (Exception e) { 669 e.printStackTrace(); 670 } 671 } 672 }.start(); 673 674 try { 675 serverChannel.accept(); 676 fail("should throw AsynchronousCloseException"); 677 } catch (AsynchronousCloseException e) { 678 // expected 679 } 680 serverChannel.close(); 681 } 682} 683