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 import java.io.File;
  24 import java.io.IOException;
  25 import java.util.ArrayList;
  26 import java.util.List;
  27 
  28 /*
  29  * @test
  30  * @bug 8066272
  31  * @summary tests a simple multi-versioned jar file
  32  * @compile -XDignore.symbol.file Utils.java MultiVersion.java
  33  * @run main MultiVersion
  34  * @author ksrini
  35  */
  36 
  37 public class MultiVersion {
  38     private static final File cwd = new File(".");
  39     private static int pass = 0;
  40     private static int fail = 0;
  41 
  42     public static void main(String... args) throws Exception {
  43         new MultiVersion().run();
  44     }
  45 
  46     void run() throws Exception {
  47         List<TestCase> testCases = new ArrayList<>();
  48         testCases.add(new TestCase1());
  49         testCases.add(new TestCase2());
  50         for (TestCase tc : testCases) {
  51             tc.run();
  52         }
  53         if (fail > 0) {
  54             throw new Exception(fail + "/" + testCases.size() + " tests fails");
  55         } else {
  56             System.out.println("All tests(" + pass + ") passes");
  57         }
  58     }
  59 
  60     /*
  61      * An abstract class to eliminate test boiler plating.
  62      */
  63     static abstract class TestCase {
  64         final File tcwd;
  65         final File metaInfDir;
  66         final File versionsDir;
  67         final File manifestFile;
  68 
  69         TestCase(String directory) throws IOException {
  70             System.out.println("initializing directories");
  71             tcwd = new File(cwd, directory);
  72             metaInfDir = mkdir(new File(tcwd, "META-INF"));
  73             versionsDir = mkdir(new File(metaInfDir, "versions"));
  74             manifestFile = new File(metaInfDir, "manifest.mf");
  75             List<String> scratch = new ArrayList<>();
  76             scratch.add("Multi-Release: true");
  77             Utils.createFile(manifestFile, scratch);
  78         }
  79 
  80         File mkdir(File f) throws IOException {
  81             if (f.exists() && f.isDirectory() && f.canRead() && f.canWrite()) {
  82                 return f;
  83             }
  84             if (!f.mkdirs()) {
  85                throw new IOException("mkdirs failed: " + f.getAbsolutePath());
  86             }
  87             return f;
  88         }
  89 
  90         abstract void emitClassFiles() throws Exception;
  91 
  92         void run() {
  93             try {
  94                 emitClassFiles();
  95                 // jar the file up
  96                 File testFile = new File(tcwd, "test" + Utils.JAR_FILE_EXT);
  97                 Utils.jar("cvfm",
  98                         testFile.getAbsolutePath(),
  99                         manifestFile.getAbsolutePath(),
 100                         "-C",
 101                         tcwd.getAbsolutePath(),
 102                         ".");
 103 
 104                 File outFile = new File(tcwd, "test-repacked" + Utils.JAR_FILE_EXT);
 105                 List<String> cmdsList = new ArrayList<>();
 106 
 107                 cmdsList.add(Utils.getPack200Cmd());
 108                 cmdsList.add("-J-ea");
 109                 cmdsList.add("-J-esa");
 110                 cmdsList.add("-v");
 111                 cmdsList.add("--repack");
 112                 cmdsList.add(outFile.getAbsolutePath());
 113                 cmdsList.add(testFile.getAbsolutePath());
 114                 List<String> output = Utils.runExec(cmdsList);
 115                 Utils.doCompareVerify(testFile.getAbsoluteFile(), outFile.getAbsoluteFile());
 116                 pass++;
 117             } catch (Exception e) {
 118                 e.printStackTrace(System.err);
 119                 fail++;
 120             }
 121         }
 122     }
 123 
 124     static class TestCase1 extends TestCase {
 125         private TestCase1(String directory) throws IOException {
 126             super(directory);
 127         }
 128 
 129         public TestCase1() throws Exception {
 130             this("case1");
 131         }
 132 
 133         @Override
 134         void emitClassFiles() throws Exception {
 135             emitClassFile("");
 136             emitClassFile("6.0");
 137             emitClassFile("7.0");
 138             emitClassFile("8.0");
 139         }
 140 
 141         /*
 142          * Adds different variants of types
 143          */
 144         void emitClassFile(String version) throws IOException {
 145             final File outDir = mkdir(version.isEmpty()
 146                     ? tcwd
 147                     : new File(versionsDir, version));
 148 
 149             final File srcDir = mkdir(version.isEmpty()
 150                             ? new File(tcwd, "src")
 151                             : new File(new File(versionsDir, version), "src"));
 152 
 153             final String fname = "Foo";
 154             final File srcFile = new File(srcDir, fname + Utils.JAVA_FILE_EXT);
 155             List<String> scratch = new ArrayList<>();
 156 
 157             scratch.add("package pkg;");
 158             switch (version) {
 159                 case "6.0":
 160                     scratch.add("public class Foo {");
 161                     scratch.add("public static final class Bar {}");
 162                     break;
 163                 case "7.0":
 164                     scratch.add("public abstract class Foo {");
 165                     scratch.add("public final class Bar {}");
 166                     break;
 167                 case "8.0":
 168                     scratch.add("public interface Foo {");
 169                     scratch.add("public final class Bar {}");
 170                     break;
 171                 default:
 172                     scratch.add("public class Foo {");
 173                     scratch.add("public final class Bar {}");
 174                     break;
 175             }
 176             scratch.add("}");
 177 
 178             Utils.createFile(srcFile, scratch);
 179             Utils.compiler("-d",
 180                     outDir.getAbsolutePath(),
 181                     srcFile.getAbsolutePath());
 182         }
 183     }
 184 
 185     static class TestCase2 extends TestCase {
 186         private TestCase2(String directory) throws IOException {
 187             super(directory);
 188         }
 189 
 190         TestCase2() throws Exception {
 191             this("case2");
 192         }
 193 
 194         @Override
 195         void emitClassFiles() throws Exception {
 196             emitClassFile("");
 197             emitClassFile("8.0");
 198         }
 199 
 200         /*
 201          * Adds different variants of types and tries to invoke an
 202          * interface or concrete method defined by them.
 203          */
 204         void emitClassFile(String version) throws IOException {
 205 
 206             final File outDir = mkdir(version.isEmpty()
 207                     ? tcwd
 208                     : new File(versionsDir, version));
 209 
 210             final File srcDir = mkdir(version.isEmpty()
 211                     ? new File(tcwd, "src")
 212                     : new File(new File(versionsDir, version), "src"));
 213 
 214             List<String> scratch = new ArrayList<>();
 215             final String fname1 = "Ab";
 216             final File srcFile1 = new File(srcDir, fname1 + Utils.JAVA_FILE_EXT);
 217 
 218             final String fname2 = "AbNormal";
 219             final File srcFile2 = new File(srcDir, fname2 + Utils.JAVA_FILE_EXT);
 220             switch (version) {
 221                 case "8.0":
 222                     scratch.clear();
 223                     scratch.add("import java.io.IOException;");
 224                     scratch.add("public interface " + fname1 + "{");
 225                     scratch.add("    public abstract void close() throws IOException ;");
 226                     scratch.add("}");
 227                     Utils.createFile(srcFile1, scratch);
 228                     break;
 229                 default:
 230                     scratch.clear();
 231                     scratch.add("import java.io.IOException;");
 232                     scratch.add("public abstract class " + fname1 + "{");
 233                     scratch.add("    public abstract void close() throws IOException ;");
 234                     scratch.add("}");
 235                     Utils.createFile(srcFile1, scratch);
 236             }
 237 
 238             scratch.clear();
 239             scratch.add("import java.io.IOException;");
 240             scratch.add("public class " + fname2 + "{");
 241             scratch.add("    public void doSomething(Ab ab) throws IOException {");
 242             scratch.add("       ab.close();");
 243             scratch.add("    }");
 244             scratch.add("}");
 245 
 246             Utils.createFile(srcFile2, scratch);
 247             Utils.compiler("-d",
 248                     outDir.getAbsolutePath(),
 249                     srcFile1.getAbsolutePath(),
 250                     srcFile2.getAbsolutePath());
 251         }
 252     }
 253 }