1 /* 2 * Copyright (c) 2020, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8224612 27 * @key randomness 28 * @library /tools/lib ../../lib 29 * @modules jdk.javadoc/jdk.javadoc.internal.tool 30 * @build javadoc.tester.* 31 * @run main/othervm OptionsTest 32 */ 33 34 import javadoc.tester.JavadocTester; 35 import jdk.javadoc.doclet.Doclet; 36 import jdk.javadoc.doclet.DocletEnvironment; 37 import jdk.javadoc.doclet.Reporter; 38 39 import javax.lang.model.SourceVersion; 40 import java.nio.file.Path; 41 import java.nio.file.Paths; 42 import java.util.Collections; 43 import java.util.HashSet; 44 import java.util.LinkedHashSet; 45 import java.util.List; 46 import java.util.Locale; 47 import java.util.Random; 48 import java.util.Set; 49 import java.util.TreeSet; 50 import java.util.function.Supplier; 51 52 public class OptionsTest extends JavadocTester { 53 main(String... args)54 public static void main(String... args) throws Exception { 55 new OptionsTest().runTests(m -> new Object[]{Paths.get(m.getName())}); 56 } 57 58 @Test testEmptySupportedOptionsDoclet(Path base)59 public void testEmptySupportedOptionsDoclet(Path base) { 60 test(EmptySupportedOptionsDoclet.class); 61 } 62 test(Class<? extends Doclet> _class)63 private void test(Class<? extends Doclet> _class) { 64 javadoc("-doclet", _class.getName(), 65 "-docletpath", System.getProperty("test.classes", "."), 66 "--help"); 67 checkExit(Exit.OK); 68 checkOutput(Output.OUT, false, "javadoc: error - fatal error encountered: java.lang.NullPointerException"); 69 checkOutput(Output.OUT, false, "Provided by the %s doclet:".formatted(_class.getSimpleName())); 70 } 71 72 @Test testNullSupportedOptionsDoclet(Path base)73 public void testNullSupportedOptionsDoclet(Path base) { 74 test(NullSupportedOptionsDoclet.class); 75 } 76 77 public static final class EmptySupportedOptionsDoclet implements Doclet { 78 79 private final Random random; 80 EmptySupportedOptionsDoclet()81 public EmptySupportedOptionsDoclet() { 82 long seed = Long.getLong("jdk.test.lib.random.seed", System.currentTimeMillis()); 83 System.out.println("new java.util.Random(" + seed + ")"); 84 this.random = new Random(seed); 85 } 86 87 @Override init(Locale locale, Reporter reporter)88 public void init(Locale locale, Reporter reporter) { 89 } 90 91 @Override getName()92 public String getName() { 93 return getClass().getSimpleName(); 94 } 95 96 @Override getSupportedOptions()97 public Set<? extends Option> getSupportedOptions() { 98 return randomEmptySet(); 99 } 100 101 /* 102 * This method is used to check that emptiness of a set is determined 103 * by value (or in this case, by behavior), rather than by reference 104 * (i.e. there's no code like `s == Collections.EMPTY_SET`, etc.) 105 */ randomEmptySet()106 private Set<? extends Option> randomEmptySet() { 107 List<Supplier<Set<? extends Option>>> emptySets = List.of( 108 Set::of, 109 Collections::emptySet, 110 HashSet::new, 111 TreeSet::new, 112 LinkedHashSet::new 113 ); 114 int idx = random.nextInt(emptySets.size()); 115 return emptySets.get(idx).get(); 116 } 117 118 @Override getSupportedSourceVersion()119 public SourceVersion getSupportedSourceVersion() { 120 return SourceVersion.latestSupported(); 121 } 122 123 @Override run(DocletEnvironment environment)124 public boolean run(DocletEnvironment environment) { 125 return true; 126 } 127 } 128 129 /** 130 * An implementation of an otherwise well-behaving Doclet, that returns 131 * {@code null} from {@link #getSupportedOptions}. 132 */ 133 public static final class NullSupportedOptionsDoclet implements Doclet { 134 135 @Override init(Locale locale, Reporter reporter)136 public void init(Locale locale, Reporter reporter) { 137 } 138 139 @Override getName()140 public String getName() { 141 return getClass().getSimpleName(); 142 } 143 144 @Override getSupportedOptions()145 public Set<? extends Option> getSupportedOptions() { 146 return null; 147 } 148 149 @Override getSupportedSourceVersion()150 public SourceVersion getSupportedSourceVersion() { 151 return SourceVersion.latestSupported(); 152 } 153 154 @Override run(DocletEnvironment environment)155 public boolean run(DocletEnvironment environment) { 156 return true; 157 } 158 } 159 } 160