1 /*
   2  * Copyright (c) 2004, 2013, 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 5006520
  26  * @summary Check many different ways to run Windows programs
  27  * @author Martin Buchholz
  28  * @key randomness
  29  */
  30 
  31 import java.io.*;
  32 import java.util.*;
  33 import static java.lang.System.*;
  34 
  35 class StreamDrainer extends Thread {
  36     private final InputStream is;
  37     private final ByteArrayOutputStream os = new ByteArrayOutputStream();
  38     public StreamDrainer(InputStream is) { this.is = is; }
  39     public void run() {
  40         try {
  41             int i;
  42             while ((i = is.read()) >= 0)
  43                 os.write(i);
  44         } catch (Exception e) {}
  45     }
  46     public String toString() { return os.toString(); }
  47 }
  48 
  49 class CommandRunner {
  50     private static Random generator = new Random();
  51     public final int exitValue;
  52     public final String out;
  53     public final String err;
  54     CommandRunner(String... args) throws Exception {
  55         Process p = (generator.nextInt(2) == 0)
  56             ? new ProcessBuilder(args).start()
  57             : Runtime.getRuntime().exec(args);
  58         StreamDrainer d1 = new StreamDrainer(p.getInputStream());
  59         StreamDrainer d2 = new StreamDrainer(p.getErrorStream());
  60         d1.start();
  61         d2.start();
  62         p.waitFor();
  63         d1.join();
  64         d2.join();
  65         this.exitValue = p.exitValue();
  66         this.out = d1.toString();
  67         this.err = d2.toString();
  68     }
  69 }
  70 
  71 public class WinCommand {
  72     private static int failed = 0;
  73 
  74     private static void fail(String msg) {
  75         err.printf("FAIL: %s%n", msg);
  76         failed++;
  77     }
  78 
  79     private static String outputOf(String... args) {
  80         try {
  81             CommandRunner cr = new CommandRunner(args);
  82             if (cr.exitValue != 0)
  83                 fail("exitValue != 0");
  84             if (! cr.err.equals(""))
  85                 fail("stderr: " + cr.err);
  86             return cr.out.replaceFirst("[\r\n]+$", "");
  87         } catch (Exception e) {
  88             fail(e.toString());
  89             return "";
  90         }
  91     }
  92 
  93     private static void checkCD(String... filespecs) {
  94         String firstCD = null;
  95         for (String filespec : filespecs) {
  96             String CD = outputOf(filespec, "/C", "CD");
  97             out.printf("%s CD ==> %s%n", filespec, CD);
  98             if (firstCD == null) {
  99                 firstCD = CD;
 100                 checkDir(CD);
 101             }
 102             if (! CD.equals(firstCD)) {
 103                 fail("Inconsistent result from CD subcommand");
 104                 checkDir(CD);
 105             }
 106         }
 107     }
 108 
 109     private static void checkDir(String dirname) {
 110         if (! new File(dirname).isDirectory())
 111             fail(String.format("Not a directory: %s%n", dirname));
 112     }
 113 
 114     private static void writeFile(String filename, String contents) {
 115         try {
 116             FileOutputStream fos = new FileOutputStream(filename);
 117             fos.write(contents.getBytes());
 118             fos.close();
 119         } catch (Exception e) {
 120             fail("Unexpected exception" + e.toString());
 121         }
 122     }
 123 
 124     public static void main(String[] args) throws Exception {
 125         File systemRoot =
 126             getenv("SystemRoot") != null ? new File(getenv("SystemRoot")) :
 127             getenv("WINDIR")     != null ? new File(getenv ("WINDIR")) :
 128             null;
 129         if (systemRoot == null || ! systemRoot.isDirectory())
 130             return; // Not Windows as we know it
 131 
 132         String systemDirW = new File(systemRoot, "System32").getPath();
 133         String systemDirM = systemDirW.replace('\\', '/');
 134         out.printf("systemDirW=%s%n", systemDirW);
 135         out.printf("systemDirM=%s%n", systemDirM);
 136 
 137         // Win9x systems don't have a cmd.exe
 138         if (new File(systemDirW, "cmd.exe").exists()) {
 139             try {
 140                 out.println("Running cmd.exe tests...");
 141                 writeFile("cdcmd.cmd", "@echo off\r\nCD\r\n");
 142                 writeFile("cdbat.bat", "@echo off\r\nCD\r\n");
 143                 checkCD("cmd",
 144                         "cmd.exe",
 145                         systemDirW + "\\cmd.exe",
 146                         // Only the ".exe" extension can be omitted
 147                         systemDirW + "\\cmd",
 148                         systemDirM + "/cmd.exe",
 149                         systemDirM + "/cmd",
 150                         "/" + systemDirM + "/cmd",
 151                         "cdcmd.cmd", "./cdcmd.cmd", ".\\cdcmd.cmd",
 152                         "cdbat.bat", "./cdbat.bat", ".\\cdbat.bat");
 153             } finally {
 154                 new File("cdcmd.cmd").delete();
 155                 new File("cdbat.bat").delete();
 156             }
 157         }
 158 
 159         // 16-bit apps like command.com must have a console;
 160         // fix this someday...
 161 
 162 //      // Win64 systems don't have a command.com
 163 //      if (new File(systemDirW, "command.com").exists()
 164 //          // no output if running without a console;
 165 //          // fix this in Mustang
 166 //          && ! outputOf("command.com", "/C", "CD").equals("")) {
 167 //          out.println("Running command.com tests...");
 168 //          checkCD("command.com",
 169 //                  systemDirM + "/command.com",
 170 //                  systemDirW + "\\command.com");
 171 //      }
 172 
 173         // Win9x systems have a %SYSTEMDRIVE%\command.com
 174 //      if (new File("C:\\COMMAND.COM").exists()
 175 //          && ! outputOf("COMMAND.COM", "/C", "CD").equals("")) {
 176 //          out.println("Running COMMAND.COM tests...");
 177 //          checkCD("C:/command.com",
 178 //                  "C:\\command.com");
 179 //      }
 180 
 181         if (failed > 0)
 182             throw new Exception(failed + " tests failed");
 183     }
 184 }