1 /*
   2  * Copyright (c) 2016, 2017, 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 8153654 8176333
  27  * @summary Tests for jdeps tool with multi-release jar files
  28  * @modules jdk.jdeps/com.sun.tools.jdeps
  29  * @library mrjar mrjar/base mrjar/9 mrjar/10 mrjar/v9 mrjar/v10
  30  * @build test.* p.* q.*
  31  * @run testng MultiReleaseJar
  32  */
  33 
  34 import org.testng.Assert;
  35 import org.testng.annotations.AfterClass;
  36 import org.testng.annotations.BeforeClass;
  37 import org.testng.annotations.Test;
  38 
  39 import java.io.File;
  40 import java.io.IOException;
  41 import java.io.InputStream;
  42 import java.nio.file.Path;
  43 import java.nio.file.Paths;
  44 import java.util.concurrent.TimeUnit;
  45 import java.util.stream.Stream;
  46 
  47 public class MultiReleaseJar {
  48     Path mrjar;
  49     String testJdk;
  50     String fileSep;
  51     Path cmdPath;
  52 
  53     @BeforeClass
  54     public void initialize() throws Exception {
  55         String testClassPath = System.getProperty("test.class.path", "");
  56         mrjar = Stream.of(testClassPath.split(File.pathSeparator))
  57                 .map(Paths::get)
  58                 .filter(e -> e.endsWith("mrjar"))
  59                 .findAny()
  60                 .orElseThrow(() -> new InternalError("mrjar not found"));
  61         testJdk = System.getProperty("test.jdk");
  62         fileSep = System.getProperty("file.separator");
  63         cmdPath = Paths.get(testJdk, "bin");
  64     }
  65 
  66     @Test
  67     public void basic() throws Exception {
  68         // build the jar file
  69         Result r = run("jar -cf Version.jar -C base test --release 9 -C 9 test --release 10 -C 10 test");
  70         checkResult(r);
  71 
  72         // try out a bunch of things
  73         r = run("jdeps --multi-release 9  -v missing.jar");
  74         checkResult(r, false, "Warning: Path does not exist: missing.jar");
  75 
  76         r = run("jdeps -v Version.jar");
  77         checkResult(r, false, "--multi-release option is not set");
  78 
  79         r = run("jdeps --multi-release base  -v Version.jar");
  80         checkResult(r, true,
  81                 "Version.jar ->",
  82                 "test.Version",
  83                 "test.Version"
  84         );
  85 
  86         r = run("jdeps --multi-release 9  -v Version.jar");
  87         checkResult(r, true,
  88                 "Version.jar ->",
  89                 "9/test.NonPublic",
  90                 "9/test.NonPublic",
  91                 "9/test.Version",
  92                 "9/test.Version",
  93                 "9/test.Version",
  94                 "9/test.Version"
  95         );
  96 
  97         r = run("jdeps --multi-release 10  -v Version.jar");
  98         checkResult(r, true,
  99                 "Version.jar ->",
 100                 "10/test.Version",
 101                 "10/test.Version",
 102                 "10/test.Version",
 103                 "10/test.Version",
 104                 "9/test.NonPublic",
 105                 "9/test.NonPublic"
 106         );
 107 
 108         r = run("jdeps --multi-release 8  -v Version.jar");
 109         checkResult(r, false, "Error: invalid argument for option: 8");
 110 
 111         r = run("jdeps --multi-release 9.1  -v Version.jar");
 112         checkResult(r, false, "Error: invalid argument for option: 9.1");
 113 
 114         r = run("jdeps -v -R -cp Version.jar test/Main.class");
 115         checkResult(r, false, "--multi-release option is not set");
 116 
 117         r = run("jdeps -v -R -cp Version.jar -multi-release 9 test/Main.class");
 118         checkResult(r, false,
 119                 "Error: unknown option: -multi-release",
 120                 "Usage: jdeps <options> <path",
 121                 "use -h, -?, -help, or --help"
 122         );
 123 
 124         r = run("jdeps -v -R -cp Version.jar --multi-release 9 test/Main.class");
 125         checkResult(r, true,
 126                 "Main.class ->",
 127                 "Main.class ->",
 128                 "test.Main",
 129                 "test.Main",
 130                 "test.Main",
 131                 "Version.jar ->",
 132                 "9/test.NonPublic",
 133                 "9/test.NonPublic",
 134                 "9/test.Version",
 135                 "9/test.Version",
 136                 "9/test.Version",
 137                 "9/test.Version"
 138         );
 139 
 140         r = run("jdeps -v -R -cp Version.jar --multi-release 10 test/Main.class");
 141         checkResult(r, true,
 142                 "Main.class ->",
 143                 "Main.class ->",
 144                 "test.Main",
 145                 "test.Main",
 146                 "test.Main",
 147                 "Version.jar ->",
 148                 "10/test.Version",
 149                 "10/test.Version",
 150                 "10/test.Version",
 151                 "10/test.Version",
 152                 "9/test.NonPublic",
 153                 "9/test.NonPublic"
 154         );
 155 
 156         r = run("jdeps -v -R -cp Version.jar --multi-release base test/Main.class");
 157         checkResult(r, true,
 158                 "Main.class ->",
 159                 "Main.class ->",
 160                 "test.Main",
 161                 "test.Main",
 162                 "test.Main",
 163                 "Version.jar ->",
 164                 "test.Version",
 165                 "test.Version"
 166         );
 167 
 168         r = run("jdeps -v -R -cp Version.jar --multi-release 9.1 test/Main.class");
 169         checkResult(r, false, "Error: invalid argument for option: 9.1");
 170 
 171         // Rebuild jar without version 10
 172         r = run("jar -cf Version.jar -C base test --release 9 -C 9 test");
 173         checkResult(r);
 174 
 175         // but ask for version 10
 176         r = run("jdeps -v -R -cp Version.jar --multi-release 10 test/Main.class");
 177         checkResult(r, true,
 178                 "Main.class ->",
 179                 "Main.class ->",
 180                 "test.Main",
 181                 "test.Main",
 182                 "test.Main",
 183                 "Version.jar ->",
 184                 "9/test.NonPublic",
 185                 "9/test.NonPublic",
 186                 "9/test.Version",
 187                 "9/test.Version",
 188                 "9/test.Version",
 189                 "9/test.Version"
 190         );
 191     }
 192 
 193     @Test
 194     public void ps_and_qs() throws Exception {
 195         // build the jar file
 196         Result r = run("jar -cf PQ.jar -C base p --release 9 -C v9 p -C v9 q --release 10 -C v10 q");
 197         checkResult(r);
 198 
 199         r = run("jdeps -v -R -cp PQ.jar --multi-release base PQ.jar");
 200         checkResult(r, true,
 201                 "PQ.jar -> java.base",
 202                 "p.Foo"
 203         );
 204 
 205         r = run("jdeps -v -R -cp PQ.jar --multi-release 9 PQ.jar");
 206         checkResult(r, true,
 207                 "PQ.jar -> java.base",
 208                 "9/p.Foo",
 209                 "9/p.Foo",
 210                 "9/q.Bar"
 211         );
 212 
 213 
 214         r = run("jdeps -v -R -cp PQ.jar --multi-release 10 PQ.jar");
 215         checkResult(r, true,
 216                 "PQ.jar -> java.base",
 217                 "10/q.Bar",
 218                 "10/q.Bar",
 219                 "10/q.Gee",
 220                 "9/p.Foo",
 221                 "9/p.Foo"
 222         );
 223     }
 224 
 225     static class Result {
 226         final String cmd;
 227         final int rc;
 228         final String out;
 229         final String err;
 230         Result(String cmd, int rc, String out, String err) {
 231             this.cmd = cmd;
 232             this.rc = rc;
 233             this.out = out;
 234             this.err = err;
 235         }
 236     }
 237 
 238     Result run(String cmd) throws Exception {
 239         String[] cmds = cmd.split(" +");
 240         cmds[0] = cmdPath.resolve(cmds[0]).toString();
 241         ProcessBuilder pb = new ProcessBuilder(cmds);
 242         pb.directory(mrjar.toFile());
 243         Process p = null;
 244         try {
 245             p = pb.start();
 246             p.waitFor();
 247 
 248             String out;
 249             try (InputStream is = p.getInputStream()) {
 250                 out = new String(is.readAllBytes());
 251             }
 252             String err;
 253             try (InputStream is = p.getErrorStream()) {
 254                 err = new String(is.readAllBytes());
 255             }
 256             return new Result(cmd, p.exitValue(), out, err);
 257         } catch (Throwable t) {
 258             if (p != null) {
 259                 p.destroyForcibly().waitFor();
 260             }
 261             throw t;
 262         }
 263     }
 264 
 265     void checkResult(Result r) throws Exception {
 266         System.out.println(r.cmd);
 267         System.out.println(r.out);
 268         if (r.rc != 0) {
 269             System.out.println(r.err);
 270             throw new Exception("rc=" + r.rc);
 271         }
 272         System.out.println();
 273     }
 274 
 275     void checkResult(Result r, boolean checkrc, String... lines) throws Exception {
 276         System.out.println(r.cmd);
 277         System.out.println(r.out);
 278         if (checkrc && r.rc != 0) {
 279             System.out.println(r.err);
 280             throw new Exception("rc=" + r.rc);
 281         }
 282         String[] out = r.out.split("\r?\n");
 283         Assert.assertEquals(out.length, lines.length);
 284         int n = 0;
 285         for (String line : lines) {
 286             Assert.assertTrue(out[n++].contains(line), "\"" + line + "\"");
 287         }
 288         System.out.println();
 289     }
 290 }