langtools/make/test/sym/CreateSymbolsTestImpl.java
changeset 31506 4e07f827a794
child 33551 1cd3c95fb546
equal deleted inserted replaced
31505:98c52b994430 31506:4e07f827a794
       
     1 /*
       
     2  * Copyright (c) 2015, 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 import java.io.File;
       
    25 import java.io.InputStream;
       
    26 import java.io.Writer;
       
    27 import java.lang.annotation.Retention;
       
    28 import java.lang.annotation.RetentionPolicy;
       
    29 import java.lang.reflect.Method;
       
    30 import java.util.Arrays;
       
    31 import java.util.List;
       
    32 import com.sun.tools.javac.file.ZipFileIndexCache;
       
    33 import java.io.IOException;
       
    34 import java.nio.file.FileVisitResult;
       
    35 import java.nio.file.FileVisitor;
       
    36 import java.nio.file.Files;
       
    37 import java.nio.file.Path;
       
    38 import java.nio.file.Paths;
       
    39 import java.nio.file.attribute.BasicFileAttributes;
       
    40 import java.util.HashSet;
       
    41 import java.util.Set;
       
    42 import java.util.stream.Collectors;
       
    43 import java.util.stream.Stream;
       
    44 import symbolgenerator.CreateSymbols;
       
    45 import symbolgenerator.CreateSymbols.ClassDescription;
       
    46 import symbolgenerator.CreateSymbols.ClassList;
       
    47 import symbolgenerator.CreateSymbols.CtSymKind;
       
    48 import symbolgenerator.CreateSymbols.ExcludeIncludeList;
       
    49 import symbolgenerator.CreateSymbols.VersionDescription;
       
    50 
       
    51 public class CreateSymbolsTestImpl {
       
    52 
       
    53     static final String CREATE_SYMBOLS_NAME = "symbolgenerator.CreateSymbols";
       
    54 
       
    55     public static void main(String... args) throws Exception {
       
    56         new CreateSymbolsTestImpl().doTest();
       
    57     }
       
    58 
       
    59     void doTest() throws Exception {
       
    60         boolean testRun = false;
       
    61         for (Method m : CreateSymbolsTestImpl.class.getDeclaredMethods()) {
       
    62             if (!"testIncluded".equals(m.getName()))
       
    63                 continue;
       
    64             if (m.isAnnotationPresent(Test.class)) {
       
    65                 m.invoke(this);
       
    66                 testRun = true;
       
    67             }
       
    68         }
       
    69         if (!testRun) {
       
    70             throw new IllegalStateException("No tests found.");
       
    71         }
       
    72     }
       
    73 
       
    74     @Test
       
    75     void testMethodRemoved() throws Exception {
       
    76         doTest("package t; public class T { public void m() { } }",
       
    77                "package t; public class T { }",
       
    78                "package t; public class Test { { T t = null; t.m(); } }",
       
    79                ToolBox.Expect.SUCCESS,
       
    80                ToolBox.Expect.FAIL);
       
    81         doTest("package t; public class T { public void b() { } public void m() { } public void a() { } }",
       
    82                "package t; public class T { public void b() { }                     public void a() { } }",
       
    83                "package t; public class Test { { T t = null; t.b(); t.a(); } }",
       
    84                ToolBox.Expect.SUCCESS,
       
    85                ToolBox.Expect.SUCCESS);
       
    86         //with additional attribute (need to properly skip the member):
       
    87         doTest("package t; public class T { public void m() throws IllegalStateException { } public void a() { } }",
       
    88                "package t; public class T {                                                  public void a() { } }",
       
    89                "package t; public class Test { { T t = null; t.a(); } }",
       
    90                ToolBox.Expect.SUCCESS,
       
    91                ToolBox.Expect.SUCCESS);
       
    92     }
       
    93 
       
    94     @Test
       
    95     void testMethodAdded() throws Exception {
       
    96         doTest("package t; public class T { }",
       
    97                "package t; public class T { public void m() { } }",
       
    98                "package t; public class Test { { T t = null; t.m(); } }",
       
    99                ToolBox.Expect.FAIL,
       
   100                ToolBox.Expect.SUCCESS);
       
   101         doTest("package t; public class T { public void b() { }                     public void a() { } }",
       
   102                "package t; public class T { public void b() { } public void m() { } public void a() { } }",
       
   103                "package t; public class Test { { T t = null; t.b(); t.a(); } }",
       
   104                ToolBox.Expect.SUCCESS,
       
   105                ToolBox.Expect.SUCCESS);
       
   106     }
       
   107 
       
   108     //verify fields added/modified/removed
       
   109 
       
   110     @Test
       
   111     void testClassAdded() throws Exception {
       
   112         doTest("class Dummy {}",
       
   113                "package t; public class T { }",
       
   114                "package t; public class Test { { T t = new T(); } }",
       
   115                ToolBox.Expect.FAIL,
       
   116                ToolBox.Expect.SUCCESS);
       
   117     }
       
   118 
       
   119     @Test
       
   120     void testClassModified() throws Exception {
       
   121         doTest("package t; public class T { public void m() { } }",
       
   122                "package t; public class T implements java.io.Serializable { public void m() { } }",
       
   123                "package t; public class Test { { java.io.Serializable t = new T(); } }",
       
   124                ToolBox.Expect.FAIL,
       
   125                ToolBox.Expect.SUCCESS);
       
   126     }
       
   127 
       
   128     @Test
       
   129     void testClassRemoved() throws Exception {
       
   130         doTest("package t; public class T { }",
       
   131                "class Dummy {}",
       
   132                "package t; public class Test { { T t = new T(); } }",
       
   133                ToolBox.Expect.SUCCESS,
       
   134                ToolBox.Expect.FAIL);
       
   135     }
       
   136 
       
   137     @Test
       
   138     void testInnerClassAttributes() throws Exception {
       
   139         doTest("package t; public class T { public static class Inner { } }",
       
   140                "package t; public class T { public static class Inner { } }",
       
   141                "package t; import t.T.Inner; public class Test { Inner i; }",
       
   142                ToolBox.Expect.SUCCESS,
       
   143                ToolBox.Expect.SUCCESS);
       
   144     }
       
   145 
       
   146     @Test
       
   147     void testConstantAdded() throws Exception {
       
   148         doTest("package t; public class T { }",
       
   149                "package t; public class T { public static final int A = 0; }",
       
   150                "package t; public class Test { void t(int i) { switch (i) { case T.A: break;} } }",
       
   151                ToolBox.Expect.FAIL,
       
   152                ToolBox.Expect.SUCCESS);
       
   153     }
       
   154 
       
   155     @Test
       
   156     void testAnnotationAttributeDefaultvalue() throws Exception {
       
   157         //TODO: this only verifies that there is *some* value, but we should also verify there is a specific value:
       
   158         doTest("package t; public @interface T { }",
       
   159                "package t;\n" +
       
   160                "public @interface T {\n" +
       
   161                "    public boolean booleanValue() default true;\n" +
       
   162                "    public byte byteValue() default 1;\n" +
       
   163                "    public char charValue() default 2;\n" +
       
   164                "    public short shortValue() default 3;\n" +
       
   165                "    public int intValue() default 4;\n" +
       
   166                "    public long longValue() default 5;\n" +
       
   167                "    public float floatValue() default 6;\n" +
       
   168                "    public double doubleValue() default 7;\n" +
       
   169                "    public String stringValue() default \"8\";\n" +
       
   170                "    public java.lang.annotation.RetentionPolicy enumValue() default java.lang.annotation.RetentionPolicy.RUNTIME;\n" +
       
   171                "    public Class classValue() default Number.class;\n" +
       
   172                "    public int[] arrayValue() default {1, 2};\n" +
       
   173                "    public SuppressWarnings annotationValue() default @SuppressWarnings(\"cast\");\n" +
       
   174                "}\n",
       
   175                "package t; public @T class Test { }",
       
   176                ToolBox.Expect.SUCCESS,
       
   177                ToolBox.Expect.SUCCESS);
       
   178     }
       
   179 
       
   180     @Test
       
   181     void testConstantTest() throws Exception {
       
   182         //XXX: other constant types (String in particular) - see testStringConstant
       
   183         doPrintElementTest("package t; public class T { public static final int A = 1; }",
       
   184                            "package t; public class T { public static final int A = 2; }",
       
   185                            "t.T",
       
   186                            "package t;\n\n" +
       
   187                            "public class T {\n" +
       
   188                            "  public static final int A = 1;\n\n" +
       
   189                            "  public T();\n" +
       
   190                            "}\n",
       
   191                            "t.T",
       
   192                            "package t;\n\n" +
       
   193                            "public class T {\n" +
       
   194                            "  public static final int A = 2;\n\n" +
       
   195                            "  public T();\n" +
       
   196                            "}\n");
       
   197         doPrintElementTest("package t; public class T { public static final boolean A = false; }",
       
   198                            "package t; public class T { public static final boolean A = true; }",
       
   199                            "t.T",
       
   200                            "package t;\n\n" +
       
   201                            "public class T {\n" +
       
   202                            "  public static final boolean A = false;\n\n" +
       
   203                            "  public T();\n" +
       
   204                            "}\n",
       
   205                            "t.T",
       
   206                            "package t;\n\n" +
       
   207                            "public class T {\n" +
       
   208                            "  public static final boolean A = true;\n\n" +
       
   209                            "  public T();\n" +
       
   210                            "}\n");
       
   211     }
       
   212 
       
   213     @Test
       
   214     void testAnnotations() throws Exception {
       
   215         doPrintElementTest("package t;" +
       
   216                            "import java.lang.annotation.*;" +
       
   217                            "public @Visible @Invisible class T { }" +
       
   218                            "@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
       
   219                            "@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
       
   220                            "package t;" +
       
   221                            "import java.lang.annotation.*;" +
       
   222                            "public @Visible @Invisible class T { }" +
       
   223                            "@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
       
   224                            "@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
       
   225                            "t.T",
       
   226                            "package t;\n\n" +
       
   227                            "@t.Invisible\n" +
       
   228                            "@t.Visible\n" +
       
   229                            "public class T {\n\n" +
       
   230                            "  public T();\n" +
       
   231                            "}\n",
       
   232                            "t.Visible",
       
   233                            "package t;\n\n" +
       
   234                            "@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" +
       
   235                            "@interface Visible {\n" +
       
   236                            "}\n");
       
   237         doPrintElementTest("package t;" +
       
   238                            "import java.lang.annotation.*;" +
       
   239                            "import java.util.*;" +
       
   240                            "public class T {" +
       
   241                            "    public void test(int h, @Invisible int i, @Visible List<String> j, int k) { }" +
       
   242                            "}" +
       
   243                            "@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
       
   244                            "@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
       
   245                            "package t;" +
       
   246                            "import java.lang.annotation.*;" +
       
   247                            "import java.util.*;" +
       
   248                            "public class T {" +
       
   249                            "    public void test(int h, @Invisible int i, @Visible List<String> j, int k) { }" +
       
   250                            "}" +
       
   251                            "@Retention(RetentionPolicy.RUNTIME) @interface Visible { }" +
       
   252                            "@Retention(RetentionPolicy.CLASS) @interface Invisible { }",
       
   253                            "t.T",
       
   254                            "package t;\n\n" +
       
   255                            "public class T {\n\n" +
       
   256                            "  public T();\n\n" +
       
   257                            "  public void test(int arg0,\n" +
       
   258                            "    @t.Invisible int arg1,\n" +
       
   259                            "    @t.Visible java.util.List<java.lang.String> arg2,\n" +
       
   260                            "    int arg3);\n" +
       
   261                            "}\n",
       
   262                            "t.Visible",
       
   263                            "package t;\n\n" +
       
   264                            "@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)\n" +
       
   265                            "@interface Visible {\n" +
       
   266                            "}\n");
       
   267         doPrintElementTest("package t;" +
       
   268                            "import java.lang.annotation.*;" +
       
   269                            "public class T {" +
       
   270                            "    public void test(@Ann(v=\"url\", dv=\"\\\"\\\"\") String str) { }" +
       
   271                            "}" +
       
   272                            "@Retention(RetentionPolicy.RUNTIME) @interface Ann {" +
       
   273                            "    public String v();" +
       
   274                            "    public String dv();" +
       
   275                            "}",
       
   276                            "package t;" +
       
   277                            "public class T { }",
       
   278                            "t.T",
       
   279                            "package t;\n\n" +
       
   280                            "public class T {\n\n" +
       
   281                            "  public T();\n\n" +
       
   282                            "  public void test(@t.Ann(dv=\"\\\"\\\"\", v=\"url\") java.lang.String arg0);\n" +
       
   283                            "}\n",
       
   284                            "t.T",
       
   285                            "package t;\n\n" +
       
   286                            "public class T {\n\n" +
       
   287                            "  public T();\n" +
       
   288                            "}\n");
       
   289     }
       
   290 
       
   291     @Test
       
   292     void testStringConstant() throws Exception {
       
   293         doTest("package t; public class T { public static final String C = \"\"; }",
       
   294                "package t; public class T { public static final String C = \"\"; }",
       
   295                "package t; public class Test { { System.err.println(T.C); } }",
       
   296                 ToolBox.Expect.SUCCESS,
       
   297                 ToolBox.Expect.SUCCESS);
       
   298     }
       
   299 
       
   300     @Test
       
   301     void testCopyProfileAnnotation() throws Exception {
       
   302         String oldProfileAnnotation = CreateSymbols.PROFILE_ANNOTATION;
       
   303         try {
       
   304             CreateSymbols.PROFILE_ANNOTATION = "Lt/Ann;";
       
   305             doTestEquivalence("package t; public class T { public void t() {} } @interface Ann { }",
       
   306                               "package t; public @Ann class T { public void t() {} } @interface Ann { }",
       
   307                               "t.T");
       
   308         } finally {
       
   309             CreateSymbols.PROFILE_ANNOTATION = oldProfileAnnotation;
       
   310         }
       
   311     }
       
   312 
       
   313     @Test
       
   314     void testParseAnnotation() throws Exception {
       
   315         CreateSymbols.parseAnnotations("@Lsun/Proprietary+Annotation;@Ljdk/Profile+Annotation;(value=I1)", new int[1]);
       
   316         CreateSymbols.parseAnnotations("@Ltest;(value={\"\"})", new int[1]);
       
   317         CreateSymbols.parseAnnotations("@Ljava/beans/ConstructorProperties;(value={\"path\"})", new int[1]);
       
   318         CreateSymbols.parseAnnotations("@Ljava/beans/ConstructorProperties;(value=I-2)", new int[1]);
       
   319     }
       
   320 
       
   321     @Test
       
   322     void testStringCharLiterals() throws Exception {
       
   323         doPrintElementTest("package t;" +
       
   324                            "public class T {" +
       
   325                            "    public static final String STR = \"\\u0000\\u0001\\uffff\";" +
       
   326                            "    public static final String EMPTY = \"\";" +
       
   327                            "    public static final String AMP = \"&amp;&&lt;<&gt;>&apos;'\";" +
       
   328                            "}",
       
   329                            "package t;" +
       
   330                            "    public class T {" +
       
   331                            "    public static final char c = '\\uffff';" +
       
   332                            "}",
       
   333                            "t.T",
       
   334                            "package t;\n\n" +
       
   335                            "public class T {\n" +
       
   336                            "  public static final java.lang.String STR = \"\\u0000\\u0001\\uffff\";\n" +
       
   337                            "  public static final java.lang.String EMPTY = \"\";\n" +
       
   338                            "  public static final java.lang.String AMP = \"&amp;&&lt;<&gt;>&apos;\\'\";\n\n" +
       
   339                            "  public T();\n" +
       
   340                            "}\n",
       
   341                            "t.T",
       
   342                            "package t;\n\n" +
       
   343                            "public class T {\n" +
       
   344                            "  public static final char c = '\\uffff';\n\n" +
       
   345                            "  public T();\n" +
       
   346                            "}\n");
       
   347     }
       
   348 
       
   349     @Test
       
   350     void testGenerification() throws Exception {
       
   351         doTest("package t; public class T { public class TT { public Object t() { return null; } } }",
       
   352                "package t; public class T<E> { public class TT { public E t() { return null; } } }",
       
   353                "package t; public class Test { { T.TT tt = null; tt.t(); } }",
       
   354                ToolBox.Expect.SUCCESS,
       
   355                ToolBox.Expect.SUCCESS);
       
   356     }
       
   357 
       
   358     int i = 0;
       
   359 
       
   360     void doTest(String code7, String code8, String testCode, ToolBox.Expect result7, ToolBox.Expect result8) throws Exception {
       
   361         ToolBox tb = new ToolBox();
       
   362         Path classes = prepareVersionedCTSym(code7, code8);
       
   363         Path output = classes.getParent();
       
   364         Path scratch = output.resolve("scratch");
       
   365 
       
   366         Files.createDirectories(scratch);
       
   367 
       
   368         tb.new JavacTask()
       
   369           .sources(testCode)
       
   370           .options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "7"), "-XDuseOptimizedZip=false")
       
   371           .run(result7)
       
   372           .writeAll();
       
   373         tb.new JavacTask()
       
   374           .sources(testCode)
       
   375           .options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "8"), "-XDuseOptimizedZip=false")
       
   376           .run(result8)
       
   377           .writeAll();
       
   378     }
       
   379 
       
   380     private static String computeClassPath(Path classes, String version) throws IOException {
       
   381         try (Stream<Path> elements = Files.list(classes)) {
       
   382             return elements.map(el -> el.toAbsolutePath().toString())
       
   383                            .collect(Collectors.joining(File.pathSeparator));
       
   384         }
       
   385     }
       
   386 
       
   387     void doPrintElementTest(String code7, String code8, String className7, String printed7, String className8, String printed8) throws Exception {
       
   388         ToolBox tb = new ToolBox();
       
   389         Path classes = prepareVersionedCTSym(code7, code8);
       
   390         Path output = classes.getParent();
       
   391         Path scratch = output.resolve("scratch");
       
   392 
       
   393         Files.createDirectories(scratch);
       
   394 
       
   395         String out;
       
   396         out = tb.new JavacTask(ToolBox.Mode.CMDLINE)
       
   397                 .options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "7"), "-XDuseOptimizedZip=false", "-Xprint", className7)
       
   398                 .run(ToolBox.Expect.SUCCESS)
       
   399                 .getOutput(ToolBox.OutputKind.STDOUT);
       
   400         if (!out.equals(printed7)) {
       
   401             throw new AssertionError("out=" + out + "; printed7=" + printed7);
       
   402         }
       
   403         out = tb.new JavacTask(ToolBox.Mode.CMDLINE)
       
   404                 .options("-d", scratch.toAbsolutePath().toString(), "-classpath", computeClassPath(classes, "8"), "-XDuseOptimizedZip=false", "-Xprint", className8)
       
   405                 .run(ToolBox.Expect.SUCCESS)
       
   406                 .getOutput(ToolBox.OutputKind.STDOUT);
       
   407         if (!out.equals(printed8)) {
       
   408             throw new AssertionError("out=" + out + "; printed8=" + printed8);
       
   409         }
       
   410     }
       
   411 
       
   412     void doTestEquivalence(String code7, String code8, String testClass) throws Exception {
       
   413         Path classes = prepareVersionedCTSym(code7, code8);
       
   414         Path classfile = classes.resolve("78").resolve(testClass.replace('.', '/') + ".class");
       
   415 
       
   416         if (!Files.isReadable(classfile)) {
       
   417             throw new AssertionError("Cannot find expected class.");
       
   418         }
       
   419     }
       
   420 
       
   421     @Test
       
   422     void testIncluded() throws Exception {
       
   423         doTestIncluded("package t;\n" +
       
   424                        "public class Test extends PP1<PP2> implements PP3<PP4>, PP5<PP6> {\n" +
       
   425                        "     public PP7 m1(PP8 p) { return null;}\n" +
       
   426                        "     public PP9<PPA> m2(PPB<PPC> p) { return null;}\n" +
       
   427                        "     public PPD f1;\n" +
       
   428                        "     public PPE<PPF> f2;\n" +
       
   429                        "     public Test2 aux;\n" +
       
   430                        "}\n" +
       
   431                        "class Test2 extends PPG implements PPH, PPI {\n" +
       
   432                        "}\n" +
       
   433                        "class PP1<T> {}\n" +
       
   434                        "class PP2 {}\n" +
       
   435                        "interface PP3<T> {}\n" +
       
   436                        "class PP4 {}\n" +
       
   437                        "interface PP5<T> {}\n" +
       
   438                        "class PP6 {}\n" +
       
   439                        "class PP7 {}\n" +
       
   440                        "class PP8 {}\n" +
       
   441                        "class PP9<T> {}\n" +
       
   442                        "class PPA {}\n" +
       
   443                        "class PPB<T> {}\n" +
       
   444                        "class PPC {}\n" +
       
   445                        "class PPD {}\n" +
       
   446                        "class PPE<T> {}\n" +
       
   447                        "class PPF {}\n" +
       
   448                        "class PPG {}\n" +
       
   449                        "interface PPH {}\n" +
       
   450                        "interface PPI {}\n",
       
   451                        "t.Test",
       
   452                        "t.Test2",
       
   453                        "t.PP1",
       
   454                        "t.PP2",
       
   455                        "t.PP3",
       
   456                        "t.PP4",
       
   457                        "t.PP5",
       
   458                        "t.PP6",
       
   459                        "t.PP7",
       
   460                        "t.PP8",
       
   461                        "t.PP9",
       
   462                        "t.PPA",
       
   463                        "t.PPB",
       
   464                        "t.PPC",
       
   465                        "t.PPD",
       
   466                        "t.PPE",
       
   467                        "t.PPF",
       
   468                        "t.PPG",
       
   469                        "t.PPH",
       
   470                        "t.PPI");
       
   471     }
       
   472 
       
   473     void doTestIncluded(String code, String... includedClasses) throws Exception {
       
   474         boolean oldIncludeAll = includeAll;
       
   475         try {
       
   476             includeAll = false;
       
   477             Path classes = prepareVersionedCTSym(code, "package other; public class Other {}");
       
   478             Path root = classes.resolve("7");
       
   479             try (Stream<Path> classFiles = Files.walk(root)) {
       
   480                 Set<String> names = classFiles.map(p -> root.relativize(p))
       
   481                                               .map(p -> p.toString())
       
   482                                               .map(n -> {System.err.println("n= " + n); return n;})
       
   483                                               .filter(n -> n.endsWith(".class"))
       
   484                                               .map(n -> n.substring(0, n.lastIndexOf('.')))
       
   485                                               .map(n -> n.replace(File.separator, "."))
       
   486                                               .collect(Collectors.toSet());
       
   487 
       
   488                 if (!names.equals(new HashSet<>(Arrays.asList(includedClasses))))
       
   489                     throw new AssertionError("Expected classes not included: " + names);
       
   490             }
       
   491         } finally {
       
   492             includeAll = oldIncludeAll;
       
   493         }
       
   494     }
       
   495 
       
   496     Path prepareVersionedCTSym(String code7, String code8) throws Exception {
       
   497         String testClasses = System.getProperty("test.classes");
       
   498         Path output = Paths.get(testClasses, "test-data" + i++);
       
   499         deleteRecursively(output);
       
   500         Files.createDirectories(output);
       
   501         Path ver7Jar = output.resolve("7.jar");
       
   502         compileAndPack(output, ver7Jar, code7);
       
   503         Path ver8Jar = output.resolve("8.jar");
       
   504         compileAndPack(output, ver8Jar, code8);
       
   505 
       
   506         ZipFileIndexCache.getSharedInstance().clearCache();
       
   507 
       
   508         Path classes = output.resolve("classes");
       
   509 
       
   510         Files.createDirectories(classes);
       
   511 
       
   512         Path ctSym = output.resolve("ct.sym");
       
   513 
       
   514         deleteRecursively(ctSym);
       
   515 
       
   516         CreateSymbols.ALLOW_NON_EXISTING_CLASSES = true;
       
   517         CreateSymbols.EXTENSION = ".class";
       
   518 
       
   519         testGenerate(ver7Jar, ver8Jar, ctSym, "8", classes.toAbsolutePath().toString());
       
   520 
       
   521         return classes;
       
   522     }
       
   523 
       
   524     boolean includeAll = true;
       
   525 
       
   526     void testGenerate(Path jar7, Path jar8, Path descDest, String version, String classDest) throws IOException {
       
   527         deleteRecursively(descDest);
       
   528 
       
   529         List<VersionDescription> versions =
       
   530                 Arrays.asList(new VersionDescription(jar7.toAbsolutePath().toString(), "7", null),
       
   531                               new VersionDescription(jar8.toAbsolutePath().toString(), "8", "7"));
       
   532 
       
   533         ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) {
       
   534             @Override public boolean accepts(String className) {
       
   535                 return true;
       
   536             }
       
   537         };
       
   538         new CreateSymbols() {
       
   539             @Override
       
   540             protected boolean includeEffectiveAccess(ClassList classes, ClassDescription clazz) {
       
   541                 return includeAll ? true : super.includeEffectiveAccess(classes, clazz);
       
   542             }
       
   543         }.createBaseLine(versions, acceptAll, descDest, null);
       
   544         Path symbolsDesc = descDest.resolve("symbols");
       
   545         try (Writer symbolsFile = Files.newBufferedWriter(symbolsDesc)) {
       
   546             symbolsFile.write("generate platforms 7:8");
       
   547             symbolsFile.write(System.lineSeparator());
       
   548             symbolsFile.write("platform version 7 files java.base-7.sym.txt");
       
   549             symbolsFile.write(System.lineSeparator());
       
   550             symbolsFile.write("platform version 8 base 7 files java.base-8.sym.txt");
       
   551             symbolsFile.write(System.lineSeparator());
       
   552         }
       
   553         new CreateSymbols().createSymbols(symbolsDesc.toAbsolutePath().toString(), classDest, CtSymKind.JOINED_VERSIONS);
       
   554     }
       
   555 
       
   556     void compileAndPack(Path output, Path outputFile, String... code) throws Exception {
       
   557         ToolBox tb = new ToolBox();
       
   558         Path scratch = output.resolve("temp");
       
   559         deleteRecursively(scratch);
       
   560         Files.createDirectories(scratch);
       
   561         System.err.println(Arrays.asList(code));
       
   562         tb.new JavacTask().sources(code).options("-d", scratch.toAbsolutePath().toString()).run(ToolBox.Expect.SUCCESS);
       
   563         List<String> classFiles = collectClassFile(scratch);
       
   564         try (Writer out = Files.newBufferedWriter(outputFile)) {
       
   565             for (String classFile : classFiles) {
       
   566                 try (InputStream in = Files.newInputStream(scratch.resolve(classFile))) {
       
   567                     int read;
       
   568 
       
   569                     while ((read = in.read()) != (-1)) {
       
   570                         out.write(String.format("%02x", read));
       
   571                     }
       
   572 
       
   573                     out.write("\n");
       
   574                 }
       
   575             }
       
   576         }
       
   577     }
       
   578 
       
   579     List<String> collectClassFile(Path root) throws IOException {
       
   580         try (Stream<Path> files = Files.walk(root)) {
       
   581             return files.filter(p -> Files.isRegularFile(p))
       
   582                         .filter(p -> p.getFileName().toString().endsWith(".class"))
       
   583                         .map(p -> root.relativize(p).toString())
       
   584                         .collect(Collectors.toList());
       
   585         }
       
   586     }
       
   587 
       
   588     void deleteRecursively(Path dir) throws IOException {
       
   589         Files.walkFileTree(dir, new FileVisitor<Path>() {
       
   590             @Override
       
   591             public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
       
   592                 return FileVisitResult.CONTINUE;
       
   593             }
       
   594             @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
       
   595                 Files.delete(file);
       
   596                 return FileVisitResult.CONTINUE;
       
   597             }
       
   598             @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
       
   599                 return FileVisitResult.CONTINUE;
       
   600             }
       
   601             @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
       
   602                 Files.delete(dir);
       
   603                 return FileVisitResult.CONTINUE;
       
   604             }
       
   605         });
       
   606     }
       
   607 
       
   608     @Retention(RetentionPolicy.RUNTIME)
       
   609     @interface Test {
       
   610     }
       
   611 }