langtools/test/tools/javac/annotations/typeAnnotations/classfile/TestAnonInnerClasses.java
changeset 21010 5ffe0d8a5e24
child 30727 a4dac07f827c
equal deleted inserted replaced
21009:b35973e2d42e 21010:5ffe0d8a5e24
       
     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 8008762 8008751 8013065 8015323 8015257
       
    27  * @summary Type annotations on anonymous and inner class.
       
    28  *  Six TYPE_USE annotations are repeated(or not); Four combinations create
       
    29  *  four test files, and each results in the test class and 2 anonymous classes.
       
    30  *  Each element of these three classes is checked for expected number of the
       
    31  *  four annotation Attributes. Expected annotation counts depend on type of
       
    32  *  annotation place on type of element (a FIELD&TYPE_USE element on a field
       
    33  *  results in 2). Elements with no annotations expect 0.
       
    34  *  Source template is read in from testanoninner.template
       
    35  *
       
    36  */
       
    37 import java.lang.annotation.*;
       
    38 import java.io.*;
       
    39 import java.util.List;
       
    40 import java.util.LinkedList;
       
    41 import com.sun.tools.classfile.*;
       
    42 import java.nio.file.Files;
       
    43 import java.nio.charset.*;
       
    44 import java.io.File;
       
    45 import java.io.IOException;
       
    46 
       
    47 
       
    48 import java.lang.annotation.*;
       
    49 import static java.lang.annotation.RetentionPolicy.*;
       
    50 import static java.lang.annotation.ElementType.*;
       
    51 
       
    52 /*
       
    53  * A source template is read in and testname and annotations are inserted
       
    54  * via replace().
       
    55  */
       
    56 public class TestAnonInnerClasses extends ClassfileTestHelper {
       
    57     // tally errors and test cases
       
    58     int errors = 0;
       
    59     int checks = 0;
       
    60     //Note expected test count in case of skips due to bugs.
       
    61     int tc = 0, xtc = 180; // 45 x 4 variations of repeated annotations.
       
    62     File testSrc = new File(System.getProperty("test.src"));
       
    63 
       
    64     String[] AnnoAttributes = {
       
    65         Attribute.RuntimeVisibleTypeAnnotations,
       
    66         Attribute.RuntimeInvisibleTypeAnnotations,
       
    67         Attribute.RuntimeVisibleAnnotations,
       
    68         Attribute.RuntimeInvisibleAnnotations
       
    69     };
       
    70 
       
    71     // template for source files
       
    72     String srcTemplate = "testanoninner.template";
       
    73 
       
    74     // Four test files generated based on combinations of repeating annotations.
       
    75     Boolean As= false, Bs=true, Cs=false, Ds=false, TAs=false,TBs=false;
       
    76     Boolean[][] bRepeat = new Boolean[][]{
       
    77                  /* no repeats    */ {false, false, false, false, false, false},
       
    78                  /* repeat A,C,TA */ {true,  false, true,  false, true,  false},
       
    79                  /* repeat B,D,TB */ {false, true,  false, true,  false, true},
       
    80                  /* repeat all    */ {true,  true,  true,  true,  true,  true}
       
    81     };
       
    82     // Save descriptions of failed test case; does not terminate upon a failure.
       
    83     List<String> failed = new LinkedList<>();
       
    84 
       
    85     public static void main(String[] args) throws Exception {
       
    86         new TestAnonInnerClasses().run();
       
    87     }
       
    88 
       
    89     // Check annotation counts and make reports sufficiently descriptive to
       
    90     // easily diagnose.
       
    91     void check(String testcase, int vtaX, int itaX, int vaX, int iaX,
       
    92                                 int vtaA, int itaA, int vaA, int iaA) {
       
    93 
       
    94         String descr = " checking " + testcase+" _TYPE_, expected: " +
       
    95             vtaX + ", " + itaX + ", " + vaX + ", " + iaX + "; actual: " +
       
    96             vtaA + ", " + itaA + ", " + vaA + ", " + iaA;
       
    97         String description;
       
    98         description=descr.replace("_TYPE_","RuntimeVisibleTypeAnnotations");
       
    99         if (vtaX != vtaA) {
       
   100             errors++;
       
   101             failed.add(++checks + " " + testcase + ": (vtaX) " + vtaX +
       
   102                        " != " + vtaA + " (vtaA)");
       
   103             println(checks + " FAIL: " + description);
       
   104         } else {
       
   105             println(++checks + " PASS: " + description);
       
   106         }
       
   107         description=descr.replace("_TYPE_","RuntimeInvisibleTypeAnnotations");
       
   108         if (itaX != itaA) {
       
   109             errors++;
       
   110             failed.add(++checks + " " + testcase + ": (itaX) " + itaX + " != " +
       
   111                        itaA + " (itaA)");
       
   112             println(checks + " FAIL: " + description);
       
   113         } else {
       
   114             println(++checks + " PASS: " + description);
       
   115         }
       
   116         description=descr.replace("_TYPE_","RuntimeVisibleAnnotations");
       
   117         if (vaX != vaA) {
       
   118             errors++;
       
   119             failed.add(++checks + " " + testcase + ": (vaX) " + vaX + " != " +
       
   120                        vaA + " (vaA)");
       
   121             println(checks + " FAIL: " + description);
       
   122         } else {
       
   123             println(++checks + " PASS: " + description);
       
   124         }
       
   125         description=descr.replace("_TYPE_","RuntimeInvisibleAnnotations");
       
   126         if (iaX != iaA) {
       
   127             errors++;
       
   128             failed.add(++checks + " " + testcase + ": (iaX) " + iaX + " != " +
       
   129                        iaA + " (iaA)");
       
   130             println(checks + " FAIL: " + description);
       
   131         } else {
       
   132             println(++checks + " PASS: " + description);
       
   133         }
       
   134         println("");
       
   135     }
       
   136 
       
   137     // Print failed cases (if any) and throw exception for fail.
       
   138     void report() {
       
   139         if (errors!=0) {
       
   140             System.err.println("Failed tests: " + errors +
       
   141                                "\nfailed test cases:\n");
       
   142             for (String t: failed) System.err.println("  " + t);
       
   143             throw new RuntimeException("FAIL: There were test failures.");
       
   144         } else
       
   145             System.out.println("PASSED all tests.");
       
   146     }
       
   147 
       
   148     void test(String ttype, ClassFile cf, Method m, Field f, boolean visible) {
       
   149         int vtaActual = 0,
       
   150             itaActual = 0,
       
   151             vaActual = 0,
       
   152             iaActual = 0,
       
   153             vtaExp = 0,
       
   154             itaExp = 0,
       
   155             vaExp = 0,
       
   156             iaExp = 0,
       
   157             index = 0,
       
   158             index2 = 0;
       
   159         String memberName = null,
       
   160             testcase = "undefined",
       
   161             testClassName = null;
       
   162         Attribute attr = null,
       
   163             cattr = null;
       
   164         Code_attribute CAttr = null;
       
   165         // Get counts of 4 annotation Attributes on element being checked.
       
   166         for (String AnnoType : AnnoAttributes) {
       
   167             try {
       
   168                 switch (ttype) {
       
   169                     case "METHOD":
       
   170                         index = m.attributes.getIndex(cf.constant_pool,
       
   171                                                       AnnoType);
       
   172                         memberName = m.getName(cf.constant_pool);
       
   173                         if (index != -1)
       
   174                             attr = m.attributes.get(index);
       
   175                         //fetch index annotations from code attribute.
       
   176                         index2 = m.attributes.getIndex(cf.constant_pool,
       
   177                                                        Attribute.Code);
       
   178                         if (index2 != -1) {
       
   179                             cattr = m.attributes.get(index2);
       
   180                             assert cattr instanceof Code_attribute;
       
   181                             CAttr = (Code_attribute)cattr;
       
   182                             index2 = CAttr.attributes.getIndex(cf.constant_pool,
       
   183                                                                AnnoType);
       
   184                             if (index2 != -1)
       
   185                                 cattr = CAttr.attributes.get(index2);
       
   186                         }
       
   187                         break;
       
   188                     case "FIELD":
       
   189                         index = f.attributes.getIndex(cf.constant_pool,
       
   190                                                       AnnoType);
       
   191                         memberName = f.getName(cf.constant_pool);
       
   192                         if (index != -1)
       
   193                             attr = f.attributes.get(index);
       
   194                         //fetch index annotations from code attribute.
       
   195                         index2 = cf.attributes.getIndex(cf.constant_pool,
       
   196                                                         Attribute.Code);
       
   197                         if (index2!= -1) {
       
   198                             cattr = cf.attributes.get(index2);
       
   199                             assert cattr instanceof Code_attribute;
       
   200                             CAttr = (Code_attribute)cattr;
       
   201                             index2 = CAttr.attributes.getIndex(cf.constant_pool,
       
   202                                                                AnnoType);
       
   203                             if (index2!= -1)
       
   204                                 cattr = CAttr.attributes.get(index2);
       
   205                         }
       
   206                         break;
       
   207 
       
   208                     default:
       
   209                         memberName = cf.getName();
       
   210                         index = cf.attributes.getIndex(cf.constant_pool,
       
   211                                                        AnnoType);
       
   212                         if (index!= -1) attr = cf.attributes.get(index);
       
   213                         break;
       
   214                 }
       
   215             }
       
   216             catch (ConstantPoolException cpe) { cpe.printStackTrace(); }
       
   217             try {
       
   218                 testClassName=cf.getName();
       
   219                 testcase = ttype + ": " + testClassName + ": " +
       
   220                            memberName + ", ";
       
   221             }
       
   222             catch (ConstantPoolException cpe) { cpe.printStackTrace(); }
       
   223             if (index != -1) {
       
   224                 switch (AnnoType) {
       
   225                     case Attribute.RuntimeVisibleTypeAnnotations:
       
   226                         //count RuntimeVisibleTypeAnnotations
       
   227                         RuntimeVisibleTypeAnnotations_attribute RVTAa =
       
   228                                 (RuntimeVisibleTypeAnnotations_attribute)attr;
       
   229                         vtaActual += RVTAa.annotations.length;
       
   230                         break;
       
   231                     case Attribute.RuntimeVisibleAnnotations:
       
   232                         //count RuntimeVisibleAnnotations
       
   233                         RuntimeVisibleAnnotations_attribute RVAa =
       
   234                                 (RuntimeVisibleAnnotations_attribute)attr;
       
   235                         vaActual += RVAa.annotations.length;
       
   236                         break;
       
   237                     case Attribute.RuntimeInvisibleTypeAnnotations:
       
   238                         //count RuntimeInvisibleTypeAnnotations
       
   239                         RuntimeInvisibleTypeAnnotations_attribute RITAa =
       
   240                                 (RuntimeInvisibleTypeAnnotations_attribute)attr;
       
   241                         itaActual += RITAa.annotations.length;
       
   242                         break;
       
   243                     case Attribute.RuntimeInvisibleAnnotations:
       
   244                         //count RuntimeInvisibleAnnotations
       
   245                         RuntimeInvisibleAnnotations_attribute RIAa =
       
   246                                 (RuntimeInvisibleAnnotations_attribute)attr;
       
   247                         iaActual += RIAa.annotations.length;
       
   248                         break;
       
   249                 }
       
   250             }
       
   251             // annotations from code attribute.
       
   252             if (index2 != -1) {
       
   253                 switch (AnnoType) {
       
   254                     case Attribute.RuntimeVisibleTypeAnnotations:
       
   255                         //count RuntimeVisibleTypeAnnotations
       
   256                         RuntimeVisibleTypeAnnotations_attribute RVTAa =
       
   257                                 (RuntimeVisibleTypeAnnotations_attribute)cattr;
       
   258                         vtaActual += RVTAa.annotations.length;
       
   259                         break;
       
   260                     case Attribute.RuntimeVisibleAnnotations:
       
   261                         //count RuntimeVisibleAnnotations
       
   262                         RuntimeVisibleAnnotations_attribute RVAa =
       
   263                                 (RuntimeVisibleAnnotations_attribute)cattr;
       
   264                         vaActual += RVAa.annotations.length;
       
   265                         break;
       
   266                     case Attribute.RuntimeInvisibleTypeAnnotations:
       
   267                         //count RuntimeInvisibleTypeAnnotations
       
   268                         RuntimeInvisibleTypeAnnotations_attribute RITAa =
       
   269                                 (RuntimeInvisibleTypeAnnotations_attribute)cattr;
       
   270                         itaActual += RITAa.annotations.length;
       
   271                         break;
       
   272                     case Attribute.RuntimeInvisibleAnnotations:
       
   273                         //count RuntimeInvisibleAnnotations
       
   274                         RuntimeInvisibleAnnotations_attribute RIAa =
       
   275                                 (RuntimeInvisibleAnnotations_attribute)cattr;
       
   276                         iaActual += RIAa.annotations.length;
       
   277                         break;
       
   278                 }
       
   279             }
       
   280         }
       
   281 
       
   282         switch (memberName) {
       
   283             //METHODs
       
   284             case "test" : vtaExp=4;  itaExp=4;  vaExp=0; iaExp=0; tc++; break;
       
   285             case "mtest": vtaExp=4;  itaExp=4;  vaExp=1; iaExp=1; tc++; break;
       
   286             case "m1":    vtaExp=2;  itaExp=2;  vaExp=1; iaExp=1; tc++; break;
       
   287             case "m2":    vtaExp=4;  itaExp=4;  vaExp=1; iaExp=1; tc++; break;
       
   288             case "m3":    vtaExp=10; itaExp=10; vaExp=1; iaExp=1; tc++; break;
       
   289             case "tm":    vtaExp=6;  itaExp=6;  vaExp=1; iaExp=1; tc++; break;
       
   290             //inner class
       
   291             case "i_m1":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   292             case "i_m2":  vtaExp=4;  itaExp=4; vaExp=1; iaExp=1; tc++; break;
       
   293             case "i_um":  vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   294             //local class
       
   295             case "l_m1":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   296             case "l_m2":  vtaExp=4;  itaExp=4; vaExp=1; iaExp=1; tc++; break;
       
   297             case "l_um":  vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   298             //anon class
       
   299             case "mm_m1": vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   300             case "mm_m2": vtaExp=4;  itaExp=4; vaExp=1; iaExp=1; tc++; break;
       
   301             case "mm_m3": vtaExp=10; itaExp=10;vaExp=1; iaExp=1; tc++; break;
       
   302             case "mm_tm": vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   303             //InnerAnon class
       
   304             case "ia_m1": vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   305             case "ia_m2": vtaExp=4;  itaExp=4; vaExp=1; iaExp=1; tc++; break;
       
   306             case "ia_um": vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   307             //FIELDs
       
   308             case "data":   vtaExp = 2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   309             case "odata1": vtaExp = 2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   310             case "pdata1": vtaExp = 2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   311             case "tdata":  vtaExp = 2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   312             case "sa1":    vtaExp = 6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   313             //inner class
       
   314             case "i_odata1":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   315             case "i_pdata1":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   316             case "i_udata":   vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   317             case "i_sa1":     vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   318             case "i_tdata":   vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   319             //local class
       
   320             case "l_odata1":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   321             case "l_pdata1":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   322             case "l_udata":   vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   323             case "l_sa1":     vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   324             case "l_tdata":   vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   325             //anon class
       
   326             case "mm_odata1": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   327             case "mm_pdata1": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   328             case "mm_sa1":    vtaExp = 6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   329             case "mm_tdata":  vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   330             // InnerAnon class
       
   331             case "ia_odata1": vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   332             case "ia_pdata1": vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   333             case "ia_udata":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   334             case "ia_sa1":    vtaExp=6;  itaExp=6; vaExp=1; iaExp=1; tc++; break;
       
   335             case "ia_tdata":  vtaExp=2;  itaExp=2; vaExp=1; iaExp=1; tc++; break;
       
   336             case "IA":        vtaExp=4;  itaExp=4; vaExp=1; iaExp=1; tc++; break;
       
   337             case "IN":        vtaExp=4;  itaExp=4; vaExp=1; iaExp=1; tc++; break;
       
   338             // default cases are <init>, this$0, this$1, mmtest, atest
       
   339             default:          vtaExp = 0;  itaExp=0; vaExp=0; iaExp=0;    break;
       
   340         }
       
   341         check(testcase,vtaExp,   itaExp,   vaExp,   iaExp,
       
   342                        vtaActual,itaActual,vaActual,iaActual);
       
   343     }
       
   344 
       
   345     public void run() {
       
   346         ClassFile cf   = null;
       
   347         InputStream in = null;
       
   348         int testcount  = 1;
       
   349         File testFile  = null;
       
   350         // Generate source, check methods and fields for each combination.
       
   351         for (Boolean[] bCombo : bRepeat) {
       
   352             As=bCombo[0]; Bs=bCombo[1]; Cs=bCombo[2];
       
   353             Ds=bCombo[3]; TAs=bCombo[4]; TBs=bCombo[5];
       
   354             String testname = "Test" + testcount++;
       
   355             println("Combinations: " + As + ", " + Bs + ", " + Cs + ", " + Ds +
       
   356                     ", " + TAs + ", " + TBs +
       
   357                     "; see " + testname + ".java");
       
   358             String[] classes = {testname + ".class",
       
   359                                 testname + "$Inner.class",
       
   360                                 testname + "$1Local1.class",
       
   361                                 testname + "$1.class",
       
   362                                 testname + "$1$1.class",
       
   363                                 testname + "$1$InnerAnon.class"
       
   364             };
       
   365             // Create test source, create and compile File.
       
   366             String sourceString = getSource(srcTemplate, testname,
       
   367                                             As, Bs, Cs, Ds, TAs, TBs);
       
   368             System.out.println(sourceString);
       
   369             try {
       
   370                 testFile = writeTestFile(testname+".java", sourceString);
       
   371             }
       
   372             catch (IOException ioe) { ioe.printStackTrace(); }
       
   373             // Compile test source and read classfile.
       
   374             File classFile = null;
       
   375             try {
       
   376                 classFile = compile(testFile);
       
   377             }
       
   378             catch (Error err) {
       
   379                 System.err.println("FAILED compile. Source:\n" + sourceString);
       
   380                 throw err;
       
   381             }
       
   382             String testloc = classFile.getAbsolutePath().substring(
       
   383                    0,classFile.getAbsolutePath().indexOf(classFile.getPath()));
       
   384             for (String clazz : classes) {
       
   385                 try {
       
   386                     cf = ClassFile.read(new File(testloc+clazz));
       
   387                 }
       
   388                 catch (Exception e) { e.printStackTrace();  }
       
   389                 // Test for all methods and fields
       
   390                 for (Method m: cf.methods) {
       
   391                     test("METHOD", cf, m, null, true);
       
   392                 }
       
   393                 for (Field f: cf.fields) {
       
   394                     test("FIELD", cf, null, f, true);
       
   395                 }
       
   396             }
       
   397         }
       
   398         report();
       
   399         if (tc!=xtc) System.out.println("Test Count: " + tc + " != " +
       
   400                                        "expected: " + xtc);
       
   401     }
       
   402 
       
   403 
       
   404     String getSrcTemplate(String sTemplate) {
       
   405         List<String> tmpl = null;
       
   406         String sTmpl = "";
       
   407         try {
       
   408             tmpl = Files.readAllLines(new File(testSrc,sTemplate).toPath(),
       
   409                                       Charset.defaultCharset());
       
   410         }
       
   411         catch (IOException ioe) {
       
   412             String error = "FAILED: Test failed to read template" + sTemplate;
       
   413             ioe.printStackTrace();
       
   414             throw new RuntimeException(error);
       
   415         }
       
   416         for (String l : tmpl)
       
   417             sTmpl=sTmpl.concat(l).concat("\n");
       
   418         return sTmpl;
       
   419     }
       
   420 
       
   421     // test class template
       
   422     String getSource(String templateName, String testname,
       
   423                      Boolean Arepeats,  Boolean Brepeats,
       
   424                      Boolean Crepeats,  Boolean Drepeats,
       
   425                      Boolean TArepeats, Boolean TBrepeats) {
       
   426         String As  = Arepeats  ? "@A @A":"@A",
       
   427                Bs  = Brepeats  ? "@B @B":"@B",
       
   428                Cs  = Crepeats  ? "@C @C":"@C",
       
   429                Ds  = Drepeats  ? "@D @D":"@D",
       
   430                TAs = TArepeats ? "@TA @TA":"@TA",
       
   431                TBs = TBrepeats ? "@TB @TB":"@TB";
       
   432 
       
   433         // split up replace() lines for readability
       
   434         String testsource = getSrcTemplate(templateName).replace("testname",testname);
       
   435         testsource = testsource.replace("_As",As).replace("_Bs",Bs).replace("_Cs",Cs);
       
   436         testsource = testsource.replace("_Ds",Ds).replace("_TAs",TAs).replace("_TBs",TBs);
       
   437         return testsource;
       
   438     }
       
   439 }