ScriptRunnable.java revision 1110:52340a35aec9
1/* 2 * Copyright (c) 2010, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.test.framework; 27 28import java.io.BufferedReader; 29import java.io.ByteArrayOutputStream; 30import java.io.File; 31import java.io.FileInputStream; 32import java.io.FileOutputStream; 33import java.io.IOException; 34import java.io.InputStreamReader; 35import java.io.OutputStream; 36import java.io.PrintStream; 37import java.io.PrintWriter; 38import java.io.StringReader; 39import java.nio.file.FileSystems; 40import java.nio.file.Files; 41import java.nio.file.StandardCopyOption; 42import java.util.ArrayList; 43import java.util.List; 44import java.util.Map; 45import jdk.nashorn.tools.Shell; 46import org.testng.Assert; 47import org.testng.ITest; 48import org.testng.annotations.Test; 49 50/** 51 * Compiles a single JavaScript script source file and executes the resulting 52 * class. Optionally, output from running the script is compared against the 53 * corresponding .EXPECTED file. 54 */ 55@SuppressWarnings("javadoc") 56public final class ScriptRunnable extends AbstractScriptRunnable implements ITest { 57 public ScriptRunnable(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> scriptArguments) { 58 super(framework, testFile, engineOptions, testOptions, scriptArguments); 59 60 if (this.shouldRun) { 61 // add --dump-on-error option always so that we can get detailed error msg. 62 engineOptions.add("-doe"); 63 } 64 } 65 66 @Override 67 public String getTestName() { 68 return testFile.getAbsolutePath(); 69 } 70 71 @Test 72 @Override 73 public void runTest() throws IOException { 74 try { 75 super.runTest(); 76 } catch(final AssertionError e) { 77 throw new AssertionError("Failed executing test " + testFile, e); 78 } 79 } 80 81 @Override 82 protected void execute() { 83 if (fork) { 84 executeInNewProcess(); 85 } else { 86 executeInThisProcess(); 87 } 88 } 89 90 // avoid direct System.out.println - use reporter to capture 91 @Override 92 protected void log(final String msg) { 93 org.testng.Reporter.log(msg, true); 94 } 95 96 // throw Assert fail - but log as well so that user can see this at console 97 @Override 98 protected void fail(final String msg) { 99 log(msg); 100 Assert.fail(msg); 101 } 102 103 @Override 104 protected void compile() throws IOException { 105 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 106 final ByteArrayOutputStream err = new ByteArrayOutputStream(); 107 final List<String> args = getCompilerArgs(); 108 int errors; 109 110 try { 111 errors = evaluateScript(out, err, args.toArray(new String[args.size()])); 112 } catch (final AssertionError e) { 113 final PrintWriter writer = new PrintWriter(err); 114 e.printStackTrace(writer); 115 writer.flush(); 116 errors = 1; 117 } 118 119 if (errors != 0 || checkCompilerMsg) { 120 if (expectCompileFailure || checkCompilerMsg) { 121 final PrintStream outputDest = new PrintStream(new FileOutputStream(errorFileName)); 122 TestHelper.dumpFile(outputDest, new StringReader(new String(err.toByteArray()))); 123 outputDest.println("--"); 124 } else { 125 log(new String(err.toByteArray())); 126 } 127 128 if (errors != 0 && !expectCompileFailure) { 129 fail(String.format("%d errors compiling %s", errors, testFile)); 130 } 131 if (checkCompilerMsg) { 132 compare(errorFileName, expectedFileName, true); 133 } 134 } 135 136 if (expectCompileFailure && errors == 0) { 137 fail(String.format("No errors encountered compiling negative test %s", testFile)); 138 } 139 } 140 141 private void executeInThisProcess() { 142 final List<String> args = getRuntimeArgs(); 143 final File outputFileHandle = new File(outputFileName); 144 final File errorFileHandle = new File(errorFileName); 145 146 try (OutputStream outputFile = new FileOutputStream(outputFileName); OutputStream errorFile = new FileOutputStream(errorFileName)) { 147 final int errors = evaluateScript(outputFile, errorFile, args.toArray(new String[args.size()])); 148 149 if (errors != 0 || errorFileHandle.length() > 0) { 150 if (expectRunFailure) { 151 return; 152 } 153 154 if (!ignoreStdError) { 155 if (outputFileHandle.length() > 0) { 156 TestHelper.dumpFile(outputFileHandle); 157 } 158 fail(TestHelper.fullContent(errorFileHandle)); 159 } 160 } 161 162 if (compare) { 163 compare(outputFileName, expectedFileName, false); 164 } 165 } catch (final IOException e) { 166 if (!expectRunFailure) { 167 fail("Failure running test " + testFile + ": " + e.getMessage()); 168 // else success 169 } 170 } 171 } 172 173 private void executeInNewProcess() { 174 175 final String separator = System.getProperty("file.separator"); 176 final List<String> cmd = new ArrayList<>(); 177 178 cmd.add(System.getProperty("java.home") + separator + "bin" + separator + "java"); 179 // cmd.add("-Djava.ext.dirs=dist"); 180 cmd.add("-Xbootclasspath/a:dist/nashorn.jar"); 181 for (final String str : forkJVMOptions) { 182 if(!str.isEmpty()) { 183 cmd.add(str); 184 } 185 } 186 cmd.add(Shell.class.getName()); 187 // now add the rest of the "in process" runtime arguments 188 cmd.addAll(getRuntimeArgs()); 189 190 final File outputFileHandle = new File(outputFileName); 191 final File errorFileHandle = new File(errorFileName); 192 193 try { 194 final ProcessBuilder pb = new ProcessBuilder(cmd); 195 pb.redirectOutput(outputFileHandle); 196 pb.redirectError(errorFileHandle); 197 final Process process = pb.start(); 198 199 process.waitFor(); 200 201 if (errorFileHandle.length() > 0) { 202 if (expectRunFailure) { 203 return; 204 } 205 if (!ignoreStdError) { 206 if (outputFileHandle.length() > 0) { 207 TestHelper.dumpFile(outputFileHandle); 208 } 209 fail(TestHelper.fullContent(errorFileHandle)); 210 } 211 } 212 213 if (compare) { 214 compare(outputFileName, expectedFileName, false); 215 } 216 } catch (final IOException | InterruptedException e) { 217 if (!expectRunFailure) { 218 fail("Failure running test " + testFile + ": " + e.getMessage()); 219 // else success 220 } 221 } 222 } 223 224 private void compare(final String outputFileName0, final String expectedFileName0, final boolean compareCompilerMsg) throws IOException { 225 final File expectedFile = new File(expectedFileName0); 226 227 BufferedReader expected; 228 if (expectedFile.exists()) { 229 expected = new BufferedReader(new InputStreamReader(new FileInputStream(expectedFileName0))); 230 // copy expected file overwriting existing file and preserving last 231 // modified time of source 232 try { 233 Files.copy(FileSystems.getDefault().getPath(expectedFileName0), 234 FileSystems.getDefault().getPath(copyExpectedFileName), 235 StandardCopyOption.REPLACE_EXISTING, 236 StandardCopyOption.COPY_ATTRIBUTES); 237 } catch (final IOException ex) { 238 fail("failed to copy expected " + expectedFileName + " to " + copyExpectedFileName + ": " + ex.getMessage()); 239 } 240 } else { 241 expected = new BufferedReader(new StringReader("")); 242 } 243 244 final BufferedReader actual = new BufferedReader(new InputStreamReader(new FileInputStream(outputFileName0))); 245 compare(actual, expected, compareCompilerMsg); 246 } 247} 248