TestFramesNoFrames.java revision 3595:81692f730015
1/* 2 * Copyright (c) 2016, 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 8162353 27 * @summary javadoc should provide a way to disable use of frames 28 * @library /tools/lib ../lib 29 * @modules 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.main 32 * jdk.javadoc/jdk.javadoc.internal.tool 33 * @build toolbox.ModuleBuilder toolbox.ToolBox 34 * @build JavadocTester 35 * @run main TestFramesNoFrames 36 */ 37 38import java.io.*; 39import java.lang.annotation.Annotation; 40import java.lang.reflect.InvocationTargetException; 41import java.lang.reflect.Method; 42import java.nio.file.*; 43import java.util.*; 44import java.util.stream.Collectors; 45 46import toolbox.ModuleBuilder; 47import toolbox.ToolBox; 48 49public class TestFramesNoFrames extends JavadocTester { 50 51 public static void main(String... args) throws Exception { 52 TestFramesNoFrames tester = new TestFramesNoFrames(); 53 tester.generateSource(); 54 tester.runTests(); 55 } 56 57 ToolBox tb = new ToolBox(); 58 Path gensrcModules = Paths.get("gensrc/modules"); 59 Path gensrcPackages = Paths.get("gensrc/packages"); 60 61 void generateSource() throws IOException { 62 String[] modules = { "", "m1", "m2", "m3" }; 63 String[] packages = { "p1", "p2", "p3" }; 64 String[] classes = { "C1", "C2", "C3" }; 65 for (String m: modules) { 66 ModuleBuilder mb = m.equals("") ? null : new ModuleBuilder(tb, m); 67 for (String p: packages) { 68 Path pkgRoot; 69 if (m.equals("")) { 70 pkgRoot = gensrcPackages; 71 } else { 72 pkgRoot = gensrcModules.resolve(m); 73 mb.exports(m + p); 74 } 75 for (String c: classes) { 76 tb.writeJavaFiles(pkgRoot, 77 "package " + (m + p) + ";\n" 78 + "/** class " + (m + p + c).toUpperCase() + ". */\n" 79 + "public class " + (m + p + c).toUpperCase() + " { }" 80 ); 81 } 82 } 83 if (!m.equals("")) { 84 mb.write(gensrcModules); 85 } 86 } 87 tb.writeFile("overview.html", 88 "<html><body>This is the overview file</body></html>"); 89 } 90 91 enum FrameKind { 92 DEFAULT(), 93 FRAMES("--frames"), 94 NO_FRAMES("--no-frames"); 95 FrameKind(String... opts) { 96 this.opts = Arrays.asList(opts); 97 } 98 final List<String> opts; 99 } 100 101 enum OverviewKind { 102 DEFAULT(), 103 OVERVIEW("-overview", "overview.html"), 104 NO_OVERVIEW("-nooverview"); 105 OverviewKind(String... opts) { 106 this.opts = Arrays.asList(opts); 107 } 108 final List<String> opts; 109 } 110 111 enum HtmlKind { 112 HTML4("-html4"), 113 HTML5("-html5"); 114 HtmlKind(String... opts) { 115 this.opts = Arrays.asList(opts); 116 } 117 final List<String> opts; 118 } 119 120 @Override 121 public void runTests() throws Exception { 122 for (Method m : getClass().getDeclaredMethods()) { 123 Annotation a = m.getAnnotation(Test.class); 124 if (a != null) { 125 for (FrameKind fk : FrameKind.values()) { 126 for (OverviewKind ok : OverviewKind.values()) { 127 for (HtmlKind hk : HtmlKind.values()) { 128 try { 129 out.println("Running test " + m.getName() + " " + fk + " " + ok + " " + hk); 130 Path base = Paths.get(m.getName() + "_" + fk + "_" + ok + "_" + hk); 131 Files.createDirectories(base); 132 m.invoke(this, new Object[]{base, fk, ok, hk}); 133 } catch (InvocationTargetException e) { 134 Throwable cause = e.getCause(); 135 throw (cause instanceof Exception) ? ((Exception) cause) : e; 136 } 137 out.println(); 138 } 139 } 140 } 141 } 142 } 143 printSummary(); 144 } 145 146 void javadoc(Path outDir, FrameKind fKind, OverviewKind oKind, HtmlKind hKind, String... rest) { 147 List<String> args = new ArrayList<>(); 148 args.add("-d"); 149 args.add(outDir.toString()); 150 args.addAll(fKind.opts); 151 args.addAll(oKind.opts); 152 args.addAll(hKind.opts); 153 args.addAll(Arrays.asList(rest)); 154 javadoc(args.toArray(new String[0])); 155 checkExit(Exit.OK); 156 } 157 158 @Test 159 void testClass(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws Exception { 160 javadoc(base, fKind, oKind, hKind, 161 gensrcPackages.resolve("p1/P1C1.java").toString()); 162 163 new Checker(fKind, oKind, hKind) 164 .classes("p1.P1C1") 165 .check(); 166 } 167 168 @Test 169 void testClasses(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException { 170 javadoc(base, fKind, oKind, hKind, 171 gensrcPackages.resolve("p1/P1C1.java").toString(), 172 gensrcPackages.resolve("p1/P1C2.java").toString(), 173 gensrcPackages.resolve("p1/P1C3.java").toString()); 174 175 new Checker(fKind, oKind, hKind) 176 .classes("p1.P1C1", "p1.P1C2", "p1.P1C3") 177 .check(); 178 } 179 180 @Test 181 void testPackage(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException { 182 javadoc(base, fKind, oKind, hKind, 183 "-sourcepath", gensrcPackages.toString(), 184 "p1"); 185 186 new Checker(fKind, oKind, hKind) 187 .classes("p1.P1C1", "p1.P1C2", "p1.P1C3") 188 .check(); 189 } 190 191 @Test 192 void testPackages(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException { 193 javadoc(base, fKind, oKind, hKind, 194 "-sourcepath", gensrcPackages.toString(), 195 "p1", "p2", "p3"); 196 197 new Checker(fKind, oKind, hKind) 198 .classes("p1.P1C1", "p1.P1C2", "p1.P1C3", 199 "p2.P2C1", "p2.P2C2", "p2.P2C3", 200 "p3.P3C1", "p3.P3C2", "p3.P3C3") 201 .check(); 202 } 203 204 @Test 205 void testModules(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException { 206 javadoc(base, fKind, oKind, hKind, 207 "-modulesourcepath", gensrcModules.toString(), 208 "--module", "m1,m2,m3"); 209 210 new Checker(fKind, oKind, hKind) 211 .classes("m1/m1p1.M1P1C1", "m1/m1p1.M1P1C2", "m1/m1p1.M1P1C3", 212 "m2/m2p1.M2P1C1", "m2/m2p1.M2P1C2", "m2/m2p1.M2P1C3", 213 "m3/m3p1.M3P1C1", "m3/m3p1.M3P1C2", "m3/m3p1.M3P1C3") 214 .check(); 215 } 216 217 /** 218 * Check the contents of the generated output, according to the 219 * specified options. 220 */ 221 class Checker { 222 private final FrameKind fKind; 223 private final OverviewKind oKind; 224 private final HtmlKind hKind; 225 List<String> classes; 226 227 private boolean frames; 228 private boolean overview; 229 230 Checker(FrameKind fKind, OverviewKind oKind, HtmlKind hKind) { 231 this.fKind = fKind; 232 this.oKind = oKind; 233 this.hKind = hKind; 234 } 235 236 Checker classes(String... classes) { 237 this.classes = Arrays.asList(classes); 238 return this; 239 } 240 241 void check() throws IOException { 242 switch (fKind) { 243 case DEFAULT: 244 case FRAMES: 245 frames = true; 246 break; 247 248 case NO_FRAMES: 249 frames = false; 250 break; 251 } 252 253 switch (oKind) { 254 case DEFAULT: 255 overview = (getPackageCount() > 1); 256 break; 257 258 case OVERVIEW: 259 overview = true; 260 break; 261 262 case NO_OVERVIEW: 263 overview = false; 264 break; 265 } 266 267 checkAllClassesFiles(); 268 checkFrameFiles(); 269 checkOverviewSummary(); 270 271 checkIndex(); 272 checkNavBar(); 273 checkHelpDoc(); 274 275 } 276 277 private void checkAllClassesFiles() { 278 // these files are only generated in frames mode 279 checkFiles(frames, 280 "allclasses-frame.html", 281 "allclasses-noframe.html"); 282 283 // this file is only generated when not in frames mode 284 checkFiles(!frames, 285 "allclasses.html"); 286 } 287 288 private void checkFrameFiles() { 289 // these files are all only generated in frames mode 290 291 // <module>-frame.html and <module>-type-frame.html files 292 checkFiles(frames, classes.stream() 293 .filter(c -> isInModule(c)) 294 .map(c -> modulePart(c)) 295 .flatMap(m -> Arrays.asList( 296 m + "-frame.html", 297 m + "-type-frame.html").stream()) 298 .collect(Collectors.toSet())); 299 300 // <package>/package-frame.html files 301 checkFiles(frames, classes.stream() 302 .map(c -> packagePart(c) + "/package-frame.html") 303 .collect(Collectors.toSet())); 304 } 305 306 private void checkHelpDoc() { 307 // the Help page only describes Frame/NoFrames in frames mode 308 checkOutput("help-doc.html", frames, 309 "<h2>Frames/No Frames</h2>"); 310 } 311 312 private void checkIndex() { 313 // the index.html page only contains frames in frames mode 314 checkOutput("index.html", frames, 315 "<iframe ", 316 "</iframe>"); 317 318 // the index.html contains the overview if one 319 // has been given, and not in frames mode 320 checkOutput("index.html", !frames && oKind == OverviewKind.OVERVIEW, 321 "This is the overview file"); 322 323 // the index.html file contains a summary table 324 // if an overview was generated and not in frames mode 325 checkOutput("index.html", !frames && overview, 326 "<table class=\"overviewSummary\""); 327 328 // the index.html file contains a redirect if 329 // no frames and no overview 330 checkOutput("index.html", !frames && !overview, 331 "<meta http-equiv=\"Refresh\" content=\"0;", 332 "<script type=\"text/javascript\">window.location.replace("); 333 334 // the index.html file <meta> refresh should only use <noscript> in HTML 5 335 if (!frames && !overview) { 336 checkOutput("index.html", hKind == HtmlKind.HTML5, 337 "<noscript>\n<meta http-equiv=\"Refresh\" content=\"0;"); 338 } 339 } 340 341 private void checkNavBar() { 342 // the files containing a navigation bar should only 343 // contain FRAMES/NO-FRAMES links in frames mode 344 List<String> navbarFiles = new ArrayList<>(); 345 navbarFiles.addAll(classes.stream() 346 .map(c -> toHtml(packageClassPart(c))) 347 .collect(Collectors.toSet())); 348 for (String f : navbarFiles) { 349 checkOutput(f, frames, 350 "target=\"_top\">Frames</a>", 351 "target=\"_top\">No Frames</a>"); 352 } 353 } 354 355 private void checkOverviewSummary() { 356 // the overview-summary.html file only appears if 357 // in frames mode and (overview requested or multiple packages) 358 checkFiles(frames && overview, 359 "overview-summary.html"); 360 } 361 362 private long getPackageCount() { 363 return this.classes.stream() 364 .filter(name -> name.contains(".")) 365 .map(name -> name.substring(0, name.lastIndexOf("."))) 366 .distinct() 367 .count(); 368 } 369 370 private String packagePart(String className) { 371 int slash = className.indexOf("/"); 372 int lastDot = className.lastIndexOf("."); 373 return className.substring(slash + 1, lastDot); 374 } 375 376 private String packageClassPart(String className) { 377 int slash = className.indexOf("/"); 378 return className.substring(slash + 1); 379 } 380 381 private boolean isInModule(String className) { 382 return className.contains("/"); 383 } 384 385 private String modulePart(String className) { 386 int slash = className.indexOf("/"); 387 return className.substring(0, slash); 388 } 389 390 private String toHtml(String className) { 391 return className.replace(".", "/") + ".html"; 392 } 393 } 394} 395