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