1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18ab762bb740405d0fefcccf4a0899a234f995be13Narayan Kamathpackage org.apache.harmony.tests.java.lang;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesimport java.io.File;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream;
24fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesimport java.util.ArrayList;
2514f694589bb5944e7f3e6862600ba25b15a37d18Elliott Hughesimport libcore.io.Libcore;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class ProcessTest extends junit.framework.TestCase {
2814f694589bb5944e7f3e6862600ba25b15a37d18Elliott Hughes  // Test that failures to exec don't leave zombies lying around.
29fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  public void test_55017() throws Exception {
30fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    ArrayList<Process> children = new ArrayList<Process>();
31fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    for (int i = 0; i < 256; ++i) {
32fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      try {
33fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes        children.add(Runtime.getRuntime().exec(new String[] { "/system/bin/does-not-exist" }, null, null));
34fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes        System.gc();
35fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      } catch (IOException expected) {
36fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      }
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
38fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertEquals(0, children.size());
39fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes
4014f694589bb5944e7f3e6862600ba25b15a37d18Elliott Hughes    String pid = Integer.toString(Libcore.os.getpid());
41fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    boolean onDevice = new File("/system/bin").exists();
4214f694589bb5944e7f3e6862600ba25b15a37d18Elliott Hughes    String[] psCommand = onDevice ? new String[] { "ps", "--ppid", pid }
4314f694589bb5944e7f3e6862600ba25b15a37d18Elliott Hughes                                  : new String[] { "ps", "S", "--ppid", pid };
44fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    Process ps = Runtime.getRuntime().exec(psCommand, null, null);
45fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    int zombieCount = 0;
46fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    for (String line : readAndCloseStream(ps.getInputStream()).split("\n")) {
47fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      if (line.contains(" Z ") || line.contains(" Z+ ")) {
4814f694589bb5944e7f3e6862600ba25b15a37d18Elliott Hughes        ++zombieCount;
49fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      }
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
51fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertEquals(0, zombieCount);
52fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  }
53fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes
54fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  public void test_getOutputStream() throws Exception {
55fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String[] commands = { "cat", "-"};
56fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    Process p = Runtime.getRuntime().exec(commands, null, null);
57fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    OutputStream os = p.getOutputStream();
58fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    // send data, and check if it is echoed back correctly
59fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String str1 = "Some data for testing communication between processes\n";
60fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String str2 = "More data that serves the same purpose.\n";
61fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String str3 = "Here is some more data.\n";
62fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    os.write(str1.getBytes());
63fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    try {
64fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      Thread.sleep(1000);
65fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    } catch (InterruptedException e) {
66fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      e.printStackTrace();
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
68fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    os.write(str2.getBytes());
69fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    os.write(str3.getBytes());
70fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    os.close();
71f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
72fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String received = readAndCloseStream(p.getInputStream());
73fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertEquals(str1 + str2 + str3, received);
74f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
75fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String stderr = readAndCloseStream(p.getErrorStream());
76fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertEquals("", stderr);
77f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
78fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    p.waitFor();
79fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    p.destroy();
80fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  }
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
82fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  public void test_getErrorStream() throws Exception {
83fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String[] commands = { "cat", "--no-such-option"};
84fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    Process p = Runtime.getRuntime().exec(commands, null, null);
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
86fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    p.getOutputStream().close();
87f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
88fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String received = readAndCloseStream(p.getInputStream());
89fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertEquals("", received);
90f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
91fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String stderr = readAndCloseStream(p.getErrorStream());
92432abb6e8635e3dcac46648e158b5dc2c71b84fcNarayan Kamath    assertTrue(stderr, stderr.contains("no-such-option"));
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
94fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    p.waitFor();
95fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    p.destroy();
96fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  }
97f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
98fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  private String readAndCloseStream(InputStream is) throws IOException {
99fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    StringBuffer result = new StringBuffer();
100fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    while (true) {
101fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      int c = is.read();
102fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      if (c == -1) {
103fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes        break;
104fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      }
105fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      result.append((char) c);
106fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    }
107fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    is.close();
108fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    return result.toString();
109fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  }
110fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes
111fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  public void test_exitValue() throws Exception {
112da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin    String[] commands = { "sh", "-c", "exit 0" };
113fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    Process process = Runtime.getRuntime().exec(commands, null, null);
114fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process.waitFor();
115fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertEquals(0, process.exitValue());
116fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes
117da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin    String[] commandsNonZeroExit = { "sh", "-c", "exit 34" };
118da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin    process = Runtime.getRuntime().exec(commandsNonZeroExit, null, null);
119da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin    process.waitFor();
120da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin    assertEquals(34, process.exitValue());
121da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin
122fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    String[] commandsSleep = { "sleep", "3000" };
123fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process = Runtime.getRuntime().exec(commandsSleep, null, null);
124fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process.destroy();
125fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process.waitFor(); // destroy is asynchronous.
126fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    assertTrue(process.exitValue() != 0);
127fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes
128fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process = Runtime.getRuntime().exec(new String[] { "sleep", "3000" }, null, null);
129fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    try {
130fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      process.exitValue();
131fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes      fail();
132fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    } catch(IllegalThreadStateException expected) {
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
134fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  }
135fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes
136fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  public void test_destroy() throws Exception {
137da57c8f771867837ebdbc6047180595dfdd013d7Paul Duffin    String[] commands = { "sh", "-c", "exit 0"};
138fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    Process process = Runtime.getRuntime().exec(commands, null, null);
139fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process.destroy();
140fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process.destroy();
141fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes    process.destroy();
142fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes  }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
144