15385
|
1 |
/*
|
|
2 |
* Copyright (c) 2013 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 8005085 8005877 8004829 8005681 8006734 8006775
|
|
27 |
* @ignore
|
|
28 |
* @summary Combinations of Target ElementTypes on (repeated)type annotations.
|
|
29 |
*/
|
|
30 |
|
|
31 |
import com.sun.tools.classfile.*;
|
|
32 |
import java.io.File;
|
|
33 |
|
|
34 |
public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
|
35 |
// Helps identify test case in event of failure.
|
|
36 |
int testcount = 0;
|
|
37 |
int src3 = 3, src8 = 8, src9 = 9;
|
|
38 |
|
|
39 |
String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR",
|
|
40 |
"LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"};
|
|
41 |
|
|
42 |
// local class tests will have an inner class.
|
|
43 |
Boolean hasInnerClass=false;
|
|
44 |
String innerClassname="";
|
|
45 |
|
|
46 |
public static void main(String[] args) throws Exception {
|
|
47 |
new CombinationsTargetTest2().run();
|
|
48 |
}
|
|
49 |
|
|
50 |
void run() throws Exception {
|
|
51 |
// Determines which repeat and order in source(ABMix).
|
|
52 |
Boolean As= false, BDs=true, ABMix=false;
|
|
53 |
int testrun=0;
|
|
54 |
// A repeats and/or B/D repeats, ABMix for order of As and Bs.
|
|
55 |
Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats
|
|
56 |
{true,false,false}, //repeat @A
|
|
57 |
{false,true,false}, //repeat @B
|
|
58 |
{true,true,false}, //repeat both
|
|
59 |
{false,false,true} //repeat mix
|
|
60 |
};
|
|
61 |
for(Boolean[] bCombo : bRepeat) {
|
|
62 |
As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
|
|
63 |
for(String et : ETypes) {
|
|
64 |
switch(et) {
|
|
65 |
case "METHOD":
|
|
66 |
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3);
|
|
67 |
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3);
|
|
68 |
break;
|
|
69 |
case "CONSTRUCTOR":
|
|
70 |
case "FIELD":
|
|
71 |
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3);
|
|
72 |
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src8);
|
|
73 |
test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src9);
|
|
74 |
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3);
|
|
75 |
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src8);
|
|
76 |
test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src9);
|
|
77 |
break;
|
|
78 |
default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/
|
|
79 |
break;
|
|
80 |
}
|
|
81 |
}
|
|
82 |
}
|
|
83 |
}
|
|
84 |
|
|
85 |
public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
|
|
86 |
Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
|
|
87 |
Integer N, int source) throws Exception {
|
|
88 |
++testcount;
|
|
89 |
expected_tvisibles = tvis;
|
|
90 |
expected_tinvisibles = tinv;
|
|
91 |
expected_visibles = vis;
|
|
92 |
expected_invisibles = inv;
|
|
93 |
File testFile = null;
|
|
94 |
String tname="Test" + N.toString();
|
|
95 |
hasInnerClass=false;
|
|
96 |
String testDef = "Test " + testcount + " parameters: tinv=" + tinv +
|
|
97 |
", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
|
|
98 |
", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
|
|
99 |
", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
|
|
100 |
et2 + ", src=" + source;
|
|
101 |
|
|
102 |
// Uncomment this block to run the tests but skip failing scenarios.
|
|
103 |
// // 8005681 - skip cases with repeated annotations on new, array, cast.
|
|
104 |
// if((source==3 || source==8 || source==9) && (ABmix || (Arepeats && BDrepeats))) {
|
|
105 |
// System.out.println(testDef+"\n8005681-skip repeated annotations on new,array,cast");
|
|
106 |
// return;
|
|
107 |
// }
|
|
108 |
|
|
109 |
println(testDef);
|
|
110 |
// Create test source and File.
|
|
111 |
String sourceString = sourceString(tname, rtn, et2, Arepeats,
|
|
112 |
BDrepeats, ABmix, source);
|
|
113 |
testFile = writeTestFile(tname+".java", sourceString);
|
|
114 |
// Compile test source and read classfile.
|
|
115 |
File classFile = null;
|
|
116 |
try {
|
|
117 |
classFile = compile(testFile);
|
|
118 |
} catch (Error err) {
|
|
119 |
System.err.println("Failed compile. Source:\n" + sourceString);
|
|
120 |
throw err;
|
|
121 |
}
|
|
122 |
//if sourcString() set hasInnerClass it also set innerClassname.
|
|
123 |
if(hasInnerClass) {
|
|
124 |
StringBuffer sb = new StringBuffer(classFile.getAbsolutePath());
|
|
125 |
classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString());
|
|
126 |
}
|
|
127 |
ClassFile cf = ClassFile.read(classFile);
|
|
128 |
|
|
129 |
//Test class,fields and method counts.
|
|
130 |
test(cf);
|
|
131 |
|
|
132 |
for (Field f : cf.fields) {
|
|
133 |
test(cf, f);
|
|
134 |
}
|
|
135 |
for (Method m: cf.methods) {
|
|
136 |
test(cf, m);
|
|
137 |
}
|
|
138 |
countAnnotations();
|
|
139 |
if (errors > 0) {
|
|
140 |
System.err.println( testDef );
|
|
141 |
System.err.println( "Source:\n" + sourceString );
|
|
142 |
throw new Exception( errors + " errors found" );
|
|
143 |
}
|
|
144 |
println("Pass");
|
|
145 |
}
|
|
146 |
|
|
147 |
//
|
|
148 |
// Source for test cases
|
|
149 |
//
|
|
150 |
String sourceString(String testname, String retentn, String annot2,
|
|
151 |
Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
|
|
152 |
int src) {
|
|
153 |
|
|
154 |
String As = "@A", Bs = "@B", Ds = "@D";
|
|
155 |
if(Arepeats) As = "@A @A";
|
|
156 |
if(BDrepeats) {
|
|
157 |
Bs = "@B @B";
|
|
158 |
Ds = "@D @D";
|
|
159 |
}
|
|
160 |
if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; }
|
|
161 |
|
|
162 |
// Source to check for TYPE_USE and TYPE_PARAMETER annotations.
|
|
163 |
// Source base (annotations) is same for all test cases.
|
|
164 |
String source = new String();
|
|
165 |
String imports = new String("import java.lang.annotation.*; \n" +
|
|
166 |
"import static java.lang.annotation.RetentionPolicy.*; \n" +
|
|
167 |
"import static java.lang.annotation.ElementType.*; \n" +
|
|
168 |
"import java.util.List; \n" +
|
|
169 |
"import java.util.HashMap; \n" +
|
|
170 |
"import java.util.Map; \n\n");
|
|
171 |
|
|
172 |
String sourceBase = new String("@Retention("+retentn+")\n" +
|
|
173 |
"@Target({TYPE_USE,_OTHER_})\n" +
|
|
174 |
"@ContainedBy( AC.class )\n" +
|
|
175 |
"@interface A { }\n\n" +
|
|
176 |
|
|
177 |
"@Retention("+retentn+")\n" +
|
|
178 |
"@Target({TYPE_USE,_OTHER_})\n" +
|
|
179 |
"@ContainerFor(A.class)\n" +
|
|
180 |
"@interface AC { A[] value(); }\n\n" +
|
|
181 |
|
|
182 |
"@Retention("+retentn+")\n" +
|
|
183 |
"@Target({TYPE_USE,_OTHER_})\n" +
|
|
184 |
"@ContainedBy( BC.class )\n" +
|
|
185 |
"@interface B { }\n\n" +
|
|
186 |
|
|
187 |
"@Retention("+retentn+")\n" +
|
|
188 |
"@Target({TYPE_USE,_OTHER_})\n" +
|
|
189 |
"@ContainerFor(B.class)\n" +
|
|
190 |
"@interface BC { B[] value(); } \n\n" +
|
|
191 |
|
|
192 |
"@Retention("+retentn+")\n" +
|
|
193 |
"@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
|
|
194 |
"@ContainedBy(DC.class)\n" +
|
|
195 |
"@interface D { }\n\n" +
|
|
196 |
|
|
197 |
"@Retention("+retentn+")\n" +
|
|
198 |
"@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
|
|
199 |
"@ContainerFor(D.class) \n" +
|
|
200 |
"@interface DC { D[] value(); }\n\n");
|
|
201 |
|
|
202 |
// Test case sources with sample generated source
|
|
203 |
switch(src) {
|
|
204 |
case 3: // (repeating) type annotations on field in method body
|
|
205 |
/*
|
|
206 |
* class Test1 {
|
|
207 |
* Test1(){}
|
|
208 |
* // type usage in method body
|
|
209 |
* String test(Test1 this, String param, String ... vararg) {
|
|
210 |
* @A @B
|
|
211 |
* Object o = new @A @B String @A @B [3];
|
|
212 |
* return (@A @B String) null;
|
|
213 |
* }}
|
|
214 |
*/
|
|
215 |
source = new String(
|
|
216 |
"class " + testname + " {\n" +
|
|
217 |
"" + testname +"(){} \n" +
|
|
218 |
"// type usage in method body \n" +
|
|
219 |
"String test("+testname+" this, " +
|
|
220 |
"String param, String ... vararg) { \n" +
|
|
221 |
" _As_ _Bs_\n Object o = new _As_ _Bs_ String _As_ _Bs_ [3]; \n" +
|
|
222 |
" return (_As_ _Bs_ String) null; \n" +
|
|
223 |
"} \n" +
|
|
224 |
"} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
|
225 |
"\n\n";
|
|
226 |
break;
|
|
227 |
case 8: // (repeating) annotations on type parameters, bounds and type arguments in new statement.
|
|
228 |
/*
|
|
229 |
* class Test2<T extends Object> {
|
|
230 |
* Map<List<String>, Integer> map =
|
|
231 |
* new HashMap<@A @B List<@A @B String>, @A @B Integer>();
|
|
232 |
* Map<List<String>, Integer> map2 = new @A @B HashMap<>();
|
|
233 |
* String test(Test2<T> this) { return null;}
|
|
234 |
* <T> String genericMethod(T t) { return null; }
|
|
235 |
* }
|
|
236 |
*/
|
|
237 |
source = new String( source +
|
|
238 |
"// (repeating) annotations on type parameters, bounds and type arguments. \n" +
|
|
239 |
"class " + testname + "<T extends Object> {\n" +
|
|
240 |
" Map<List<String>, Integer> map =\n" +
|
|
241 |
" new HashMap<_As_ _Bs_ List<_As_ _Bs_ String>, _As_ _Bs_ Integer>();\n" +
|
|
242 |
" Map<List<String>, Integer> map2 = new _As_ _Bs_ HashMap<>();\n" +
|
|
243 |
" String test(" + testname + "<T> this) { return null;}\n" +
|
|
244 |
" <T> String genericMethod(T t) { return null; }\n" +
|
|
245 |
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
|
246 |
"\n\n";
|
|
247 |
break;
|
|
248 |
case 9: // (repeating)annotations on type parameters of class, method return value in method.
|
|
249 |
/*
|
|
250 |
* class Test3{
|
|
251 |
* <E extends Comparable> Map<List<E>, E > foo(E e) {
|
|
252 |
* class maptest <E> {
|
|
253 |
* Map<List<E>,E> getMap() {
|
|
254 |
* Map<List<E>,E> Em = new HashMap<List<@A @B @D E>,@A @B @D E>();
|
|
255 |
* return Em;
|
|
256 |
* }
|
|
257 |
* }
|
|
258 |
* return new maptest<E>().getMap();
|
|
259 |
* }
|
|
260 |
* Map<List<String>,String> shm = foo(new String("hello"));
|
|
261 |
* }
|
|
262 |
*/
|
|
263 |
source = new String( source +
|
|
264 |
"// (repeating)annotations on type parameters of class, method return value in method. \n" +
|
|
265 |
"class "+ testname + "{\n" +
|
|
266 |
" <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
|
|
267 |
" class maptest <E> {\n" + // inner class $1maptest
|
|
268 |
" Map<List<E>,E> getMap() { \n" +
|
|
269 |
" Map<List<E>,E> Em = new HashMap<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E>();\n" +
|
|
270 |
" return Em;\n" +
|
|
271 |
" }\n" +
|
|
272 |
" }\n" +
|
|
273 |
" return new maptest<E>().getMap();\n" +
|
|
274 |
" }\n" +
|
|
275 |
" Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
|
|
276 |
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
|
277 |
"\n\n";
|
|
278 |
hasInnerClass=true;
|
|
279 |
innerClassname="$1maptest";
|
|
280 |
break;
|
|
281 |
|
|
282 |
}
|
|
283 |
return imports + source;
|
|
284 |
}
|
|
285 |
}
|