langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java
changeset 26101 d5dd2ecd2353
child 26103 3f96599b20da
equal deleted inserted replaced
26099:c425126bfadf 26101:d5dd2ecd2353
       
     1 /*
       
     2  * Copyright (c) 2014, 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 8042251
       
    27  * @summary Test that inner classes have in its inner classes attribute enclosing classes and its immediate members.
       
    28  * @library /tools/javac/lib ../lib
       
    29  * @build TestResult TestBase InMemoryFileManager ToolBox
       
    30  * @run main InnerClassesHierarchyTest
       
    31  */
       
    32 
       
    33 import com.sun.tools.classfile.*;
       
    34 import com.sun.tools.classfile.InnerClasses_attribute.Info;
       
    35 
       
    36 import java.io.File;
       
    37 import java.io.FilenameFilter;
       
    38 import java.io.IOException;
       
    39 import java.lang.annotation.Annotation;
       
    40 import java.util.*;
       
    41 import java.util.stream.Collectors;
       
    42 
       
    43 public class InnerClassesHierarchyTest extends TestResult {
       
    44 
       
    45     private final Map<String, Set<String>> innerClasses;
       
    46     private final String outerClassName;
       
    47 
       
    48     public InnerClassesHierarchyTest() throws IOException, ConstantPoolException {
       
    49         innerClasses = new HashMap<>();
       
    50         outerClassName = InnerClassesHierarchyTest.class.getSimpleName();
       
    51         File classDir = getClassDir();
       
    52         FilenameFilter filter =
       
    53                 (dir, name) -> name.matches(outerClassName + ".*\\.class");
       
    54         for (File file : Arrays.asList(classDir.listFiles(filter))) {
       
    55             ClassFile classFile = readClassFile(file);
       
    56             String className = classFile.getName();
       
    57             for (ConstantPool.CPInfo info : classFile.constant_pool.entries()) {
       
    58                 if (info instanceof ConstantPool.CONSTANT_Class_info) {
       
    59                     ConstantPool.CONSTANT_Class_info classInfo =
       
    60                             (ConstantPool.CONSTANT_Class_info) info;
       
    61                     String cpClassName = classInfo.getBaseName();
       
    62                     if (isInnerClass(cpClassName)) {
       
    63                         get(className).add(cpClassName);
       
    64                     }
       
    65                 }
       
    66             }
       
    67         }
       
    68     }
       
    69 
       
    70     private boolean isInnerClass(String cpClassName) {
       
    71         return cpClassName.contains("$");
       
    72     }
       
    73 
       
    74     private Set<String> get(String className) {
       
    75         if (!innerClasses.containsKey(className)) {
       
    76             innerClasses.put(className, new HashSet<>());
       
    77         }
       
    78         return innerClasses.get(className);
       
    79     }
       
    80 
       
    81     public static void main(String[] args) throws IOException, ConstantPoolException, TestFailedException {
       
    82         new InnerClassesHierarchyTest().test();
       
    83     }
       
    84 
       
    85     private void test() throws TestFailedException {
       
    86         addTestCase("Source file is InnerClassesHierarchyTest.java");
       
    87         try {
       
    88             Queue<String> queue = new LinkedList<>();
       
    89             Set<String> visitedClasses = new HashSet<>();
       
    90             queue.add(outerClassName);
       
    91             while (!queue.isEmpty()) {
       
    92                 String currentClassName = queue.poll();
       
    93                 if (!currentClassName.startsWith(outerClassName)) {
       
    94                     continue;
       
    95                 }
       
    96                 ClassFile cf = readClassFile(currentClassName);
       
    97                 InnerClasses_attribute attr = (InnerClasses_attribute)
       
    98                         cf.getAttribute(Attribute.InnerClasses);
       
    99                 assertNotNull(attr, "Class should not contain "
       
   100                         + "inner classes attribute : " + currentClassName);
       
   101                 assertTrue(innerClasses.containsKey(currentClassName),
       
   102                         "map contains class name : " + currentClassName);
       
   103                 Set<String> setClasses = innerClasses.get(currentClassName);
       
   104                 if (setClasses == null) {
       
   105                     continue;
       
   106                 }
       
   107                 assertEquals(attr.number_of_classes,
       
   108                         setClasses.size(),
       
   109                         "Check number of inner classes : " + setClasses);
       
   110                 for (Info info : attr.classes) {
       
   111                     String innerClassName = info
       
   112                             .getInnerClassInfo(cf.constant_pool).getBaseName();
       
   113                     assertTrue(setClasses.contains(innerClassName),
       
   114                             currentClassName + " contains inner class : "
       
   115                                     + innerClassName);
       
   116                     if (visitedClasses.add(innerClassName)) {
       
   117                         queue.add(innerClassName);
       
   118                     }
       
   119                 }
       
   120             }
       
   121             Set<String> allClasses = innerClasses.entrySet().stream()
       
   122                     .flatMap(entry -> entry.getValue().stream())
       
   123                     .collect(Collectors.toSet());
       
   124 
       
   125             Set<String> a_b = removeAll(visitedClasses, allClasses);
       
   126             Set<String> b_a = removeAll(allClasses, visitedClasses);
       
   127             assertEquals(visitedClasses, allClasses,
       
   128                     "All classes are found\n"
       
   129                     + "visited - all classes : " + a_b
       
   130                     + "\nall classes - visited : " + b_a);
       
   131         } catch (Exception e) {
       
   132             addFailure(e);
       
   133         } finally {
       
   134             checkStatus();
       
   135         }
       
   136     }
       
   137 
       
   138     private Set<String> removeAll(Set<String> set1, Set<String> set2) {
       
   139         Set<String> set = new HashSet<>(set1);
       
   140         set.removeAll(set2);
       
   141         return set;
       
   142     }
       
   143 
       
   144     public static class A1 {
       
   145 
       
   146         public class B1 {
       
   147         }
       
   148 
       
   149         public enum B2 {
       
   150         }
       
   151 
       
   152         public interface B3 {
       
   153         }
       
   154 
       
   155         public @interface B4 {
       
   156         }
       
   157 
       
   158         public void f() {
       
   159             new B1() {
       
   160             };
       
   161             new B3() {
       
   162             };
       
   163             new B4() {
       
   164                 @Override
       
   165                 public Class<? extends Annotation> annotationType() {
       
   166                     return null;
       
   167                 }
       
   168             };
       
   169             class B5 {
       
   170             }
       
   171         }
       
   172 
       
   173         Runnable r = () -> {
       
   174             new B1() {
       
   175             };
       
   176             new B3() {
       
   177             };
       
   178             new B4() {
       
   179                 @Override
       
   180                 public Class<? extends Annotation> annotationType() {
       
   181                     return null;
       
   182                 }
       
   183             };
       
   184             class B5 {
       
   185             }
       
   186         };
       
   187     }
       
   188 
       
   189     public enum A2 {;
       
   190 
       
   191         public class B1 {
       
   192         }
       
   193 
       
   194         public enum B2 {
       
   195         }
       
   196 
       
   197         public interface B3 {
       
   198         }
       
   199 
       
   200         public @interface B4 {
       
   201         }
       
   202 
       
   203         public void a2() {
       
   204             new B1() {
       
   205             };
       
   206             new B3() {
       
   207             };
       
   208             new B4() {
       
   209                 @Override
       
   210                 public Class<? extends Annotation> annotationType() {
       
   211                     return null;
       
   212                 }
       
   213             };
       
   214             class B5 {
       
   215             }
       
   216         }
       
   217 
       
   218         Runnable r = () -> {
       
   219             new B1() {
       
   220             };
       
   221             new B3() {
       
   222             };
       
   223             new B4() {
       
   224                 @Override
       
   225                 public Class<? extends Annotation> annotationType() {
       
   226                     return null;
       
   227                 }
       
   228             };
       
   229             class B5 {
       
   230             }
       
   231         };
       
   232     }
       
   233 
       
   234     public interface A3 {
       
   235 
       
   236         public class B1 {
       
   237         }
       
   238 
       
   239         public enum B2 {
       
   240         }
       
   241 
       
   242         public interface B3 {
       
   243         }
       
   244 
       
   245         public @interface B4 {
       
   246         }
       
   247 
       
   248         default void a1() {
       
   249             new B1() {
       
   250             };
       
   251             new B3() {
       
   252             };
       
   253             new B4() {
       
   254                 @Override
       
   255                 public Class<? extends Annotation> annotationType() {
       
   256                     return null;
       
   257                 }
       
   258             };
       
   259             class B5 {
       
   260             }
       
   261         }
       
   262 
       
   263         static void a2() {
       
   264             new B1() {
       
   265             };
       
   266             new B3() {
       
   267             };
       
   268             new B4() {
       
   269                 @Override
       
   270                 public Class<? extends Annotation> annotationType() {
       
   271                     return null;
       
   272                 }
       
   273             };
       
   274             class B5 {
       
   275             }
       
   276         }
       
   277     }
       
   278 
       
   279     public @interface A4 {
       
   280 
       
   281         public class B1 {
       
   282         }
       
   283 
       
   284         public enum B2 {
       
   285         }
       
   286 
       
   287         public interface B3 {
       
   288         }
       
   289 
       
   290         public @interface B4 {
       
   291         }
       
   292     }
       
   293 
       
   294     {
       
   295         new A1() {
       
   296             class B1 {
       
   297             }
       
   298 
       
   299             public void a2() {
       
   300                 new B1() {
       
   301                 };
       
   302                 class B5 {
       
   303                 }
       
   304             }
       
   305         };
       
   306         new A3() {
       
   307             class B1 {
       
   308             }
       
   309 
       
   310             public void a3() {
       
   311                 new B1() {
       
   312                 };
       
   313                 class B5 {
       
   314                 }
       
   315             }
       
   316         };
       
   317         new A4() {
       
   318             @Override
       
   319             public Class<? extends Annotation> annotationType() {
       
   320                 return null;
       
   321             }
       
   322 
       
   323             class B1 {
       
   324             }
       
   325 
       
   326             public void a4() {
       
   327                 new B1() {
       
   328                 };
       
   329                 class B5 {
       
   330                 }
       
   331             }
       
   332         };
       
   333         Runnable r = () -> {
       
   334             new A1() {
       
   335             };
       
   336             new A3() {
       
   337             };
       
   338             new A4() {
       
   339                 @Override
       
   340                 public Class<? extends Annotation> annotationType() {
       
   341                     return null;
       
   342                 }
       
   343             };
       
   344             class B5 {
       
   345             }
       
   346         };
       
   347     }
       
   348 
       
   349     static {
       
   350         new A1() {
       
   351             class B1 {
       
   352             }
       
   353 
       
   354             public void a2() {
       
   355                 new B1() {
       
   356                 };
       
   357                 class B5 {
       
   358                 }
       
   359             }
       
   360         };
       
   361         new A3() {
       
   362             class B1 {
       
   363             }
       
   364 
       
   365             public void a3() {
       
   366                 new B1() {
       
   367                 };
       
   368                 class B5 {
       
   369                 }
       
   370             }
       
   371         };
       
   372         new A4() {
       
   373             @Override
       
   374             public Class<? extends Annotation> annotationType() {
       
   375                 return null;
       
   376             }
       
   377 
       
   378             class B1 {
       
   379             }
       
   380 
       
   381             public void a4() {
       
   382                 new B1() {
       
   383                 };
       
   384                 class B5 {
       
   385                 }
       
   386             }
       
   387         };
       
   388         Runnable r = () -> {
       
   389             new A1() {
       
   390             };
       
   391             new A3() {
       
   392             };
       
   393             new A4() {
       
   394                 @Override
       
   395                 public Class<? extends Annotation> annotationType() {
       
   396                     return null;
       
   397                 }
       
   398             };
       
   399             class B5 {
       
   400             }
       
   401         };
       
   402     }
       
   403 
       
   404     public void a5() {
       
   405         class A5 {
       
   406 
       
   407             class B1 {
       
   408             }
       
   409 
       
   410             public void a5() {
       
   411                 new B1() {
       
   412                 };
       
   413 
       
   414                 class B5 {
       
   415                 }
       
   416             }
       
   417         }
       
   418         Runnable r = () -> {
       
   419             new A1() {
       
   420             };
       
   421             new A3() {
       
   422             };
       
   423             new A4() {
       
   424                 @Override
       
   425                 public Class<? extends Annotation> annotationType() {
       
   426                     return null;
       
   427                 }
       
   428             };
       
   429             class B5 {
       
   430             }
       
   431         };
       
   432     }
       
   433 }