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 
18 package libcore.java.nio.channels;
19 
20 import java.io.IOException;
21 import java.net.InetSocketAddress;
22 import java.net.ServerSocket;
23 import java.net.Socket;
24 import java.net.SocketAddress;
25 import java.net.SocketOption;
26 import java.net.SocketException;
27 import java.nio.ByteBuffer;
28 import java.nio.channels.NoConnectionPendingException;
29 import java.nio.channels.NotYetConnectedException;
30 import java.nio.channels.SelectionKey;
31 import java.nio.channels.ServerSocketChannel;
32 import java.nio.channels.SocketChannel;
33 import java.nio.channels.UnresolvedAddressException;
34 import java.nio.channels.UnsupportedAddressTypeException;
35 import java.nio.channels.spi.SelectorProvider;
36 import java.util.Set;
37 import junit.framework.TestCase;
38 
39 public class OldSocketChannelTest extends TestCase {
40 
41     private static final int CAPACITY_NORMAL = 200;
42 
43     private static final int CAPACITY_HUGE = 512 * 1024;
44 
45     private InetSocketAddress localAddr1;
46 
47     private SocketChannel channel1;
48 
49     private SocketChannel channel2;
50 
51     private ServerSocket server1;
52 
53     private final static int TIMEOUT = 60000;
54 
setUp()55     protected void setUp() throws Exception {
56         super.setUp();
57         this.channel1 = SocketChannel.open();
58         this.channel2 = SocketChannel.open();
59         this.server1 = new ServerSocket(0);
60         this.localAddr1 = (InetSocketAddress) server1.getLocalSocketAddress();
61     }
62 
tearDown()63     protected void tearDown() throws Exception {
64         super.tearDown();
65         if (null != this.channel1) {
66             try {
67                 this.channel1.close();
68             } catch (Exception e) {
69                 // ignore
70             }
71         }
72         if (null != this.channel2) {
73             try {
74                 this.channel2.close();
75             } catch (Exception e) {
76                 // ignore
77             }
78         }
79         if (null != this.server1) {
80             try {
81                 this.server1.close();
82             } catch (Exception e) {
83                 // ignore
84             }
85         }
86     }
87 
88     // -------------------------------------------------------------------
89     // Test for methods in abstract class.
90     // -------------------------------------------------------------------
testConstructor()91     public void testConstructor() throws IOException {
92         SocketChannel channel =
93                 SelectorProvider.provider().openSocketChannel();
94         assertNotNull(channel);
95         assertSame(SelectorProvider.provider(), channel.provider());
96         channel = SocketChannel.open();
97         assertNotNull(channel);
98         assertSame(SelectorProvider.provider(), channel.provider());
99         MockSocketChannel chan = new MockSocketChannel(
100                 SelectorProvider.provider());
101         assertTrue(chan.isConstructorCalled);
102     }
103 
testValidOps()104     public void testValidOps() {
105         MockSocketChannel testMSChannel = new MockSocketChannel(null);
106         assertEquals(13, this.channel1.validOps());
107         assertEquals(13, testMSChannel.validOps());
108     }
109 
testOpen()110     public void testOpen() throws IOException {
111         java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
112         buf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
113         MockSocketChannel testMSChannel = new MockSocketChannel(null);
114         MockSocketChannel testMSChannelnotnull = new MockSocketChannel(
115                 SelectorProvider.provider());
116         SocketChannel testSChannel = MockSocketChannel.open();
117         assertTrue(testSChannel.isOpen());
118         assertNull(testMSChannel.provider());
119         assertNotNull(testSChannel.provider());
120         assertEquals(SelectorProvider.provider(), testSChannel.provider());
121         assertNotNull(testMSChannelnotnull.provider());
122         assertEquals(this.channel1.provider(), testMSChannelnotnull.provider());
123         try {
124             this.channel1.write(buf);
125             fail("Should throw NotYetConnectedException");
126         } catch (NotYetConnectedException e) {
127             // correct
128         }
129     }
130 
testIsOpen()131     public void testIsOpen() throws Exception {
132         assertTrue(this.channel1.isOpen());
133         this.channel1.close();
134         assertFalse(this.channel1.isOpen());
135     }
136 
testIsConnected()137     public void testIsConnected() throws Exception {
138         assertFalse(this.channel1.isConnected());// not connected
139         this.channel1.configureBlocking(false);
140         assertFalse(this.channel1.connect(localAddr1));
141         assertFalse(this.channel1.isConnected());
142         assertTrue(this.channel1.isConnectionPending());
143         assertTrue(tryFinish());
144         assertTrue(this.channel1.isConnected());
145         this.channel1.close();
146         assertFalse(this.channel1.isConnected());
147     }
148 
testIsConnectionPending()149     public void testIsConnectionPending() throws Exception {
150         // ensure
151         ensureServerClosed();
152         this.channel1.configureBlocking(false);
153         assertFalse(this.channel1.isConnectionPending());
154         // finish
155         try {
156             this.channel1.finishConnect();
157             fail("Should throw NoConnectionPendingException");
158         } catch (NoConnectionPendingException e) {
159             // OK.
160         }
161         assertFalse(this.channel1.isConnectionPending());
162         // connect
163         assertFalse(this.channel1.connect(localAddr1));
164         assertTrue(this.channel1.isConnectionPending());
165         this.channel1.close();
166 
167         assertFalse(this.channel1.isConnectionPending());
168     }
169 
testChannelBasicStatus()170     public void testChannelBasicStatus() {
171         Socket gotSocket = this.channel1.socket();
172         assertFalse(gotSocket.isClosed());
173         assertTrue(this.channel1.isBlocking());
174         assertFalse(this.channel1.isRegistered());
175         assertEquals((SelectionKey.OP_CONNECT | SelectionKey.OP_READ |
176                 SelectionKey.OP_WRITE), this.channel1.validOps());
177         assertEquals(SelectorProvider.provider(), this.channel1.provider());
178     }
179 
testOpenSocketAddress()180     public void testOpenSocketAddress() throws IOException {
181         this.channel1 = SocketChannel.open(localAddr1);
182         assertTrue(this.channel1.isConnected());
183 
184         SocketAddress newTypeAddress = new SubSocketAddress();
185         try {
186             this.channel1 = SocketChannel.open(newTypeAddress);
187             fail("Should throw UnexpectedAddressTypeException");
188         } catch (UnsupportedAddressTypeException e) {
189             // expected
190         }
191 
192         SocketAddress unresolvedAddress =
193                 InetSocketAddress.createUnresolved("127.0.0.1", 8080);
194         try {
195             this.channel1 = SocketChannel.open(unresolvedAddress);
196             fail("Should throw UnresolvedAddressException");
197         } catch (UnresolvedAddressException e) {
198             // expected
199         }
200 
201         try {
202             SocketChannel.open(null);
203             fail("Should throw an IllegalArgumentException");
204         } catch (IllegalArgumentException e) {
205             // correct
206         }
207     }
208 
ensureServerClosed()209     private void ensureServerClosed() throws IOException {
210         if (null != this.server1) {
211             this.server1.close();
212             assertTrue(this.server1.isClosed());
213         }
214     }
215 
statusConnected_NotPending()216     private void statusConnected_NotPending() {
217         assertTrue(this.channel1.isConnected());
218         assertFalse(this.channel1.isConnectionPending());
219         assertTrue(this.channel1.isOpen());
220     }
221 
tryFinish()222     private boolean tryFinish() throws IOException {
223         /*
224          * the result of finish will be asserted in multi-thread tests.
225          */
226         boolean connected = false;
227         assertTrue(this.channel1.isOpen());
228         try {
229             connected = this.channel1.finishConnect();
230         } catch (SocketException e) {
231             // Finish connection failed, probably due to reset by peer error.
232         }
233         if (connected) {
234             statusConnected_NotPending();
235         }
236         return connected;
237     }
238 
239     // Broken Test: Occasionally fail in CTS, but works in CoreTestRunner
test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData()240     public void test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData() throws IOException {
241         // initialize write content
242         ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_HUGE);
243         for (int i = 0; i < CAPACITY_HUGE; i++) {
244             writeContent.put((byte) i);
245         }
246         writeContent.flip();
247 
248         // establish connection
249         channel1.connect(localAddr1);
250         Socket acceptedSocket = server1.accept();
251 
252         channel1.configureBlocking(false);
253         int writtenTotalCount = 0;
254         int writtenCount = 1;
255         long startTime = System.currentTimeMillis();
256         // use SocketChannel.write(ByteBuffer) to try to write CAPACITY_HUGE bytes
257         while (writtenTotalCount < CAPACITY_HUGE && writtenCount > 0) {
258             writtenCount = channel1.write(writeContent);
259             if (writtenCount == 0 && writtenTotalCount < CAPACITY_HUGE) {
260                 assertEquals(0, channel1.write(writeContent));
261                 break;
262             }
263             writtenTotalCount += writtenCount;
264             // if the channel could not finish writing in TIMEOUT ms, the
265             // test fails. It is used to guarantee the test never hangs even
266             // if there are bugs of SocketChannel implementation.
267             assertTimeout(startTime, TIMEOUT);
268         }
269     }
270 
271     /*
272      * Fails if the difference between current time and start time is greater
273      * than timeout.
274      */
assertTimeout(long startTime, long timeout)275     private void assertTimeout(long startTime, long timeout) {
276         long currentTime = System.currentTimeMillis();
277         if ((currentTime - startTime) > timeout) {
278             fail("Timeout");
279         }
280     }
281 
test_socketChannel_read_DirectByteBuffer()282     public void test_socketChannel_read_DirectByteBuffer() throws InterruptedException, IOException {
283         final ServerSocketChannel ssc = ServerSocketChannel.open();
284         ssc.socket().bind(null, 0);
285 
286         Thread server = new Thread() {
287             @Override public void run() {
288                 try {
289                     for (int i = 0; i < 2; ++i) {
290                         ByteBuffer buf = ByteBuffer.allocate(10);
291                         buf.put(data);
292                         buf.rewind();
293                         ssc.accept().write(buf);
294                     }
295                 } catch (Exception ignored) {
296                 }
297             }
298         };
299         server.start();
300 
301         // First test with array based byte buffer
302         SocketChannel sc = SocketChannel.open();
303         sc.connect(ssc.socket().getLocalSocketAddress());
304 
305         ByteBuffer buf = ByteBuffer.allocate(data.length);
306         buf.limit(data.length / 2);
307         sc.read(buf);
308 
309         buf.limit(buf.capacity());
310         sc.read(buf);
311         sc.close();
312 
313         // Make sure the buffer is filled correctly
314         buf.rewind();
315         assertSameContent(data, buf);
316 
317         // Now test with direct byte buffer
318         sc = SocketChannel.open();
319         sc.connect(ssc.socket().getLocalSocketAddress());
320 
321         buf = ByteBuffer.allocateDirect(data.length);
322         buf.limit(data.length / 2);
323         sc.read(buf);
324 
325         buf.limit(buf.capacity());
326         sc.read(buf);
327         sc.close();
328 
329         // Make sure the buffer is filled correctly
330         buf.rewind();
331         assertSameContent(data, buf);
332     }
333 
assertSameContent(byte[] data, ByteBuffer buf)334     private void assertSameContent(byte[] data, ByteBuffer buf) {
335         for (byte b : data) {
336             if (b != buf.get()) {
337                 int pos = buf.position() - 1;
338                 fail("Content not equal. Buffer position: " +
339                         (pos) + " expected: " + b + " was: " + buf.get(pos));
340             }
341         }
342     }
343 
344     public static boolean done = false;
345     public static byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
346 
347     class MockSocketChannel extends SocketChannel {
348 
349         private boolean isConstructorCalled = false;
350 
MockSocketChannel(SelectorProvider provider)351         public MockSocketChannel(SelectorProvider provider) {
352             super(provider);
353             isConstructorCalled = true;
354         }
355 
356         @Override
socket()357         public Socket socket() {
358             return null;
359         }
360 
361         @Override
isConnected()362         public boolean isConnected() {
363             return false;
364         }
365 
366         @Override
isConnectionPending()367         public boolean isConnectionPending() {
368             return false;
369         }
370 
371         @Override
connect(SocketAddress address)372         public boolean connect(SocketAddress address) throws IOException {
373             return false;
374         }
375 
376         @Override
finishConnect()377         public boolean finishConnect() throws IOException {
378             return false;
379         }
380 
381         @Override
read(ByteBuffer target)382         public int read(ByteBuffer target) throws IOException {
383             return 0;
384         }
385 
386         @Override
read(ByteBuffer[] targets, int offset, int length)387         public long read(ByteBuffer[] targets, int offset, int length)
388                 throws IOException {
389             return 0;
390         }
391 
392         @Override
write(ByteBuffer source)393         public int write(ByteBuffer source) throws IOException {
394             return 0;
395         }
396 
397         @Override
write(ByteBuffer[] sources, int offset, int length)398         public long write(ByteBuffer[] sources, int offset, int length)
399                 throws IOException {
400             return 0;
401         }
402 
403         @Override
implCloseSelectableChannel()404         protected void implCloseSelectableChannel() throws IOException {
405             // empty
406         }
407 
408         @Override
implConfigureBlocking(boolean blockingMode)409         protected void implConfigureBlocking(boolean blockingMode)
410                 throws IOException {
411             // empty
412         }
413 
414         @Override
getRemoteAddress()415         public SocketAddress getRemoteAddress() throws IOException {
416             return null;
417         }
418 
419         @Override
shutdownOutput()420         public SocketChannel shutdownOutput() throws IOException {
421             return null;
422         }
423 
424         @Override
shutdownInput()425         public SocketChannel shutdownInput() throws IOException {
426             return null;
427         }
428 
429         @Override
setOption(SocketOption<T> name, T value)430         public <T> SocketChannel setOption(SocketOption<T> name, T value) {
431             return null;
432         }
433 
434         @Override
bind(SocketAddress local)435         public SocketChannel bind(SocketAddress local) throws IOException {
436             return null;
437         }
438 
439         @Override
supportedOptions()440         public Set<SocketOption<?>> supportedOptions() {
441             return null;
442         }
443 
444         @Override
getOption(SocketOption<T> name)445         public <T> T getOption(SocketOption<T> name) throws IOException {
446             return null;
447         }
448 
449         @Override
getLocalAddress()450         public SocketAddress getLocalAddress() throws IOException {
451             return null;
452         }
453     }
454 
455     class SubSocketAddress extends SocketAddress {
456         private static final long serialVersionUID = 1L;
457 
458         // empty
SubSocketAddress()459         public SubSocketAddress() {
460             super();
461         }
462     }
463 }
464