1 /*
2  * Copyright (c) 2014, 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 import com.sun.tools.attach.*;
25 
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.util.Properties;
29 import java.util.List;
30 import java.io.File;
31 
32 import jdk.test.lib.thread.ProcessThread;
33 import jdk.test.lib.process.OutputAnalyzer;
34 import jdk.test.lib.process.ProcessTools;
35 
36 /*
37  * @test
38  * @bug 8033104
39  * @summary Test to make sure attach and jvmstat works correctly when java.io.tmpdir is set
40  *
41  * @library /test/lib
42  * @modules jdk.attach
43  *          jdk.jartool/sun.tools.jar
44  *
45  * @run build Application RunnerUtil
46  * @run main/timeout=200 TempDirTest
47  */
48 
49 /*
50  * This test runs with an extra long timeout since it takes a really long time with -Xcomp
51  * when starting many processes.
52  */
53 
54 public class TempDirTest {
55 
56     private static long startTime;
57 
main(String args[])58     public static void main(String args[]) throws Throwable {
59 
60         startTime = System.currentTimeMillis();
61 
62         Path clientTmpDir = Files.createTempDirectory("TempDirTest-client");
63         clientTmpDir.toFile().deleteOnExit();
64         Path targetTmpDir = Files.createTempDirectory("TempDirTest-target");
65         targetTmpDir.toFile().deleteOnExit();
66 
67         // run the test with all possible combinations of setting java.io.tmpdir
68         runExperiment(null, null);
69         runExperiment(clientTmpDir, null);
70         runExperiment(clientTmpDir, targetTmpDir);
71         runExperiment(null, targetTmpDir);
72 
73     }
74 
75     private static int counter = 0;
76 
77     /*
78      * The actual test is in the nested class TestMain.
79      * The responsibility of this class is to:
80      * 1. Start the Application class in a separate process.
81      * 2. Find the pid and shutdown port of the running Application.
82      * 3. Launches the tests in nested class TestMain that will attach to the Application.
83      * 4. Shut down the Application.
84      */
runExperiment(Path clientTmpDir, Path targetTmpDir)85     public static void runExperiment(Path clientTmpDir, Path targetTmpDir) throws Throwable {
86 
87         System.out.print("### Running tests with overridden tmpdir for");
88         System.out.print(" client: " + (clientTmpDir == null ? "no" : "yes"));
89         System.out.print(" target: " + (targetTmpDir == null ? "no" : "yes"));
90         System.out.println(" ###");
91 
92         long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
93         System.out.println("Started after " + elapsedTime + "s");
94 
95         final String pidFile = "TempDirTest.Application.pid-" + counter++;
96         ProcessThread processThread = null;
97         try {
98             String[] tmpDirArg = null;
99             if (targetTmpDir != null) {
100                 tmpDirArg = new String[] {"-Djava.io.tmpdir=" + targetTmpDir};
101             }
102             processThread = RunnerUtil.startApplication(tmpDirArg);
103             launchTests(processThread.getPid(), clientTmpDir);
104         } catch (Throwable t) {
105             System.out.println("TempDirTest got unexpected exception: " + t);
106             t.printStackTrace();
107             throw t;
108         } finally {
109             // Make sure the Application process is stopped.
110             RunnerUtil.stopApplication(processThread);
111         }
112 
113         elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
114         System.out.println("Completed after " + elapsedTime + "s");
115 
116     }
117 
118     /**
119      * Runs the actual tests in nested class TestMain.
120      * The reason for running the tests in a separate process
121      * is that we need to modify the class path and
122      * the -Djava.io.tmpdir property.
123      */
launchTests(long pid, Path clientTmpDir)124     private static void launchTests(long pid, Path clientTmpDir) throws Throwable {
125         final String sep = File.separator;
126 
127         String classpath =
128             System.getProperty("test.class.path", "");
129 
130         String[] tmpDirArg = null;
131         if (clientTmpDir != null) {
132             tmpDirArg = new String [] {"-Djava.io.tmpdir=" + clientTmpDir};
133         }
134 
135         // Arguments : [-Djava.io.tmpdir=] -classpath cp TempDirTest$TestMain pid
136         String[] args = RunnerUtil.concat(
137                 tmpDirArg,
138                 new String[] {
139                     "-classpath",
140                     classpath,
141                     "TempDirTest$TestMain",
142                     Long.toString(pid) });
143         OutputAnalyzer output = ProcessTools.executeTestJvm(args);
144         output.shouldHaveExitValue(0);
145     }
146 
147     /**
148      * This is the actual test. It will attach to the running Application
149      * and perform a number of basic attach tests.
150      */
151     public static class TestMain {
main(String args[])152         public static void main(String args[]) throws Exception {
153             String pid = args[0];
154 
155             // Test 1 - list method should list the target VM
156             System.out.println(" - Test: VirtualMachine.list");
157             List<VirtualMachineDescriptor> l = VirtualMachine.list();
158             boolean found = false;
159             for (VirtualMachineDescriptor vmd: l) {
160                 if (vmd.id().equals(pid)) {
161                     found = true;
162                     break;
163                 }
164             }
165             if (found) {
166                 System.out.println(" - " + pid + " found.");
167             } else {
168                 throw new RuntimeException(pid + " not found in VM list");
169             }
170 
171             // Test 2 - try to attach and verify connection
172 
173             System.out.println(" - Attaching to application ...");
174             VirtualMachine vm = VirtualMachine.attach(pid);
175 
176             System.out.println(" - Test: system properties in target VM");
177             Properties props = vm.getSystemProperties();
178             String value = props.getProperty("attach.test");
179             if (value == null || !value.equals("true")) {
180                 throw new RuntimeException("attach.test property not set");
181             }
182             System.out.println(" - attach.test property set as expected");
183         }
184     }
185 }
186