PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/java-1.7.0-openjdk/openjdk/jdk/test/java/lang/ProcessBuilder/Basic.java

#
Java | 2266 lines | 1745 code | 233 blank | 288 comment | 159 complexity | dfe3fea570dcb9a103fb95f4d4e50dc5 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation.
  8. *
  9. * This code is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * version 2 for more details (a copy is included in the LICENSE file that
  13. * accompanied this code).
  14. *
  15. * You should have received a copy of the GNU General Public License version
  16. * 2 along with this work; if not, write to the Free Software Foundation,
  17. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20. * or visit www.oracle.com if you need additional information or have any
  21. * questions.
  22. */
  23. /*
  24. * @test
  25. * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
  26. * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
  27. * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
  28. * 4947220 7018606 7034570
  29. * @summary Basic tests for Process and Environment Variable code
  30. * @run main/othervm/timeout=300 Basic
  31. * @author Martin Buchholz
  32. */
  33. import java.lang.ProcessBuilder.Redirect;
  34. import static java.lang.ProcessBuilder.Redirect.*;
  35. import java.io.*;
  36. import java.util.*;
  37. import java.util.concurrent.CountDownLatch;
  38. import java.security.*;
  39. import java.util.regex.Pattern;
  40. import java.util.regex.Matcher;
  41. import static java.lang.System.getenv;
  42. import static java.lang.System.out;
  43. import static java.lang.Boolean.TRUE;
  44. import static java.util.AbstractMap.SimpleImmutableEntry;
  45. public class Basic {
  46. /* used for Windows only */
  47. static final String systemRoot = System.getenv("SystemRoot");
  48. /* used for Mac OS X only */
  49. static final String cfUserTextEncoding = System.getenv("__CF_USER_TEXT_ENCODING");
  50. private static String commandOutput(Reader r) throws Throwable {
  51. StringBuilder sb = new StringBuilder();
  52. int c;
  53. while ((c = r.read()) > 0)
  54. if (c != '\r')
  55. sb.append((char) c);
  56. return sb.toString();
  57. }
  58. private static String commandOutput(Process p) throws Throwable {
  59. check(p.getInputStream() == p.getInputStream());
  60. check(p.getOutputStream() == p.getOutputStream());
  61. check(p.getErrorStream() == p.getErrorStream());
  62. Reader r = new InputStreamReader(p.getInputStream(),"UTF-8");
  63. String output = commandOutput(r);
  64. equal(p.waitFor(), 0);
  65. equal(p.exitValue(), 0);
  66. return output;
  67. }
  68. private static String commandOutput(ProcessBuilder pb) {
  69. try {
  70. return commandOutput(pb.start());
  71. } catch (Throwable t) {
  72. String commandline = "";
  73. for (String arg : pb.command())
  74. commandline += " " + arg;
  75. System.out.println("Exception trying to run process: " + commandline);
  76. unexpected(t);
  77. return "";
  78. }
  79. }
  80. private static String commandOutput(String...command) {
  81. try {
  82. return commandOutput(Runtime.getRuntime().exec(command));
  83. } catch (Throwable t) {
  84. String commandline = "";
  85. for (String arg : command)
  86. commandline += " " + arg;
  87. System.out.println("Exception trying to run process: " + commandline);
  88. unexpected(t);
  89. return "";
  90. }
  91. }
  92. private static void checkCommandOutput(ProcessBuilder pb,
  93. String expected,
  94. String failureMsg) {
  95. String got = commandOutput(pb);
  96. check(got.equals(expected),
  97. failureMsg + "\n" +
  98. "Expected: \"" + expected + "\"\n" +
  99. "Got: \"" + got + "\"");
  100. }
  101. private static String absolutifyPath(String path) {
  102. StringBuilder sb = new StringBuilder();
  103. for (String file : path.split(File.pathSeparator)) {
  104. if (sb.length() != 0)
  105. sb.append(File.pathSeparator);
  106. sb.append(new File(file).getAbsolutePath());
  107. }
  108. return sb.toString();
  109. }
  110. // compare windows-style, by canonicalizing to upper case,
  111. // not lower case as String.compareToIgnoreCase does
  112. private static class WindowsComparator
  113. implements Comparator<String> {
  114. public int compare(String x, String y) {
  115. return x.toUpperCase(Locale.US)
  116. .compareTo(y.toUpperCase(Locale.US));
  117. }
  118. }
  119. private static String sortedLines(String lines) {
  120. String[] arr = lines.split("\n");
  121. List<String> ls = new ArrayList<String>();
  122. for (String s : arr)
  123. ls.add(s);
  124. Collections.sort(ls, new WindowsComparator());
  125. StringBuilder sb = new StringBuilder();
  126. for (String s : ls)
  127. sb.append(s + "\n");
  128. return sb.toString();
  129. }
  130. private static void compareLinesIgnoreCase(String lines1, String lines2) {
  131. if (! (sortedLines(lines1).equalsIgnoreCase(sortedLines(lines2)))) {
  132. String dashes =
  133. "-----------------------------------------------------";
  134. out.println(dashes);
  135. out.print(sortedLines(lines1));
  136. out.println(dashes);
  137. out.print(sortedLines(lines2));
  138. out.println(dashes);
  139. out.println("sizes: " + sortedLines(lines1).length() +
  140. " " + sortedLines(lines2).length());
  141. fail("Sorted string contents differ");
  142. }
  143. }
  144. private static final Runtime runtime = Runtime.getRuntime();
  145. private static final String[] winEnvCommand = {"cmd.exe", "/c", "set"};
  146. private static String winEnvFilter(String env) {
  147. return env.replaceAll("\r", "")
  148. .replaceAll("(?m)^(?:COMSPEC|PROMPT|PATHEXT)=.*\n","");
  149. }
  150. private static String unixEnvProg() {
  151. return new File("/usr/bin/env").canExecute() ? "/usr/bin/env"
  152. : "/bin/env";
  153. }
  154. private static String nativeEnv(String[] env) {
  155. try {
  156. if (Windows.is()) {
  157. return winEnvFilter
  158. (commandOutput(runtime.exec(winEnvCommand, env)));
  159. } else {
  160. return commandOutput(runtime.exec(unixEnvProg(), env));
  161. }
  162. } catch (Throwable t) { throw new Error(t); }
  163. }
  164. private static String nativeEnv(ProcessBuilder pb) {
  165. try {
  166. if (Windows.is()) {
  167. pb.command(winEnvCommand);
  168. return winEnvFilter(commandOutput(pb));
  169. } else {
  170. pb.command(new String[]{unixEnvProg()});
  171. return commandOutput(pb);
  172. }
  173. } catch (Throwable t) { throw new Error(t); }
  174. }
  175. private static void checkSizes(Map<String,String> environ, int size) {
  176. try {
  177. equal(size, environ.size());
  178. equal(size, environ.entrySet().size());
  179. equal(size, environ.keySet().size());
  180. equal(size, environ.values().size());
  181. boolean isEmpty = (size == 0);
  182. equal(isEmpty, environ.isEmpty());
  183. equal(isEmpty, environ.entrySet().isEmpty());
  184. equal(isEmpty, environ.keySet().isEmpty());
  185. equal(isEmpty, environ.values().isEmpty());
  186. } catch (Throwable t) { unexpected(t); }
  187. }
  188. private interface EnvironmentFrobber {
  189. void doIt(Map<String,String> environ);
  190. }
  191. private static void testVariableDeleter(EnvironmentFrobber fooDeleter) {
  192. try {
  193. Map<String,String> environ = new ProcessBuilder().environment();
  194. environ.put("Foo", "BAAR");
  195. fooDeleter.doIt(environ);
  196. equal(environ.get("Foo"), null);
  197. equal(environ.remove("Foo"), null);
  198. } catch (Throwable t) { unexpected(t); }
  199. }
  200. private static void testVariableAdder(EnvironmentFrobber fooAdder) {
  201. try {
  202. Map<String,String> environ = new ProcessBuilder().environment();
  203. environ.remove("Foo");
  204. fooAdder.doIt(environ);
  205. equal(environ.get("Foo"), "Bahrein");
  206. } catch (Throwable t) { unexpected(t); }
  207. }
  208. private static void testVariableModifier(EnvironmentFrobber fooModifier) {
  209. try {
  210. Map<String,String> environ = new ProcessBuilder().environment();
  211. environ.put("Foo","OldValue");
  212. fooModifier.doIt(environ);
  213. equal(environ.get("Foo"), "NewValue");
  214. } catch (Throwable t) { unexpected(t); }
  215. }
  216. private static void printUTF8(String s) throws IOException {
  217. out.write(s.getBytes("UTF-8"));
  218. }
  219. private static String getenvAsString(Map<String,String> environment) {
  220. StringBuilder sb = new StringBuilder();
  221. for (Map.Entry<String,String> e : environment.entrySet())
  222. // Ignore magic environment variables added by the launcher
  223. if (! e.getKey().equals("NLSPATH") &&
  224. ! e.getKey().equals("XFILESEARCHPATH") &&
  225. ! e.getKey().equals("LD_LIBRARY_PATH"))
  226. sb.append(e.getKey())
  227. .append('=')
  228. .append(e.getValue())
  229. .append(',');
  230. return sb.toString();
  231. }
  232. static void print4095(OutputStream s, byte b) throws Throwable {
  233. byte[] bytes = new byte[4095];
  234. Arrays.fill(bytes, b);
  235. s.write(bytes); // Might hang!
  236. }
  237. static void checkPermissionDenied(ProcessBuilder pb) {
  238. try {
  239. pb.start();
  240. fail("Expected IOException not thrown");
  241. } catch (IOException e) {
  242. String m = e.getMessage();
  243. if (EnglishUnix.is() &&
  244. ! matches(m, "Permission denied"))
  245. unexpected(e);
  246. } catch (Throwable t) { unexpected(t); }
  247. }
  248. public static class JavaChild {
  249. public static void main(String args[]) throws Throwable {
  250. String action = args[0];
  251. if (action.equals("sleep")) {
  252. Thread.sleep(10 * 60 * 1000L);
  253. } else if (action.equals("testIO")) {
  254. String expected = "standard input";
  255. char[] buf = new char[expected.length()+1];
  256. int n = new InputStreamReader(System.in).read(buf,0,buf.length);
  257. if (n != expected.length())
  258. System.exit(5);
  259. if (! new String(buf,0,n).equals(expected))
  260. System.exit(5);
  261. System.err.print("standard error");
  262. System.out.print("standard output");
  263. } else if (action.equals("testInheritIO")) {
  264. List<String> childArgs = new ArrayList<String>(javaChildArgs);
  265. childArgs.add("testIO");
  266. ProcessBuilder pb = new ProcessBuilder(childArgs);
  267. pb.inheritIO();
  268. ProcessResults r = run(pb);
  269. if (! r.out().equals(""))
  270. System.exit(7);
  271. if (! r.err().equals(""))
  272. System.exit(8);
  273. if (r.exitValue() != 0)
  274. System.exit(9);
  275. } else if (action.equals("System.getenv(String)")) {
  276. String val = System.getenv(args[1]);
  277. printUTF8(val == null ? "null" : val);
  278. } else if (action.equals("System.getenv(\\u1234)")) {
  279. String val = System.getenv("\u1234");
  280. printUTF8(val == null ? "null" : val);
  281. } else if (action.equals("System.getenv()")) {
  282. printUTF8(getenvAsString(System.getenv()));
  283. } else if (action.equals("ArrayOOME")) {
  284. Object dummy;
  285. switch(new Random().nextInt(3)) {
  286. case 0: dummy = new Integer[Integer.MAX_VALUE]; break;
  287. case 1: dummy = new double[Integer.MAX_VALUE]; break;
  288. case 2: dummy = new byte[Integer.MAX_VALUE][]; break;
  289. default: throw new InternalError();
  290. }
  291. } else if (action.equals("pwd")) {
  292. printUTF8(new File(System.getProperty("user.dir"))
  293. .getCanonicalPath());
  294. } else if (action.equals("print4095")) {
  295. print4095(System.out, (byte) '!');
  296. print4095(System.err, (byte) 'E');
  297. System.exit(5);
  298. } else if (action.equals("OutErr")) {
  299. // You might think the system streams would be
  300. // buffered, and in fact they are implemented using
  301. // BufferedOutputStream, but each and every print
  302. // causes immediate operating system I/O.
  303. System.out.print("out");
  304. System.err.print("err");
  305. System.out.print("out");
  306. System.err.print("err");
  307. } else if (action.equals("null PATH")) {
  308. equal(System.getenv("PATH"), null);
  309. check(new File("/bin/true").exists());
  310. check(new File("/bin/false").exists());
  311. ProcessBuilder pb1 = new ProcessBuilder();
  312. ProcessBuilder pb2 = new ProcessBuilder();
  313. pb2.environment().put("PATH", "anyOldPathIgnoredAnyways");
  314. ProcessResults r;
  315. for (final ProcessBuilder pb :
  316. new ProcessBuilder[] {pb1, pb2}) {
  317. pb.command("true");
  318. equal(run(pb).exitValue(), True.exitValue());
  319. pb.command("false");
  320. equal(run(pb).exitValue(), False.exitValue());
  321. }
  322. if (failed != 0) throw new Error("null PATH");
  323. } else if (action.equals("PATH search algorithm")) {
  324. equal(System.getenv("PATH"), "dir1:dir2:");
  325. check(new File("/bin/true").exists());
  326. check(new File("/bin/false").exists());
  327. String[] cmd = {"prog"};
  328. ProcessBuilder pb1 = new ProcessBuilder(cmd);
  329. ProcessBuilder pb2 = new ProcessBuilder(cmd);
  330. ProcessBuilder pb3 = new ProcessBuilder(cmd);
  331. pb2.environment().put("PATH", "anyOldPathIgnoredAnyways");
  332. pb3.environment().remove("PATH");
  333. for (final ProcessBuilder pb :
  334. new ProcessBuilder[] {pb1, pb2, pb3}) {
  335. try {
  336. // Not on PATH at all; directories don't exist
  337. try {
  338. pb.start();
  339. fail("Expected IOException not thrown");
  340. } catch (IOException e) {
  341. String m = e.getMessage();
  342. if (EnglishUnix.is() &&
  343. ! matches(m, "No such file"))
  344. unexpected(e);
  345. } catch (Throwable t) { unexpected(t); }
  346. // Not on PATH at all; directories exist
  347. new File("dir1").mkdirs();
  348. new File("dir2").mkdirs();
  349. try {
  350. pb.start();
  351. fail("Expected IOException not thrown");
  352. } catch (IOException e) {
  353. String m = e.getMessage();
  354. if (EnglishUnix.is() &&
  355. ! matches(m, "No such file"))
  356. unexpected(e);
  357. } catch (Throwable t) { unexpected(t); }
  358. // Can't execute a directory -- permission denied
  359. // Report EACCES errno
  360. new File("dir1/prog").mkdirs();
  361. checkPermissionDenied(pb);
  362. // continue searching if EACCES
  363. copy("/bin/true", "dir2/prog");
  364. equal(run(pb).exitValue(), True.exitValue());
  365. new File("dir1/prog").delete();
  366. new File("dir2/prog").delete();
  367. new File("dir2/prog").mkdirs();
  368. copy("/bin/true", "dir1/prog");
  369. equal(run(pb).exitValue(), True.exitValue());
  370. // Check empty PATH component means current directory.
  371. //
  372. // While we're here, let's test different kinds of
  373. // Unix executables, and PATH vs explicit searching.
  374. new File("dir1/prog").delete();
  375. new File("dir2/prog").delete();
  376. for (String[] command :
  377. new String[][] {
  378. new String[] {"./prog"},
  379. cmd}) {
  380. pb.command(command);
  381. File prog = new File("./prog");
  382. // "Normal" binaries
  383. copy("/bin/true", "./prog");
  384. equal(run(pb).exitValue(),
  385. True.exitValue());
  386. copy("/bin/false", "./prog");
  387. equal(run(pb).exitValue(),
  388. False.exitValue());
  389. prog.delete();
  390. // Interpreter scripts with #!
  391. setFileContents(prog, "#!/bin/true\n");
  392. prog.setExecutable(true);
  393. equal(run(pb).exitValue(),
  394. True.exitValue());
  395. prog.delete();
  396. setFileContents(prog, "#!/bin/false\n");
  397. prog.setExecutable(true);
  398. equal(run(pb).exitValue(),
  399. False.exitValue());
  400. // Traditional shell scripts without #!
  401. setFileContents(prog, "exec /bin/true\n");
  402. prog.setExecutable(true);
  403. equal(run(pb).exitValue(),
  404. True.exitValue());
  405. prog.delete();
  406. setFileContents(prog, "exec /bin/false\n");
  407. prog.setExecutable(true);
  408. equal(run(pb).exitValue(),
  409. False.exitValue());
  410. prog.delete();
  411. }
  412. // Test Unix interpreter scripts
  413. File dir1Prog = new File("dir1/prog");
  414. dir1Prog.delete();
  415. pb.command(new String[] {"prog", "world"});
  416. setFileContents(dir1Prog, "#!/bin/echo hello\n");
  417. checkPermissionDenied(pb);
  418. dir1Prog.setExecutable(true);
  419. equal(run(pb).out(), "hello dir1/prog world\n");
  420. equal(run(pb).exitValue(), True.exitValue());
  421. dir1Prog.delete();
  422. pb.command(cmd);
  423. // Test traditional shell scripts without #!
  424. setFileContents(dir1Prog, "/bin/echo \"$@\"\n");
  425. pb.command(new String[] {"prog", "hello", "world"});
  426. checkPermissionDenied(pb);
  427. dir1Prog.setExecutable(true);
  428. equal(run(pb).out(), "hello world\n");
  429. equal(run(pb).exitValue(), True.exitValue());
  430. dir1Prog.delete();
  431. pb.command(cmd);
  432. // If prog found on both parent and child's PATH,
  433. // parent's is used.
  434. new File("dir1/prog").delete();
  435. new File("dir2/prog").delete();
  436. new File("prog").delete();
  437. new File("dir3").mkdirs();
  438. copy("/bin/true", "dir1/prog");
  439. copy("/bin/false", "dir3/prog");
  440. pb.environment().put("PATH","dir3");
  441. equal(run(pb).exitValue(), True.exitValue());
  442. copy("/bin/true", "dir3/prog");
  443. copy("/bin/false", "dir1/prog");
  444. equal(run(pb).exitValue(), False.exitValue());
  445. } finally {
  446. // cleanup
  447. new File("dir1/prog").delete();
  448. new File("dir2/prog").delete();
  449. new File("dir3/prog").delete();
  450. new File("dir1").delete();
  451. new File("dir2").delete();
  452. new File("dir3").delete();
  453. new File("prog").delete();
  454. }
  455. }
  456. if (failed != 0) throw new Error("PATH search algorithm");
  457. }
  458. else throw new Error("JavaChild invocation error");
  459. }
  460. }
  461. private static void copy(String src, String dst) {
  462. system("/bin/cp", "-fp", src, dst);
  463. }
  464. private static void system(String... command) {
  465. try {
  466. ProcessBuilder pb = new ProcessBuilder(command);
  467. ProcessResults r = run(pb.start());
  468. equal(r.exitValue(), 0);
  469. equal(r.out(), "");
  470. equal(r.err(), "");
  471. } catch (Throwable t) { unexpected(t); }
  472. }
  473. private static String javaChildOutput(ProcessBuilder pb, String...args) {
  474. List<String> list = new ArrayList<String>(javaChildArgs);
  475. for (String arg : args)
  476. list.add(arg);
  477. pb.command(list);
  478. return commandOutput(pb);
  479. }
  480. private static String getenvInChild(ProcessBuilder pb) {
  481. return javaChildOutput(pb, "System.getenv()");
  482. }
  483. private static String getenvInChild1234(ProcessBuilder pb) {
  484. return javaChildOutput(pb, "System.getenv(\\u1234)");
  485. }
  486. private static String getenvInChild(ProcessBuilder pb, String name) {
  487. return javaChildOutput(pb, "System.getenv(String)", name);
  488. }
  489. private static String pwdInChild(ProcessBuilder pb) {
  490. return javaChildOutput(pb, "pwd");
  491. }
  492. private static final String javaExe =
  493. System.getProperty("java.home") +
  494. File.separator + "bin" + File.separator + "java";
  495. private static final String classpath =
  496. System.getProperty("java.class.path");
  497. private static final List<String> javaChildArgs =
  498. Arrays.asList(new String[]
  499. { javaExe, "-classpath", absolutifyPath(classpath),
  500. "Basic$JavaChild"});
  501. private static void testEncoding(String encoding, String tested) {
  502. try {
  503. // If round trip conversion works, should be able to set env vars
  504. // correctly in child.
  505. if (new String(tested.getBytes()).equals(tested)) {
  506. out.println("Testing " + encoding + " environment values");
  507. ProcessBuilder pb = new ProcessBuilder();
  508. pb.environment().put("ASCIINAME",tested);
  509. equal(getenvInChild(pb,"ASCIINAME"), tested);
  510. }
  511. } catch (Throwable t) { unexpected(t); }
  512. }
  513. static class Windows {
  514. public static boolean is() { return is; }
  515. private static final boolean is =
  516. System.getProperty("os.name").startsWith("Windows");
  517. }
  518. static class Unix {
  519. public static boolean is() { return is; }
  520. private static final boolean is =
  521. (! Windows.is() &&
  522. new File("/bin/sh").exists() &&
  523. new File("/bin/true").exists() &&
  524. new File("/bin/false").exists());
  525. }
  526. static class UnicodeOS {
  527. public static boolean is() { return is; }
  528. private static final String osName = System.getProperty("os.name");
  529. private static final boolean is =
  530. // MacOS X would probably also qualify
  531. osName.startsWith("Windows") &&
  532. ! osName.startsWith("Windows 9") &&
  533. ! osName.equals("Windows Me");
  534. }
  535. static class MacOSX {
  536. public static boolean is() { return is; }
  537. private static final String osName = System.getProperty("os.name");
  538. private static final boolean is = osName.contains("OS X");
  539. }
  540. static class True {
  541. public static int exitValue() { return 0; }
  542. }
  543. private static class False {
  544. public static int exitValue() { return exitValue; }
  545. private static final int exitValue = exitValue0();
  546. private static int exitValue0() {
  547. // /bin/false returns an *unspecified* non-zero number.
  548. try {
  549. if (! Unix.is())
  550. return -1;
  551. else {
  552. int rc = new ProcessBuilder("/bin/false")
  553. .start().waitFor();
  554. check(rc != 0);
  555. return rc;
  556. }
  557. } catch (Throwable t) { unexpected(t); return -1; }
  558. }
  559. }
  560. static class EnglishUnix {
  561. private final static Boolean is =
  562. (! Windows.is() && isEnglish("LANG") && isEnglish("LC_ALL"));
  563. private static boolean isEnglish(String envvar) {
  564. String val = getenv(envvar);
  565. return (val == null) || val.matches("en.*");
  566. }
  567. /** Returns true if we can expect English OS error strings */
  568. static boolean is() { return is; }
  569. }
  570. private static boolean matches(String str, String regex) {
  571. return Pattern.compile(regex).matcher(str).find();
  572. }
  573. private static String matchAndExtract(String str, String regex) {
  574. Matcher matcher = Pattern.compile(regex).matcher(str);
  575. if (matcher.find()) {
  576. return matcher.group();
  577. } else {
  578. return "";
  579. }
  580. }
  581. /* Only used for Mac OS X --
  582. * Mac OS X adds the variable __CF_USER_TEXT_ENCODING to an empty
  583. * environment. The environment variable JAVA_MAIN_CLASS_<pid> should also
  584. * be set in Mac OS X.
  585. * Check for both by removing them both from the list of env variables.
  586. */
  587. private static String removeMacExpectedVars(String vars) {
  588. // Check for __CF_USER_TEXT_ENCODING
  589. String cleanedVars = vars.replace("__CF_USER_TEXT_ENCODING="
  590. +cfUserTextEncoding+",","");
  591. if (cleanedVars.equals(vars)) {
  592. fail("Environment variable __CF_USER_TEXT_ENCODING not set. "
  593. + "MAC OS X should set __CF_USER_TEXT_ENCODING in "
  594. + "an empty environment.");
  595. }
  596. // Check for JAVA_MAIN_CLASS_<pid>
  597. String javaMainClassStr
  598. = matchAndExtract(cleanedVars,
  599. "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,");
  600. if (javaMainClassStr.equals("")) {
  601. fail("JAVA_MAIN_CLASS_<pid> not set. "
  602. + "Should be set in Mac OS X env.");
  603. }
  604. return cleanedVars.replace(javaMainClassStr,"");
  605. }
  606. private static String sortByLinesWindowsly(String text) {
  607. String[] lines = text.split("\n");
  608. Arrays.sort(lines, new WindowsComparator());
  609. StringBuilder sb = new StringBuilder();
  610. for (String line : lines)
  611. sb.append(line).append("\n");
  612. return sb.toString();
  613. }
  614. private static void checkMapSanity(Map<String,String> map) {
  615. try {
  616. Set<String> keySet = map.keySet();
  617. Collection<String> values = map.values();
  618. Set<Map.Entry<String,String>> entrySet = map.entrySet();
  619. equal(entrySet.size(), keySet.size());
  620. equal(entrySet.size(), values.size());
  621. StringBuilder s1 = new StringBuilder();
  622. for (Map.Entry<String,String> e : entrySet)
  623. s1.append(e.getKey() + "=" + e.getValue() + "\n");
  624. StringBuilder s2 = new StringBuilder();
  625. for (String var : keySet)
  626. s2.append(var + "=" + map.get(var) + "\n");
  627. equal(s1.toString(), s2.toString());
  628. Iterator<String> kIter = keySet.iterator();
  629. Iterator<String> vIter = values.iterator();
  630. Iterator<Map.Entry<String,String>> eIter = entrySet.iterator();
  631. while (eIter.hasNext()) {
  632. Map.Entry<String,String> entry = eIter.next();
  633. String key = kIter.next();
  634. String value = vIter.next();
  635. check(entrySet.contains(entry));
  636. check(keySet.contains(key));
  637. check(values.contains(value));
  638. check(map.containsKey(key));
  639. check(map.containsValue(value));
  640. equal(entry.getKey(), key);
  641. equal(entry.getValue(), value);
  642. }
  643. check(! kIter.hasNext() &&
  644. ! vIter.hasNext());
  645. } catch (Throwable t) { unexpected(t); }
  646. }
  647. private static void checkMapEquality(Map<String,String> map1,
  648. Map<String,String> map2) {
  649. try {
  650. equal(map1.size(), map2.size());
  651. equal(map1.isEmpty(), map2.isEmpty());
  652. for (String key : map1.keySet()) {
  653. equal(map1.get(key), map2.get(key));
  654. check(map2.keySet().contains(key));
  655. }
  656. equal(map1, map2);
  657. equal(map2, map1);
  658. equal(map1.entrySet(), map2.entrySet());
  659. equal(map2.entrySet(), map1.entrySet());
  660. equal(map1.keySet(), map2.keySet());
  661. equal(map2.keySet(), map1.keySet());
  662. equal(map1.hashCode(), map2.hashCode());
  663. equal(map1.entrySet().hashCode(), map2.entrySet().hashCode());
  664. equal(map1.keySet().hashCode(), map2.keySet().hashCode());
  665. } catch (Throwable t) { unexpected(t); }
  666. }
  667. static void checkRedirects(ProcessBuilder pb,
  668. Redirect in, Redirect out, Redirect err) {
  669. equal(pb.redirectInput(), in);
  670. equal(pb.redirectOutput(), out);
  671. equal(pb.redirectError(), err);
  672. }
  673. static void redirectIO(ProcessBuilder pb,
  674. Redirect in, Redirect out, Redirect err) {
  675. pb.redirectInput(in);
  676. pb.redirectOutput(out);
  677. pb.redirectError(err);
  678. }
  679. static void setFileContents(File file, String contents) {
  680. try {
  681. Writer w = new FileWriter(file);
  682. w.write(contents);
  683. w.close();
  684. } catch (Throwable t) { unexpected(t); }
  685. }
  686. static String fileContents(File file) {
  687. try {
  688. Reader r = new FileReader(file);
  689. StringBuilder sb = new StringBuilder();
  690. char[] buffer = new char[1024];
  691. int n;
  692. while ((n = r.read(buffer)) != -1)
  693. sb.append(buffer,0,n);
  694. r.close();
  695. return new String(sb);
  696. } catch (Throwable t) { unexpected(t); return ""; }
  697. }
  698. static void testIORedirection() throws Throwable {
  699. final File ifile = new File("ifile");
  700. final File ofile = new File("ofile");
  701. final File efile = new File("efile");
  702. ifile.delete();
  703. ofile.delete();
  704. efile.delete();
  705. //----------------------------------------------------------------
  706. // Check mutual inequality of different types of Redirect
  707. //----------------------------------------------------------------
  708. Redirect[] redirects =
  709. { PIPE,
  710. INHERIT,
  711. Redirect.from(ifile),
  712. Redirect.to(ifile),
  713. Redirect.appendTo(ifile),
  714. Redirect.from(ofile),
  715. Redirect.to(ofile),
  716. Redirect.appendTo(ofile),
  717. };
  718. for (int i = 0; i < redirects.length; i++)
  719. for (int j = 0; j < redirects.length; j++)
  720. equal(redirects[i].equals(redirects[j]), (i == j));
  721. //----------------------------------------------------------------
  722. // Check basic properties of different types of Redirect
  723. //----------------------------------------------------------------
  724. equal(PIPE.type(), Redirect.Type.PIPE);
  725. equal(PIPE.toString(), "PIPE");
  726. equal(PIPE.file(), null);
  727. equal(INHERIT.type(), Redirect.Type.INHERIT);
  728. equal(INHERIT.toString(), "INHERIT");
  729. equal(INHERIT.file(), null);
  730. equal(Redirect.from(ifile).type(), Redirect.Type.READ);
  731. equal(Redirect.from(ifile).toString(),
  732. "redirect to read from file \"ifile\"");
  733. equal(Redirect.from(ifile).file(), ifile);
  734. equal(Redirect.from(ifile),
  735. Redirect.from(ifile));
  736. equal(Redirect.from(ifile).hashCode(),
  737. Redirect.from(ifile).hashCode());
  738. equal(Redirect.to(ofile).type(), Redirect.Type.WRITE);
  739. equal(Redirect.to(ofile).toString(),
  740. "redirect to write to file \"ofile\"");
  741. equal(Redirect.to(ofile).file(), ofile);
  742. equal(Redirect.to(ofile),
  743. Redirect.to(ofile));
  744. equal(Redirect.to(ofile).hashCode(),
  745. Redirect.to(ofile).hashCode());
  746. equal(Redirect.appendTo(ofile).type(), Redirect.Type.APPEND);
  747. equal(Redirect.appendTo(efile).toString(),
  748. "redirect to append to file \"efile\"");
  749. equal(Redirect.appendTo(efile).file(), efile);
  750. equal(Redirect.appendTo(efile),
  751. Redirect.appendTo(efile));
  752. equal(Redirect.appendTo(efile).hashCode(),
  753. Redirect.appendTo(efile).hashCode());
  754. //----------------------------------------------------------------
  755. // Check initial values of redirects
  756. //----------------------------------------------------------------
  757. List<String> childArgs = new ArrayList<String>(javaChildArgs);
  758. childArgs.add("testIO");
  759. final ProcessBuilder pb = new ProcessBuilder(childArgs);
  760. checkRedirects(pb, PIPE, PIPE, PIPE);
  761. //----------------------------------------------------------------
  762. // Check inheritIO
  763. //----------------------------------------------------------------
  764. pb.inheritIO();
  765. checkRedirects(pb, INHERIT, INHERIT, INHERIT);
  766. //----------------------------------------------------------------
  767. // Check setters and getters agree
  768. //----------------------------------------------------------------
  769. pb.redirectInput(ifile);
  770. equal(pb.redirectInput().file(), ifile);
  771. equal(pb.redirectInput(), Redirect.from(ifile));
  772. pb.redirectOutput(ofile);
  773. equal(pb.redirectOutput().file(), ofile);
  774. equal(pb.redirectOutput(), Redirect.to(ofile));
  775. pb.redirectError(efile);
  776. equal(pb.redirectError().file(), efile);
  777. equal(pb.redirectError(), Redirect.to(efile));
  778. THROWS(IllegalArgumentException.class,
  779. new Fun(){void f() {
  780. pb.redirectInput(Redirect.to(ofile)); }},
  781. new Fun(){void f() {
  782. pb.redirectInput(Redirect.appendTo(ofile)); }},
  783. new Fun(){void f() {
  784. pb.redirectOutput(Redirect.from(ifile)); }},
  785. new Fun(){void f() {
  786. pb.redirectError(Redirect.from(ifile)); }});
  787. THROWS(IOException.class,
  788. // Input file does not exist
  789. new Fun(){void f() throws Throwable { pb.start(); }});
  790. setFileContents(ifile, "standard input");
  791. //----------------------------------------------------------------
  792. // Writing to non-existent files
  793. //----------------------------------------------------------------
  794. {
  795. ProcessResults r = run(pb);
  796. equal(r.exitValue(), 0);
  797. equal(fileContents(ofile), "standard output");
  798. equal(fileContents(efile), "standard error");
  799. equal(r.out(), "");
  800. equal(r.err(), "");
  801. ofile.delete();
  802. efile.delete();
  803. }
  804. //----------------------------------------------------------------
  805. // Both redirectErrorStream + redirectError
  806. //----------------------------------------------------------------
  807. {
  808. pb.redirectErrorStream(true);
  809. ProcessResults r = run(pb);
  810. equal(r.exitValue(), 0);
  811. equal(fileContents(ofile),
  812. "standard error" + "standard output");
  813. equal(fileContents(efile), "");
  814. equal(r.out(), "");
  815. equal(r.err(), "");
  816. ofile.delete();
  817. efile.delete();
  818. }
  819. //----------------------------------------------------------------
  820. // Appending to existing files
  821. //----------------------------------------------------------------
  822. {
  823. setFileContents(ofile, "ofile-contents");
  824. setFileContents(efile, "efile-contents");
  825. pb.redirectOutput(Redirect.appendTo(ofile));
  826. pb.redirectError(Redirect.appendTo(efile));
  827. pb.redirectErrorStream(false);
  828. ProcessResults r = run(pb);
  829. equal(r.exitValue(), 0);
  830. equal(fileContents(ofile),
  831. "ofile-contents" + "standard output");
  832. equal(fileContents(efile),
  833. "efile-contents" + "standard error");
  834. equal(r.out(), "");
  835. equal(r.err(), "");
  836. ofile.delete();
  837. efile.delete();
  838. }
  839. //----------------------------------------------------------------
  840. // Replacing existing files
  841. //----------------------------------------------------------------
  842. {
  843. setFileContents(ofile, "ofile-contents");
  844. setFileContents(efile, "efile-contents");
  845. pb.redirectOutput(ofile);
  846. pb.redirectError(Redirect.to(efile));
  847. ProcessResults r = run(pb);
  848. equal(r.exitValue(), 0);
  849. equal(fileContents(ofile), "standard output");
  850. equal(fileContents(efile), "standard error");
  851. equal(r.out(), "");
  852. equal(r.err(), "");
  853. ofile.delete();
  854. efile.delete();
  855. }
  856. //----------------------------------------------------------------
  857. // Appending twice to the same file?
  858. //----------------------------------------------------------------
  859. {
  860. setFileContents(ofile, "ofile-contents");
  861. setFileContents(efile, "efile-contents");
  862. Redirect appender = Redirect.appendTo(ofile);
  863. pb.redirectOutput(appender);
  864. pb.redirectError(appender);
  865. ProcessResults r = run(pb);
  866. equal(r.exitValue(), 0);
  867. equal(fileContents(ofile),
  868. "ofile-contents" +
  869. "standard error" +
  870. "standard output");
  871. equal(fileContents(efile), "efile-contents");
  872. equal(r.out(), "");
  873. equal(r.err(), "");
  874. ifile.delete();
  875. ofile.delete();
  876. efile.delete();
  877. }
  878. //----------------------------------------------------------------
  879. // Testing INHERIT is harder.
  880. // Note that this requires __FOUR__ nested JVMs involved in one test,
  881. // if you count the harness JVM.
  882. //----------------------------------------------------------------
  883. {
  884. redirectIO(pb, PIPE, PIPE, PIPE);
  885. List<String> command = pb.command();
  886. command.set(command.size() - 1, "testInheritIO");
  887. Process p = pb.start();
  888. new PrintStream(p.getOutputStream()).print("standard input");
  889. p.getOutputStream().close();
  890. ProcessResults r = run(p);
  891. equal(r.exitValue(), 0);
  892. equal(r.out(), "standard output");
  893. equal(r.err(), "standard error");
  894. }
  895. //----------------------------------------------------------------
  896. // Test security implications of I/O redirection
  897. //----------------------------------------------------------------
  898. // Read access to current directory is always granted;
  899. // So create a tmpfile for input instead.
  900. final File tmpFile = File.createTempFile("Basic", "tmp");
  901. setFileContents(tmpFile, "standard input");
  902. final Policy policy = new Policy();
  903. Policy.setPolicy(policy);
  904. System.setSecurityManager(new SecurityManager());
  905. try {
  906. final Permission xPermission
  907. = new FilePermission("<<ALL FILES>>", "execute");
  908. final Permission rxPermission
  909. = new FilePermission("<<ALL FILES>>", "read,execute");
  910. final Permission wxPermission
  911. = new FilePermission("<<ALL FILES>>", "write,execute");
  912. final Permission rwxPermission
  913. = new FilePermission("<<ALL FILES>>", "read,write,execute");
  914. THROWS(SecurityException.class,
  915. new Fun() { void f() throws IOException {
  916. policy.setPermissions(xPermission);
  917. redirectIO(pb, from(tmpFile), PIPE, PIPE);
  918. pb.start();}},
  919. new Fun() { void f() throws IOException {
  920. policy.setPermissions(rxPermission);
  921. redirectIO(pb, PIPE, to(ofile), PIPE);
  922. pb.start();}},
  923. new Fun() { void f() throws IOException {
  924. policy.setPermissions(rxPermission);
  925. redirectIO(pb, PIPE, PIPE, to(efile));
  926. pb.start();}});
  927. {
  928. policy.setPermissions(rxPermission);
  929. redirectIO(pb, from(tmpFile), PIPE, PIPE);
  930. ProcessResults r = run(pb);
  931. equal(r.out(), "standard output");
  932. equal(r.err(), "standard error");
  933. }
  934. {
  935. policy.setPermissions(wxPermission);
  936. redirectIO(pb, PIPE, to(ofile), to(efile));
  937. Process p = pb.start();
  938. new PrintStream(p.getOutputStream()).print("standard input");
  939. p.getOutputStream().close();
  940. ProcessResults r = run(p);
  941. policy.setPermissions(rwxPermission);
  942. equal(fileContents(ofile), "standard output");
  943. equal(fileContents(efile), "standard error");
  944. }
  945. {
  946. policy.setPermissions(rwxPermission);
  947. redirectIO(pb, from(tmpFile), to(ofile), to(efile));
  948. ProcessResults r = run(pb);
  949. policy.setPermissions(rwxPermission);
  950. equal(fileContents(ofile), "standard output");
  951. equal(fileContents(efile), "standard error");
  952. }
  953. } finally {
  954. policy.setPermissions(new RuntimePermission("setSecurityManager"));
  955. System.setSecurityManager(null);
  956. tmpFile.delete();
  957. ifile.delete();
  958. ofile.delete();
  959. efile.delete();
  960. }
  961. }
  962. private static void realMain(String[] args) throws Throwable {
  963. if (Windows.is())
  964. System.out.println("This appears to be a Windows system.");
  965. if (Unix.is())
  966. System.out.println("This appears to be a Unix system.");
  967. if (UnicodeOS.is())
  968. System.out.println("This appears to be a Unicode-based OS.");
  969. try { testIORedirection(); }
  970. catch (Throwable t) { unexpected(t); }
  971. //----------------------------------------------------------------
  972. // Basic tests for setting, replacing and deleting envvars
  973. //----------------------------------------------------------------
  974. try {
  975. ProcessBuilder pb = new ProcessBuilder();
  976. Map<String,String> environ = pb.environment();
  977. // New env var
  978. environ.put("QUUX", "BAR");
  979. equal(environ.get("QUUX"), "BAR");
  980. equal(getenvInChild(pb,"QUUX"), "BAR");
  981. // Modify env var
  982. environ.put("QUUX","bear");
  983. equal(environ.get("QUUX"), "bear");
  984. equal(getenvInChild(pb,"QUUX"), "bear");
  985. checkMapSanity(environ);
  986. // Remove env var
  987. environ.remove("QUUX");
  988. equal(environ.get("QUUX"), null);
  989. equal(getenvInChild(pb,"QUUX"), "null");
  990. checkMapSanity(environ);
  991. // Remove non-existent env var
  992. environ.remove("QUUX");
  993. equal(environ.get("QUUX"), null);
  994. equal(getenvInChild(pb,"QUUX"), "null");
  995. checkMapSanity(environ);
  996. } catch (Throwable t) { unexpected(t); }
  997. //----------------------------------------------------------------
  998. // Pass Empty environment to child
  999. //----------------------------------------------------------------
  1000. try {
  1001. ProcessBuilder pb = new ProcessBuilder();
  1002. pb.environment().clear();
  1003. String expected = Windows.is() ? "SystemRoot="+systemRoot+",": "";
  1004. if (Windows.is()) {
  1005. pb.environment().put("SystemRoot", systemRoot);
  1006. }
  1007. String result = getenvInChild(pb);
  1008. if (MacOSX.is()) {
  1009. result = removeMacExpectedVars(result);
  1010. }
  1011. equal(result, expected);
  1012. } catch (Throwable t) { unexpected(t); }
  1013. //----------------------------------------------------------------
  1014. // System.getenv() is read-only.
  1015. //----------------------------------------------------------------
  1016. THROWS(UnsupportedOperationException.class,
  1017. new Fun(){void f(){ getenv().put("FOO","BAR");}},
  1018. new Fun(){void f(){ getenv().remove("PATH");}},
  1019. new Fun(){void f(){ getenv().keySet().remove("PATH");}},
  1020. new Fun(){void f(){ getenv().values().remove("someValue");}});
  1021. try {
  1022. Collection<Map.Entry<String,String>> c = getenv().entrySet();
  1023. if (! c.isEmpty())
  1024. try {
  1025. c.iterator().next().setValue("foo");
  1026. fail("Expected UnsupportedOperationException not thrown");
  1027. } catch (UnsupportedOperationException e) {} // OK
  1028. } catch (Throwable t) { unexpected(t); }
  1029. //----------------------------------------------------------------
  1030. // System.getenv() always returns the same object in our implementation.
  1031. //----------------------------------------------------------------
  1032. try {
  1033. check(System.getenv() == System.getenv());
  1034. } catch (Throwable t) { unexpected(t); }
  1035. //----------------------------------------------------------------
  1036. // You can't create an env var name containing "=",
  1037. // or an env var name or value containing NUL.
  1038. //----------------------------------------------------------------
  1039. {
  1040. final Map<String,String> m = new ProcessBuilder().environment();
  1041. THROWS(IllegalArgumentException.class,
  1042. new Fun(){void f(){ m.put("FOO=","BAR");}},
  1043. new Fun(){void f(){ m.put("FOO\u0000","BAR");}},
  1044. new Fun(){void f(){ m.put("FOO","BAR\u0000");}});
  1045. }
  1046. //----------------------------------------------------------------
  1047. // Commands must never be null.
  1048. //----------------------------------------------------------------
  1049. THROWS(NullPointerException.class,
  1050. new Fun(){void f(){
  1051. new ProcessBuilder((List<String>)null);}},
  1052. new Fun(){void f(){
  1053. new ProcessBuilder().command((List<String>)null);}});
  1054. //----------------------------------------------------------------
  1055. // Put in a command; get the same one back out.
  1056. //----------------------------------------------------------------
  1057. try {
  1058. List<String> command = new ArrayList<String>();
  1059. ProcessBuilder pb = new ProcessBuilder(command);
  1060. check(pb.command() == command);
  1061. List<String> command2 = new ArrayList<String>(2);
  1062. command2.add("foo");
  1063. command2.add("bar");
  1064. pb.command(command2);
  1065. check(pb.command() == command2);
  1066. pb.command("foo", "bar");
  1067. check(pb.command() != command2 && pb.command().equals(command2));
  1068. pb.command(command2);
  1069. command2.add("baz");
  1070. equal(pb.command().get(2), "baz");
  1071. } catch (Throwable t) { unexpected(t); }
  1072. //----------------------------------------------------------------
  1073. // Commands must contain at least one element.
  1074. //----------------------------------------------------------------
  1075. THROWS(IndexOutOfBoundsException.class,
  1076. new Fun() { void f() throws IOException {
  1077. new ProcessBuilder().start();}},
  1078. new Fun() { void f() throws IOException {
  1079. new ProcessBuilder(new ArrayList<String>()).start();}},
  1080. new Fun() { void f() throws IOException {
  1081. Runtime.getRuntime().exec(new String[]{});}});
  1082. //----------------------------------------------------------------
  1083. // Commands must not contain null elements at start() time.

Large files files are truncated, but you can click here to view the full file