1 /* 2 * Copyright (c) 2016, 2018, 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.* foo/* 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.InputStream; 41 import java.nio.file.Path; 42 import java.nio.file.Paths; 43 import java.util.stream.Stream; 44 45 public class MultiReleaseJar { 46 Path mrjar; 47 String testJdk; 48 String fileSep; 49 Path cmdPath; 50 51 @BeforeClass 52 public void initialize() throws Exception { 53 String testClassPath = System.getProperty("test.class.path", ""); 54 mrjar = Stream.of(testClassPath.split(File.pathSeparator)) 55 .map(Paths::get) 56 .filter(e -> e.endsWith("mrjar")) 57 .findAny() 58 .orElseThrow(() -> new InternalError("mrjar not found")); 59 testJdk = System.getProperty("test.jdk"); 60 fileSep = System.getProperty("file.separator"); 61 cmdPath = Paths.get(testJdk, "bin"); 62 } 63 64 @Test 65 public void basic() throws Exception { 66 // build Version.jar, Version_9.jar and main.jar 67 Result r = run("jar -cf Version.jar -C base test --release 9 -C 9 test --release 10 -C 10 test"); 68 checkResult(r); 69 70 r = run("jar -cf Version_9.jar -C base test --release 9 -C 9 test"); 71 checkResult(r); 72 73 r = run("jar -cf Main.jar test/Main.class"); 74 checkResult(r); 75 76 // try out a bunch of things 77 r = run("jdeps --multi-release 9 -v missing.jar"); 78 checkResult(r, false, "Warning: Path does not exist: missing.jar"); 79 80 r = run("jdeps -v Version.jar"); 81 checkResult(r, false, "--multi-release option is not set"); 82 83 r = run("jdeps --multi-release base -v Version.jar"); 84 checkResult(r, true, 85 "Version.jar ->", 86 "test.Version", 87 "test.Version" 88 ); 89 90 r = run("jdeps --multi-release 9 -v Version.jar"); 91 checkResult(r, true, 92 "Version.jar ->", 93 "9/test.NonPublic", 94 "9/test.NonPublic", 95 "9/test.Version", 96 "9/test.Version", 97 "9/test.Version", 98 "9/test.Version" 99 ); 100 101 r = run("jdeps --multi-release 10 -v Version.jar"); 102 checkResult(r, true, 103 "Version.jar ->", 104 "10/test.Version", 105 "10/test.Version", 106 "10/test.Version", 107 "10/test.Version", 108 "9/test.NonPublic", 109 "9/test.NonPublic" 110 ); 111 112 r = run("jdeps --multi-release 8 -v Version.jar"); 113 checkResult(r, false, "Error: invalid argument for option: 8"); 114 115 r = run("jdeps --multi-release 9.1 -v Version.jar"); 116 checkResult(r, false, "Error: invalid argument for option: 9.1"); 117 118 runJdeps("test/Main.class"); 119 runJdeps("Main.jar"); 120 } 121 122 123 private void runJdeps(String path) throws Exception { 124 Result r = run("jdeps -v -R -cp Version.jar " + path); 125 checkResult(r, false, "--multi-release option is not set"); 126 127 r = run("jdeps -v -R -cp Version.jar -multi-release 9 " + path); 128 checkResult(r, false, 129 "Error: unknown option: -multi-release", 130 "Usage: jdeps <options> <path", 131 "use --help" 132 ); 133 134 r = run("jdeps -v -R -cp Version.jar --multi-release 9 " + path); 135 136 String name = path; 137 int index = path.lastIndexOf('/'); 138 if (index >= 0) { 139 name = path.substring(index + 1, path.length()); 140 } 141 checkResult(r, true, 142 name + " ->", 143 name + " ->", 144 "test.Main", 145 "test.Main", 146 "test.Main", 147 "Version.jar ->", 148 "9/test.NonPublic", 149 "9/test.NonPublic", 150 "9/test.Version", 151 "9/test.Version", 152 "9/test.Version", 153 "9/test.Version" 154 ); 155 156 r = run("jdeps -v -R -cp Version.jar --multi-release 10 " + path); 157 checkResult(r, true, 158 name + " ->", 159 name + " ->", 160 "test.Main", 161 "test.Main", 162 "test.Main", 163 "Version.jar ->", 164 "10/test.Version", 165 "10/test.Version", 166 "10/test.Version", 167 "10/test.Version", 168 "9/test.NonPublic", 169 "9/test.NonPublic" 170 ); 171 172 r = run("jdeps -v -R -cp Version.jar --multi-release base " + path); 173 checkResult(r, true, 174 name + " ->", 175 name + " ->", 176 "test.Main", 177 "test.Main", 178 "test.Main", 179 "Version.jar ->", 180 "test.Version", 181 "test.Version" 182 ); 183 184 r = run("jdeps -v -R -cp Version.jar --multi-release 9.1 " + path); 185 checkResult(r, false, "Error: invalid argument for option: 9.1"); 186 187 // Version_9.jar does not have any version 10 entry 188 r = run("jdeps -v -R -cp Version_9.jar --multi-release 10 " + path); 189 checkResult(r, true, 190 name + " ->", 191 name + " ->", 192 "test.Main", 193 "test.Main", 194 "test.Main", 195 "Version_9.jar ->", 196 "9/test.NonPublic", 197 "9/test.NonPublic", 198 "9/test.Version", 199 "9/test.Version", 200 "9/test.Version", 201 "9/test.Version" 202 ); 203 } 204 205 @Test 206 public void ps_and_qs() throws Exception { 207 // build the jar file 208 Result r = run("jar -cf PQ.jar -C base p --release 9 -C v9 p -C v9 q --release 10 -C v10 q"); 209 checkResult(r); 210 211 r = run("jdeps -v -R -cp PQ.jar --multi-release base PQ.jar"); 212 checkResult(r, true, 213 "PQ.jar -> java.base", 214 "p.Foo" 215 ); 216 217 r = run("jdeps -v -R -cp PQ.jar --multi-release 9 PQ.jar"); 218 checkResult(r, true, 219 "PQ.jar -> java.base", 220 "9/p.Foo", 221 "9/p.Foo", 222 "9/q.Bar" 223 ); 224 225 226 r = run("jdeps -v -R -cp PQ.jar --multi-release 10 PQ.jar"); 227 checkResult(r, true, 228 "PQ.jar -> java.base", 229 "10/q.Bar", 230 "10/q.Bar", 231 "10/q.Gee", 232 "9/p.Foo", 233 "9/p.Foo" 234 ); 235 } 236 237 @Test 238 public void modularJar() throws Exception { 239 Result r = run("jar -cf foo.jar -C base p"); 240 checkResult(r); 241 242 Path foo = Paths.get(System.getProperty("test.classes")).resolve("modules").resolve("foo"); 243 r = run("jar -uf foo.jar --release 9 -C " + foo.toString() + " module-info.class --release 10 -C v10 q"); 244 checkResult(r); 245 246 r = run("jdeps -v --multi-release 10 --module-path foo.jar -m foo"); 247 checkResult(r, true, 248 "foo", // module name 249 "foo.jar", // the path to foo.jar 250 "requires mandated java.base", // module dependences 251 "foo -> java.base", 252 "10/q.Bar", 253 "10/q.Bar", 254 "10/q.Gee", 255 "p.Foo" 256 ); 257 258 r = run("jdeps --multi-release 9 --module-path foo.jar Main.jar"); 259 checkResult(r, true, 260 "Main.jar ->", 261 "test", 262 "foo", // module name 263 "foo.jar", // the path to foo.jar 264 "requires mandated java.base", // module dependences 265 "foo -> java.base", 266 "p" 267 ); 268 269 r = run("jdeps --multi-release 10 --module-path foo.jar Main.jar"); 270 checkResult(r, true, 271 "Main.jar ->", 272 "test", 273 "foo", // module name 274 "foo.jar", // the path to foo.jar 275 "requires mandated java.base", // module dependences 276 "foo -> java.base", 277 "p", 278 "q" 279 ); 280 } 281 282 static class Result { 283 final String cmd; 284 final int rc; 285 final String out; 286 final String err; 287 Result(String cmd, int rc, String out, String err) { 288 this.cmd = cmd; 289 this.rc = rc; 290 this.out = out; 291 this.err = err; 292 } 293 } 294 295 Result run(String cmd) throws Exception { 296 String[] cmds = cmd.split(" +"); 297 cmds[0] = cmdPath.resolve(cmds[0]).toString(); 298 ProcessBuilder pb = new ProcessBuilder(cmds); 299 pb.directory(mrjar.toFile()); 300 Process p = null; 301 try { 302 p = pb.start(); 303 p.waitFor(); 304 305 String out; 306 try (InputStream is = p.getInputStream()) { 307 out = new String(is.readAllBytes()); 308 } 309 String err; 310 try (InputStream is = p.getErrorStream()) { 311 err = new String(is.readAllBytes()); 312 } 313 return new Result(cmd, p.exitValue(), out, err); 314 } catch (Throwable t) { 315 if (p != null) { 316 p.destroyForcibly().waitFor(); 317 } 318 throw t; 319 } 320 } 321 322 void checkResult(Result r) throws Exception { 323 System.out.println(r.cmd); 324 System.out.println(r.out); 325 if (r.rc != 0) { 326 System.out.println(r.err); 327 throw new Exception("rc=" + r.rc); 328 } 329 System.out.println(); 330 } 331 332 void checkResult(Result r, boolean checkrc, String... lines) throws Exception { 333 System.out.println(r.cmd); 334 System.out.println(r.out); 335 if (checkrc && r.rc != 0) { 336 System.out.println(r.err); 337 throw new Exception("rc=" + r.rc); 338 } 339 String[] out = r.out.split("\r?\n"); 340 Assert.assertEquals(out.length, lines.length); 341 int n = 0; 342 for (String line : lines) { 343 Assert.assertTrue(out[n++].contains(line), "\"" + line + "\""); 344 } 345 System.out.println(); 346 } 347 }