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