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(tcwd, "manifest.tmp");
  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                 File outFile = new File(tcwd, "test-repacked" + Utils.JAR_FILE_EXT);
 104                 List<String> cmdsList = new ArrayList<>();
 105 
 106                 cmdsList.add(Utils.getPack200Cmd());
 107                 cmdsList.add("-J-ea");
 108                 cmdsList.add("-J-esa");
 109                 cmdsList.add("-v");
 110                 cmdsList.add("--repack");
 111                 cmdsList.add(outFile.getAbsolutePath());
 112                 cmdsList.add(testFile.getAbsolutePath());
 113                 List<String> output = Utils.runExec(cmdsList);
 114                 Utils.doCompareVerify(testFile.getAbsoluteFile(), outFile.getAbsoluteFile());
 115                 pass++;
 116             } catch (Exception e) {
 117                 e.printStackTrace(System.err);
 118                 fail++;
 119             }
 120         }
 121     }
 122 
 123     static class TestCase1 extends TestCase {
 124         private TestCase1(String directory) throws IOException {
 125             super(directory);
 126         }
 127 
 128         public TestCase1() throws Exception {
 129             this("case1");
 130         }
 131 
 132         @Override
 133         void emitClassFiles() throws Exception {
 134             emitClassFile("");
 135             emitClassFile("7");
 136             emitClassFile("8");
 137             emitClassFile("9");
 138         }
 139 
 140         /*
 141          * Adds different variants of types
 142          */
 143         void emitClassFile(String version) throws IOException {
 144             final File outDir = mkdir(version.isEmpty()
 145                     ? tcwd
 146                     : new File(versionsDir, version));
 147 
 148             final File srcDir = mkdir(version.isEmpty()
 149                             ? new File(tcwd, "src")
 150                             : new File(new File(versionsDir, version), "src"));
 151 
 152             final String fname = "Foo";
 153             final File srcFile = new File(srcDir, fname + Utils.JAVA_FILE_EXT);
 154             List<String> scratch = new ArrayList<>();
 155 
 156             scratch.add("package pkg;");
 157             switch (version) {
 158                 case "7":
 159                     scratch.add("public class Foo {");
 160                     scratch.add("public static final class Bar {}");
 161                     break;
 162                 case "8":
 163                     scratch.add("public abstract class Foo {");
 164                     scratch.add("public final class Bar {}");
 165                     break;
 166                 case "9":
 167                     scratch.add("public interface Foo {");
 168                     scratch.add("public final class Bar {}");
 169                     break;
 170                 default:
 171                     scratch.add("public class Foo {");
 172                     scratch.add("public final class Bar {}");
 173                     break;
 174             }
 175             scratch.add("}");
 176 
 177             Utils.createFile(srcFile, scratch);
 178             Utils.compiler("-d",
 179                     outDir.getAbsolutePath(),
 180                     srcFile.getAbsolutePath());
 181         }
 182     }
 183 
 184     static class TestCase2 extends TestCase {
 185         private TestCase2(String directory) throws IOException {
 186             super(directory);
 187         }
 188 
 189         TestCase2() throws Exception {
 190             this("case2");
 191         }
 192 
 193         @Override
 194         void emitClassFiles() throws Exception {
 195             emitClassFile("");
 196             emitClassFile("8");
 197         }
 198 
 199         /*
 200          * Adds different variants of types and tries to invoke an
 201          * interface or concrete method defined by them.
 202          */
 203         void emitClassFile(String version) throws IOException {
 204 
 205             final File outDir = mkdir(version.isEmpty()
 206                     ? tcwd
 207                     : new File(versionsDir, version));
 208 
 209             final File srcDir = mkdir(version.isEmpty()
 210                     ? new File(tcwd, "src")
 211                     : new File(new File(versionsDir, version), "src"));
 212 
 213             List<String> scratch = new ArrayList<>();
 214             final String fname1 = "Ab";
 215             final File srcFile1 = new File(srcDir, fname1 + Utils.JAVA_FILE_EXT);
 216 
 217             final String fname2 = "AbNormal";
 218             final File srcFile2 = new File(srcDir, fname2 + Utils.JAVA_FILE_EXT);
 219             switch (version) {
 220                 case "8":
 221                     scratch.clear();
 222                     scratch.add("import java.io.IOException;");
 223                     scratch.add("public interface " + fname1 + "{");
 224                     scratch.add("    public abstract void close() throws IOException ;");
 225                     scratch.add("}");
 226                     Utils.createFile(srcFile1, scratch);
 227                     break;
 228                 default:
 229                     scratch.clear();
 230                     scratch.add("import java.io.IOException;");
 231                     scratch.add("public abstract class " + fname1 + "{");
 232                     scratch.add("    public abstract void close() throws IOException ;");
 233                     scratch.add("}");
 234                     Utils.createFile(srcFile1, scratch);
 235             }
 236 
 237             scratch.clear();
 238             scratch.add("import java.io.IOException;");
 239             scratch.add("public class " + fname2 + "{");
 240             scratch.add("    public void doSomething(Ab ab) throws IOException {");
 241             scratch.add("       ab.close();");
 242             scratch.add("    }");
 243             scratch.add("}");
 244 
 245             Utils.createFile(srcFile2, scratch);
 246             Utils.compiler("-d",
 247                     outDir.getAbsolutePath(),
 248                     srcFile1.getAbsolutePath(),
 249                     srcFile2.getAbsolutePath());
 250         }
 251     }
 252 }