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 8013497 27 * @summary test for API: Class.getAnnotatedInterfaces() 28 * @author Charlie Wang 29 * @library ../../../ 30 * @build AnnotationTest TestCaseGenerator DeclarationGenerator Helper 31 * @run main ClassGetAnnotatedInterfacesTest 32 */ 33 import java.lang.reflect.AnnotatedType; 34 import java.util.LinkedHashMap; 35 import java.util.List; 36 import java.util.Map; 37 38 /* 39 * This file is intended to test API: Class.getAnnotatedInterfaces(). 40 * It can be run directly by java command or by jtreg. 41 * By setting Helper.DEBUG = true/false, one can display/hide the test code 42 * on the command line output, which is constructed for the annotation test. 43 * Here's more details about test code generation: 44 * Construct the test code in a structure specified in TestCase. 45 * In each of the following cases, different combinations of annotation 46 * specified in AnnotationTest.annotationCombinations are tested. The output 47 * annotations must be the same as input both in value and order. 48 * 1. Single interface 49 * 2. Interface extends interface 50 * 3. Single class 51 * 4. Class extends class implements interface 52 * The program test all the cases in TestCase by looping over each one of it. 53 * Test cases are constructed with small code snippet from Helper.SrcType 54 * using changable annotations, type and name. After these values are specified, 55 * the method GenTestCode() generates corresponding java code, encapsulate them 56 * with a class. Then this class is compiled by Helper.compileCode() into 57 * classes which is later loaded into memory by Helper.loadClass(). 58 * The test fails if any of the cases fail. 59 */ 60 public class ClassGetAnnotatedInterfacesTest extends AnnotationTest{ 61 62 enum TestCase implements TestCaseGenerator{ 63 64 TESTBASECLS() { 65 /** 66 * generate test base, which is the class name used to compile the 67 * code: 68 * import java.io.*; 69 * import java.util.*; 70 * import java.lang.*; 71 * import java.lang.reflect.*; 72 * import java.lang.annotation.*; 73 * class testBaseClsName { } 74 */ 75 public String genTestCase(String str) { 76 if (0 == testInput.size()) { 77 testInput.put(null, null); 78 return AnnotationTest.genBaseClass(testBaseClsName); 79 } else { 80 return ""; 81 } 82 } 83 }, 84 SINGLEINT() { 85 /** 86 * generate single interface: 87 * [#ANNO] interface TypeAnnoInt1 { } 88 * then append annotations on [#ANNO] 89 * 90 * input should be like [@anno] 91 */ 92 public String genTestCase(String str) { 93 if (null == str) { 94 throw new RuntimeException("bad test case."); 95 } 96 String testCode = ""; 97 int clsIdx = testInput.size(); 98 TestCodeGenerator tcg = new TestCodeGenerator(); 99 tcg.put(Helper.Declaration.INTERFACE, typeAnnoIntName + clsIdx); 100 tcg.put(Helper.Declaration.CLASS_BODY_START, ""); 101 tcg.put(Helper.Declaration.CLASS_BODY_END, ""); 102 testCode += tcg.genTestCode(); 103 testInput.put(typeAnnoIntName + clsIdx, ""); 104 return testCode; 105 } 106 }, 107 INTEXTINT() { 108 /** 109 * generate interface extends interface: 110 * [#ANNO] interface TypeAnnoInt extends 111 * [#ANNO] Serializable {} 112 * then append annotations on [#ANNO] 113 * 114 * input should be like [@anno] 115 */ 116 public String genTestCase(String str) { 117 if (null == str) { 118 throw new RuntimeException("bad test case."); 119 } 120 String testCode = ""; 121 int clsIdx = testInput.size(); 122 TestCodeGenerator tcg = new TestCodeGenerator(); 123 tcg.put(Helper.Declaration.INTERFACE, typeAnnoIntName + clsIdx); 124 tcg.put(Helper.Declaration.EXTENDS, str + " Serializable"); 125 tcg.put(Helper.Declaration.CLASS_BODY_START, ""); 126 tcg.put(Helper.Declaration.CLASS_BODY_END, ""); 127 testCode += tcg.genTestCode(); 128 testInput.put(typeAnnoIntName + clsIdx, str); 129 return testCode; 130 } 131 }, 132 SINGLECLS() { 133 /** 134 * generate single class: 135 * [#ANNO] class TypeAnnoCls3 { } 136 * then append annotations on [#ANNO] 137 * 138 * input should be like [@anno] 139 */ 140 public String genTestCase(String str) { 141 if (null == str) { 142 throw new RuntimeException("bad test case."); 143 } 144 String testCode = ""; 145 int clsIdx = testInput.size(); 146 TestCodeGenerator tcg = new TestCodeGenerator(); 147 tcg.put(Helper.Declaration.CLASS, typeAnnoClsName + clsIdx); 148 tcg.put(Helper.Declaration.CLASS_BODY_START, ""); 149 tcg.put(Helper.Declaration.CLASS_BODY_END, ""); 150 testCode += tcg.genTestCode(); 151 testInput.put(typeAnnoClsName + clsIdx, ""); 152 return testCode; 153 } 154 }, 155 CLSIMPINTS() { 156 /** 157 * generate cls implements interface: 158 * [#ANNO] class TypeAnnoCls4 implements 159 * [#ANNO] Serializable, [#ANNO] Cloneable {} 160 * then append annotations on [#ANNO] 161 * 162 * input should be like [@anno] 163 */ 164 public String genTestCase(String str) { 165 if (null == str) { 166 throw new RuntimeException("bad test case."); 167 } 168 String testCode = ""; 169 int clsIdx = testInput.size(); 170 TestCodeGenerator tcg = new TestCodeGenerator(); 171 tcg.put(Helper.Declaration.CLASS, typeAnnoClsName + clsIdx); 172 tcg.put(Helper.Declaration.IMPLEMENTS, new String[]{ 173 str + " Serializable", str + " Cloneable"}); 174 tcg.put(Helper.Declaration.CLASS_BODY_START, ""); 175 tcg.put(Helper.Declaration.CLASS_BODY_END, ""); 176 testCode += tcg.genTestCode(); 177 testInput.put(typeAnnoClsName + clsIdx, str); 178 return testCode; 179 } 180 }; 181 182 // a place to hold class name -- annotation correspondence 183 public static Map<String, String> testInput = new LinkedHashMap<>(); 184 185 // generate test class of a specific case 186 public String genTestCase(String str) { 187 return ""; 188 } 189 } 190 191 // generate source code for test according to TestCase 192 protected String genTestCode(Class<? extends TestCaseGenerator> tcg) { 193 String testCode = ""; 194 testCode += super.genTestCode(tcg); 195 196 // special cases 197 TestCase.testInput.put("Object.class", ""); 198 TestCase.testInput.put("int.class", ""); 199 TestCase.testInput.put("void.class", ""); 200 return testCode; 201 } 202 203 // compare input with result 204 protected boolean checkResult() throws Exception { 205 boolean ret = true; 206 compileCode(TestCase.class); 207 for (String clsName : TestCase.testInput.keySet()) { 208 if (null == clsName) { 209 continue; 210 } 211 Class cls = loadClass(clsName); 212 AnnotatedType[] as = cls.getAnnotatedInterfaces(); 213 List<String> result = Helper.getMultipleAT(as); 214 if (0 == result.size()) { 215 if (!"".equals(TestCase.testInput.get(clsName))) { 216 // should be empty output 217 ret = false; 218 Helper.debugPrint(clsName.toString() 219 + " failed without empty output."); 220 } 221 } else { 222 for (int i = 0; i < result.size(); i++) { 223 if (!result.get(i).equals(TestCase.testInput.get(clsName))) { 224 // annotations not match 225 ret = false; 226 Helper.debugPrint(clsName.toString() 227 + " failed with faulty annotations."); 228 } 229 } 230 } 231 } 232 return ret; 233 } 234 235 public static void main(String[] args) throws Exception { 236 new ClassGetAnnotatedInterfacesTest().test(); 237 } 238 }