Home | History | Annotate | Download | only in channels
      1 /*
      2  * Copyright (C) 2016 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  */
     16 
     17 package libcore.java.nio.channels;
     18 
     19 import org.junit.Rule;
     20 
     21 import java.io.IOException;
     22 import java.net.BindException;
     23 import java.net.InetSocketAddress;
     24 import java.net.ServerSocket;
     25 import java.net.Socket;
     26 import java.net.SocketOption;
     27 import java.net.StandardSocketOptions;
     28 import java.nio.channels.AlreadyBoundException;
     29 import java.nio.channels.AsynchronousChannelGroup;
     30 import java.nio.channels.AsynchronousCloseException;
     31 import java.nio.channels.AsynchronousServerSocketChannel;
     32 import java.nio.channels.AsynchronousSocketChannel;
     33 import java.nio.channels.ClosedChannelException;
     34 import java.nio.channels.NotYetBoundException;
     35 import java.nio.channels.UnresolvedAddressException;
     36 import java.nio.channels.spi.AsynchronousChannelProvider;
     37 import java.util.Set;
     38 import java.util.concurrent.ExecutionException;
     39 import java.util.concurrent.Executors;
     40 import java.util.concurrent.Future;
     41 import java.util.concurrent.TimeUnit;
     42 import java.util.concurrent.atomic.AtomicReference;
     43 import libcore.junit.junit3.TestCaseWithRules;
     44 import libcore.junit.util.ResourceLeakageDetector;
     45 import libcore.junit.util.ResourceLeakageDetector.LeakageDetectorRule;
     46 
     47 public class AsynchronousServerSocketChannelTest extends TestCaseWithRules {
     48 
     49     @Rule
     50     public LeakageDetectorRule leakageDetectorRule = ResourceLeakageDetector.getRule();
     51 
     52     public void test_bind() throws Throwable {
     53         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
     54         assertTrue(assc.isOpen());
     55         assertNull(assc.getLocalAddress());
     56         assc.bind(new InetSocketAddress(0));
     57         assertNotNull(assc.getLocalAddress());
     58         try {
     59             assc.bind(new InetSocketAddress(0));
     60             fail();
     61         } catch (AlreadyBoundException expected) {}
     62 
     63         assc.close();
     64         assertFalse(assc.isOpen());
     65     }
     66 
     67     public void test_bind_null() throws Throwable {
     68         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
     69         assertTrue(assc.isOpen());
     70         assertNull(assc.getLocalAddress());
     71         assc.bind(null);
     72         assertNotNull(assc.getLocalAddress());
     73         try {
     74             assc.bind(null);
     75             fail();
     76         } catch (AlreadyBoundException expected) {}
     77 
     78         assc.close();
     79         assertFalse(assc.isOpen());
     80     }
     81 
     82     public void test_bind_unresolvedAddress() throws Throwable {
     83         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
     84         try {
     85             assc.bind(new InetSocketAddress("unresolvedname", 31415));
     86             fail();
     87         } catch (UnresolvedAddressException expected) {}
     88 
     89         assertNull(assc.getLocalAddress());
     90         assertTrue(assc.isOpen());
     91         assc.close();
     92     }
     93 
     94     public void test_bind_used() throws Throwable {
     95         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
     96         ServerSocket ss = new ServerSocket(0);
     97         try {
     98             assc.bind(ss.getLocalSocketAddress());
     99             fail();
    100         } catch (BindException expected) {}
    101         assertNull(assc.getLocalAddress());
    102 
    103         ss.close();
    104         assc.close();
    105     }
    106 
    107     public void test_futureAccept() throws Throwable {
    108         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    109         assc.bind(new InetSocketAddress(0));
    110 
    111         Future<AsynchronousSocketChannel> acceptFuture = assc.accept();
    112 
    113         Socket s = new Socket();
    114         s.connect(assc.getLocalAddress());
    115 
    116         AsynchronousSocketChannel asc = acceptFuture.get(1000, TimeUnit.MILLISECONDS);
    117 
    118         assertTrue(s.isConnected());
    119         assertNotNull(asc.getLocalAddress());
    120         assertEquals(asc.getLocalAddress(), s.getRemoteSocketAddress());
    121         assertNotNull(asc.getRemoteAddress());
    122         assertEquals(asc.getRemoteAddress(), s.getLocalSocketAddress());
    123 
    124         asc.close();
    125         s.close();
    126         assc.close();
    127     }
    128 
    129     public void test_completionHandlerAccept() throws Throwable {
    130         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    131         assc.bind(new InetSocketAddress(0));
    132 
    133         FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler =
    134             new FutureLikeCompletionHandler<AsynchronousSocketChannel>();
    135 
    136         assc.accept(null /* attachment */, acceptCompletionHandler);
    137 
    138         Socket s = new Socket();
    139         s.connect(assc.getLocalAddress());
    140         AsynchronousSocketChannel asc = acceptCompletionHandler.get(1000);
    141 
    142         assertNotNull(asc);
    143         assertTrue(s.isConnected());
    144         assertNotNull(asc.getLocalAddress());
    145         assertEquals(asc.getLocalAddress(), s.getRemoteSocketAddress());
    146         assertNotNull(asc.getRemoteAddress());
    147         assertEquals(asc.getRemoteAddress(), s.getLocalSocketAddress());
    148 
    149         assertNull(acceptCompletionHandler.getAttachment());
    150 
    151         asc.close();
    152         s.close();
    153         assc.close();
    154     }
    155 
    156     public void test_completionHandlerAccept_attachment() throws Throwable {
    157         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    158         assc.bind(new InetSocketAddress(0));
    159 
    160         FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler =
    161             new FutureLikeCompletionHandler<AsynchronousSocketChannel>();
    162 
    163         Integer attachment = new Integer(123);
    164         assc.accept(attachment, acceptCompletionHandler);
    165 
    166         Socket s = new Socket();
    167         s.connect(assc.getLocalAddress());
    168         AsynchronousSocketChannel asc = acceptCompletionHandler.get(1000);
    169 
    170         assertNotNull(asc);
    171         assertTrue(s.isConnected());
    172 
    173         assertEquals(attachment, acceptCompletionHandler.getAttachment());
    174 
    175         asc.close();
    176         s.close();
    177         assc.close();
    178     }
    179 
    180     public void test_completionHandlerAccept_nyb() throws Throwable {
    181         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    182 
    183         FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler =
    184             new FutureLikeCompletionHandler<AsynchronousSocketChannel>();
    185         try {
    186             assc.accept(null /* attachment */, acceptCompletionHandler);
    187             fail();
    188         } catch(NotYetBoundException expected) {}
    189 
    190         assc.close();
    191     }
    192 
    193     public void test_completionHandlerAccept_npe() throws Throwable {
    194         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    195         assc.bind(new InetSocketAddress(0));
    196 
    197         try {
    198             assc.accept(null /* attachment */, null /* completionHandler */);
    199             fail();
    200         } catch(NullPointerException expected) {}
    201 
    202         assc.close();
    203     }
    204 
    205 
    206     public void test_options() throws Throwable {
    207         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    208 
    209         assc.setOption(StandardSocketOptions.SO_RCVBUF, 5000);
    210         assertEquals(5000, (long)assc.getOption(StandardSocketOptions.SO_RCVBUF));
    211 
    212         assc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
    213         assertTrue(assc.getOption(StandardSocketOptions.SO_REUSEADDR));
    214 
    215         assc.close();
    216     }
    217 
    218     public void test_options_iae() throws Throwable {
    219         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    220 
    221         try {
    222             assc.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
    223             fail();
    224         } catch (UnsupportedOperationException expected) {}
    225 
    226         assc.close();
    227     }
    228 
    229     public void test_group() throws Throwable {
    230         AsynchronousChannelProvider provider =
    231             AsynchronousChannelProvider.provider();
    232         AsynchronousChannelGroup group =
    233             provider.openAsynchronousChannelGroup(2, Executors.defaultThreadFactory());
    234 
    235         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(group);
    236         assertNull(assc.getLocalAddress());
    237         assc.bind(new InetSocketAddress(0));
    238         assertNotNull(assc.getLocalAddress());
    239         assertEquals(provider, assc.provider());
    240         assc.close();
    241     }
    242 
    243     public void test_close() throws Throwable {
    244         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    245         assc.bind(new InetSocketAddress(0));
    246         assc.close();
    247 
    248         Future<AsynchronousSocketChannel> acceptFuture = assc.accept();
    249         try {
    250             acceptFuture.get(1000, TimeUnit.MILLISECONDS);
    251             fail();
    252         } catch(ExecutionException expected) {
    253             assertTrue(expected.getCause() instanceof ClosedChannelException);
    254         }
    255 
    256         FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler =
    257             new FutureLikeCompletionHandler<AsynchronousSocketChannel>();
    258         assc.accept(null /* attachment */, acceptCompletionHandler);
    259         try {
    260             acceptCompletionHandler.get(1000);
    261             fail();
    262         } catch(ClosedChannelException expected) {}
    263 
    264         try {
    265             assc.bind(new InetSocketAddress(0));
    266             fail();
    267         } catch(ClosedChannelException expected) {}
    268 
    269         try {
    270             assc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
    271             fail();
    272         } catch(ClosedChannelException expected) {}
    273 
    274         // Try second close
    275         assc.close();
    276     }
    277 
    278     public void test_future_concurrent_close() throws Throwable {
    279         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    280         assc.bind(new InetSocketAddress(0));
    281 
    282         final AtomicReference<Exception> killerThreadException =
    283             new AtomicReference<Exception>(null);
    284         final Thread killer = new Thread(new Runnable() {
    285             public void run() {
    286                 try {
    287                     Thread.sleep(2000);
    288                     assc.close();
    289                 } catch (Exception ex) {
    290                     killerThreadException.set(ex);
    291                 }
    292             }
    293         });
    294         killer.start();
    295         Future<AsynchronousSocketChannel> acceptFuture = assc.accept();
    296         try {
    297             // This may timeout on slow devices, they may need more time for the killer thread to
    298             // do its thing.
    299             acceptFuture.get(10000, TimeUnit.MILLISECONDS);
    300             fail();
    301         } catch(ExecutionException expected) {
    302             assertTrue(expected.getCause() instanceof ClosedChannelException);
    303         }
    304 
    305         assertNull(killerThreadException.get());
    306     }
    307 
    308     public void test_completionHandler_concurrent_close() throws Throwable {
    309         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    310         assc.bind(new InetSocketAddress(0));
    311 
    312         final AtomicReference<Exception> killerThreadException =
    313             new AtomicReference<Exception>(null);
    314         final Thread killer = new Thread(new Runnable() {
    315             public void run() {
    316                 try {
    317                     Thread.sleep(2000);
    318                     assc.close();
    319                 } catch (Exception ex) {
    320                     killerThreadException.set(ex);
    321                 }
    322             }
    323         });
    324         killer.start();
    325 
    326         FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler =
    327             new FutureLikeCompletionHandler<AsynchronousSocketChannel>();
    328 
    329         assc.accept(null /* attachment */, acceptCompletionHandler);
    330 
    331         try {
    332             // This may timeout on slow devices, they may need more time for the killer thread to
    333             // do its thing.
    334             acceptCompletionHandler.get(10000);
    335             fail();
    336         } catch(AsynchronousCloseException expected) {}
    337 
    338         assertNull(killerThreadException.get());
    339     }
    340 
    341     public void test_supportedOptions() throws Throwable {
    342         AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open();
    343 
    344         Set<SocketOption<?>> supportedOptions = assc.supportedOptions();
    345         assertEquals(2, supportedOptions.size());
    346 
    347         assertTrue(supportedOptions.contains(StandardSocketOptions.SO_REUSEADDR));
    348         assertTrue(supportedOptions.contains(StandardSocketOptions.SO_RCVBUF));
    349 
    350         // supportedOptions should work after close according to spec
    351         assc.close();
    352         supportedOptions = assc.supportedOptions();
    353         assertEquals(2, supportedOptions.size());
    354     }
    355 
    356     public void test_closeGuardSupport() throws IOException {
    357         try (AsynchronousServerSocketChannel asc = AsynchronousServerSocketChannel.open()) {
    358             leakageDetectorRule.assertUnreleasedResourceCount(asc, 1);
    359         }
    360     }
    361 
    362     public void test_closeGuardSupport_group() throws IOException {
    363         AsynchronousChannelProvider provider =
    364                 AsynchronousChannelProvider.provider();
    365         AsynchronousChannelGroup group =
    366                 provider.openAsynchronousChannelGroup(2, Executors.defaultThreadFactory());
    367 
    368         try (AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(group)) {
    369             leakageDetectorRule.assertUnreleasedResourceCount(assc, 1);
    370         }
    371     }
    372 }
    373