Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/test/tools/javadoc/TestScriptInComment.java
32285 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/**26* @test27* @bug 8138725 822676528* @summary test --allow-script-in-comments29* @run main TestScriptInComment30*/3132import java.io.File;33import java.io.FileWriter;34import java.io.IOException;35import java.io.PrintStream;36import java.io.PrintWriter;37import java.io.StringWriter;38import java.util.ArrayList;39import java.util.Arrays;40import java.util.Collections;41import java.util.List;42import java.util.regex.Matcher;43import java.util.regex.Pattern;4445/**46* Combo-style test, exercising combinations of different HTML fragments that may contain47* JavaScript, different places to place those fragments, and whether or not to allow the use48* of JavaScript.49*/50public class TestScriptInComment {51public static void main(String... args) throws Exception {52new TestScriptInComment().run();53}5455/**56* Representative samples of different fragments of HTML that may contain JavaScript.57* To facilitate checking the output manually in a browser, the text "#ALERT" will be58* replaced by a JavaScript call of "alert(msg)", using a message string that is specific59* to the test case.60*/61enum Comment {62LC("<script>#ALERT</script>", true), // script tag in Lower Case63UC("<SCRIPT>#ALERT</script>", true), // script tag in Upper Case64WS("< script >#ALERT</script>", false, "-Xdoclint:none"), // script tag with invalid white space65SA("<script src=\"file\"> #ALERT </script>", true), // script tag with an attribute66ON("<a onclick='#ALERT'>x</a>", true), // event handler attribute67OME("<img alt='1' onmouseenter='#ALERT'>", true), // onmouseenter event handler attribute68OML("<img alt='1' onmouseleave='#ALERT'>", true), // onmouseleave event handler attribute69OFI("<a href='#' onfocusin='#ALERT'>x</a>", true), // onfocusin event handler attribute70OBE("<a onbogusevent='#ALERT'>x</a>", true), // bogus/future event handler attribute71URI("<a href='javascript:#ALERT'>x</a>", true); // javadcript URI7273/**74* Creates an HTML fragment to be injected into a template.75* @param text the HTML fragment to put into a doc comment or option.76* @param hasScript whether or not this fragment does contain legal JavaScript77* @param opts any additional options to be specified when javadoc is run78*/79Comment(String text, boolean hasScript, String... opts) {80this.text = text;81this.hasScript = hasScript;82this.opts = Arrays.asList(opts);83}8485final String text;86final boolean hasScript;87final List<String> opts;88};8990/**91* Representative samples of positions in which javadoc may find JavaScript.92* Each template contains a series of strings, which are written to files or inferred as options.93* The first source file implies a corresponding output file which should not be written94* if the comment contains JavaScript and JavaScript is not allowed.95*/96enum Template {97OVR("<html><body> overview #COMMENT </body></html>", "package p; public class C { }"),98PKGINFO("#COMMENT package p;", "package p; public class C { }"),99PKGHTML("<html><body>#COMMENT package p;</body></html>", "package p; public class C { }"),100CLS("package p; #COMMENT public class C { }"),101CON("package p; public class C { #COMMENT public C() { } }"),102FLD("package p; public class C { #COMMENT public int f; }"),103MTH("package p; public class C { #COMMENT public void m() { } }"),104TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"),105HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"),106FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"),107BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"),108DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"),109PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }");110111Template(String... args) {112opts = new ArrayList<String>();113sources = new ArrayList<String>();114int i = 0;115while (args[i].startsWith("-")) {116// all options being tested have a single argument that follow the option117opts.add(args[i++]);118opts.add(args[i++]);119}120while(i < args.length) {121sources.add(args[i++]);122}123}124125// groups: 1 <html> or not; 2: package name; 3: class name126private final Pattern pat =127Pattern.compile("(?i)(<html>)?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?");128129/**130* Infer the file in which to write the given source.131* @param dir the base source directory132* @param src the source text133* @return the file in which the source should be written134*/135File getSrcFile(File srcDir, String src) {136String f;137Matcher m = pat.matcher(src);138if (!m.matches())139throw new Error("match failed");140if (m.group(3) != null) {141f = m.group(2) + "/" + m.group(3) + ".java";142} else if (m.group(2) != null) {143f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html");144} else {145f = "overview.html";146}147return new File(srcDir, f);148}149150/**151* Get the options to give to javadoc.152* @param srcDir the srcDir to use -overview is needed153* @return154*/155List<String> getOpts(File srcDir) {156if (!opts.isEmpty()) {157return opts;158} else if (sources.get(0).contains("overview")) {159return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath());160} else {161return Collections.emptyList();162}163}164165/**166* Gets the output file corresponding to the first source file.167* This file should not be written if the comment contains JavaScript and JavaScripot is168* not allowed.169* @param dir the base output directory170* @return the output file171*/172File getOutFile(File outDir) {173String f;174Matcher m = pat.matcher(sources.get(0));175if (!m.matches())176throw new Error("match failed");177if (m.group(3) != null) {178f = m.group(2) + "/" + m.group(3) + ".html";179} else if (m.group(2) != null) {180f = m.group(2) + "/package-summary.html";181} else {182f = "overview-summary.html";183}184return new File(outDir, f);185}186187final List<String> opts;188final List<String> sources;189};190191enum Option {192OFF(null),193ON("--allow-script-in-comments");194195Option(String text) {196this.text = text;197}198199final String text;200};201202private PrintStream out = System.err;203204public void run() throws Exception {205int count = 0;206for (Template template: Template.values()) {207for (Comment comment: Comment.values()) {208for (Option option: Option.values()) {209if (test(template, comment, option)) {210count++;211}212}213}214}215216out.println(count + " test cases run");217if (errors > 0) {218throw new Exception(errors + " errors occurred");219}220}221222boolean test(Template template, Comment comment, Option option) throws IOException {223if (option == Option.ON && !comment.hasScript) {224// skip --allowScriptInComments if comment does not contain JavaScript225return false;226}227228String test = template + "-" + comment + "-" + option;229out.println("Test: " + test);230231File dir = new File(test);232dir.mkdirs();233File srcDir = new File(dir, "src");234File outDir = new File(dir, "out");235236String alert = "alert(\"" + test + "\");";237for (String src: template.sources) {238writeFile(template.getSrcFile(srcDir, src),239src.replace("#COMMENT",240"/** " + comment.text.replace("#ALERT", alert) + " **/"));241}242243List<String> opts = new ArrayList<String>();244opts.add("-sourcepath");245opts.add(srcDir.getPath());246opts.add("-d");247opts.add(outDir.getPath());248if (option.text != null)249opts.add(option.text);250for (String opt: template.getOpts(srcDir)) {251opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert)));252}253opts.addAll(comment.opts);254opts.add("-noindex"); // index not required; save time/space writing files255opts.add("p");256257StringWriter sw = new StringWriter();258PrintWriter pw = new PrintWriter(sw);259int rc = javadoc(opts, pw);260pw.close();261String log = sw.toString();262writeFile(new File(dir, "log.txt"), log);263264out.println("opts: " + opts);265out.println(" rc: " + rc);266out.println(" log:");267out.println(log);268269String ERROR = "Use --allow-script-in-comment";270File outFile = template.getOutFile(outDir);271272boolean expectErrors = comment.hasScript && (option == Option.OFF);273274if (expectErrors) {275check(rc != 0, "unexpected exit code: " + rc);276check(log.contains(ERROR), "expected error message not found");277check(!outFile.exists(), "output file found unexpectedly");278} else {279check(rc == 0, "unexpected exit code: " + rc);280check(!log.contains(ERROR), "error message found");281check(outFile.exists(), "output file not found");282}283284out.println();285return true;286}287288int javadoc(List<String> opts, PrintWriter pw) {289return com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw,290"com.sun.tools.doclets.standard.Standard", opts.toArray(new String[opts.size()]));291}292293File writeFile(File f, String text) throws IOException {294f.getParentFile().mkdirs();295FileWriter fw = new FileWriter(f);296try {297fw.write(text);298} finally {299fw.close();300}301return f;302}303304void check(boolean cond, String errMessage) {305if (!cond) {306error(errMessage);307}308}309310void error(String message) {311out.println("Error: " + message);312errors++;313}314315int errors = 0;316}317318319320