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 
  43     public static void main(String... args) throws Exception {
  44         new CaptureTest().run();
  45     }
  46 
  47 
  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 
  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 
  79         public Tester(final int param) {}
  80 
  81         protected abstract String[] names();
  82         protected abstract int[] modifiers();
  83         protected abstract Class[] types();
  84 
  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 {
 118             public InnerTester(final int innerparam) {
 119                 super(innerparam);
 120             }
 121 
 122             protected String[] names() {
 123                 return new String[] {
 124                     "this$1",
 125                     "innerparam"
 126                 };
 127             }
 128 
 129             protected int[] modifiers() {
 130                 return new int[] { 
 131                     Modifier.FINAL | SYNTHETIC,
 132                     Modifier.FINAL
 133                 };
 134             }
 135 
 136             protected Class[] types() {
 137                 return new Class[] {
 138                     Encloser.class,
 139                     int.class
 140                 };
 141             }
 142         }
 143 
 144         public Tester makeInner(final String message) {
 145             return new InnerTester(2);
 146         }
 147 
 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 
 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 
 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 }