jjg@1643: /* jjg@1643: * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. jjg@1643: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@1643: * jjg@1643: * This code is free software; you can redistribute it and/or modify it jjg@1643: * under the terms of the GNU General Public License version 2 only, as jjg@1643: * published by the Free Software Foundation. jjg@1643: * jjg@1643: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@1643: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@1643: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@1643: * version 2 for more details (a copy is included in the LICENSE file that jjg@1643: * accompanied this code). jjg@1643: * jjg@1643: * You should have received a copy of the GNU General Public License version jjg@1643: * 2 along with this work; if not, write to the Free Software Foundation, jjg@1643: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@1643: * jjg@1643: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@1643: * or visit www.oracle.com if you need additional information or have any jjg@1643: * questions. jjg@1643: */ jjg@1643: jjg@1643: /* jjg@1643: * @test jjg@1643: * @bug 8005220 jjg@1643: * @summary javap must display repeating annotations jjg@1643: */ jjg@1643: import java.io.*; jjg@1643: import java.util.*; jjg@1643: jjg@1643: /** jjg@1643: * This class extends the abstract {@link Tester} test-driver, and jjg@1643: * encapusulates a number of test-case classes (i.e. classes extending jjg@1643: * this class and annotated with {@code TestCase}). jjg@1643: *

jjg@1643: * By default (no argument), this test runs all test-cases, except jjg@1643: * if annotated with {@code ignore}. jjg@1643: *

jjg@1643: * Individual test cases can be executed using a run action. jjg@1643: *

jjg@1643: * Example: @run main RepeatingTypeAnnotations RepeatingTypeAnnotations$TC4 jjg@1643: *

jjg@1643: * Note: when specific test-cases are run, additional debug output is jjg@1643: * produced to help debugging. Test annotated with {@code ignore} jjg@1643: * can be executed explicitly. jjg@1643: */ jjg@1643: public class RepeatingTypeAnnotations extends Tester { jjg@1643: jjg@1643: /** jjg@1643: * Main method instantiates test and run test-cases. jjg@1643: */ jjg@1643: public static void main(String... args) throws Exception { jjg@1643: Tester tester = new RepeatingTypeAnnotations(); jjg@1643: tester.run(args); jjg@1643: } jjg@1643: jjg@1643: /** jjg@1643: * Testcases are classes extending {@code RepeatingTypeAnnotations}, jjg@1643: * and calling {@link setSrc}, followed by one or more invocations jjg@1643: * of {@link verify} in the body of the constructor. jjg@1643: */ jjg@1643: public RepeatingTypeAnnotations() { jjg@1643: setSrc(new TestSource(template)); jjg@1643: } jjg@1643: jjg@1643: /** jjg@1643: * Common template for test cases. The line TESTCASE is jjg@1643: * replaced with the specific lines of individual tests. jjg@1643: */ jjg@1643: private static final String[] template = { jjg@1643: "import java.lang.annotation.*;", jjg@1643: "class Test {", jjg@1643: " @Repeatable(As.class)", jjg@1643: " @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})", jjg@1643: " @Retention(RetentionPolicy.CLASS)", jjg@1643: " @interface A {", jjg@1643: " Class f() default int.class;", jjg@1643: " }", jjg@1643: jjg@1643: " @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})", jjg@1643: " @Retention(RetentionPolicy.CLASS)", jjg@1643: " @interface As { A[] value(); }", jjg@1643: jjg@1643: " @Repeatable(Bs.class)", jjg@1643: " @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})", jjg@1643: " @Retention(RetentionPolicy.CLASS)", jjg@1643: " @interface B {", jjg@1643: " Class f() default int.class;", jjg@1643: " }", jjg@1643: jjg@1643: " @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})", jjg@1643: " @Retention(RetentionPolicy.CLASS)", jjg@1643: " @interface Bs { B[] value(); }", jjg@1643: jjg@1643: " @Repeatable(Cs.class)", jjg@1643: " @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})", jjg@1643: " @Retention(RetentionPolicy.RUNTIME)", jjg@1643: " @interface C {", jjg@1643: " Class f() default int.class;", jjg@1643: " }", jjg@1643: jjg@1643: " @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})", jjg@1643: " @Retention(RetentionPolicy.RUNTIME)", jjg@1643: " @interface Cs { C[] value(); }", jjg@1643: "TESTCASE", jjg@1643: "}" jjg@1643: }; jjg@1643: jjg@1643: /* jjg@1643: * The test cases covers annotation in the following locations: jjg@1643: * - static and non-static fields jjg@1643: * - local variables jjg@1643: * - constructor and method return type and parameter types jjg@1643: * - casts in class and method contexts. jjg@1643: * For the above locations the test-cases covers: jjg@1643: * - single annotation type jjg@1643: * - two annotation types with same retention jjg@1643: * - two annotation types with different retention jjg@1643: * - three annotation types, two of same retention, one different. jjg@1643: */ jjg@1643: jjg@1643: @TestCase jjg@1721: @ignore // 8008082: missing type annotation for cast jjg@1643: public static class TC1 extends RepeatingTypeAnnotations { jjg@1643: public TC1() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public @A @A @A Object o = (@A @A @A String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #25(#26=[@#27(),@#27(),@#27()]): FIELD", jjg@1643: "1: #25(#26=[@#27(),@#27(),@#27()]): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC2 extends RepeatingTypeAnnotations { jjg@1643: public TC2() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public @A @B @A Object o = (@B @A @B String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #25(#26=[@#27(),@#27()]): FIELD", jjg@1643: "1: #28(): FIELD", jjg@1643: "2: #29(#26=[@#28(),@#28()]): CAST, offset=5", jjg@1643: "3: #27(): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC3 extends RepeatingTypeAnnotations { jjg@1643: public TC3() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public @A @A @C Object o = (@B @C @B String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #25(): FIELD", jjg@1643: "1: #25(): CAST, offset=5", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #27(#28=[@#29(),@#29()]): FIELD", jjg@1643: "1: #30(#28=[@#31(),@#31()]): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC4 extends RepeatingTypeAnnotations { jjg@1643: public TC4() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public @A @B @C Object o = (@C @B @A String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #25(): FIELD", jjg@1643: "1: #25(): CAST, offset=5", jjg@1643: "0: #27(): FIELD", jjg@1643: "1: #28(): FIELD", jjg@1643: "2: #28(): CAST, offset=5", jjg@1643: "3: #27(): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1721: @ignore // 8008082: missing type annotation for cast jjg@1643: public static class TC5 extends RepeatingTypeAnnotations { jjg@1643: public TC5() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public static @A @A @A Object o = (@B @B @B String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #25(#26=[@#27(),@#27(),@#27()]): FIELD", jjg@1643: "1: #28(#26=[@#29(),@#29(),@#29()]): CAST, offset=5, type_index=0"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC6 extends RepeatingTypeAnnotations { jjg@1643: public TC6() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public static @A @B @A Object o = (@B @A @B String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #25(#26=[@#27(),@#27()]): FIELD", jjg@1643: "1: #28(): FIELD", jjg@1643: "2: #29(#26=[@#28(),@#28()]): CAST, offset=5", jjg@1643: "3: #27(): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC7 extends RepeatingTypeAnnotations { jjg@1643: public TC7() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public static @A @A @C Object o = (@B @C @B String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #25(): FIELD", jjg@1643: "1: #25(): CAST, offset=5", jjg@1643: "0: #27(#28=[@#29(),@#29()]): FIELD", jjg@1643: "1: #30(#28=[@#31(),@#31()]): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC8 extends RepeatingTypeAnnotations { jjg@1643: public TC8() { jjg@1643: setSrc(" static String so = \"hello world\";", jjg@1643: " public static @A @B @C Object o = (@C @B @A String) Test.so;"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #25(): FIELD", jjg@1643: "1: #25(): CAST, offset=5", jjg@1643: "0: #27(): FIELD", jjg@1643: "1: #28(): FIELD", jjg@1643: "2: #28(): CAST, offset=5", jjg@1643: "3: #27(): CAST, offset=5"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1721: @ignore // 8008082: missing type annotation for cast jjg@1643: public static class TC9 extends RepeatingTypeAnnotations { jjg@1643: public TC9() { jjg@1643: setSrc(" public Test(@A @A @A Object o, @A int i, long l) {", jjg@1643: " @A @A @A String ls = (@B @B @B String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #34(#35=[@#36(),@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "1: #36(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "2: #37(#35=[@#38(),@#38(),@#38()]): CAST, offset=4, type_index=0", jjg@1643: "3: #34(#35=[@#36(),@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC10 extends RepeatingTypeAnnotations { jjg@1643: public TC10() { jjg@1643: setSrc(" public Test(@A @A @B Object o, @A @B int i, long l) {", jjg@1643: " @A @A @B String ls = (@B @A @B String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations:", jjg@1643: "0: #34(#35=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "1: #37(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "2: #36(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "3: #37(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "4: #38(#35=[@#37(),@#37()]): CAST, offset=4, type_index=0", jjg@1643: "5: #36(): CAST, offset=4, type_index=0", jjg@1643: "6: #34(#35=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}", jjg@1643: "7: #37(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC11 extends RepeatingTypeAnnotations { jjg@1643: public TC11() { jjg@1643: setSrc(" public Test(@C @C @A Object o, @A @B int i, long l) {", jjg@1643: " @C @C @A String ls = (@A @A @C String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #34(#35=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "1: #36(): CAST, offset=4", jjg@1643: "2: #34(#35=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}", jjg@1643: "0: #38(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "1: #38(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "2: #39(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "3: #40(#35=[@#38(),@#38()]): CAST, offset=4", jjg@1643: "4: #38(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC12 extends RepeatingTypeAnnotations { jjg@1643: public TC12() { jjg@1643: setSrc(" public Test(@A @B @C Object o, @A @C int i, long l) {", jjg@1643: " @A @B @C String ls = (@C @A @B String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #34(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "1: #34(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "2: #34(): CAST, offset=4", jjg@1643: "3: #34(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}", jjg@1643: "0: #36(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "1: #37(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "2: #36(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "3: #36(): CAST, offset=4", jjg@1643: "4: #37(): CAST, offset=4", jjg@1643: "5: #36(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}", jjg@1643: "6: #37(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1721: @ignore // 8008082: missing type annotation for cast jjg@1643: public static class TC13 extends RepeatingTypeAnnotations { jjg@1643: public TC13() { jjg@1643: setSrc(" public @A @A @A String foo(@A @A @A Object o, @A int i, long l) {", jjg@1643: " @A @A @A String ls = (@B @B @B String) o;", jjg@1643: " return (@A @A @A String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #36(#37=[@#38(),@#38(),@#38()]): METHOD_RETURN", jjg@1643: "1: #36(#37=[@#38(),@#38(),@#38()]): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "2: #38(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "3: #39(#37=[@#40(),@#40(),@#40()]): CAST, offset=0, type_index=0", jjg@1643: "4: #36(#37=[@#38(),@#38(),@#38()]): CAST, offset=6, type_index=0", jjg@1643: "5: #36(#37=[@#38(),@#38(),@#38()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC14 extends RepeatingTypeAnnotations { jjg@1643: public TC14() { jjg@1643: setSrc(" public @A @B @B String foo(@A @A @B Object o, @A @B int i, long l) {", jjg@1643: " @A @A @B String ls = (@B @A @B String) o;", jjg@1643: " return (@A @B @B String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "0: #36(): METHOD_RETURN", jjg@1643: "1: #37(#38=[@#39(),@#39()]): METHOD_RETURN", jjg@1643: "2: #40(#38=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "3: #39(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "4: #36(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "5: #39(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "6: #37(#38=[@#39(),@#39()]): CAST, offset=0", jjg@1643: "7: #36(): CAST, offset=0", jjg@1643: "8: #36(): CAST, offset=6", jjg@1643: "9: #37(#38=[@#39(),@#39()]): CAST, offset=6", jjg@1643: "10: #40(#38=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}", jjg@1643: "11: #39(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC15 extends RepeatingTypeAnnotations { jjg@1643: public TC15() { jjg@1643: setSrc(" public @A @A @C String foo(@C @C @A Object o, @A @B int i, long l) {", jjg@1643: " @C @C @A String ls = (@A @A @C String) o;", jjg@1643: " return (@C @B @B String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #36(): METHOD_RETURN", jjg@1643: "1: #37(#38=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "2: #36(): CAST, offset=0", jjg@1643: "3: #36(): CAST, offset=6", jjg@1643: "4: #37(#38=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}", jjg@1643: "0: #40(#38=[@#41(),@#41()]): METHOD_RETURN", jjg@1643: "1: #41(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "2: #41(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "3: #42(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "4: #40(#38=[@#41(),@#41()]): CAST, offset=0", jjg@1643: "5: #43(#38=[@#42(),@#42()]): CAST, offset=6", jjg@1643: "6: #41(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: jjg@1643: @TestCase jjg@1643: public static class TC16 extends RepeatingTypeAnnotations { jjg@1643: public TC16() { jjg@1643: setSrc(" public @A @B @C String foo(@A @B @C Object o, @A @C int i, long l) {", jjg@1643: " @A @B @C String ls = (@C @A @B String) o;", jjg@1643: " return (@B @A @C String) o;", jjg@1643: " }"); jjg@1643: verify("RuntimeInvisibleTypeAnnotations", jjg@1643: "RuntimeVisibleTypeAnnotations", jjg@1643: "0: #36(): METHOD_RETURN", jjg@1643: "1: #36(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "2: #36(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "3: #36(): CAST, offset=0", jjg@1643: "4: #36(): CAST, offset=6", jjg@1643: "5: #36(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}", jjg@1643: "0: #38(): METHOD_RETURN", jjg@1643: "1: #39(): METHOD_RETURN", jjg@1643: "2: #38(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "3: #39(): METHOD_FORMAL_PARAMETER, param_index=0", jjg@1643: "4: #38(): METHOD_FORMAL_PARAMETER, param_index=1", jjg@1643: "5: #38(): CAST, offset=0", jjg@1643: "6: #39(): CAST, offset=0", jjg@1643: "7: #39(): CAST, offset=6", jjg@1643: "8: #38(): CAST, offset=6", jjg@1643: "9: #38(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}", jjg@1643: "10: #39(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}"); jjg@1643: } jjg@1643: } jjg@1643: }