--- /dev/null 2019-05-13 14:24:52.059439902 -0700 +++ new/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java 2019-10-30 16:24:37.103746812 -0700 @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8225055 + * @summary Record types + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @compile --enable-preview --source ${jdk.version} TestRecordTypes.java + * @run main/othervm --enable-preview TestRecordTypes + */ + + +import java.io.IOException; +import java.lang.annotation.ElementType; +import java.nio.file.Path; +import java.util.EnumSet; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +public class TestRecordTypes extends JavadocTester { + public static void main(String... args) throws Exception { + TestRecordTypes tester = new TestRecordTypes(); + tester.runTests(m -> new Object[] { Path.of(m.getName()) }); + } + + private final ToolBox tb = new ToolBox(); + + // The following constants are set up for use with -linkoffline + // (but note: JDK 11 does not include java.lang.Record, so expect + // some 404 broken links until we can update this to a stable version.) + private static final String externalDocs = + "https://docs.oracle.com/en/java/javase/11/docs/api"; + private static final String localDocs = + Path.of(testSrc).resolve("jdk11").toUri().toString(); + + @Test + public void testRecordKeywordUnnamedPackage(Path base) throws IOException { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + "public record R(int r1) { }"); + + javadoc("-d", base.resolve("out").toString(), + "-quiet", "-noindex", + "-sourcepath", src.toString(), + "--enable-preview", "--source", thisRelease, + src.resolve("R.java").toString()); + checkExit(Exit.OK); + + checkOutput("R.html", true, + "
R(int r1)
");
+ }
+
+ @Test
+ public void testRecordKeywordNamedPackage(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; public record R(int r1) { }");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ checkOutput("p/R.html", true,
+ "R(int r1)
");
+ }
+
+ @Test
+ public void testEmptyRecord(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; public record R() { }");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ checkOutput("p/R.html", true,
+ "R()
");
+ }
+
+ @Test
+ public void testAtParam(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; /** This is record R. \n"
+ + " * @param r1 This is a component.\n"
+ + " */\n"
+ + "public record R(int r1) { }");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ checkOutput("p/R.html", true,
+ "r1
- This is a component.R(int r1)
");
+ }
+
+ @Test
+ public void testAtParamTyParam(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; /** This is record R. \n"
+ + " * @param r1 This is a component.\n"
+ + " * @param T
- This is a type parameter.r1
- This is a component.R(int r1)
");
+ }
+
+ @Test
+ public void testGeneratedComments(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; /** This is record R. \n"
+ + " * @param r1 This is a component.\n"
+ + " */\n"
+ + "public record R(int r1) { }");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ // While we don't normally test values that just come from resource files,
+ // in these cases, we want to verify that something non-empty was put into
+ // the documentation for the generated members.
+ checkOrder("p/R.html",
+ "R
record.",
+ "r1
record component.",
+ "toString",
+ "Returns a string representation of this record.",
+ "Method Details",
+ "toString",
+ "Returns a string representation of this record. The representation "
+ + "contains the name of the type, followed by the name and value of "
+ + "each of the record components.",
+ "hashCode",
+ "Returns a hash code value for this object. The value is derived "
+ + "from the hash code of each of the record components.",
+ "equals",
+ "Indicates whether some other object is \"equal to\" this one. "
+ + "The objects are equal if the other object is of the same class "
+ + "and if all the record components are equal. All components "
+ + "in this record are compared with '=='.",
+ "r1",
+ "Returns the value of the r1
"
+ + "record component."
+ );
+ }
+
+ @Test
+ public void testGeneratedCommentsWithLinkOffline(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; /** This is record R. \n"
+ + " * @param r1 This is a component.\n"
+ + " */\n"
+ + "public record R(int r1) { }");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "-linkoffline", externalDocs, localDocs,
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ // While we don't normally test values that just come from resource files,
+ // in these cases, we want to verify that something non-empty was put into
+ // the documentation for the generated members.
+ checkOrder("p/R.html",
+ "R
record.",
+ "r1
record component.",
+ "toString",
+ "Returns a string representation of this record.",
+ "Method Details",
+ "toString",
+ "Returns a string representation of this record. The representation "
+ + "contains the name of the type, followed by the name and value of "
+ + "each of the record components.",
+ "hashCode",
+ "Returns a hash code value for this object. The value is derived "
+ + "from the hash code of each of the record components.",
+ "equals",
+ "Indicates whether some other object is \"equal to\" this one. "
+ + "The objects are equal if the other object is of the same class "
+ + "and if all the record components are equal. All components "
+ + "in this record are compared with '=='.",
+ "r1",
+ "Returns the value of the r1
"
+ + "record component."
+ );
+ }
+
+ @Test
+ public void testGeneratedEqualsPrimitive(Path base) throws IOException {
+ testGeneratedEquals(base, "int a, int b",
+ "All components in this record are compared with '=='.");
+ }
+
+ @Test
+ public void testGeneratedEqualsReference(Path base) throws IOException {
+ testGeneratedEquals(base, "Object a, Object b",
+ "All components in this record are compared with Objects::equals(Object,Object)
");
+ }
+
+ @Test
+ public void testGeneratedEqualsMixed(Path base) throws IOException {
+ testGeneratedEquals(base, "int a, Object b",
+ "Reference components are compared with Objects::equals(Object,Object)
; "
+ + "primitive components are compared with '=='.");
+ }
+
+ private void testGeneratedEquals(Path base, String comps, String expect) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; /** This is record R. \n"
+ + " */\n"
+ + "public record R(" + comps + ") { }");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/R.html", expect);
+ }
+
+ @Test
+ public void testUserComments(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "package p; /** This is record R. \n"
+ + " * @param r1 This is a component.\n"
+ + " */\n"
+ + "public record R(int r1) {\n"
+ + "/** User constructor. */ public R { }\n"
+ + "/** User equals. */ public boolean equals(Object other) { return false; }\n"
+ + "/** User hashCode. */ public int hashCode() { return 0; }\n"
+ + "/** User toString. */ public String toString() { return \"\"; }\n"
+ + "/** User accessor. */ public int r1() { return r1; }\n"
+ + "}");
+
+ javadoc("-d", base.resolve("out").toString(),
+ "-quiet", "-noindex",
+ "-sourcepath", src.toString(),
+ "--enable-preview", "--source", thisRelease,
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/R.html",
+ "public record R("
+ + rcAnno
+ + "int i)\n" +
+ "extends java.lang.Record
",
+ "