diff options
Diffstat (limited to 'luni/src/test/java/libcore/io/OsTest.java')
-rw-r--r-- | luni/src/test/java/libcore/io/OsTest.java | 229 |
1 files changed, 225 insertions, 4 deletions
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java index a0d1e5a..9b38ee9 100644 --- a/luni/src/test/java/libcore/io/OsTest.java +++ b/luni/src/test/java/libcore/io/OsTest.java @@ -16,18 +16,27 @@ package libcore.io; +import android.system.ErrnoException; +import android.system.NetlinkSocketAddress; +import android.system.OsConstants; +import android.system.PacketSocketAddress; +import android.system.StructTimeval; import android.system.StructUcred; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.InetUnixAddress; +import java.net.NetworkInterface; import java.net.ServerSocket; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Locale; import junit.framework.TestCase; import static android.system.OsConstants.*; @@ -44,6 +53,20 @@ public class OsTest extends TestCase { s.close(); } + public void testFcntlInt() throws Exception { + File f = File.createTempFile("OsTest", "tst"); + FileInputStream fis = null; + try { + fis = new FileInputStream(f); + Libcore.os.fcntlInt(fis.getFD(), F_SETFD, FD_CLOEXEC); + int flags = Libcore.os.fcntlVoid(fis.getFD(), F_GETFD); + assertTrue((flags & FD_CLOEXEC) != 0); + } finally { + IoUtils.closeQuietly(fis); + f.delete(); + } + } + public void testUnixDomainSockets_in_file_system() throws Exception { String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket"; new File(path).delete(); @@ -196,9 +219,10 @@ public class OsTest extends TestCase { fis.close(); } - public void test_byteBufferPositions_sendto_recvfrom() throws Exception { - final FileDescriptor serverFd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); - Libcore.os.bind(serverFd, InetAddress.getLoopbackAddress(), 0); + static void checkByteBufferPositions_sendto_recvfrom( + int family, InetAddress loopback) throws Exception { + final FileDescriptor serverFd = Libcore.os.socket(family, SOCK_STREAM, 0); + Libcore.os.bind(serverFd, loopback, 0); Libcore.os.listen(serverFd, 5); InetSocketAddress address = (InetSocketAddress) Libcore.os.getsockname(serverFd); @@ -232,7 +256,7 @@ public class OsTest extends TestCase { server.start(); - FileDescriptor clientFd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); + FileDescriptor clientFd = Libcore.os.socket(family, SOCK_STREAM, 0); Libcore.os.connect(clientFd, address.getAddress(), address.getPort()); final byte[] bytes = "good bye, cruel black hole with fancy distortion".getBytes(StandardCharsets.US_ASCII); @@ -254,4 +278,201 @@ public class OsTest extends TestCase { Libcore.os.close(clientFd); } + + public void test_NetlinkSocket() throws Exception { + FileDescriptor nlSocket = Libcore.os.socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + Libcore.os.bind(nlSocket, new NetlinkSocketAddress()); + NetlinkSocketAddress address = (NetlinkSocketAddress) Libcore.os.getsockname(nlSocket); + assertTrue(address.getPortId() > 0); + assertEquals(0, address.getGroupsMask()); + + NetlinkSocketAddress nlKernel = new NetlinkSocketAddress(); + Libcore.os.connect(nlSocket, nlKernel); + NetlinkSocketAddress nlPeer = (NetlinkSocketAddress) Libcore.os.getpeername(nlSocket); + assertEquals(0, nlPeer.getPortId()); + assertEquals(0, nlPeer.getGroupsMask()); + Libcore.os.close(nlSocket); + } + + public void test_PacketSocketAddress() throws Exception { + NetworkInterface lo = NetworkInterface.getByName("lo"); + FileDescriptor fd = Libcore.os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6); + PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex()); + Libcore.os.bind(fd, addr); + + PacketSocketAddress bound = (PacketSocketAddress) Libcore.os.getsockname(fd); + assertEquals((short) ETH_P_IPV6, bound.sll_protocol); // ETH_P_IPV6 is an int. + assertEquals(lo.getIndex(), bound.sll_ifindex); + assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype); + assertEquals(0, bound.sll_pkttype); + + // The loopback address is ETH_ALEN bytes long and is all zeros. + // http://lxr.free-electrons.com/source/drivers/net/loopback.c?v=3.10#L167 + assertEquals(6, bound.sll_addr.length); + for (int i = 0; i < 6; i++) { + assertEquals(0, bound.sll_addr[i]); + } + } + + public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception { + checkByteBufferPositions_sendto_recvfrom(AF_INET, InetAddress.getByName("127.0.0.1")); + } + + public void test_byteBufferPositions_sendto_recvfrom_af_inet6() throws Exception { + checkByteBufferPositions_sendto_recvfrom(AF_INET6, InetAddress.getByName("::1")); + } + + private void checkSendToSocketAddress(int family, InetAddress loopback) throws Exception { + FileDescriptor recvFd = Libcore.os.socket(family, SOCK_DGRAM, 0); + Libcore.os.bind(recvFd, loopback, 0); + StructTimeval tv = StructTimeval.fromMillis(20); + Libcore.os.setsockoptTimeval(recvFd, SOL_SOCKET, SO_RCVTIMEO, tv); + + InetSocketAddress to = ((InetSocketAddress) Libcore.os.getsockname(recvFd)); + FileDescriptor sendFd = Libcore.os.socket(family, SOCK_DGRAM, 0); + byte[] msg = ("Hello, I'm going to a socket address: " + to.toString()).getBytes("UTF-8"); + int len = msg.length; + + assertEquals(len, Libcore.os.sendto(sendFd, msg, 0, len, 0, to)); + byte[] received = new byte[msg.length + 42]; + InetSocketAddress from = new InetSocketAddress(); + assertEquals(len, Libcore.os.recvfrom(recvFd, received, 0, received.length, 0, from)); + assertEquals(loopback, from.getAddress()); + } + + public void test_sendtoSocketAddress_af_inet() throws Exception { + checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1")); + } + + public void test_sendtoSocketAddress_af_inet6() throws Exception { + checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1")); + } + + public void test_socketFamilies() throws Exception { + FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); + Libcore.os.bind(fd, InetAddress.getByName("::"), 0); + InetSocketAddress localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); + assertEquals(Inet6Address.ANY, localSocketAddress.getAddress()); + + fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); + Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0); + localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); + assertEquals(Inet6Address.ANY, localSocketAddress.getAddress()); + + fd = Libcore.os.socket(AF_INET, SOCK_STREAM, 0); + Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0); + localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); + assertEquals(Inet4Address.ANY, localSocketAddress.getAddress()); + try { + Libcore.os.bind(fd, InetAddress.getByName("::"), 0); + fail("Expected ErrnoException binding IPv4 socket to ::"); + } catch (ErrnoException expected) { + assertEquals("Expected EAFNOSUPPORT binding IPv4 socket to ::", EAFNOSUPPORT, expected.errno); + } + } + + private static void assertArrayEquals(byte[] expected, byte[] actual) { + assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual), + Arrays.equals(expected, actual)); + } + + private static void checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet, + byte type, byte responseType, boolean useSendto) throws Exception { + int len = packet.length; + packet[0] = type; + if (useSendto) { + assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, to, 0)); + } else { + Libcore.os.connect(fd, to, 0); + assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, null, 0)); + } + + int icmpId = ((InetSocketAddress) Libcore.os.getsockname(fd)).getPort(); + byte[] received = new byte[4096]; + InetSocketAddress srcAddress = new InetSocketAddress(); + assertEquals(len, Libcore.os.recvfrom(fd, received, 0, received.length, 0, srcAddress)); + assertEquals(to, srcAddress.getAddress()); + assertEquals(responseType, received[0]); + assertEquals(received[4], (byte) (icmpId >> 8)); + assertEquals(received[5], (byte) (icmpId & 0xff)); + + received = Arrays.copyOf(received, len); + received[0] = (byte) type; + received[2] = received[3] = 0; // Checksum. + received[4] = received[5] = 0; // ICMP ID. + assertArrayEquals(packet, received); + } + + public void test_socketPing() throws Exception { + final byte ICMP_ECHO = 8, ICMP_ECHOREPLY = 0; + final byte ICMPV6_ECHO_REQUEST = (byte) 128, ICMPV6_ECHO_REPLY = (byte) 129; + final byte[] packet = ("\000\000\000\000" + // ICMP type, code. + "\000\000\000\003" + // ICMP ID (== port), sequence number. + "Hello myself").getBytes(StandardCharsets.US_ASCII); + + FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); + InetAddress ipv6Loopback = InetAddress.getByName("::1"); + checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, true); + checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, false); + + fd = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + InetAddress ipv4Loopback = InetAddress.getByName("127.0.0.1"); + checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, true); + checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false); + } + + private static void assertPartial(byte[] expected, byte[] actual) { + for (int i = 0; i < expected.length; i++) { + if (expected[i] != actual[i]) { + fail("Expected " + Arrays.toString(expected) + " but found " + + Arrays.toString(actual)); + } + } + } + + public void test_xattr() throws Exception { + final String NAME_TEST = "user.meow"; + + final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8); + final byte[] VALUE_PIE = "pie".getBytes(StandardCharsets.UTF_8); + + File file = File.createTempFile("xattr", "test"); + String path = file.getAbsolutePath(); + + byte[] tmp = new byte[1024]; + try { + try { + Libcore.os.getxattr(path, NAME_TEST, tmp); + fail("Expected ENODATA"); + } catch (ErrnoException e) { + assertEquals(OsConstants.ENODATA, e.errno); + } + + Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); + assertEquals(VALUE_CAKE.length, Libcore.os.getxattr(path, NAME_TEST, tmp)); + assertPartial(VALUE_CAKE, tmp); + + try { + Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_CREATE); + fail("Expected EEXIST"); + } catch (ErrnoException e) { + assertEquals(OsConstants.EEXIST, e.errno); + } + + Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_REPLACE); + assertEquals(VALUE_PIE.length, Libcore.os.getxattr(path, NAME_TEST, tmp)); + assertPartial(VALUE_PIE, tmp); + + Libcore.os.removexattr(path, NAME_TEST); + try { + Libcore.os.getxattr(path, NAME_TEST, tmp); + fail("Expected ENODATA"); + } catch (ErrnoException e) { + assertEquals(OsConstants.ENODATA, e.errno); + } + + } finally { + file.delete(); + } + } } |