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 libcore.java.nio.channels;
19
20import java.io.IOException;
21import java.net.InetSocketAddress;
22import java.net.ServerSocket;
23import java.net.Socket;
24import java.net.SocketAddress;
25import java.net.SocketOption;
26import java.net.SocketException;
27import java.nio.ByteBuffer;
28import java.nio.channels.NoConnectionPendingException;
29import java.nio.channels.NotYetConnectedException;
30import java.nio.channels.SelectionKey;
31import java.nio.channels.ServerSocketChannel;
32import java.nio.channels.SocketChannel;
33import java.nio.channels.UnresolvedAddressException;
34import java.nio.channels.UnsupportedAddressTypeException;
35import java.nio.channels.spi.SelectorProvider;
36import java.util.Set;
37import junit.framework.TestCase;
38
39public 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
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
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    // -------------------------------------------------------------------
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
104    public void testValidOps() {
105        MockSocketChannel testMSChannel = new MockSocketChannel(null);
106        assertEquals(13, this.channel1.validOps());
107        assertEquals(13, testMSChannel.validOps());
108    }
109
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
131    public void testIsOpen() throws Exception {
132        assertTrue(this.channel1.isOpen());
133        this.channel1.close();
134        assertFalse(this.channel1.isOpen());
135    }
136
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
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
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
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
209    private void ensureServerClosed() throws IOException {
210        if (null != this.server1) {
211            this.server1.close();
212            assertTrue(this.server1.isClosed());
213        }
214    }
215
216    private void statusConnected_NotPending() {
217        assertTrue(this.channel1.isConnected());
218        assertFalse(this.channel1.isConnectionPending());
219        assertTrue(this.channel1.isOpen());
220    }
221
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
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     */
275    private void assertTimeout(long startTime, long timeout) {
276        long currentTime = System.currentTimeMillis();
277        if ((currentTime - startTime) > timeout) {
278            fail("Timeout");
279        }
280    }
281
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
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
351        public MockSocketChannel(SelectorProvider provider) {
352            super(provider);
353            isConstructorCalled = true;
354        }
355
356        @Override
357        public Socket socket() {
358            return null;
359        }
360
361        @Override
362        public boolean isConnected() {
363            return false;
364        }
365
366        @Override
367        public boolean isConnectionPending() {
368            return false;
369        }
370
371        @Override
372        public boolean connect(SocketAddress address) throws IOException {
373            return false;
374        }
375
376        @Override
377        public boolean finishConnect() throws IOException {
378            return false;
379        }
380
381        @Override
382        public int read(ByteBuffer target) throws IOException {
383            return 0;
384        }
385
386        @Override
387        public long read(ByteBuffer[] targets, int offset, int length)
388                throws IOException {
389            return 0;
390        }
391
392        @Override
393        public int write(ByteBuffer source) throws IOException {
394            return 0;
395        }
396
397        @Override
398        public long write(ByteBuffer[] sources, int offset, int length)
399                throws IOException {
400            return 0;
401        }
402
403        @Override
404        protected void implCloseSelectableChannel() throws IOException {
405            // empty
406        }
407
408        @Override
409        protected void implConfigureBlocking(boolean blockingMode)
410                throws IOException {
411            // empty
412        }
413
414        @Override
415        public SocketAddress getRemoteAddress() throws IOException {
416            return null;
417        }
418
419        @Override
420        public SocketChannel shutdownOutput() throws IOException {
421            return null;
422        }
423
424        @Override
425        public SocketChannel shutdownInput() throws IOException {
426            return null;
427        }
428
429        @Override
430        public <T> SocketChannel setOption(SocketOption<T> name, T value) {
431            return null;
432        }
433
434        @Override
435        public SocketChannel bind(SocketAddress local) throws IOException {
436            return null;
437        }
438
439        @Override
440        public Set<SocketOption<?>> supportedOptions() {
441            return null;
442        }
443
444        @Override
445        public <T> T getOption(SocketOption<T> name) throws IOException {
446            return null;
447        }
448
449        @Override
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
459        public SubSocketAddress() {
460            super();
461        }
462    }
463}
464