1/*
2 * Copyright (C) 2007 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 tests.api.java.lang;
18
19import dalvik.annotation.BrokenTest;
20import dalvik.annotation.TestLevel;
21import dalvik.annotation.TestTargetNew;
22import dalvik.annotation.TestTargetClass;
23
24import junit.framework.TestCase;
25
26import java.io.BufferedReader;
27import java.io.File;
28import java.io.FileInputStream;
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.InputStreamReader;
32import java.io.OutputStream;
33
34@TestTargetClass(Process.class)
35public class ProcessManagerTest extends TestCase {
36
37    Thread thread = null;
38    Process process = null;
39    boolean isThrown = false;
40
41    @TestTargetNew(
42        level = TestLevel.COMPLETE,
43        notes = "",
44        method = "getOutputStream",
45        args = {}
46    )
47    public void testCat() throws IOException, InterruptedException {
48        String[] commands = { "cat" };
49        Process process = Runtime.getRuntime().exec(commands, null, null);
50
51        OutputStream out = process.getOutputStream();
52        String greeting = "Hello, World!";
53        out.write(greeting.getBytes());
54        out.write('\n');
55        out.close();
56
57        assertEquals(greeting, readLine(process));
58    }
59
60    @TestTargetNew(
61        level = TestLevel.COMPLETE,
62        notes = "",
63        method = "waitFor",
64        args = {}
65    )
66    @BrokenTest("Sporadic failures in CTS, but not in CoreTestRunner")
67    public void testSleep() throws IOException {
68        String[] commands = { "sleep", "1" };
69        process = Runtime.getRuntime().exec(commands, null, null);
70        try {
71            assertEquals(0, process.waitFor());
72
73        } catch(InterruptedException ie) {
74            fail("InterruptedException was thrown.");
75        }
76
77        isThrown = false;
78        thread = new Thread() {
79            public void run() {
80                String[] commands = { "sleep", "1000"};
81                try {
82                    process = Runtime.getRuntime().exec(commands, null, null);
83                } catch (IOException e1) {
84                    fail("IOException was thrown.");
85                }
86                try {
87                    process.waitFor();
88                    fail("InterruptedException was not thrown.");
89                } catch(InterruptedException ie) {
90                    isThrown = true;
91                }
92            }
93        };
94
95        Thread interruptThread = new Thread() {
96            public void run() {
97                try {
98                    sleep(10);
99                } catch(InterruptedException ie) {
100                    fail("InterruptedException was thrown in " +
101                            "the interruptThread.");
102                }
103                thread.interrupt();
104            }
105        };
106        thread.start();
107        interruptThread.start();
108        try {
109            interruptThread.join();
110        } catch (InterruptedException e) {
111            fail("InterruptedException was thrown.");
112        }
113        try {
114            Thread.sleep(100);
115        } catch(InterruptedException ie) {
116
117        }
118
119        thread.interrupt();
120        //process.destroy();
121        try {
122            Thread.sleep(100);
123        } catch(InterruptedException ie) {
124
125        }
126
127        assertTrue(isThrown);
128    }
129
130    @TestTargetNew(
131        level = TestLevel.COMPLETE,
132        notes = "",
133        method = "getInputStream",
134        args = {}
135    )
136    public void testPwd() throws IOException, InterruptedException {
137        String[] commands = { "sh", "-c", "pwd" };
138        Process process = Runtime.getRuntime().exec(
139                commands, null, new File("/"));
140        logErrors(process);
141        assertEquals("/", readLine(process));
142    }
143
144    @TestTargetNew(
145        level = TestLevel.COMPLETE,
146        notes = "",
147        method = "getInputStream",
148        args = {}
149    )
150    public void testEnvironment() throws IOException, InterruptedException {
151        String[] commands = { "sh", "-c", "echo $FOO" };
152
153        // Remember to set the path so we can find sh.
154        String[] environment = { "FOO=foo", "PATH=" + System.getenv("PATH") };
155        Process process = Runtime.getRuntime().exec(
156                commands, environment, null);
157        logErrors(process);
158        assertEquals("foo", readLine(process));
159    }
160
161    String readLine(Process process) throws IOException {
162        InputStream in = process.getInputStream();
163        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
164        return reader.readLine();
165    }
166
167    void logErrors(final Process process) throws IOException {
168        Thread thread = new Thread() {
169            public void run() {
170                InputStream in = process.getErrorStream();
171                BufferedReader reader
172                        = new BufferedReader(new InputStreamReader(in));
173                String line;
174                try {
175                    while ((line = reader.readLine()) != null) {
176                        System.err.println(line);
177                    }
178                } catch (IOException e) {
179                    e.printStackTrace();
180                }
181            }
182        };
183        thread.setDaemon(true);
184        thread.start();
185    }
186
187    @TestTargetNew(
188        level = TestLevel.PARTIAL_COMPLETE,
189        notes = "Stress test.",
190        method = "waitFor",
191        args = {}
192    )
193    public void testHeavyLoad() {
194        int i;
195        for (i = 0; i < 100; i++)
196            stuff();
197    }
198
199    private static void stuff() {
200        Runtime rt = Runtime.getRuntime();
201        try {
202            Process proc = rt.exec("ls");
203            proc.waitFor();
204            proc = null;
205        } catch (Exception ex) {
206            System.err.println("Failure: " + ex);
207            throw new RuntimeException(ex);
208        }
209        rt.gc();
210        rt = null;
211    }
212
213    InputStream in;
214
215    @TestTargetNew(
216        level = TestLevel.ADDITIONAL,
217        notes = "Check non standard fd behavior",
218        clazz = Runtime.class,
219        method = "exec",
220        args = {String[].class, String[].class, java.io.File.class}
221    )
222    public void testCloseNonStandardFds()
223            throws IOException, InterruptedException {
224        String[] commands = { "ls", "/proc/self/fd" };
225
226        Process process = Runtime.getRuntime().exec(commands, null, null);
227        int before = countLines(process);
228
229        // Open a new fd.
230        this.in = new FileInputStream("/proc/version");
231
232        try {
233            process = Runtime.getRuntime().exec(commands, null, null);
234            int after = countLines(process);
235
236            // Assert that the new fd wasn't open in the second run.
237            assertEquals(before, after);
238        } finally {
239            this.in = null;
240        }
241    }
242
243    /**
244     * Counts lines of input from the given process. Equivalent to "wc -l".
245     */
246    private int countLines(Process process) throws IOException {
247        logErrors(process);
248        InputStream in = process.getInputStream();
249        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
250        int count = 0;
251        while (reader.readLine() != null) {
252            count++;
253        }
254        return count;
255    }
256
257    @TestTargetNew(
258        level = TestLevel.ADDITIONAL,
259        notes = "Check non standard fd behavior",
260        clazz = Runtime.class,
261        method = "exec",
262        args = {String[].class, String[].class, java.io.File.class}
263    )
264    public void testInvalidCommand()
265            throws IOException, InterruptedException {
266        try {
267            String[] commands = { "doesnotexist" };
268            Runtime.getRuntime().exec(commands, null, null);
269        } catch (IOException e) { /* expected */ }
270    }
271}
272