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