| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package libcore.java.nio.channels; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.junit.Assume.assumeNotNull; |
| |
| import java.io.IOException; |
| import java.net.BindException; |
| import java.net.DatagramSocket; |
| import java.net.Inet4Address; |
| import java.net.Inet6Address; |
| import java.net.InetAddress; |
| import java.net.InetSocketAddress; |
| import java.net.NetworkInterface; |
| import java.net.ProtocolFamily; |
| import java.net.StandardProtocolFamily; |
| import java.net.StandardSocketOptions; |
| import java.nio.ByteBuffer; |
| import java.nio.channels.AlreadyBoundException; |
| import java.nio.channels.ClosedChannelException; |
| import java.nio.channels.DatagramChannel; |
| import java.nio.channels.UnsupportedAddressTypeException; |
| import java.nio.channels.spi.SelectorProvider; |
| import java.util.Enumeration; |
| import libcore.junit.util.ResourceLeakageDetector; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| @RunWith(JUnit4.class) |
| public class DatagramChannelTest { |
| @Rule |
| public ResourceLeakageDetector.LeakageDetectorRule guardRule = |
| ResourceLeakageDetector.getRule(); |
| |
| @Test |
| public void test_read_intoReadOnlyByteArrays() throws Exception { |
| ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer(); |
| try (DatagramSocket ds = new DatagramSocket(0); |
| DatagramChannel dc = DatagramChannel.open()) { |
| dc.connect(ds.getLocalSocketAddress()); |
| try { |
| dc.read(readOnly); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| try { |
| dc.read(new ByteBuffer[] { readOnly }); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| try { |
| dc.read(new ByteBuffer[] { readOnly }, 0, 1); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| } |
| |
| // http://code.google.com/p/android/issues/detail?id=16579 |
| @Test |
| public void testNonBlockingRecv() throws Exception { |
| try (DatagramChannel dc = DatagramChannel.open()) { |
| dc.configureBlocking(false); |
| dc.socket().bind(null); |
| // Should return immediately, since we're non-blocking. |
| assertNull(dc.receive(ByteBuffer.allocate(2048))); |
| } |
| } |
| |
| @Test |
| public void testInitialState() throws Exception { |
| try (DatagramChannel dc = DatagramChannel.open()) { |
| DatagramSocket socket = dc.socket(); |
| assertFalse(socket.isBound()); |
| assertFalse(socket.getBroadcast()); |
| assertFalse(socket.isClosed()); |
| assertFalse(socket.isConnected()); |
| assertEquals(0, socket.getLocalPort()); |
| assertTrue(socket.getLocalAddress().isAnyLocalAddress()); |
| assertNull(socket.getLocalSocketAddress()); |
| assertNull(socket.getInetAddress()); |
| assertEquals(-1, socket.getPort()); |
| assertNull(socket.getRemoteSocketAddress()); |
| assertFalse(socket.getReuseAddress()); |
| |
| assertSame(dc, socket.getChannel()); |
| } |
| } |
| |
| @Test |
| public void test_bind_unresolvedAddress() throws IOException { |
| DatagramChannel dc = DatagramChannel.open(); |
| try { |
| dc.socket().bind(new InetSocketAddress("unresolvedname", 31415)); |
| fail(); |
| } catch (IOException expected) { |
| } |
| |
| assertTrue(dc.isOpen()); |
| assertFalse(dc.isConnected()); |
| |
| dc.close(); |
| } |
| |
| @Test |
| public void test_bind_any_IPv4() throws Exception { |
| test_bind_any(InetAddress.getByName("0.0.0.0")); |
| } |
| |
| @Test |
| public void test_bind_any_IPv6() throws Exception { |
| test_bind_any(InetAddress.getByName("::")); |
| } |
| |
| private void test_bind_any(InetAddress bindAddress) throws Exception { |
| try (DatagramChannel dc = DatagramChannel.open()) { |
| dc.socket().bind(new InetSocketAddress(bindAddress, 0)); |
| |
| assertTrue(dc.isOpen()); |
| assertFalse(dc.isConnected()); |
| |
| InetSocketAddress actualAddress = (InetSocketAddress) dc.socket() |
| .getLocalSocketAddress(); |
| assertTrue(actualAddress.getAddress().isAnyLocalAddress()); |
| assertTrue(actualAddress.getPort() > 0); |
| } |
| } |
| |
| @Test |
| public void test_bind_loopback_IPv4() throws Exception { |
| test_bind(InetAddress.getByName("127.0.0.1")); |
| } |
| |
| @Test |
| public void test_bind_loopback_IPv6() throws Exception { |
| test_bind(InetAddress.getByName("::1")); |
| } |
| |
| @Test |
| public void test_bind_IPv4() throws Exception { |
| InetAddress bindAddress = getNonLoopbackNetworkInterfaceAddress(true /* ipv4 */); |
| assumeNotNull(bindAddress); |
| test_bind(bindAddress); |
| } |
| |
| @Test |
| public void test_bind_IPv6() throws Exception { |
| InetAddress bindAddress = getNonLoopbackNetworkInterfaceAddress(false /* ipv4 */); |
| assumeNotNull(bindAddress); |
| test_bind(bindAddress); |
| } |
| |
| private void test_bind(InetAddress bindAddress) throws IOException { |
| try (DatagramChannel dc = DatagramChannel.open()) { |
| dc.socket().bind(new InetSocketAddress(bindAddress, 0)); |
| |
| InetSocketAddress actualAddress = (InetSocketAddress) dc.socket().getLocalSocketAddress(); |
| assertEquals(bindAddress, actualAddress.getAddress()); |
| assertTrue(actualAddress.getPort() > 0); |
| } |
| } |
| |
| @Test |
| public void test_setOption() throws Exception { |
| DatagramChannel dc = DatagramChannel.open(); |
| // There were problems in the past as the number used here was below the minimum for |
| // some platforms (b/27821554). It was increased from 1024 to 4096. |
| dc.setOption(StandardSocketOptions.SO_SNDBUF, 4096); |
| |
| // Assert that we can read back the option from the channel... |
| assertEquals(4096, (int) dc.getOption(StandardSocketOptions.SO_SNDBUF)); |
| // ... and its socket adaptor. |
| assertEquals(4096, dc.socket().getSendBufferSize()); |
| |
| dc.close(); |
| try { |
| dc.setOption(StandardSocketOptions.SO_SNDBUF, 4096); |
| fail(); |
| } catch (ClosedChannelException expected) { |
| } |
| } |
| |
| // http://b/26292854 |
| @Test |
| public void test_getFileDescriptor() throws Exception { |
| try (DatagramSocket socket = DatagramChannel.open().socket()) { |
| socket.getReuseAddress(); |
| assertNotNull(socket.getFileDescriptor$()); |
| } |
| } |
| |
| @Test |
| public void test_bind() throws IOException { |
| InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); |
| DatagramChannel channel = DatagramChannel.open(); |
| channel.bind(socketAddress); |
| assertEquals(socketAddress.getAddress(), |
| ((InetSocketAddress)(channel.getLocalAddress())).getAddress()); |
| assertTrue(((InetSocketAddress)(channel.getLocalAddress())).getPort() > 0); |
| |
| try { |
| channel.bind(socketAddress); |
| fail(); |
| } catch (AlreadyBoundException expected) { |
| } |
| |
| socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, |
| ((InetSocketAddress)(channel.getLocalAddress())).getPort()); |
| try (DatagramChannel dc = DatagramChannel.open()){ |
| dc.bind(socketAddress); |
| fail(); |
| } catch (BindException expected) {} |
| |
| channel.close(); |
| socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); |
| try { |
| channel.bind(socketAddress); |
| fail(); |
| } catch (ClosedChannelException expected) {} |
| } |
| |
| @Test |
| public void test_getRemoteAddress() throws IOException { |
| InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); |
| try (DatagramChannel clientChannel = DatagramChannel.open(); |
| DatagramChannel serverChannel = DatagramChannel.open()) { |
| serverChannel.bind(socketAddress); |
| |
| assertNull(clientChannel.getRemoteAddress()); |
| |
| clientChannel.connect(serverChannel.getLocalAddress()); |
| assertEquals(socketAddress.getAddress(), |
| ((InetSocketAddress) (clientChannel.getRemoteAddress())).getAddress()); |
| assertEquals(((InetSocketAddress) (serverChannel.getLocalAddress())).getPort(), |
| ((InetSocketAddress) (clientChannel.getRemoteAddress())).getPort()); |
| } |
| } |
| |
| @Test |
| public void test_open$java_net_ProtocolFamily() throws IOException { |
| try (DatagramChannel channel = DatagramChannel.open(StandardProtocolFamily.INET)) { |
| channel.bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)); |
| assertEquals(SelectorProvider.provider(), channel.provider()); |
| } |
| |
| // Should not support IPv6 Address |
| // InetSocketAddress(int) returns IPv6 ANY address |
| try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { |
| dc.bind(new InetSocketAddress(0)); |
| fail(); |
| } catch (UnsupportedAddressTypeException expected) {} |
| |
| try (DatagramChannel dc = DatagramChannel.open(MockProtocolFamily.MOCK)) { |
| fail(); |
| } catch (UnsupportedOperationException expected) {} |
| |
| try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) { |
| assertSame(dc, dc.bind(new InetSocketAddress(0))); |
| } |
| |
| // NullPointerException |
| try (DatagramChannel dc = DatagramChannel.open(null)) { |
| fail(); |
| } catch (NullPointerException expected) {} |
| } |
| |
| @Test |
| public void test_closeGuardSupport() throws IOException { |
| try(DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { |
| guardRule.assertUnreleasedResourceCount(dc, 1); |
| } |
| } |
| |
| private static InetAddress getNonLoopbackNetworkInterfaceAddress(boolean ipv4) throws IOException { |
| Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); |
| assertNotNull(networkInterfaces); |
| while (networkInterfaces.hasMoreElements()) { |
| NetworkInterface networkInterface = networkInterfaces.nextElement(); |
| if (networkInterface.isLoopback() || !networkInterface.isUp()) { |
| continue; |
| } |
| Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); |
| while (inetAddresses.hasMoreElements()) { |
| InetAddress inetAddress = inetAddresses.nextElement(); |
| if ( (ipv4 && inetAddress instanceof Inet4Address) |
| || (!ipv4 && inetAddress instanceof Inet6Address)) { |
| return inetAddress; |
| } |
| } |
| } |
| return null; |
| } |
| |
| enum MockProtocolFamily implements ProtocolFamily { |
| MOCK, |
| } |
| } |