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 8159596
27 * @library /lib/testlibrary
28 * @modules jdk.compiler
29 *          jdk.jartool
30 * @build DryRunTest CompilerUtils jdk.testlibrary.ProcessTools
31 * @run testng DryRunTest
32 * @summary Test java --dry-run
33 */
34
35import java.io.File;
36import java.io.IOException;
37import java.nio.file.Files;
38import java.nio.file.Path;
39import java.nio.file.Paths;
40import java.util.spi.ToolProvider;
41
42import jdk.testlibrary.ProcessTools;
43
44import org.testng.annotations.BeforeTest;
45import org.testng.annotations.Test;
46import static org.testng.Assert.*;
47
48
49@Test
50public class DryRunTest {
51
52    private static final String TEST_SRC = System.getProperty("test.src");
53
54    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
55    private static final Path MODS_DIR = Paths.get("mods");
56    private static final Path LIBS_DIR = Paths.get("libs");
57
58    // the module name of the test module
59    private static final String TEST_MODULE = "test";
60    private static final String M_MODULE = "m";
61
62    // the module main class
63    private static final String MAIN_CLASS = "jdk.test.Main";
64    private static final String MAIN_CLINIT_CLASS = "jdk.test.MainWithClinit";
65
66
67    @BeforeTest
68    public void compileTestModule() throws Exception {
69
70        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
71        assertTrue(CompilerUtils.compile(SRC_DIR.resolve(M_MODULE),
72                                         MODS_DIR,
73                                         "--module-source-path", SRC_DIR.toString()));
74
75        assertTrue(CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
76                                         MODS_DIR,
77                                         "--module-source-path", SRC_DIR.toString()));
78
79        Files.createDirectories(LIBS_DIR);
80
81        // create JAR files with no module-info.class
82        assertTrue(jar(M_MODULE, "p/Lib.class") == 0);
83        assertTrue(jar(TEST_MODULE, "jdk/test/Main.class") == 0);
84    }
85
86    /**
87     * Execute "java" with the given arguments, returning the exit code.
88     */
89    private int exec(String... args) throws Exception {
90       return ProcessTools.executeTestJava(args)
91                .outputTo(System.out)
92                .errorTo(System.out)
93                .getExitValue();
94    }
95
96
97    /**
98     * Launch module main
99     */
100    public void testModule() throws Exception {
101        String dir = MODS_DIR.toString();
102        String mid = TEST_MODULE + "/" + MAIN_CLASS;
103
104        // no resolution failure
105        int exitValue = exec("--dry-run", "--module-path", dir, "-m", mid);
106        assertTrue(exitValue == 0);
107    }
108
109    /**
110     * Test dryrun that does not invoke <clinit> of the main class
111     */
112    public void testMainClinit() throws Exception {
113        String dir = MODS_DIR.toString();
114        String mid = TEST_MODULE + "/" + MAIN_CLINIT_CLASS;
115
116        int exitValue = exec("--dry-run", "--module-path", dir, "-m", mid);
117        assertTrue(exitValue == 0);
118
119        // expect the test to fail if main class is initialized
120        exitValue = exec("--module-path", dir, "-m", mid);
121        assertTrue(exitValue != 0);
122    }
123
124    /**
125     * Test non-existence module in --add-modules
126     */
127    public void testNonExistAddModules() throws Exception {
128        String dir = MODS_DIR.toString();
129        String mid = TEST_MODULE + "/" + MAIN_CLASS;
130
131        int exitValue = exec("--dry-run", "--module-path", dir,
132                             "--add-modules", "non.existence",
133                             "-m", mid);
134        assertTrue(exitValue != 0);
135    }
136
137    /**
138     * Launch main class from class path
139     */
140    public void testClassPath() throws Exception {
141        Path testJar = LIBS_DIR.resolve(TEST_MODULE + ".jar");
142        String libs = testJar.toString() + File.pathSeparator +
143                        LIBS_DIR.resolve(M_MODULE + ".jar").toString();
144
145        // test pass with m.jar:test.jar
146        int exitValue = exec("-classpath", libs, MAIN_CLASS);
147        assertTrue(exitValue == 0);
148
149        // m.jar is not on classpath and fails with p.Lib not found
150        exitValue = exec("-classpath", testJar.toString(), MAIN_CLASS);
151        assertTrue(exitValue != 0);
152
153        // dry pass passes since main is not executed
154        exitValue = exec("--dry-run", "-classpath", testJar.toString(), MAIN_CLASS);
155        assertTrue(exitValue == 0);
156    }
157
158    /**
159     * Test automatic modules
160     */
161    public void testAutomaticModule() throws Exception {
162        String libs = LIBS_DIR.resolve(M_MODULE + ".jar").toString() +
163                        File.pathSeparator +
164                        LIBS_DIR.resolve(TEST_MODULE + ".jar").toString();
165        String mid = TEST_MODULE + "/" + MAIN_CLASS;
166
167        // test main method with and without --add-modules mm
168        int exitValue = exec("--module-path", LIBS_DIR.toString(),
169                             "-m", mid);
170        assertTrue(exitValue == 0);
171    }
172
173    /**
174     * module m not found
175     */
176    public void testMissingModule() throws Exception {
177        String subdir = MODS_DIR.resolve(TEST_MODULE).toString();
178        String mid = TEST_MODULE + "/" + MAIN_CLASS;
179
180        // resolution failure
181        int exitValue = exec("--dry-run", "--module-path", subdir, "-m", mid);
182        assertTrue(exitValue != 0);
183    }
184
185    private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
186        .orElseThrow(() ->
187            new RuntimeException("jar tool not found")
188        );
189
190    private static int jar(String name, String entries) throws IOException {
191        Path jar = LIBS_DIR.resolve(name + ".jar");
192
193        // jar --create ...
194        String classes = MODS_DIR.resolve(name).toString();
195        String[] args = {
196            "--create",
197            "--file=" + jar,
198            "-C", classes, entries
199        };
200        return JAR_TOOL.run(System.out, System.out, args);
201    }
202}
203