PageRenderTime 68ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/hamishm/haiku-jdk-jdk
Java | 2198 lines | 1691 code | 228 blank | 279 comment | 151 complexity | dae75c6bb5b195bdf50a862e96e4c2fa MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0, GPL-2.0

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

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

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