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\">&nbsp;</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\">&nbsp;</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\">&nbsp;</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\">&nbsp;</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\">&nbsp;</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\">&nbsp;</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\">&nbsp;<br>(<span class=\"implementationLabel\">Implementation(s):</span>&nbsp;<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\">&nbsp;<br>(<span class=\"implementationLabel\">Implementation(s):</span>&nbsp;<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\">&nbsp;</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\">&nbsp;</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\">&nbsp;</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 }