ParseAPITest.java revision 1512:d827dd6e0139
1/*
2 * Copyright (c) 2015, 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 */
25package jdk.nashorn.api.tree.test;
26
27import java.io.File;
28import java.io.IOException;
29import java.nio.charset.Charset;
30import java.nio.charset.StandardCharsets;
31import java.nio.file.Files;
32import jdk.nashorn.api.tree.Parser;
33import jdk.nashorn.api.tree.SimpleTreeVisitorES5_1;
34import jdk.nashorn.api.tree.Tree;
35import org.testng.Assert;
36import org.testng.annotations.Test;
37
38/**
39 * Test for nashorn Parser API (jdk.nashorn.api.tree.*)
40 *
41 * @test
42 * @run testng jdk.nashorn.api.tree.test.ParseAPITest
43 */
44public class ParseAPITest {
45
46    private static final boolean VERBOSE   = Boolean.valueOf(System.getProperty("parserapitest.verbose"));
47    private static final boolean TEST262   = Boolean.valueOf(System.getProperty("parserapitest.test262"));
48
49    private static final String TEST_BASIC_DIR;
50    private static final String TEST_MAPTESTS_DIR;
51    private static final String TEST_SANDBOX_DIR;
52    private static final String TEST_TRUSTED_DIR;
53    private static final String TEST262_SUITE_DIR;
54
55    static {
56        String testSrc = System.getProperty("test.src");
57        if (testSrc != null) {
58            String testScriptDir = testSrc + "/../../../../../../script/";
59            TEST_BASIC_DIR    = testScriptDir + "basic";
60            TEST_MAPTESTS_DIR = testScriptDir + "maptests";
61            TEST_SANDBOX_DIR  = testScriptDir + "sandbox";
62            TEST_TRUSTED_DIR  = testScriptDir + "trusted";
63            TEST262_SUITE_DIR = testScriptDir + "external/test262/test/suite";
64        } else {
65            TEST_BASIC_DIR     = System.getProperty("test.basic.dir");
66            TEST_MAPTESTS_DIR  = System.getProperty("test.maptests.dir");
67            TEST_SANDBOX_DIR   = System.getProperty("test.sandbox.dir");
68            TEST_TRUSTED_DIR   = System.getProperty("test.trusted.dir");
69            TEST262_SUITE_DIR  = System.getProperty("test262.suite.dir");
70        }
71    }
72
73    interface TestFilter {
74        public boolean exclude(File file, String content);
75    }
76
77    private void log(String msg) {
78        org.testng.Reporter.log(msg, true);
79    }
80
81    private static final String[] options = new String[] {
82        "-scripting", "--const-as-var"
83    };
84
85    @Test
86    public void parseAllTests() {
87        if (TEST262) {
88            parseTestSet(TEST262_SUITE_DIR, new TestFilter() {
89                @Override
90                public boolean exclude(final File file, final String content) {
91                    return content.contains("@negative");
92                }
93            });
94        }
95        parseTestSet(TEST_BASIC_DIR, new TestFilter() {
96            @Override
97            public boolean exclude(final File file, final String content) {
98                return file.getParentFile().getName().equals("es6");
99            }
100        });
101        parseTestSet(TEST_MAPTESTS_DIR, null);
102        parseTestSet(TEST_SANDBOX_DIR, null);
103        parseTestSet(TEST_TRUSTED_DIR, null);
104    }
105
106    private void parseTestSet(final String testSet, final TestFilter filter) {
107        passed  = 0;
108        failed  = 0;
109        skipped = 0;
110
111        final File testSetDir = new File(testSet);
112        if (! testSetDir.isDirectory()) {
113            log("WARNING: " + testSetDir + " not found or not a directory");
114            return;
115        }
116        log(testSetDir.getAbsolutePath());
117        parseJSDirectory(testSetDir, filter);
118
119        log(testSet + " parse API done!");
120        log("parse API ok: " + passed);
121        log("parse API failed: " + failed);
122        log("parse API skipped: " + skipped);
123        if (failed != 0) {
124            Assert.fail(failed + " tests failed to parse in " + testSetDir.getAbsolutePath());
125        }
126    }
127
128    // number of scripts that parsed fine
129    private int passed;
130    // number of scripts resulting in parse failure
131    private int failed;
132    // scripts that were skipped - all tests with @negative are
133    // skipped for now.
134    private int skipped;
135
136    private void parseJSDirectory(final File dir, final TestFilter filter) {
137        for (final File f : dir.listFiles()) {
138            if (f.isDirectory()) {
139                parseJSDirectory(f, filter);
140            } else if (f.getName().endsWith(".js")) {
141                parseJSFile(f, filter);
142            }
143        }
144    }
145
146    private void parseJSFile(final File file, final TestFilter filter) {
147        if (VERBOSE) {
148            log("Begin parsing " + file.getAbsolutePath());
149        }
150
151        try {
152            final char[] buffer = readFully(file);
153            final String content = new String(buffer);
154            boolean excluded = false;
155            if (filter != null) {
156                excluded = filter.exclude(file, content);
157            }
158
159            if (excluded) {
160                if (VERBOSE) {
161                    log("Skipping " + file.getAbsolutePath());
162                }
163                skipped++;
164                return;
165            }
166
167            final Parser parser = Parser.create(options);
168            final Tree tree = parser.parse(file.getAbsolutePath(), content, null);
169            tree.accept(new SimpleTreeVisitorES5_1<Void, Void>(), null);
170            passed++;
171        } catch (final Throwable exp) {
172            log("Parse API failed: " + file.getAbsolutePath() + " : " + exp);
173            //if (VERBOSE) {
174                exp.printStackTrace(System.out);
175            //}
176            failed++;
177        }
178
179        if (VERBOSE) {
180            log("Done parsing via parser API " + file.getAbsolutePath());
181        }
182    }
183
184    private static char[] byteToCharArray(final byte[] bytes) {
185        Charset cs = StandardCharsets.UTF_8;
186        int start = 0;
187        // BOM detection.
188        if (bytes.length > 1 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) {
189            start = 2;
190            cs = StandardCharsets.UTF_16BE;
191        } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) {
192            start = 2;
193            cs = StandardCharsets.UTF_16LE;
194        } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) {
195            start = 3;
196            cs = StandardCharsets.UTF_8;
197        } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) {
198            start = 4;
199            cs = Charset.forName("UTF-32LE");
200        } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) {
201            start = 4;
202            cs = Charset.forName("UTF-32BE");
203        }
204
205        return new String(bytes, start, bytes.length - start, cs).toCharArray();
206    }
207
208    private static char[] readFully(final File file) throws IOException {
209        final byte[] buf = Files.readAllBytes(file.toPath());
210        return byteToCharArray(buf);
211    }
212}
213