Path: blob/master/test/langtools/jdk/javadoc/tool/modules/ModuleTestBase.java
40974 views
/*1* Copyright (c) 2016, 2019, 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.IOException;24import java.io.PrintWriter;25import java.io.StringWriter;26import java.nio.file.Path;27import java.nio.file.Paths;28import java.util.Arrays;29import java.util.HashSet;30import java.util.List;31import java.util.Locale;32import java.util.Set;33import java.util.TreeSet;34import java.util.stream.Collectors;3536import javax.lang.model.SourceVersion;37import javax.lang.model.element.Element;38import javax.lang.model.element.ElementKind;39import javax.lang.model.element.ModuleElement;40import javax.lang.model.element.PackageElement;41import javax.lang.model.element.TypeElement;42import javax.lang.model.util.ElementFilter;43import javax.lang.model.util.SimpleElementVisitor14;4445import jdk.javadoc.doclet.Doclet;46import jdk.javadoc.doclet.DocletEnvironment;47import jdk.javadoc.doclet.Reporter;4849import toolbox.JavadocTask;50import toolbox.Task;51import toolbox.Task.Expect;52import toolbox.TestRunner;53import toolbox.ToolBox;5455import static toolbox.Task.OutputKind.*;5657/**58* Base class for module tests.59*/60public class ModuleTestBase extends TestRunner {6162// Field Separator63private static final String FS = " ";6465protected ToolBox tb;66private final Class<?> docletClass;6768private Task.Result currentTask = null;6970ModuleTestBase() {71super(System.err);72tb = new ToolBox();73ClassLoader cl = ModuleTestBase.class.getClassLoader();74try {75docletClass = cl.loadClass("ModuleTestBase$ModulesTesterDoclet");76} catch (ClassNotFoundException cfe) {77throw new Error(cfe);78}79}8081/**82* Execute methods annotated with @Test, and throw an exception if any83* errors are reported..84*85* @throws Exception if any errors occurred86*/87protected void runTests() throws Exception {88runTests(m -> new Object[] { Paths.get(m.getName()) });89}9091Task.Result execTask(String... args) {92return execTask0(false, args);93}9495Task.Result execNegativeTask(String... args) {96return execTask0(true, args);97}9899private Task.Result execTask0(boolean isNegative, String... args) {100JavadocTask et = new JavadocTask(tb, Task.Mode.API);101et.docletClass(docletClass);102//Arrays.asList(args).forEach((a -> System.err.println("arg: " + a)));103System.err.println(Arrays.asList(args));104currentTask = isNegative105? et.options(args).run(Expect.FAIL)106: et.options(args).run();107return currentTask;108}109110Path[] findHtmlFiles(Path... paths) throws IOException {111return tb.findFiles(".html", paths);112}113114boolean grep(String regex, Path file) throws Exception {115List<String> lines = tb.readAllLines(file);116List<String> foundList = tb.grep(regex, lines);117return !foundList.isEmpty();118}119120String normalize(String in) {121return in.replace('\\', '/');122}123124void checkModulesSpecified(String... args) throws Exception {125for (String arg : args) {126checkDocletOutputPresent("Specified", ElementKind.MODULE, arg);127}128}129130void checkPackagesSpecified(String... args) throws Exception {131for (String arg : args) {132checkDocletOutputPresent("Specified", ElementKind.PACKAGE, arg);133}134}135136void checkTypesSpecified(String... args) throws Exception {137for (String arg : args) {138checkDocletOutputPresent("Specified", ElementKind.CLASS, arg);139}140}141142void checkModulesIncluded(String... args) throws Exception {143for (String arg : args) {144checkDocletOutputPresent("Included", ElementKind.MODULE, arg);145}146}147148void checkPackagesIncluded(String... args) throws Exception {149for (String arg : args) {150checkDocletOutputPresent("Included", ElementKind.PACKAGE, arg);151}152}153154void checkTypesIncluded(String... args) throws Exception {155for (String arg : args) {156checkDocletOutputPresent("Included", ElementKind.CLASS, arg);157}158}159160void checkTypesSelected(String... args) throws Exception {161for (String arg : args) {162checkDocletOutputPresent("Selected", ElementKind.CLASS, arg);163}164}165166void checkMembersSelected(String... args) throws Exception {167for (String arg : args) {168checkDocletOutputPresent("Selected", ElementKind.METHOD, arg);169}170}171172void checkModuleMode(String mode) throws Exception {173assertPresent("^ModuleMode" + FS + mode);174}175176void checkStringPresent(String regex) throws Exception {177assertPresent(regex);178}179180void checkDocletOutputPresent(String category, ElementKind kind, String regex) throws Exception {181assertPresent("^" + category + " " + kind.toString() + " " + regex);182}183184void assertPresent(String regex) throws Exception {185assertPresent(regex, STDOUT);186}187188void assertMessagePresent(String regex) throws Exception {189assertPresent(regex, Task.OutputKind.DIRECT);190}191192void assertMessageNotPresent(String regex) throws Exception {193assertNotPresent(regex, Task.OutputKind.DIRECT);194}195196void assertPresent(String regex, Task.OutputKind kind) throws Exception {197List<String> foundList = tb.grep(regex, currentTask.getOutputLines(kind));198if (foundList.isEmpty()) {199dumpDocletDiagnostics();200throw new Exception(regex + " not found in: " + kind);201}202}203204void assertNotPresent(String regex, Task.OutputKind kind) throws Exception {205List<String> foundList = tb.grep(regex, currentTask.getOutputLines(kind));206if (!foundList.isEmpty()) {207dumpDocletDiagnostics();208throw new Exception(regex + " found in: " + kind);209}210}211212void dumpDocletDiagnostics() {213for (Task.OutputKind kind : Task.OutputKind.values()) {214String output = currentTask.getOutput(kind);215if (output != null && !output.isEmpty()) {216System.err.println("<" + kind + ">");217System.err.println(output);218}219}220}221222void checkModulesNotSpecified(String... args) throws Exception {223for (String arg : args) {224checkDocletOutputAbsent("Specified", ElementKind.MODULE, arg);225}226}227228void checkPackagesNotSpecified(String... args) throws Exception {229for (String arg : args) {230checkDocletOutputAbsent("Specified", ElementKind.PACKAGE, arg);231}232}233234void checkTypesNotSpecified(String... args) throws Exception {235for (String arg : args) {236checkDocletOutputAbsent("Specified", ElementKind.CLASS, arg);237}238}239240void checkModulesNotIncluded(String... args) throws Exception {241for (String arg : args) {242checkDocletOutputAbsent("Included", ElementKind.MODULE, arg);243}244}245246void checkPackagesNotIncluded(String... args) throws Exception {247for (String arg : args) {248checkDocletOutputAbsent("Included", ElementKind.PACKAGE, arg);249}250}251252void checkTypesNotIncluded(String... args) throws Exception {253for (String arg : args) {254checkDocletOutputAbsent("Included", ElementKind.CLASS, arg);255}256}257258void checkMembersNotSelected(String... args) throws Exception {259for (String arg : args) {260checkDocletOutputAbsent("Selected", ElementKind.METHOD, arg);261}262}263264void checkStringAbsent(String regex) throws Exception {265assertAbsent(regex);266}267268void checkDocletOutputAbsent(String category, ElementKind kind, String regex) throws Exception {269assertAbsent("^" + category + FS + kind.toString() + FS + regex);270}271272void assertAbsent(String regex) throws Exception {273assertAbsent(regex, STDOUT);274}275276void assertAbsent(String regex, Task.OutputKind kind) throws Exception {277List<String> foundList = tb.grep(regex, currentTask.getOutputLines(kind));278if (!foundList.isEmpty()) {279dumpDocletDiagnostics();280throw new Exception(regex + " found in: " + kind);281}282}283284public static class ModulesTesterDoclet implements Doclet {285StringWriter sw = new StringWriter();286PrintWriter ps = new PrintWriter(sw);287288DocletEnvironment docEnv = null;289290boolean hasDocComments = false;291292String hasDocComments(Element e) {293String comment = docEnv.getElementUtils().getDocComment(e);294return comment != null && !comment.isEmpty()295? "hasDocComments"296: "noDocComments";297}298299// csv style output, for simple regex verification300void printDataSet(String header, Set<? extends Element> set) {301for (Element e : set) {302ps.print(header);303new SimpleElementVisitor14<Void, Void>() {304@Override305public Void visitModule(ModuleElement e, Void p) {306ps.print(FS);307ps.print(e.getKind());308ps.print(FS);309ps.print(e.getQualifiedName());310if (hasDocComments) {311ps.print(FS);312ps.print(hasDocComments(e));313}314ps.println();315return null;316}317318@Override319public Void visitPackage(PackageElement e, Void p) {320ps.print(FS);321ps.print(e.getKind());322ps.print(FS);323ps.print(e.getQualifiedName());324if (hasDocComments) {325ps.print(FS);326ps.print(hasDocComments(e));327}328ps.println();329return null;330}331332@Override333public Void visitType(TypeElement e, Void p) {334ps.print(FS);335ps.print(ElementKind.CLASS);336ps.print(FS);337ps.print(e.getQualifiedName());338if (hasDocComments) {339ps.print(FS);340ps.print(hasDocComments(e));341}342ps.println();343return null;344}345346@Override347protected Void defaultAction(Element e, Void p) {348Element encl = e.getEnclosingElement();349CharSequence fqn = new SimpleElementVisitor14<CharSequence, Void>() {350@Override351public CharSequence visitModule(ModuleElement e, Void p) {352return e.getQualifiedName();353}354355@Override356public CharSequence visitType(TypeElement e, Void p) {357return e.getQualifiedName();358}359360@Override361public CharSequence visitPackage(PackageElement e, Void p) {362return e.getQualifiedName();363}364365}.visit(encl);366367ps.print(FS);368ps.print(ElementKind.METHOD); // always METHOD369ps.print(FS);370ps.print(fqn);371ps.print(".");372ps.print(e.getSimpleName());373if (hasDocComments) {374ps.print(FS);375ps.print(hasDocComments(e));376}377ps.println();378return null;379}380}.visit(e);381}382}383384@Override385public boolean run(DocletEnvironment docenv) {386this.docEnv = docenv;387ps.println("ModuleMode" + FS + docenv.getModuleMode());388printDataSet("Specified", docenv.getSpecifiedElements());389printDataSet("Included", docenv.getIncludedElements());390printDataSet("Selected", getAllSelectedElements(docenv));391System.out.println(sw);392return true;393}394395Set<Element> getAllSelectedElements(DocletEnvironment docenv) {396Set<Element> result = new TreeSet<Element>((Element e1, Element e2) -> {397// some grouping by kind preferred398int rc = e1.getKind().compareTo(e2.getKind());399if (rc != 0) return rc;400rc = e1.toString().compareTo(e2.toString());401if (rc != 0) return rc;402return Integer.compare(e1.hashCode(), e2.hashCode());403});404Set<? extends Element> elements = docenv.getIncludedElements();405for (ModuleElement me : ElementFilter.modulesIn(elements)) {406addEnclosedElements(docenv, result, me);407}408for (PackageElement pe : ElementFilter.packagesIn(elements)) {409ModuleElement mdle = docenv.getElementUtils().getModuleOf(pe);410if (mdle != null)411addEnclosedElements(docenv, result, mdle);412addEnclosedElements(docenv, result, pe);413}414for (TypeElement te : ElementFilter.typesIn(elements)) {415addEnclosedElements(docenv, result, te);416}417return result;418}419420void addEnclosedElements(DocletEnvironment docenv, Set<Element> result, Element e) {421List<Element> elems = e.getEnclosedElements().stream()422.filter(el -> docenv.isIncluded(el))423.collect(Collectors.toList());424result.addAll(elems);425for (TypeElement t : ElementFilter.typesIn(elems)) {426addEnclosedElements(docenv, result, t);427}428}429430@Override431public Set<Doclet.Option> getSupportedOptions() {432Option[] options = {433new Option() {434private final List<String> someOption = Arrays.asList(435"-hasDocComments"436);437438@Override439public int getArgumentCount() {440return 0;441}442443@Override444public String getDescription() {445return "print disposition of doc comments on an element";446}447448@Override449public Option.Kind getKind() {450return Option.Kind.STANDARD;451}452453@Override454public List<String> getNames() {455return someOption;456}457458@Override459public String getParameters() {460return "flag";461}462463@Override464public boolean process(String opt, List<String> arguments) {465hasDocComments = true;466return true;467}468}469};470return new HashSet<>(Arrays.asList(options));471}472473@Override474public void init(Locale locale, Reporter reporter) {}475476@Override477public String getName() {478return "ModulesTesterDoclet";479}480481@Override482public SourceVersion getSupportedSourceVersion() {483return SourceVersion.latest();484}485}486}487488489