1/* 2 * Copyright (C) 2010 The Android Open Source Project 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 libcore.java.nio.channels; 17 18import android.system.OsConstants; 19import java.io.IOException; 20import java.net.InetSocketAddress; 21import java.net.ServerSocket; 22import java.nio.ByteBuffer; 23import java.nio.channels.NoConnectionPendingException; 24import java.nio.channels.SelectionKey; 25import java.nio.channels.Selector; 26import java.nio.channels.ServerSocketChannel; 27import java.nio.channels.SocketChannel; 28import java.util.concurrent.CountDownLatch; 29import java.util.concurrent.TimeUnit; 30import junit.framework.TestCase; 31import libcore.io.Libcore; 32import tests.net.StuckServer; 33 34public class SelectorTest extends TestCase { 35 public void testNonBlockingConnect_immediate() throws Exception { 36 // Test the case where we [probably] connect immediately. 37 Selector selector = Selector.open(); 38 ServerSocketChannel ssc = ServerSocketChannel.open(); 39 try { 40 ssc.configureBlocking(false); 41 ssc.socket().bind(null); 42 43 SocketChannel sc = SocketChannel.open(); 44 sc.configureBlocking(false); 45 sc.connect(ssc.socket().getLocalSocketAddress()); 46 SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); 47 assertEquals(1, selector.select()); 48 assertEquals(SelectionKey.OP_CONNECT, key.readyOps()); 49 sc.finishConnect(); 50 } finally { 51 selector.close(); 52 ssc.close(); 53 } 54 } 55 56 public void testNonBlockingConnect_slow() throws Exception { 57 // Test the case where we have to wait for the connection. 58 Selector selector = Selector.open(); 59 StuckServer ss = new StuckServer(true); 60 try { 61 SocketChannel sc = SocketChannel.open(); 62 sc.configureBlocking(false); 63 sc.connect(ss.getLocalSocketAddress()); 64 SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); 65 assertEquals(1, selector.select()); 66 assertEquals(SelectionKey.OP_CONNECT, key.readyOps()); 67 sc.finishConnect(); 68 } finally { 69 selector.close(); 70 ss.close(); 71 } 72 } 73 74 // http://b/6453247 75 // This test won't work on the host until/unless we start using libcorkscrew there. 76 // The runtime itself blocks SIGQUIT, so that doesn't cause poll(2) to EINTR directly. 77 // The EINTR is caused by the way libcorkscrew works. 78 public void testEINTR() throws Exception { 79 Selector selector = Selector.open(); 80 new Thread(new Runnable() { 81 @Override public void run() { 82 try { 83 Thread.sleep(2000); 84 Libcore.os.kill(Libcore.os.getpid(), OsConstants.SIGQUIT); 85 } catch (Exception ex) { 86 fail(); 87 } 88 } 89 }).start(); 90 assertEquals(0, selector.select()); 91 } 92 93 // http://code.google.com/p/android/issues/detail?id=15388 94 public void testInterrupted() throws IOException { 95 Selector selector = Selector.open(); 96 Thread.currentThread().interrupt(); 97 try { 98 int count = selector.select(); 99 assertEquals(0, count); 100 assertTrue(Thread.currentThread().isInterrupted()); 101 } finally { 102 // Clear the interrupted thread state so that it does not interfere with later tests. 103 Thread.interrupted(); 104 105 selector.close(); 106 } 107 } 108 109 public void testManyWakeupCallsTriggerOnlyOneWakeup() throws Exception { 110 final Selector selector = Selector.open(); 111 try { 112 selector.wakeup(); 113 selector.wakeup(); 114 selector.wakeup(); 115 selector.select(); 116 117 // create a latch that will reach 0 when select returns 118 final CountDownLatch selectReturned = new CountDownLatch(1); 119 Thread thread = new Thread(new Runnable() { 120 @Override public void run() { 121 try { 122 selector.select(); 123 selectReturned.countDown(); 124 } catch (IOException ignored) { 125 } 126 } 127 }); 128 thread.start(); 129 130 // select doesn't ever return, so await() times out and returns false 131 assertFalse(selectReturned.await(2, TimeUnit.SECONDS)); 132 } finally { 133 selector.close(); 134 } 135 } 136 137 // We previously leaked a file descriptor for each selector instance created. 138 // 139 // http://code.google.com/p/android/issues/detail?id=5993 140 // http://code.google.com/p/android/issues/detail?id=4825 141 public void testLeakingPipes() throws IOException { 142 for (int i = 0; i < 2000; i++) { 143 Selector selector = Selector.open(); 144 selector.close(); 145 } 146 } 147 148 public void test_57456() throws Exception { 149 Selector selector = Selector.open(); 150 ServerSocketChannel ssc = ServerSocketChannel.open(); 151 152 try { 153 // Connect. 154 ssc.configureBlocking(false); 155 ssc.socket().bind(null); 156 SocketChannel sc = SocketChannel.open(); 157 sc.connect(ssc.socket().getLocalSocketAddress()); 158 sc.finishConnect(); 159 160 // Switch to non-blocking so we can use a Selector. 161 sc.configureBlocking(false); 162 163 // Have the 'server' write something. 164 ssc.accept().write(ByteBuffer.allocate(128)); 165 166 // At this point, the client should be able to read or write immediately. 167 // (It shouldn't be able to connect because it's already connected.) 168 SelectionKey key = sc.register(selector, 169 SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE); 170 assertEquals(1, selector.select()); 171 assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.readyOps()); 172 assertEquals(0, selector.select()); 173 } finally { 174 selector.close(); 175 ssc.close(); 176 } 177 } 178 179 // http://code.google.com/p/android/issues/detail?id=80785 180 public void test_80785() throws Exception { 181 Selector selector = Selector.open(); 182 selector.close(); 183 184 // Historically on android this did not throw an exception. Due to the bug it would throw 185 // an (undeclared) IOException. 186 selector.wakeup(); 187 } 188} 189