1 /* 2 * Copyright (c) 2012, 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 8015701 27 * @summary Test method parameter attribute generation with captured locals. 28 * @compile -parameters CaptureTest.java 29 * @run main CaptureTest 30 */ 31 import java.lang.Class; 32 import java.lang.reflect.Constructor; 33 import java.lang.reflect.Parameter; 34 import java.lang.reflect.Modifier; 35 import java.util.List; 36 import java.util.ArrayList; 37 38 public class CaptureTest { 39 40 private static final int SYNTHETIC = 0x1000; 41 private static final int MANDATED = 0x8000; 42 main(String... args)43 public static void main(String... args) throws Exception { 44 new CaptureTest().run(); 45 } 46 47 run()48 private void run() throws Exception { 49 final Encloser pn = new Encloser(); 50 51 /* Cases covered here: 52 * 53 * - Local class 54 * - Inner class 55 * - Anonymous class 56 * - Anonymous class extending a local 57 * - Anonymous class extending an inner 58 */ 59 pn.makeLocal("hello").check(); 60 pn.makeInner("hello").check(); 61 pn.makeAnon("hello").check(); 62 pn.makeAnonExtendsLocal("hello").check(); 63 pn.makeAnonExtendsInner("hello").check(); 64 65 if (0 != errors) 66 throw new Exception("MethodParameters test failed with " + 67 errors + " errors"); 68 } 69 error(final String msg)70 private void error(final String msg) { 71 System.err.println("Error: " + msg); 72 errors++; 73 } 74 75 int errors; 76 77 abstract class Tester { 78 Tester(final int param)79 public Tester(final int param) {} 80 names()81 protected abstract String[] names(); modifiers()82 protected abstract int[] modifiers(); types()83 protected abstract Class[] types(); 84 check()85 public void check() { 86 final Class<?> cls = this.getClass(); 87 final Constructor<?> ctor = cls.getDeclaredConstructors()[0]; 88 final Parameter[] params = ctor.getParameters(); 89 final String[] names = names(); 90 final int[] modifiers = modifiers(); 91 final Class[] types = types(); 92 93 System.err.println("Testing class " + cls); 94 95 if (params.length == names.length) { 96 for (int i = 0; i < names.length; i++) { 97 System.err.println("Testing parameter " + params[i].getName()); 98 if (!params[i].getName().equals(names[i])) 99 error("Expected parameter name " + names[i] + 100 " got " + params[i].getName()); 101 if (params[i].getModifiers() != modifiers[i]) 102 error("Expected parameter modifiers " + 103 modifiers[i] + " got " + 104 params[i].getModifiers()); 105 if (!params[i].getType().equals(types[i])) 106 error("Expected parameter type " + types[i] + 107 " got " + params[i].getType()); 108 } 109 } else 110 error("Expected " + names.length + " parameters"); 111 112 } 113 114 } 115 116 class Encloser { 117 private class InnerTester extends Tester { InnerTester(final int innerparam)118 public InnerTester(final int innerparam) { 119 super(innerparam); 120 } 121 names()122 protected String[] names() { 123 return new String[] { 124 "this$1", 125 "innerparam" 126 }; 127 } 128 modifiers()129 protected int[] modifiers() { 130 return new int[] { 131 Modifier.FINAL | SYNTHETIC, 132 Modifier.FINAL 133 }; 134 } 135 types()136 protected Class[] types() { 137 return new Class[] { 138 Encloser.class, 139 int.class 140 }; 141 } 142 } 143 makeInner(final String message)144 public Tester makeInner(final String message) { 145 return new InnerTester(2); 146 } 147 makeLocal(final String message)148 public Tester makeLocal(final String message) { 149 class LocalTester extends Tester { 150 public LocalTester(final int localparam) { 151 super(localparam); 152 } 153 154 protected String[] names() { 155 return new String[] { 156 "this$1", 157 "localparam", 158 "val$message" 159 }; 160 } 161 162 protected int[] modifiers() { 163 return new int[] { 164 Modifier.FINAL | MANDATED, 165 Modifier.FINAL, 166 Modifier.FINAL | SYNTHETIC 167 }; 168 } 169 170 protected Class[] types() { 171 return new Class[] { 172 Encloser.class, 173 int.class, 174 String.class 175 }; 176 } 177 178 public String message() { 179 return message; 180 } 181 } 182 183 return new LocalTester(2); 184 } 185 makeAnonExtendsLocal(final String message)186 public Tester makeAnonExtendsLocal(final String message) { 187 abstract class LocalTester extends Tester { 188 public LocalTester(final int localparam) { 189 super(localparam); 190 } 191 192 protected String[] names() { 193 return new String[] { 194 "this$1", 195 "localparam", 196 "val$message" 197 }; 198 } 199 200 protected int[] modifiers() { 201 return new int[] { 202 Modifier.FINAL | MANDATED, 203 Modifier.FINAL, 204 Modifier.FINAL | SYNTHETIC 205 }; 206 } 207 208 protected Class[] types() { 209 return new Class[] { 210 Encloser.class, 211 int.class, 212 String.class 213 }; 214 } 215 216 } 217 218 return new LocalTester(2) { 219 public String message() { 220 return message; 221 } 222 }; 223 } 224 makeAnonExtendsInner(final String message)225 public Tester makeAnonExtendsInner(final String message) { 226 return new InnerTester(2) { 227 protected String[] names() { 228 return new String[] { 229 "this$1", 230 "innerparam", 231 "val$message" 232 }; 233 } 234 235 protected int[] modifiers() { 236 return new int[] { 237 Modifier.FINAL | MANDATED, 238 Modifier.FINAL, 239 Modifier.FINAL | SYNTHETIC 240 }; 241 } 242 243 protected Class[] types() { 244 return new Class[] { 245 Encloser.class, 246 int.class, 247 String.class 248 }; 249 } 250 251 public String message() { 252 return message; 253 } 254 }; 255 } 256 257 public Tester makeAnon(final String message) { 258 return new Tester(2) { 259 protected String[] names() { 260 return new String[] { 261 "this$1", 262 "param", 263 "val$message" 264 }; 265 } 266 267 protected int[] modifiers() { 268 return new int[] { 269 Modifier.FINAL | MANDATED, 270 Modifier.FINAL, 271 Modifier.FINAL | SYNTHETIC 272 }; 273 } 274 275 protected Class[] types() { 276 return new Class[] { 277 Encloser.class, 278 int.class, 279 String.class 280 }; 281 } 282 283 public String message() { 284 return message; 285 } 286 }; 287 } 288 } 289 } 290