PageRenderTime 66ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/test/java/lang/ProcessBuilder/Basic.java

https://bitbucket.org/chegar/jigsaw_jigsaw_jdk
Java | 2256 lines | 1736 code | 232 blank | 288 comment | 157 complexity | 37497c678731bd92a7ecda1d028c8af0 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.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 (may) add the variable __CF_USER_TEXT_ENCODING to an empty
  583. * environment. The environment variable JAVA_MAIN_CLASS_<pid> may also
  584. * be set in Mac OS X.
  585. * Remove 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. // Check for JAVA_MAIN_CLASS_<pid>
  592. String javaMainClassStr
  593. = matchAndExtract(cleanedVars,
  594. "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,");
  595. return cleanedVars.replace(javaMainClassStr,"");
  596. }
  597. private static String sortByLinesWindowsly(String text) {
  598. String[] lines = text.split("\n");
  599. Arrays.sort(lines, new WindowsComparator());
  600. StringBuilder sb = new StringBuilder();
  601. for (String line : lines)
  602. sb.append(line).append("\n");
  603. return sb.toString();
  604. }
  605. private static void checkMapSanity(Map<String,String> map) {
  606. try {
  607. Set<String> keySet = map.keySet();
  608. Collection<String> values = map.values();
  609. Set<Map.Entry<String,String>> entrySet = map.entrySet();
  610. equal(entrySet.size(), keySet.size());
  611. equal(entrySet.size(), values.size());
  612. StringBuilder s1 = new StringBuilder();
  613. for (Map.Entry<String,String> e : entrySet)
  614. s1.append(e.getKey() + "=" + e.getValue() + "\n");
  615. StringBuilder s2 = new StringBuilder();
  616. for (String var : keySet)
  617. s2.append(var + "=" + map.get(var) + "\n");
  618. equal(s1.toString(), s2.toString());
  619. Iterator<String> kIter = keySet.iterator();
  620. Iterator<String> vIter = values.iterator();
  621. Iterator<Map.Entry<String,String>> eIter = entrySet.iterator();
  622. while (eIter.hasNext()) {
  623. Map.Entry<String,String> entry = eIter.next();
  624. String key = kIter.next();
  625. String value = vIter.next();
  626. check(entrySet.contains(entry));
  627. check(keySet.contains(key));
  628. check(values.contains(value));
  629. check(map.containsKey(key));
  630. check(map.containsValue(value));
  631. equal(entry.getKey(), key);
  632. equal(entry.getValue(), value);
  633. }
  634. check(! kIter.hasNext() &&
  635. ! vIter.hasNext());
  636. } catch (Throwable t) { unexpected(t); }
  637. }
  638. private static void checkMapEquality(Map<String,String> map1,
  639. Map<String,String> map2) {
  640. try {
  641. equal(map1.size(), map2.size());
  642. equal(map1.isEmpty(), map2.isEmpty());
  643. for (String key : map1.keySet()) {
  644. equal(map1.get(key), map2.get(key));
  645. check(map2.keySet().contains(key));
  646. }
  647. equal(map1, map2);
  648. equal(map2, map1);
  649. equal(map1.entrySet(), map2.entrySet());
  650. equal(map2.entrySet(), map1.entrySet());
  651. equal(map1.keySet(), map2.keySet());
  652. equal(map2.keySet(), map1.keySet());
  653. equal(map1.hashCode(), map2.hashCode());
  654. equal(map1.entrySet().hashCode(), map2.entrySet().hashCode());
  655. equal(map1.keySet().hashCode(), map2.keySet().hashCode());
  656. } catch (Throwable t) { unexpected(t); }
  657. }
  658. static void checkRedirects(ProcessBuilder pb,
  659. Redirect in, Redirect out, Redirect err) {
  660. equal(pb.redirectInput(), in);
  661. equal(pb.redirectOutput(), out);
  662. equal(pb.redirectError(), err);
  663. }
  664. static void redirectIO(ProcessBuilder pb,
  665. Redirect in, Redirect out, Redirect err) {
  666. pb.redirectInput(in);
  667. pb.redirectOutput(out);
  668. pb.redirectError(err);
  669. }
  670. static void setFileContents(File file, String contents) {
  671. try {
  672. Writer w = new FileWriter(file);
  673. w.write(contents);
  674. w.close();
  675. } catch (Throwable t) { unexpected(t); }
  676. }
  677. static String fileContents(File file) {
  678. try {
  679. Reader r = new FileReader(file);
  680. StringBuilder sb = new StringBuilder();
  681. char[] buffer = new char[1024];
  682. int n;
  683. while ((n = r.read(buffer)) != -1)
  684. sb.append(buffer,0,n);
  685. r.close();
  686. return new String(sb);
  687. } catch (Throwable t) { unexpected(t); return ""; }
  688. }
  689. static void testIORedirection() throws Throwable {
  690. final File ifile = new File("ifile");
  691. final File ofile = new File("ofile");
  692. final File efile = new File("efile");
  693. ifile.delete();
  694. ofile.delete();
  695. efile.delete();
  696. //----------------------------------------------------------------
  697. // Check mutual inequality of different types of Redirect
  698. //----------------------------------------------------------------
  699. Redirect[] redirects =
  700. { PIPE,
  701. INHERIT,
  702. Redirect.from(ifile),
  703. Redirect.to(ifile),
  704. Redirect.appendTo(ifile),
  705. Redirect.from(ofile),
  706. Redirect.to(ofile),
  707. Redirect.appendTo(ofile),
  708. };
  709. for (int i = 0; i < redirects.length; i++)
  710. for (int j = 0; j < redirects.length; j++)
  711. equal(redirects[i].equals(redirects[j]), (i == j));
  712. //----------------------------------------------------------------
  713. // Check basic properties of different types of Redirect
  714. //----------------------------------------------------------------
  715. equal(PIPE.type(), Redirect.Type.PIPE);
  716. equal(PIPE.toString(), "PIPE");
  717. equal(PIPE.file(), null);
  718. equal(INHERIT.type(), Redirect.Type.INHERIT);
  719. equal(INHERIT.toString(), "INHERIT");
  720. equal(INHERIT.file(), null);
  721. equal(Redirect.from(ifile).type(), Redirect.Type.READ);
  722. equal(Redirect.from(ifile).toString(),
  723. "redirect to read from file \"ifile\"");
  724. equal(Redirect.from(ifile).file(), ifile);
  725. equal(Redirect.from(ifile),
  726. Redirect.from(ifile));
  727. equal(Redirect.from(ifile).hashCode(),
  728. Redirect.from(ifile).hashCode());
  729. equal(Redirect.to(ofile).type(), Redirect.Type.WRITE);
  730. equal(Redirect.to(ofile).toString(),
  731. "redirect to write to file \"ofile\"");
  732. equal(Redirect.to(ofile).file(), ofile);
  733. equal(Redirect.to(ofile),
  734. Redirect.to(ofile));
  735. equal(Redirect.to(ofile).hashCode(),
  736. Redirect.to(ofile).hashCode());
  737. equal(Redirect.appendTo(ofile).type(), Redirect.Type.APPEND);
  738. equal(Redirect.appendTo(efile).toString(),
  739. "redirect to append to file \"efile\"");
  740. equal(Redirect.appendTo(efile).file(), efile);
  741. equal(Redirect.appendTo(efile),
  742. Redirect.appendTo(efile));
  743. equal(Redirect.appendTo(efile).hashCode(),
  744. Redirect.appendTo(efile).hashCode());
  745. //----------------------------------------------------------------
  746. // Check initial values of redirects
  747. //----------------------------------------------------------------
  748. List<String> childArgs = new ArrayList<String>(javaChildArgs);
  749. childArgs.add("testIO");
  750. final ProcessBuilder pb = new ProcessBuilder(childArgs);
  751. checkRedirects(pb, PIPE, PIPE, PIPE);
  752. //----------------------------------------------------------------
  753. // Check inheritIO
  754. //----------------------------------------------------------------
  755. pb.inheritIO();
  756. checkRedirects(pb, INHERIT, INHERIT, INHERIT);
  757. //----------------------------------------------------------------
  758. // Check setters and getters agree
  759. //----------------------------------------------------------------
  760. pb.redirectInput(ifile);
  761. equal(pb.redirectInput().file(), ifile);
  762. equal(pb.redirectInput(), Redirect.from(ifile));
  763. pb.redirectOutput(ofile);
  764. equal(pb.redirectOutput().file(), ofile);
  765. equal(pb.redirectOutput(), Redirect.to(ofile));
  766. pb.redirectError(efile);
  767. equal(pb.redirectError().file(), efile);
  768. equal(pb.redirectError(), Redirect.to(efile));
  769. THROWS(IllegalArgumentException.class,
  770. new Fun(){void f() {
  771. pb.redirectInput(Redirect.to(ofile)); }},
  772. new Fun(){void f() {
  773. pb.redirectInput(Redirect.appendTo(ofile)); }},
  774. new Fun(){void f() {
  775. pb.redirectOutput(Redirect.from(ifile)); }},
  776. new Fun(){void f() {
  777. pb.redirectError(Redirect.from(ifile)); }});
  778. THROWS(IOException.class,
  779. // Input file does not exist
  780. new Fun(){void f() throws Throwable { pb.start(); }});
  781. setFileContents(ifile, "standard input");
  782. //----------------------------------------------------------------
  783. // Writing to non-existent files
  784. //----------------------------------------------------------------
  785. {
  786. ProcessResults r = run(pb);
  787. equal(r.exitValue(), 0);
  788. equal(fileContents(ofile), "standard output");
  789. equal(fileContents(efile), "standard error");
  790. equal(r.out(), "");
  791. equal(r.err(), "");
  792. ofile.delete();
  793. efile.delete();
  794. }
  795. //----------------------------------------------------------------
  796. // Both redirectErrorStream + redirectError
  797. //----------------------------------------------------------------
  798. {
  799. pb.redirectErrorStream(true);
  800. ProcessResults r = run(pb);
  801. equal(r.exitValue(), 0);
  802. equal(fileContents(ofile),
  803. "standard error" + "standard output");
  804. equal(fileContents(efile), "");
  805. equal(r.out(), "");
  806. equal(r.err(), "");
  807. ofile.delete();
  808. efile.delete();
  809. }
  810. //----------------------------------------------------------------
  811. // Appending to existing files
  812. //----------------------------------------------------------------
  813. {
  814. setFileContents(ofile, "ofile-contents");
  815. setFileContents(efile, "efile-contents");
  816. pb.redirectOutput(Redirect.appendTo(ofile));
  817. pb.redirectError(Redirect.appendTo(efile));
  818. pb.redirectErrorStream(false);
  819. ProcessResults r = run(pb);
  820. equal(r.exitValue(), 0);
  821. equal(fileContents(ofile),
  822. "ofile-contents" + "standard output");
  823. equal(fileContents(efile),
  824. "efile-contents" + "standard error");
  825. equal(r.out(), "");
  826. equal(r.err(), "");
  827. ofile.delete();
  828. efile.delete();
  829. }
  830. //----------------------------------------------------------------
  831. // Replacing existing files
  832. //----------------------------------------------------------------
  833. {
  834. setFileContents(ofile, "ofile-contents");
  835. setFileContents(efile, "efile-contents");
  836. pb.redirectOutput(ofile);
  837. pb.redirectError(Redirect.to(efile));
  838. ProcessResults r = run(pb);
  839. equal(r.exitValue(), 0);
  840. equal(fileContents(ofile), "standard output");
  841. equal(fileContents(efile), "standard error");
  842. equal(r.out(), "");
  843. equal(r.err(), "");
  844. ofile.delete();
  845. efile.delete();
  846. }
  847. //----------------------------------------------------------------
  848. // Appending twice to the same file?
  849. //----------------------------------------------------------------
  850. {
  851. setFileContents(ofile, "ofile-contents");
  852. setFileContents(efile, "efile-contents");
  853. Redirect appender = Redirect.appendTo(ofile);
  854. pb.redirectOutput(appender);
  855. pb.redirectError(appender);
  856. ProcessResults r = run(pb);
  857. equal(r.exitValue(), 0);
  858. equal(fileContents(ofile),
  859. "ofile-contents" +
  860. "standard error" +
  861. "standard output");
  862. equal(fileContents(efile), "efile-contents");
  863. equal(r.out(), "");
  864. equal(r.err(), "");
  865. ifile.delete();
  866. ofile.delete();
  867. efile.delete();
  868. }
  869. //----------------------------------------------------------------
  870. // Testing INHERIT is harder.
  871. // Note that this requires __FOUR__ nested JVMs involved in one test,
  872. // if you count the harness JVM.
  873. //----------------------------------------------------------------
  874. {
  875. redirectIO(pb, PIPE, PIPE, PIPE);
  876. List<String> command = pb.command();
  877. command.set(command.size() - 1, "testInheritIO");
  878. Process p = pb.start();
  879. new PrintStream(p.getOutputStream()).print("standard input");
  880. p.getOutputStream().close();
  881. ProcessResults r = run(p);
  882. equal(r.exitValue(), 0);
  883. equal(r.out(), "standard output");
  884. equal(r.err(), "standard error");
  885. }
  886. //----------------------------------------------------------------
  887. // Test security implications of I/O redirection
  888. //----------------------------------------------------------------
  889. // Read access to current directory is always granted;
  890. // So create a tmpfile for input instead.
  891. final File tmpFile = File.createTempFile("Basic", "tmp");
  892. setFileContents(tmpFile, "standard input");
  893. final Policy policy = new Policy();
  894. Policy.setPolicy(policy);
  895. System.setSecurityManager(new SecurityManager());
  896. try {
  897. final Permission xPermission
  898. = new FilePermission("<<ALL FILES>>", "execute");
  899. final Permission rxPermission
  900. = new FilePermission("<<ALL FILES>>", "read,execute");
  901. final Permission wxPermission
  902. = new FilePermission("<<ALL FILES>>", "write,execute");
  903. final Permission rwxPermission
  904. = new FilePermission("<<ALL FILES>>", "read,write,execute");
  905. THROWS(SecurityException.class,
  906. new Fun() { void f() throws IOException {
  907. policy.setPermissions(xPermission);
  908. redirectIO(pb, from(tmpFile), PIPE, PIPE);
  909. pb.start();}},
  910. new Fun() { void f() throws IOException {
  911. policy.setPermissions(rxPermission);
  912. redirectIO(pb, PIPE, to(ofile), PIPE);
  913. pb.start();}},
  914. new Fun() { void f() throws IOException {
  915. policy.setPermissions(rxPermission);
  916. redirectIO(pb, PIPE, PIPE, to(efile));
  917. pb.start();}});
  918. {
  919. policy.setPermissions(rxPermission);
  920. redirectIO(pb, from(tmpFile), PIPE, PIPE);
  921. ProcessResults r = run(pb);
  922. equal(r.out(), "standard output");
  923. equal(r.err(), "standard error");
  924. }
  925. {
  926. policy.setPermissions(wxPermission);
  927. redirectIO(pb, PIPE, to(ofile), to(efile));
  928. Process p = pb.start();
  929. new PrintStream(p.getOutputStream()).print("standard input");
  930. p.getOutputStream().close();
  931. ProcessResults r = run(p);
  932. policy.setPermissions(rwxPermission);
  933. equal(fileContents(ofile), "standard output");
  934. equal(fileContents(efile), "standard error");
  935. }
  936. {
  937. policy.setPermissions(rwxPermission);
  938. redirectIO(pb, from(tmpFile), to(ofile), to(efile));
  939. ProcessResults r = run(pb);
  940. policy.setPermissions(rwxPermission);
  941. equal(fileContents(ofile), "standard output");
  942. equal(fileContents(efile), "standard error");
  943. }
  944. } finally {
  945. policy.setPermissions(new RuntimePermission("setSecurityManager"));
  946. System.setSecurityManager(null);
  947. tmpFile.delete();
  948. ifile.delete();
  949. ofile.delete();
  950. efile.delete();
  951. }
  952. }
  953. private static void realMain(String[] args) throws Throwable {
  954. if (Windows.is())
  955. System.out.println("This appears to be a Windows system.");
  956. if (Unix.is())
  957. System.out.println("This appears to be a Unix system.");
  958. if (UnicodeOS.is())
  959. System.out.println("This appears to be a Unicode-based OS.");
  960. try { testIORedirection(); }
  961. catch (Throwable t) { unexpected(t); }
  962. //----------------------------------------------------------------
  963. // Basic tests for setting, replacing and deleting envvars
  964. //----------------------------------------------------------------
  965. try {
  966. ProcessBuilder pb = new ProcessBuilder();
  967. Map<String,String> environ = pb.environment();
  968. // New env var
  969. environ.put("QUUX", "BAR");
  970. equal(environ.get("QUUX"), "BAR");
  971. equal(getenvInChild(pb,"QUUX"), "BAR");
  972. // Modify env var
  973. environ.put("QUUX","bear");
  974. equal(environ.get("QUUX"), "bear");
  975. equal(getenvInChild(pb,"QUUX"), "bear");
  976. checkMapSanity(environ);
  977. // Remove env var
  978. environ.remove("QUUX");
  979. equal(environ.get("QUUX"), null);
  980. equal(getenvInChild(pb,"QUUX"), "null");
  981. checkMapSanity(environ);
  982. // Remove non-existent env var
  983. environ.remove("QUUX");
  984. equal(environ.get("QUUX"), null);
  985. equal(getenvInChild(pb,"QUUX"), "null");
  986. checkMapSanity(environ);
  987. } catch (Throwable t) { unexpected(t); }
  988. //----------------------------------------------------------------
  989. // Pass Empty environment to child
  990. //----------------------------------------------------------------
  991. try {
  992. ProcessBuilder pb = new ProcessBuilder();
  993. pb.environment().clear();
  994. String expected = Windows.is() ? "SystemRoot="+systemRoot+",": "";
  995. if (Windows.is()) {
  996. pb.environment().put("SystemRoot", systemRoot);
  997. }
  998. String result = getenvInChild(pb);
  999. if (MacOSX.is()) {
  1000. result = removeMacExpectedVars(result);
  1001. }
  1002. equal(result, expected);
  1003. } catch (Throwable t) { unexpected(t); }
  1004. //----------------------------------------------------------------
  1005. // System.getenv() is read-only.
  1006. //----------------------------------------------------------------
  1007. THROWS(UnsupportedOperationException.class,
  1008. new Fun(){void f(){ getenv().put("FOO","BAR");}},
  1009. new Fun(){void f(){ getenv().remove("PATH");}},
  1010. new Fun(){void f(){ getenv().keySet().remove("PATH");}},
  1011. new Fun(){void f(){ getenv().values().remove("someValue");}});
  1012. try {
  1013. Collection<Map.Entry<String,String>> c = getenv().entrySet();
  1014. if (! c.isEmpty())
  1015. try {
  1016. c.iterator().next().setValue("foo");
  1017. fail("Expected UnsupportedOperationException not thrown");
  1018. } catch (UnsupportedOperationException e) {} // OK
  1019. } catch (Throwable t) { unexpected(t); }
  1020. //----------------------------------------------------------------
  1021. // System.getenv() always returns the same object in our implementation.
  1022. //----------------------------------------------------------------
  1023. try {
  1024. check(System.getenv() == System.getenv());
  1025. } catch (Throwable t) { unexpected(t); }
  1026. //----------------------------------------------------------------
  1027. // You can't create an env var name containing "=",
  1028. // or an env var name or value containing NUL.
  1029. //----------------------------------------------------------------
  1030. {
  1031. final Map<String,String> m = new ProcessBuilder().environment();
  1032. THROWS(IllegalArgumentException.class,
  1033. new Fun(){void f(){ m.put("FOO=","BAR");}},
  1034. new Fun(){void f(){ m.put("FOO\u0000","BAR");}},
  1035. new Fun(){void f(){ m.put("FOO","BAR\u0000");}});
  1036. }
  1037. //----------------------------------------------------------------
  1038. // Commands must never be null.
  1039. //----------------------------------------------------------------
  1040. THROWS(NullPointerException.class,
  1041. new Fun(){void f(){
  1042. new ProcessBuilder((List<String>)null);}},
  1043. new Fun(){void f(){
  1044. new ProcessBuilder().command((List<String>)null);}});
  1045. //----------------------------------------------------------------
  1046. // Put in a command; get the same one back out.
  1047. //----------------------------------------------------------------
  1048. try {
  1049. List<String> command = new ArrayList<String>();
  1050. ProcessBuilder pb = new ProcessBuilder(command);
  1051. check(pb.command() == command);
  1052. List<String> command2 = new ArrayList<String>(2);
  1053. command2.add("foo");
  1054. command2.add("bar");
  1055. pb.command(command2);
  1056. check(pb.command() == command2);
  1057. pb.command("foo", "bar");
  1058. check(pb.command() != command2 && pb.command().equals(command2));
  1059. pb.command(command2);
  1060. command2.add("baz");
  1061. equal(pb.command().get(2), "baz");
  1062. } catch (Throwable t) { unexpected(t); }
  1063. //----------------------------------------------------------------
  1064. // Commands must contain at least one element.
  1065. //----------------------------------------------------------------
  1066. THROWS(IndexOutOfBoundsException.class,
  1067. new Fun() { void f() throws IOException {
  1068. new ProcessBuilder().start();}},
  1069. new Fun() { void f() throws IOException {
  1070. new ProcessBuilder(new ArrayList<String>()).start();}},
  1071. new Fun() { void f() throws IOException {
  1072. Runtime.getRuntime().exec(new String[]{});}});
  1073. //----------------------------------------------------------------
  1074. // Commands must not contain null elements at start() time.
  1075. //----------------------------------------------------------------
  1076. THROWS(NullPointerException.class,
  1077. new Fun() { void f() throws IOException {
  1078. new ProcessBuilder("foo",null,"bar").start();}},
  1079. new Fun() { void f() throws IOException {
  1080. new ProcessBuilder((String)null).start();}},
  1081. new Fun() { void f() throws IOException {

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