1/*
2 * Copyright (C) 2011 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
17package libcore.io;
18
19import android.system.StructUcred;
20import java.io.File;
21import java.io.FileDescriptor;
22import java.io.FileInputStream;
23import java.net.InetAddress;
24import java.net.InetSocketAddress;
25import java.net.InetUnixAddress;
26import java.net.ServerSocket;
27import java.net.SocketAddress;
28import java.util.Locale;
29import junit.framework.TestCase;
30import static android.system.OsConstants.*;
31
32public class OsTest extends TestCase {
33  public void testIsSocket() throws Exception {
34    File f = new File("/dev/null");
35    FileInputStream fis = new FileInputStream(f);
36    assertFalse(S_ISSOCK(Libcore.os.fstat(fis.getFD()).st_mode));
37    fis.close();
38
39    ServerSocket s = new ServerSocket();
40    assertTrue(S_ISSOCK(Libcore.os.fstat(s.getImpl$().getFD$()).st_mode));
41    s.close();
42  }
43
44  public void testUnixDomainSockets_in_file_system() throws Exception {
45    String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket";
46    new File(path).delete();
47    checkUnixDomainSocket(new InetUnixAddress(path), false);
48  }
49
50  public void testUnixDomainSocket_abstract_name() throws Exception {
51    // Linux treats a sun_path starting with a NUL byte as an abstract name. See unix(7).
52    byte[] path = "/abstract_name_unix_socket".getBytes("UTF-8");
53    path[0] = 0;
54    checkUnixDomainSocket(new InetUnixAddress(path), true);
55  }
56
57  private void checkUnixDomainSocket(final InetUnixAddress address, final boolean isAbstract) throws Exception {
58    final FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
59    Libcore.os.bind(serverFd, address, 0);
60    Libcore.os.listen(serverFd, 5);
61
62    checkSockName(serverFd, isAbstract, address);
63
64    Thread server = new Thread(new Runnable() {
65      public void run() {
66        try {
67          InetSocketAddress peerAddress = new InetSocketAddress();
68          FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress);
69          checkSockName(clientFd, isAbstract, address);
70          checkNoName(peerAddress);
71
72          checkNoPeerName(clientFd);
73
74          StructUcred credentials = Libcore.os.getsockoptUcred(clientFd, SOL_SOCKET, SO_PEERCRED);
75          assertEquals(Libcore.os.getpid(), credentials.pid);
76          assertEquals(Libcore.os.getuid(), credentials.uid);
77          assertEquals(Libcore.os.getgid(), credentials.gid);
78
79          byte[] request = new byte[256];
80          int requestLength = Libcore.os.read(clientFd, request, 0, request.length);
81
82          String s = new String(request, "UTF-8");
83          byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8");
84          Libcore.os.write(clientFd, response, 0, response.length);
85
86          Libcore.os.close(clientFd);
87        } catch (Exception ex) {
88          throw new RuntimeException(ex);
89        }
90      }
91    });
92    server.start();
93
94    FileDescriptor clientFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
95
96    Libcore.os.connect(clientFd, address, 0);
97    checkNoSockName(clientFd);
98
99    String string = "hello, world!";
100
101    byte[] request = string.getBytes("UTF-8");
102    assertEquals(request.length, Libcore.os.write(clientFd, request, 0, request.length));
103
104    byte[] response = new byte[request.length];
105    assertEquals(response.length, Libcore.os.read(clientFd, response, 0, response.length));
106
107    assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8"));
108
109    Libcore.os.close(clientFd);
110  }
111
112  private void checkSockName(FileDescriptor fd, boolean isAbstract, InetAddress address) throws Exception {
113    InetSocketAddress isa = (InetSocketAddress) Libcore.os.getsockname(fd);
114    if (isAbstract) {
115      checkNoName(isa);
116    } else {
117      assertEquals(address, isa.getAddress());
118    }
119  }
120
121  private void checkNoName(SocketAddress sa) {
122    InetSocketAddress isa = (InetSocketAddress) sa;
123    assertEquals(0, isa.getAddress().getAddress().length);
124  }
125
126  private void checkNoPeerName(FileDescriptor fd) throws Exception {
127    checkNoName(Libcore.os.getpeername(fd));
128  }
129
130  private void checkNoSockName(FileDescriptor fd) throws Exception {
131    checkNoName(Libcore.os.getsockname(fd));
132  }
133
134  public void test_strsignal() throws Exception {
135    assertEquals("Killed", Libcore.os.strsignal(9));
136    assertEquals("Unknown signal -1", Libcore.os.strsignal(-1));
137  }
138}
139