1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. 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 */ 16 17package org.apache.harmony.nio.tests.java.nio.channels; 18 19import java.io.IOException; 20import java.net.InetSocketAddress; 21import java.net.ServerSocket; 22import java.nio.ByteBuffer; 23import java.nio.channels.ClosedChannelException; 24import java.nio.channels.ClosedSelectorException; 25import java.nio.channels.Pipe; 26import java.nio.channels.SelectionKey; 27import java.nio.channels.Selector; 28import java.nio.channels.ServerSocketChannel; 29import java.nio.channels.SocketChannel; 30import java.nio.channels.spi.SelectorProvider; 31import java.util.Set; 32import java.util.concurrent.atomic.AtomicBoolean; 33import java.util.concurrent.atomic.AtomicReference; 34 35import junit.framework.TestCase; 36import tests.support.Support_PortManager; 37 38/* 39 * Tests for Selector and its default implementation 40 */ 41public class SelectorTest extends TestCase { 42 43 private static final int WAIT_TIME = 100; 44 45 private static final int PORT = Support_PortManager.getNextPort(); 46 47 private static final InetSocketAddress LOCAL_ADDRESS = new InetSocketAddress( 48 "127.0.0.1", PORT); 49 50 Selector selector; 51 52 ServerSocketChannel ssc; 53 54 enum SelectType { 55 NULL, TIMEOUT, NOW 56 }; 57 58 protected void setUp() throws Exception { 59 super.setUp(); 60 ssc = ServerSocketChannel.open(); 61 ssc.configureBlocking(false); 62 ServerSocket ss = ssc.socket(); 63 InetSocketAddress address = new InetSocketAddress(PORT); 64 ss.bind(address); 65 selector = Selector.open(); 66 } 67 68 protected void tearDown() throws Exception { 69 try { 70 ssc.close(); 71 } catch (Exception e) { 72 // do nothing 73 } 74 try { 75 selector.close(); 76 } catch (Exception e) { 77 // do nothing 78 } 79 super.tearDown(); 80 } 81 82 /** 83 * @tests java.nio.channels.Selector#open() 84 */ 85 public void test_open() throws IOException { 86 assertNotNull(selector); 87 } 88 89 /** 90 * @tests Selector#isOpen() 91 */ 92 public void test_isOpen() throws IOException { 93 assertTrue(selector.isOpen()); 94 selector.close(); 95 assertFalse(selector.isOpen()); 96 } 97 98 /** 99 * @tests java.nio.channels.Selector#provider() 100 */ 101 public void test_provider() throws IOException { 102 // should be system default provider 103 assertNotNull(selector.provider()); 104 assertSame(SelectorProvider.provider(), selector.provider()); 105 } 106 107 /** 108 * @tests java.nio.channels.Selector#keys() 109 */ 110 public void test_keys() throws IOException { 111 SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT); 112 113 Set<SelectionKey> keySet = selector.keys(); 114 Set<SelectionKey> keySet2 = selector.keys(); 115 116 assertSame(keySet, keySet2); 117 assertEquals(1,keySet.size()); 118 SelectionKey key2 = keySet.iterator().next(); 119 assertEquals(key,key2); 120 121 // Any attempt to modify keys will cause UnsupportedOperationException 122 SocketChannel sc = SocketChannel.open(); 123 sc.configureBlocking(false); 124 SelectionKey key3 = sc.register(selector, SelectionKey.OP_READ); 125 try { 126 keySet2.add(key3); 127 fail("should throw UnsupportedOperationException"); 128 } catch (UnsupportedOperationException e) { 129 // expected 130 } 131 try { 132 keySet2.remove(key3); 133 fail("should throw UnsupportedOperationException"); 134 } catch (UnsupportedOperationException e) { 135 // expected 136 } 137 try { 138 keySet2.clear(); 139 fail("should throw UnsupportedOperationException"); 140 } catch (UnsupportedOperationException e) { 141 // expected 142 } 143 144 selector.close(); 145 try { 146 selector.keys(); 147 fail("should throw ClosedSelectorException"); 148 } catch (ClosedSelectorException e) { 149 // expected 150 } 151 } 152 153 /** 154 * @tests java.nio.channels.Selector#keys() 155 */ 156 public void test_selectedKeys() throws IOException { 157 SocketChannel sc = SocketChannel.open(); 158 ssc.register(selector, SelectionKey.OP_ACCEPT); 159 try { 160 int count = 0; 161 sc.connect(LOCAL_ADDRESS); 162 count = blockingSelect(SelectType.NULL, 0); 163 assertEquals(1, count); 164 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 165 Set<SelectionKey> selectedKeys2 = selector.selectedKeys(); 166 assertSame(selectedKeys, selectedKeys2); 167 168 assertEquals(1, selectedKeys.size()); 169 assertEquals(ssc.keyFor(selector), selectedKeys.iterator().next()); 170 // add one key into selectedKeys 171 try { 172 selectedKeys.add(ssc.keyFor(selector)); 173 fail("Should throw UnsupportedOperationException"); 174 } catch (UnsupportedOperationException e) { 175 // expected 176 } 177 178 // no exception should be thrown 179 selectedKeys.clear(); 180 181 Set<SelectionKey> selectedKeys3 = selector.selectedKeys(); 182 assertSame(selectedKeys, selectedKeys3); 183 184 ssc.keyFor(selector).cancel(); 185 assertEquals(0, selectedKeys.size()); 186 selector.close(); 187 try { 188 selector.selectedKeys(); 189 fail("should throw ClosedSelectorException"); 190 } catch (ClosedSelectorException e) { 191 // expected 192 } 193 } finally { 194 sc.close(); 195 } 196 } 197 198 /** 199 * @tests java.nio.channel.Selector#selectNow() 200 */ 201 public void test_selectNow() throws IOException { 202 assert_select_OP_ACCEPT(SelectType.NOW, 0); 203 assert_select_OP_CONNECT(SelectType.NOW, 0); 204 assert_select_OP_READ(SelectType.NOW, 0); 205 assert_select_OP_WRITE(SelectType.NOW, 0); 206 } 207 208 /** 209 * @tests java.nio.channel.Selector#selectNow() 210 */ 211 public void test_selectNow_SelectorClosed() throws IOException { 212 assert_select_SelectorClosed(SelectType.NOW, 0); 213 } 214 215 /** 216 * @test java.nio.channels.Selector#selectNow() 217 */ 218 public void test_selectNow_Timeout() throws IOException { 219 // make sure selectNow doesn't block 220 selector.selectNow(); 221 } 222 223 /** 224 * @tests java.nio.channel.Selector#select() 225 */ 226 public void test_select() throws IOException { 227 assert_select_OP_ACCEPT(SelectType.NULL, 0); 228 assert_select_OP_CONNECT(SelectType.NULL, 0); 229 assert_select_OP_READ(SelectType.NULL, 0); 230 assert_select_OP_WRITE(SelectType.NULL, 0); 231 } 232 233 /** 234 * @tests java.nio.channel.Selector#select() 235 */ 236 public void test_select_SelectorClosed() throws IOException { 237 assert_select_SelectorClosed(SelectType.NULL, 0); 238 } 239 240 /** 241 * @tests java.nio.channel.Selector#select(long) 242 */ 243 public void test_selectJ() throws IOException { 244 assert_select_OP_ACCEPT(SelectType.TIMEOUT, 0); 245 assert_select_OP_CONNECT(SelectType.TIMEOUT, 0); 246 assert_select_OP_READ(SelectType.TIMEOUT, 0); 247 assert_select_OP_WRITE(SelectType.TIMEOUT, 0); 248 249 assert_select_OP_ACCEPT(SelectType.TIMEOUT, WAIT_TIME); 250 assert_select_OP_CONNECT(SelectType.TIMEOUT, WAIT_TIME); 251 assert_select_OP_READ(SelectType.TIMEOUT, WAIT_TIME); 252 assert_select_OP_WRITE(SelectType.TIMEOUT, WAIT_TIME); 253 } 254 255 /** 256 * @tests java.nio.channel.Selector#select(long) 257 */ 258 public void test_selectJ_SelectorClosed() throws IOException { 259 assert_select_SelectorClosed(SelectType.TIMEOUT, 0); 260 selector = Selector.open(); 261 assert_select_SelectorClosed(SelectType.TIMEOUT, WAIT_TIME); 262 } 263 264 /** 265 * @tests java.nio.channel.Selector#select(long) 266 */ 267 public void test_selectJ_Exception() throws IOException { 268 try { 269 selector.select(-1); 270 } catch (IllegalArgumentException e) { 271 // expected 272 } 273 } 274 275 /** 276 * @test java.nio.channels.Selector#select(long) 277 */ 278 public void test_selectJ_Timeout() throws IOException { 279 // make sure select(timeout) doesn't block 280 selector.select(WAIT_TIME); 281 } 282 283 /** 284 * @test java.nio.channels.Selector#select(long) 285 */ 286 public void test_selectJ_Empty_Keys() throws IOException { 287 // regression test, see HARMONY-3888. 288 // make sure select(long) does wait for specified amount of 289 // time if keys.size() == 0 (initial state of selector). 290 291 final long SELECT_TIMEOUT = 2000; 292 293 long time1 = System.currentTimeMillis(); 294 selector.select(SELECT_TIMEOUT); 295 long time2 = System.currentTimeMillis(); 296 assertEquals("elapsed time", SELECT_TIMEOUT, (time2 - time1), 297 SELECT_TIMEOUT * 0.05); // 5% accuracy 298 } 299 300 /** 301 * @tests java.nio.channels.Selector#wakeup() 302 */ 303 public void test_wakeup() throws IOException { 304 /* 305 * make sure the test does not block on select 306 */ 307 selector.wakeup(); 308 selectOnce(SelectType.NULL, 0); 309 selector.wakeup(); 310 selectOnce(SelectType.TIMEOUT, 0); 311 312 // try to wakeup select. The invocation sequence of wakeup and select 313 // doesn't affect test result. 314 new Thread() { 315 public void run() { 316 317 try { 318 Thread.sleep(WAIT_TIME); 319 } catch (InterruptedException e) { 320 // ignore 321 } 322 selector.wakeup(); 323 } 324 }.start(); 325 selectOnce(SelectType.NULL, 0); 326 327 // try to wakeup select. The invocation sequence of wakeup and select 328 // doesn't affect test result. 329 new Thread() { 330 public void run() { 331 332 try { 333 Thread.sleep(WAIT_TIME); 334 } catch (InterruptedException e) { 335 // ignore 336 } 337 selector.wakeup(); 338 } 339 }.start(); 340 selectOnce(SelectType.TIMEOUT, 0); 341 } 342 343 public void test_keySetViewsModifications() throws IOException { 344 Set<SelectionKey> keys = selector.keys(); 345 346 SelectionKey key1 = ssc.register(selector, SelectionKey.OP_ACCEPT); 347 348 assertTrue(keys.contains(key1)); 349 350 SocketChannel sc = SocketChannel.open(); 351 sc.configureBlocking(false); 352 SelectionKey key2 = sc.register(selector, SelectionKey.OP_READ); 353 354 assertTrue(keys.contains(key1)); 355 assertTrue(keys.contains(key2)); 356 357 key1.cancel(); 358 assertTrue(keys.contains(key1)); 359 360 selector.selectNow(); 361 assertFalse(keys.contains(key1)); 362 assertTrue(keys.contains(key2)); 363 } 364 365 /** 366 * This test cancels a key while selecting to verify that the cancelled 367 * key set is processed both before and after the call to the underlying 368 * operating system. 369 */ 370 public void test_cancelledKeys() throws Exception { 371 final AtomicReference<Throwable> failure = new AtomicReference<Throwable>(); 372 final AtomicBoolean complete = new AtomicBoolean(); 373 374 final Pipe pipe = Pipe.open(); 375 pipe.source().configureBlocking(false); 376 final SelectionKey key = pipe.source().register(selector, SelectionKey.OP_READ); 377 378 Thread thread = new Thread() { 379 public void run() { 380 try { 381 // make sure to call key.cancel() while the main thread is selecting 382 Thread.sleep(500); 383 key.cancel(); 384 assertFalse(key.isValid()); 385 pipe.sink().write(ByteBuffer.allocate(4)); // unblock select() 386 } catch (Throwable e) { 387 failure.set(e); 388 } finally { 389 complete.set(true); 390 } 391 } 392 }; 393 assertTrue(key.isValid()); 394 395 thread.start(); 396 do { 397 assertEquals(0, selector.select(5000)); // blocks 398 assertEquals(0, selector.selectedKeys().size()); 399 } while (!complete.get()); // avoid spurious interrupts 400 assertFalse(key.isValid()); 401 402 thread.join(); 403 assertNull(failure.get()); 404 } 405 406 public void testOpChange() throws Exception { 407 SocketChannel sc = SocketChannel.open(); 408 sc.configureBlocking(false); 409 sc.register(selector, SelectionKey.OP_CONNECT); 410 try { 411 sc.connect(LOCAL_ADDRESS); 412 int count = blockingSelect(SelectType.TIMEOUT, 100); 413 assertEquals(1, count); 414 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 415 assertEquals(1, selectedKeys.size()); 416 SelectionKey key = selectedKeys.iterator().next(); 417 assertEquals(sc.keyFor(selector), key); 418 assertEquals(SelectionKey.OP_CONNECT, key.readyOps()); 419 // select again, it should return 0 420 count = selectOnce(SelectType.TIMEOUT, 100); 421 assertEquals(0, count); 422 // but selectedKeys remains the same as previous 423 assertSame(selectedKeys, selector.selectedKeys()); 424 sc.finishConnect(); 425 426 // same selector, but op is changed 427 SelectionKey key1 = sc.register(selector, SelectionKey.OP_WRITE); 428 assertEquals(key, key1); 429 count = blockingSelect(SelectType.TIMEOUT, 100); 430 assertEquals(1, count); 431 selectedKeys = selector.selectedKeys(); 432 assertEquals(1, selectedKeys.size()); 433 key = selectedKeys.iterator().next(); 434 assertEquals(key, key1); 435 assertEquals(SelectionKey.OP_WRITE, key.readyOps()); 436 437 selectedKeys.clear(); 438 } finally { 439 try { 440 ssc.accept().close(); 441 } catch (Exception e) { 442 // do nothing 443 } 444 try { 445 sc.close(); 446 } catch (IOException e) { 447 // do nothing 448 } 449 } 450 } 451 452 public void test_nonBlockingConnect() throws IOException { 453 SocketChannel channel = null; 454 try { 455 channel = SocketChannel.open(); 456 channel.configureBlocking(false); 457 Selector selector = Selector.open(); 458 channel.register(selector, SelectionKey.OP_CONNECT); 459 channel.connect(LOCAL_ADDRESS); 460 channel.finishConnect(); 461 selector.select(); 462 assertEquals(1, selector.selectedKeys().size()); 463 } finally { 464 channel.close(); 465 } 466 } 467 468 private void assert_select_SelectorClosed(SelectType type, int timeout) 469 throws IOException { 470 // selector is closed 471 selector.close(); 472 try { 473 selectOnce(type, timeout); 474 fail("should throw ClosedSelectorException"); 475 } catch (ClosedSelectorException e) { 476 // expected 477 } 478 } 479 480 private void assert_select_OP_ACCEPT(SelectType type, int timeout) 481 throws IOException, ClosedChannelException { 482 SocketChannel sc = SocketChannel.open(); 483 SocketChannel client = null; 484 try { 485 ssc.register(selector, SelectionKey.OP_ACCEPT); 486 sc.connect(LOCAL_ADDRESS); 487 int count = blockingSelect(type, timeout); 488 assertEquals(1, count); 489 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 490 assertEquals(1, selectedKeys.size()); 491 SelectionKey key = selectedKeys.iterator().next(); 492 assertEquals(ssc.keyFor(selector), key); 493 assertEquals(SelectionKey.OP_ACCEPT, key.readyOps()); 494 // select again, it should return 0 495 count = selectOnce(type, timeout); 496 assertEquals(0,count); 497 // but selectedKeys remains the same as previous 498 assertSame(selectedKeys, selector.selectedKeys()); 499 client = ssc.accept(); 500 selectedKeys.clear(); 501 } finally { 502 try { 503 sc.close(); 504 } catch (IOException e) { 505 // do nothing 506 } 507 if (null != client) { 508 client.close(); 509 } 510 } 511 ssc.keyFor(selector).cancel(); 512 } 513 514 private void assert_select_OP_CONNECT(SelectType type, int timeout) 515 throws IOException, ClosedChannelException { 516 SocketChannel sc = SocketChannel.open(); 517 sc.configureBlocking(false); 518 sc.register(selector, SelectionKey.OP_CONNECT); 519 try { 520 sc.connect(LOCAL_ADDRESS); 521 int count = blockingSelect(type, timeout); 522 assertEquals(1, count); 523 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 524 assertEquals(1, selectedKeys.size()); 525 SelectionKey key = selectedKeys.iterator().next(); 526 assertEquals(sc.keyFor(selector), key); 527 assertEquals(SelectionKey.OP_CONNECT, key.readyOps()); 528 // select again, it should return 0 529 count = selectOnce(type, timeout); 530 assertEquals(0, count); 531 // but selectedKeys remains the same as previous 532 assertSame(selectedKeys, selector.selectedKeys()); 533 sc.finishConnect(); 534 selectedKeys.clear(); 535 } finally { 536 try { 537 ssc.accept().close(); 538 } catch (Exception e) { 539 // do nothing 540 } 541 542 try { 543 sc.close(); 544 } catch (IOException e) { 545 // do nothing 546 } 547 } 548 } 549 550 private void assert_select_OP_READ(SelectType type, int timeout) 551 throws IOException { 552 SocketChannel sc = SocketChannel.open(); 553 SocketChannel client = null; 554 SocketChannel sc2 = SocketChannel.open(); 555 SocketChannel client2 = null; 556 try { 557 ssc.configureBlocking(true); 558 sc.connect(LOCAL_ADDRESS); 559 client = ssc.accept(); 560 sc.configureBlocking(false); 561 sc.register(selector, SelectionKey.OP_READ); 562 client.configureBlocking(true); 563 564 sc2.connect(LOCAL_ADDRESS); 565 client2 = ssc.accept(); 566 sc2.configureBlocking(false); 567 sc2.register(selector, SelectionKey.OP_READ); 568 client2.configureBlocking(true); 569 570 client.write(ByteBuffer.wrap("a".getBytes())); 571 int count = blockingSelect(type, timeout); 572 assertEquals(1, count); 573 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 574 assertEquals(1, selectedKeys.size()); 575 SelectionKey key = selectedKeys.iterator().next(); 576 assertEquals(sc.keyFor(selector), key); 577 assertEquals(SelectionKey.OP_READ, key.readyOps()); 578 // select again, it should return 0 579 count = selectOnce(type, timeout); 580 assertEquals(0, count); 581 // but selectedKeys remains the same as previous 582 assertSame(selectedKeys, selector.selectedKeys()); 583 584 sc.read(ByteBuffer.allocate(8)); 585 586 // the second SocketChannel should be selected this time 587 client2.write(ByteBuffer.wrap("a".getBytes())); 588 count = blockingSelect(type, timeout); 589 assertEquals(1, count); 590 // selectedKeys still includes the key of sc, because the key of sc 591 // is not removed last time. 592 selectedKeys = selector.selectedKeys(); 593 assertEquals(2, selectedKeys.size()); 594 } finally { 595 if (null != client) { 596 try { 597 client.close(); 598 } catch (Exception e) { 599 // ignore 600 } 601 } 602 if (null != client2) { 603 try { 604 client2.close(); 605 } catch (Exception e) { 606 // ignore 607 } 608 } 609 try { 610 sc.close(); 611 } catch (Exception e) { 612 // ignore 613 } 614 try { 615 sc2.close(); 616 } catch (Exception e) { 617 // ignore 618 } 619 ssc.configureBlocking(false); 620 } 621 } 622 623 private void assert_select_OP_WRITE(SelectType type, int timeout) 624 throws IOException { 625 SocketChannel sc = SocketChannel.open(); 626 SocketChannel client = null; 627 try { 628 sc.connect(LOCAL_ADDRESS); 629 ssc.configureBlocking(true); 630 client = ssc.accept(); 631 sc.configureBlocking(false); 632 sc.register(selector, SelectionKey.OP_WRITE); 633 int count = blockingSelect(type, timeout); 634 assertEquals(1, count); 635 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 636 assertEquals(1, selectedKeys.size()); 637 SelectionKey key = selectedKeys.iterator().next(); 638 assertEquals(sc.keyFor(selector), key); 639 assertEquals(SelectionKey.OP_WRITE, key.readyOps()); 640 // select again, it should return 0 641 count = selectOnce(type, timeout); 642 assertEquals(0, count); 643 // but selectedKeys remains the same as previous 644 assertSame(selectedKeys, selector.selectedKeys()); 645 } finally { 646 if (null != client) { 647 client.close(); 648 } 649 try { 650 sc.close(); 651 } catch (IOException e) { 652 // do nothing 653 } 654 ssc.configureBlocking(false); 655 } 656 } 657 658 private int blockingSelect(SelectType type, int timeout) throws IOException { 659 int ret = 0; 660 do { 661 ret = selectOnce(type, timeout); 662 if (ret > 0) { 663 return ret; 664 } 665 try { 666 Thread.sleep(100); 667 } catch (InterruptedException e) { 668 // ignore 669 } 670 } while (true); 671 } 672 673 private int selectOnce(SelectType type, int timeout) throws IOException { 674 int ret = 0; 675 switch (type) { 676 case NULL: 677 ret = selector.select(); 678 break; 679 case TIMEOUT: 680 ret = selector.select(timeout); 681 break; 682 case NOW: 683 ret = selector.selectNow(); 684 break; 685 } 686 return ret; 687 } 688 689} 690