1 /* 2 * Copyright (c) 2017, 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 8178067 8192007 27 * @summary tests the module's services, such as provides and uses 28 * @modules jdk.javadoc/jdk.javadoc.internal.api 29 * jdk.javadoc/jdk.javadoc.internal.tool 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.main 32 * @library ../lib /tools/lib 33 * @build toolbox.ToolBox toolbox.ModuleBuilder JavadocTester 34 * @run main TestModuleServices 35 */ 36 37 import java.nio.file.Files; 38 import java.nio.file.Path; 39 import java.nio.file.Paths; 40 41 import toolbox.*; 42 43 public class TestModuleServices extends JavadocTester { 44 45 public final ToolBox tb; 46 public static void main(String... args) throws Exception { 47 TestModuleServices tester = new TestModuleServices(); 48 tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); 49 } 50 51 public TestModuleServices() { 52 tb = new ToolBox(); 53 } 54 55 @Test 56 public void checkModuleServicesDescription(Path base) throws Exception { 57 Path src = Files.createDirectories(base.resolve("src")); 58 ModuleBuilder mb = new ModuleBuilder(tb, "moduleService") 59 .comment("This module exports a package containing the declaration of a service type.") 60 .exports("pkgService") 61 .classes("/**A Package that has a service.*/ package pkgService;") 62 .classes("package pkgService; /**A service Interface for service providers.*/ " 63 + "public interface Service {\n" 64 + " /**\n" 65 + " * A test method for the service.\n" 66 + " */\n" 67 + " void testMethod1();\n" 68 + " /**\n" 69 + " * Another test method for the service.\n" 70 + " */\n" 71 + " void testMethod2();\n" 72 + "}"); 73 mb.write(src); 74 mb = new ModuleBuilder(tb, "moduleServiceProvider") 75 .comment("This module provides an implementation of a service.\n" + 76 "@provides pkgService.Service Provides a service whose name is ServiceProvider.") 77 .requires("moduleService") 78 .provides("pkgService.Service", "pkgServiceProvider.ServiceProvider") 79 .classes("/**A Package that has a service provider.*/ package pkgServiceProvider;") 80 .classes("package pkgServiceProvider;\n" 81 + "public class ServiceProvider implements pkgService.Service {\n" 82 + " /**\n" 83 + " * {@inheritDoc}\n" 84 + " */\n" 85 + " public void testMethod1() {}\n" 86 + " /**\n" 87 + " * This is an internal implementation so the documentation will not be seen.\n" 88 + " */\n" 89 + " public void testMethod2() {}\n" 90 + "}"); 91 mb.write(src); 92 mb = new ModuleBuilder(tb, "moduleServiceUser") 93 .comment("This module uses a service defined in another module.\n" 94 + "@uses pkgService.Service If no other provider is found, a default internal implementation will be used.") 95 .requires("moduleService") 96 .uses("pkgService.Service") 97 .classes("/**A Package that has a service user.*/ package pkgServiceUser;") 98 .classes("package pkgServiceUser;\n" 99 + "/**\n" 100 + " * A service user class.\n" 101 + " */\n" 102 + "public class ServiceUser {\n" 103 + "}"); 104 mb.write(src); 105 mb = new ModuleBuilder(tb, "moduleServiceUserNoDescription") 106 .comment("This is another module that uses a service defined in another module.\n" 107 + "@uses pkgService.Service") 108 .requires("moduleService") 109 .uses("pkgService.Service") 110 .classes("/**A Package that has a service user with no description.*/ package pkgServiceUserNoDescription;") 111 .classes("package pkgServiceUserNoDescription;\n" 112 + "/**\n" 113 + " * A service user class.\n" 114 + " */\n" 115 + "public class ServiceUserNoDescription {\n" 116 + "}"); 117 mb.write(src); 118 119 javadoc("-d", base.resolve("out").toString(), 120 "-quiet", "-noindex", 121 "--module-source-path", src.toString(), 122 "--module", "moduleService,moduleServiceProvider,moduleServiceUser,moduleServiceUserNoDescription", 123 "pkgService", "moduleServiceProvider/pkgServiceProvider", "moduleServiceUser/pkgServiceUser", 124 "moduleServiceUserNoDescription/pkgServiceUserNoDescription"); 125 checkExit(Exit.OK); 126 127 checkOutput("moduleServiceProvider-summary.html", true, 128 "<tr class=\"altColor\">\n" 129 + "<th class=\"colFirst\" scope=\"row\"><a href=\"pkgService/Service.html\" " 130 + "title=\"interface in pkgService\">Service</a></th>\n" 131 + "<td class=\"colLast\">\n" 132 + "<div class=\"block\">Provides a service whose name is ServiceProvider.</div>\n" 133 + "</td>\n" 134 + "</tr>"); 135 checkOutput("moduleServiceUser-summary.html", true, 136 "<tr class=\"altColor\">\n" 137 + "<th class=\"colFirst\" scope=\"row\"><a href=\"pkgService/Service.html\" title=\"interface in pkgService\">Service</a></th>\n" 138 + "<td class=\"colLast\">\n" 139 + "<div class=\"block\">If no other provider is found, a default internal implementation will be used.</div>\n" 140 + "</td>\n" 141 + "</tr>"); 142 checkOutput("moduleServiceUserNoDescription-summary.html", true, 143 "<tr class=\"altColor\">\n" 144 + "<th class=\"colFirst\" scope=\"row\"><a href=\"pkgService/Service.html\" title=\"interface in pkgService\">Service</a></th>\n" 145 + "<td class=\"colLast\">\n" 146 + "<div class=\"block\">A service Interface for service providers.</div>\n" 147 + "</td>\n" 148 + "</tr>"); 149 checkOutput("moduleServiceProvider-summary.html", false, 150 "A service Interface for service providers."); 151 checkOutput("moduleServiceUser-summary.html", false, 152 "A service Interface for service providers."); 153 } 154 155 @Test 156 public void checkUsesNoApiTagModuleModeDefault(Path base) throws Exception { 157 ModuleBuilder mb = new ModuleBuilder(tb, "m") 158 .comment("module m.\n@provides p1.A abc") // bogus tag 159 .uses("p1.A") 160 .uses("p1.B") 161 .exports("p1") 162 .classes("package p1; public class A {}") 163 .classes("package p1; public class B {}"); 164 mb.write(base); 165 166 javadoc("-d", base.toString() + "/out", 167 "-quiet", 168 "--module-source-path", base.toString(), 169 "--module", "m"); 170 checkExit(Exit.OK); 171 172 checkOutput("m-summary.html", false, 173 "<h3>Services</h3>"); 174 } 175 176 @Test 177 public void checkUsesNoApiTagModuleModeAll(Path base) throws Exception { 178 ModuleBuilder mb = new ModuleBuilder(tb, "m") 179 .uses("p1.A") 180 .uses("p1.B") 181 .exports("p1") 182 .classes("package p1; public class A {}") 183 .classes("package p1; public class B {}"); 184 mb.write(base); 185 186 javadoc("-d", base.toString() + "/out", 187 "-quiet", 188 "--show-module-contents", "all", 189 "--module-source-path", base.toString(), 190 "--module", "m"); 191 checkExit(Exit.OK); 192 193 checkOutput("m-summary.html", true, 194 "<h3>Services</h3>"); 195 196 checkOutput("m-summary.html", true, 197 "<table class=\"usesSummary\" summary=\"Uses table, listing types, and an explanation\">\n" + 198 "<caption><span>Uses</span><span class=\"tabEnd\"> </span></caption>\n" + 199 "<tr>\n" + 200 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" + 201 "<th class=\"colLast\" scope=\"col\">Description</th>\n" + 202 "</tr>\n" + 203 "<tbody>\n" + 204 "<tr class=\"altColor\">\n" + 205 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"class in p1\">A</a></th>\n" + 206 "<td class=\"colLast\"> </td>\n" + 207 "</tr>\n" + 208 "<tr class=\"rowColor\">\n" + 209 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/B.html\" title=\"class in p1\">B</a></th>\n" + 210 "<td class=\"colLast\"> </td>\n" + 211 "</tr>\n" + 212 "</tbody>\n" + 213 "</table>\n"); 214 } 215 216 @Test 217 public void checkUsesWithApiTagModuleModeDefault(Path base) throws Exception { 218 ModuleBuilder mb = new ModuleBuilder(tb, "m") 219 .comment("module m.\n@uses p1.A") 220 .uses("p1.A") 221 .uses("p1.B") 222 .exports("p1") 223 .classes("package p1; public class A {}") 224 .classes("package p1; public class B {}"); 225 mb.write(base); 226 227 javadoc("-d", base.toString() + "/out", 228 "-quiet", 229 "--module-source-path", base.toString(), 230 "--module", "m"); 231 checkExit(Exit.OK); 232 233 checkOutput("m-summary.html", true, 234 "<h3>Services</h3>"); 235 236 checkOutput("m-summary.html", true, 237 "<table class=\"usesSummary\" summary=\"Uses table, listing types, and an explanation\">\n" + 238 "<caption><span>Uses</span><span class=\"tabEnd\"> </span></caption>\n" + 239 "<tr>\n" + 240 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" + 241 "<th class=\"colLast\" scope=\"col\">Description</th>\n" + 242 "</tr>\n" + 243 "<tbody>\n" + 244 "<tr class=\"altColor\">\n" + 245 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"class in p1\">A</a></th>\n" + 246 "<td class=\"colLast\"> </td>\n" + 247 "</tr>\n" + 248 "</tbody>\n" + 249 "</table>\n"); 250 } 251 252 @Test 253 public void checkProvidesNoApiTagModuleModeDefault(Path base) throws Exception { 254 ModuleBuilder mb = new ModuleBuilder(tb, "m") 255 .comment("module m.\n@uses p1.A") 256 .provides("p1.A", "p1.B") 257 .exports("p1") 258 .classes("package p1; public interface A {}") 259 .classes("package p1; public class B implements A {}") 260 .provides("p2.A", "p2.B") 261 .exports("p2") 262 .classes("package p2; public interface A {}") 263 .classes("package p2; public class B implements A {}"); 264 mb.write(base); 265 266 javadoc("-d", base.toString() + "/out", 267 "-quiet", 268 "--module-source-path", base.toString(), 269 "--module", "m"); 270 271 checkExit(Exit.OK); 272 273 checkOutput("m-summary.html", false, 274 "<h3>Services</h3>"); 275 } 276 277 @Test 278 public void checkProvidesNoApiTagModuleModeAll(Path base) throws Exception { 279 ModuleBuilder mb = new ModuleBuilder(tb, "m") 280 .comment("module m.\n@uses p1.A") // bogus uses tag 281 .provides("p1.A", "p1.B") 282 .exports("p1") 283 .classes("package p1; public interface A {}") 284 .classes("package p1; public class B implements A {}") 285 .provides("p2.A", "p2.B") 286 .exports("p2") 287 .classes("package p2; public interface A {}") 288 .classes("package p2; public class B implements A {}"); 289 mb.write(base); 290 291 javadoc("-d", base.toString() + "/out", 292 "-quiet", 293 "--show-module-contents", "all", 294 "--module-source-path", base.toString(), 295 "--module", "m"); 296 297 checkExit(Exit.OK); 298 299 checkOutput("m-summary.html", true, 300 "<h3>Services</h3>"); 301 302 checkOutput("m-summary.html", true, 303 "<table class=\"providesSummary\" summary=\"Provides table, listing types, and an explanation\">\n" + 304 "<caption><span>Provides</span><span class=\"tabEnd\"> </span></caption>\n" + 305 "<tr>\n" + 306 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" + 307 "<th class=\"colLast\" scope=\"col\">Description</th>\n" + 308 "</tr>\n" + 309 "<tbody>\n" + 310 "<tr class=\"altColor\">\n" + 311 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"interface in p1\">A</a></th>\n" + 312 "<td class=\"colLast\"> <br>(<span class=\"implementationLabel\">Implementation(s):</span> <a href=\"p1/B.html\" title=\"class in p1\">B</a>)</td>\n" + 313 "</tr>\n" + 314 "<tr class=\"rowColor\">\n" + 315 "<th class=\"colFirst\" scope=\"row\"><a href=\"p2/A.html\" title=\"interface in p2\">A</a></th>\n" + 316 "<td class=\"colLast\"> <br>(<span class=\"implementationLabel\">Implementation(s):</span> <a href=\"p2/B.html\" title=\"class in p2\">B</a>)</td>\n" + 317 "</tr>\n" + 318 "</tbody>\n"); 319 } 320 321 @Test 322 public void checkProvidesWithApiTagModuleModeDefault(Path base) throws Exception { 323 ModuleBuilder mb = new ModuleBuilder(tb, "m") 324 .comment("module m.\n@provides p1.A abc") 325 .provides("p1.A", "p1.B") 326 .exports("p1") 327 .classes("package p1; public interface A {}") 328 .classes("package p1; public class B implements A {}") 329 .provides("p2.A", "p2.B") 330 .exports("p2") 331 .classes("package p2; public interface A {}") 332 .classes("package p2; public class B implements A {}"); 333 mb.write(base); 334 335 javadoc("-d", base.toString() + "/out", 336 "-quiet", 337 "--module-source-path", base.toString(), 338 "--module", "m"); 339 340 checkExit(Exit.OK); 341 342 checkOutput("m-summary.html", true, 343 "<h3>Services</h3>"); 344 345 checkOutput("m-summary.html", true, 346 "<table class=\"providesSummary\" summary=\"Provides table, listing types, and an explanation\">\n" + 347 "<caption><span>Provides</span><span class=\"tabEnd\"> </span></caption>\n" + 348 "<tr>\n" + 349 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" + 350 "<th class=\"colLast\" scope=\"col\">Description</th>\n" + 351 "</tr>\n" + 352 "<tbody>\n" + 353 "<tr class=\"altColor\">\n" + 354 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"interface in p1\">A</a></th>\n" + 355 "<td class=\"colLast\">\n" + 356 "<div class=\"block\">abc</div>\n</td>\n" + 357 "</tr>\n" + 358 "</tbody>\n" + 359 "</table>\n"); 360 } 361 362 @Test 363 public void checkUsesProvidesWithApiTagsModeDefault(Path base) throws Exception { 364 ModuleBuilder mb = new ModuleBuilder(tb, "m") 365 .comment("module m.\n@provides p1.A abc\n@uses p2.B def") 366 .provides("p1.A", "p1.B") 367 .exports("p1") 368 .classes("package p1; public interface A {}") 369 .classes("package p1; public class B implements A {}") 370 .provides("p2.A", "p2.B") 371 .uses("p2.B") 372 .exports("p2") 373 .classes("package p2; public interface A {}") 374 .classes("package p2; public class B implements A {}"); 375 mb.write(base); 376 377 javadoc("-d", base.toString() + "/out", 378 "-quiet", 379 "--module-source-path", base.toString(), 380 "--module", "m"); 381 382 checkExit(Exit.OK); 383 384 checkOutput("m-summary.html", true, 385 "<h3>Services</h3>"); 386 387 checkOutput("m-summary.html", true, 388 "<table class=\"providesSummary\" summary=\"Provides table, listing types, and an explanation\">\n" + 389 "<caption><span>Provides</span><span class=\"tabEnd\"> </span></caption>\n" + 390 "<tr>\n" + 391 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" + 392 "<th class=\"colLast\" scope=\"col\">Description</th>\n" + 393 "</tr>\n" + 394 "<tbody>\n" + 395 "<tr class=\"altColor\">\n" + 396 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"interface in p1\">A</a></th>\n" + 397 "<td class=\"colLast\">\n" + 398 "<div class=\"block\">abc</div>\n</td>\n" + 399 "</tr>\n" + 400 "</tbody>\n" + 401 "</table>", 402 "<table class=\"usesSummary\" summary=\"Uses table, listing types, and an explanation\">\n" + 403 "<caption><span>Uses</span><span class=\"tabEnd\"> </span></caption>\n" + 404 "<tr>\n" + 405 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" + 406 "<th class=\"colLast\" scope=\"col\">Description</th>\n" + 407 "</tr>\n" + 408 "<tbody>\n" + 409 "<tr class=\"altColor\">\n" + 410 "<th class=\"colFirst\" scope=\"row\"><a href=\"p2/B.html\" title=\"class in p2\">B</a></th>\n" + 411 "<td class=\"colLast\">\n" + 412 "<div class=\"block\">def</div>\n</td>\n" + 413 "</tr>\n" + 414 "</tbody>\n" + 415 "</table>\n"); 416 } 417 418 }