| /* | |
| * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* | |
| * @test | |
| * @bug 8234808 | |
| * | |
| * @library /test/lib | |
| * @run main/othervm JdbOptions | |
| */ | |
| import jdk.test.lib.Platform; | |
| import lib.jdb.Jdb; | |
| import lib.jdb.JdbCommand; | |
| import jdk.test.lib.process.OutputAnalyzer; | |
| import java.io.IOException; | |
| import java.io.PrintStream; | |
| import java.lang.management.ManagementFactory; | |
| import java.nio.charset.StandardCharsets; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| import java.util.UUID; | |
| import java.util.stream.Collectors; | |
| class JbdOptionsTarg { | |
| static final String OK_MSG = "JbdOptionsTarg: OK"; | |
| static String argString(String s) { | |
| return "arg >" + s + "<"; | |
| } | |
| static String propString(String name, String value) { | |
| return "prop[" + name + "] = >" + value + "<"; | |
| } | |
| /** | |
| * 1st argument is a filename to redirect application output, | |
| * the rest are names of the properties to dump. | |
| */ | |
| public static void main(String[] args) throws IOException { | |
| String outFile = args[0]; | |
| try (PrintStream out = new PrintStream(outFile, StandardCharsets.UTF_8)) { | |
| out.println(OK_MSG); | |
| // print all args | |
| List<String> vmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); | |
| for (String s : vmArgs) { | |
| out.println(argString(s)); | |
| } | |
| // print requested sys.props (skip 1st arg which is output filename) | |
| for (int i=1; i < args.length; i++) { | |
| String p = args[i]; | |
| out.println(propString(p, System.getProperty(p))); | |
| } | |
| } | |
| } | |
| } | |
| public class JdbOptions { | |
| private static final String outFilename = UUID.randomUUID().toString() + ".out"; | |
| private static final Path outPath = Paths.get(outFilename); | |
| private static final String targ = JbdOptionsTarg.class.getName(); | |
| public static void main(String[] args) throws Exception { | |
| // the simplest case | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-client -XX:+PrintVMOptions" | |
| + ",main=" + targ + " " + outFilename) | |
| .expectedArg("-XX:+PrintVMOptions"); | |
| // pass property through 'options' | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo'" | |
| + ",main=" + targ + " " + outFilename + " boo") | |
| .expectedProp("boo", "foo"); | |
| // property with spaces | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-Dboo=foo 2\"" | |
| + ",main=" + targ + " " + outFilename + " boo") | |
| .expectedProp("boo", "foo 2"); | |
| // property with spaces (with single quotes) | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo 2'" | |
| + ",main=" + targ + " " + outFilename + " boo") | |
| .expectedProp("boo", "foo 2"); | |
| // properties with spaces (with single quotes) | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-Dboo=foo '-Dboo2=foo 2'" | |
| + ",main=" + targ + " " + outFilename + " boo boo2") | |
| .expectedProp("boo", "foo") | |
| .expectedProp("boo2", "foo 2"); | |
| // 'options' contains commas - values are quoted (double quotes) | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-client\" \"-XX:+PrintVMOptions\"" | |
| + " -XX:+IgnoreUnrecognizedVMOptions" | |
| + " \"-XX:StartFlightRecording:dumponexit=true,maxsize=500M\" \"-XX:FlightRecorderOptions:repository=jfrrep\"" | |
| + ",main=" + targ + " " + outFilename) | |
| .expectedArg("-XX:StartFlightRecording:dumponexit=true,maxsize=500M") | |
| .expectedArg("-XX:FlightRecorderOptions:repository=jfrrep"); | |
| // 'options' contains commas - values are quoted (single quotes) | |
| test("-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-client' '-XX:+PrintVMOptions'" | |
| + " -XX:+IgnoreUnrecognizedVMOptions" | |
| + " '-XX:StartFlightRecording:dumponexit=true,maxsize=500M' '-XX:FlightRecorderOptions:repository=jfrrep'" | |
| + ",main=" + targ + " " + outFilename) | |
| .expectedArg("-XX:StartFlightRecording:dumponexit=true,maxsize=500M") | |
| .expectedArg("-XX:FlightRecorderOptions:repository=jfrrep"); | |
| // java options are specified in 2 ways, with and without spaces | |
| // options are quoted by using single and double quotes. | |
| test("-Dprop1=val1", | |
| "-Dprop2=val 2", | |
| "-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-Dprop3=val3 '-Dprop4=val 4'" | |
| + " -XX:+IgnoreUnrecognizedVMOptions" | |
| + " \"-XX:StartFlightRecording:dumponexit=true,maxsize=500M\"" | |
| + " '-XX:FlightRecorderOptions:repository=jfrrep'" | |
| + ",main=" + targ + " " + outFilename + " prop1 prop2 prop3 prop4") | |
| .expectedProp("prop1", "val1") | |
| .expectedProp("prop2", "val 2") | |
| .expectedProp("prop3", "val3") | |
| .expectedProp("prop4", "val 4") | |
| .expectedArg("-XX:StartFlightRecording:dumponexit=true,maxsize=500M") | |
| .expectedArg("-XX:FlightRecorderOptions:repository=jfrrep"); | |
| // -R is tested to see if options are passed through. | |
| test("-R-Dprop1=val1", | |
| "-R-Dprop2=val 2", | |
| "-R-Xmixed", | |
| "-R--add-modules", "-Rjdk.attach", | |
| "-R-Xcheck:jni", | |
| "-R--enable-preview", | |
| "-connect", | |
| "com.sun.jdi.CommandLineLaunch:vmexec=java,main=" + targ + " " + outFilename + " prop1 prop2") | |
| .expectedProp("prop1", "val1") | |
| .expectedProp("prop2", "val 2") | |
| .expectedArg("-Xmixed") | |
| .expectedArg("--add-modules=jdk.attach") | |
| .expectedArg("-Xcheck:jni") | |
| .expectedArg("--enable-preview"); | |
| } | |
| private static class TestResult { | |
| OutputAnalyzer out; | |
| TestResult(OutputAnalyzer output) { | |
| out = output; | |
| } | |
| TestResult expectedArg(String s) { | |
| out.shouldContain(JbdOptionsTarg.argString(s)); | |
| return this; | |
| } | |
| TestResult expectedProp(String name, String value) { | |
| out.shouldContain(JbdOptionsTarg.propString(name, value)); | |
| return this; | |
| } | |
| } | |
| private static TestResult test(String... args) throws Exception { | |
| System.out.println(); | |
| System.out.println("...testcase..."); | |
| if (Platform.isWindows()) { | |
| // on Windows we need to escape quotes | |
| args = Arrays.stream(args) | |
| .map(s -> s.replace("\"", "\\\"")) | |
| .toArray(String[]::new); | |
| } | |
| try (Jdb jdb = new Jdb(args)) { | |
| jdb.waitForSimplePrompt(1024, true); // 1024 lines should be enough | |
| jdb.command(JdbCommand.run().allowExit()); | |
| } | |
| String output = Files.readAllLines(outPath, StandardCharsets.UTF_8).stream() | |
| .collect(Collectors.joining(System.getProperty("line.separator"))); | |
| Files.deleteIfExists(outPath); | |
| System.out.println("Debuggee output: ["); | |
| System.out.println(output); | |
| System.out.println("]"); | |
| OutputAnalyzer out = new OutputAnalyzer(output); | |
| return new TestResult(out); | |
| } | |
| } |