1 /*
   2  * Copyright (c) 2012, 2015, 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 7124089 7131021 8042469 8066185 8074373
  27  * @summary Checks for Launcher special flags, such as MacOSX specific flags,
  28  *          and JVM NativeMemoryTracking flags.
  29  * @compile -XDignore.symbol.file TestSpecialArgs.java EnvironmentVariables.java
  30  * @run main TestSpecialArgs
  31  */
  32 import java.io.File;
  33 import java.io.FileNotFoundException;
  34 import java.util.HashMap;
  35 import java.util.HashSet;
  36 import java.util.Map;
  37 import java.util.Set;
  38 
  39 public class TestSpecialArgs extends TestHelper {
  40 
  41     public static void main(String... args) throws Exception {
  42         new TestSpecialArgs().run(args);
  43     }
  44 
  45     @Test
  46     void testDocking() {
  47         final Map<String, String> envMap = new HashMap<>();
  48         envMap.put("_JAVA_LAUNCHER_DEBUG", "true");
  49         TestResult tr = doExec(envMap, javaCmd, "-XstartOnFirstThread", "-version");
  50         if (isMacOSX) {
  51             if (!tr.contains("In same thread")) {
  52                 System.out.println(tr);
  53                 throw new RuntimeException("Error: not running in the same thread ?");
  54             }
  55             if (!tr.isOK()) {
  56                 System.out.println(tr);
  57                 throw new RuntimeException("Error: arg was rejected ????");
  58             }
  59         } else {
  60             if (tr.isOK()) {
  61                 System.out.println(tr);
  62                 throw new RuntimeException("Error: argument was accepted ????");
  63             }
  64         }
  65 
  66         tr = doExec(javaCmd, "-Xdock:/tmp/not-available", "-version");
  67         if (isMacOSX) {
  68             if (!tr.isOK()) {
  69                 System.out.println(tr);
  70                 throw new RuntimeException("Error: arg was rejected ????");
  71             }
  72         } else {
  73             if (tr.isOK()) {
  74                 System.out.println(tr);
  75                 throw new RuntimeException("Error: argument was accepted ????");
  76             }
  77         }
  78         // MacOSX specific tests ensue......
  79         if (!isMacOSX) {
  80             return;
  81         }
  82         Set<String> envToRemove = new HashSet<>();
  83         Map<String, String> map = System.getenv();
  84         for (String s : map.keySet()) {
  85             if (s.startsWith("JAVA_MAIN_CLASS_")
  86                     || s.startsWith("APP_NAME_")
  87                     || s.startsWith("APP_ICON_")) {
  88                 envToRemove.add(s);
  89             }
  90         }
  91         runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(),
  92                 "EnvironmentVariables", "JAVA_MAIN_CLASS_*",
  93                 "EnvironmentVariables");
  94 
  95         runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(),
  96                 "-Xdock:name=TestAppName", "EnvironmentVariables",
  97                 "APP_NAME_*", "TestAppName");
  98 
  99         runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(),
 100                 "-Xdock:icon=TestAppIcon", "EnvironmentVariables",
 101                 "APP_ICON_*", "TestAppIcon");
 102     }
 103 
 104     void runTest(Set<String> envToRemove, String... args) {
 105         TestResult tr = doExec(null, envToRemove, args);
 106         if (!tr.isOK()) {
 107             System.err.println(tr.toString());
 108             throw new RuntimeException("Test Fails");
 109         }
 110     }
 111 
 112     @Test
 113     void testNativeMemoryTracking() {
 114         final Map<String, String> envMap = new HashMap<>();
 115         envMap.put("_JAVA_LAUNCHER_DEBUG", "true");
 116         TestResult tr;
 117         /*
 118          * test argument : -XX:NativeMemoryTracking=value
 119          * A JVM flag, comsumed by the JVM, but requiring launcher
 120          * to set an environmental variable if and only if value is supplied.
 121          * Test and order:
 122          * 1) execute with valid parameter: -XX:NativeMemoryTracking=MyValue
 123          *    a) check for correct env variable name: "NMT_LEVEL_" + pid
 124          *    b) check that "MyValue" was found in local env.
 125          * 2) execute with invalid parameter: -XX:NativeMemoryTracking=
 126          *    !) Won't find "NativeMemoryTracking:"
 127          *       Code to create env variable not executed.
 128          * 3) execute with invalid parameter: -XX:NativeMemoryTracking
 129          *    !) Won't find "NativeMemoryTracking:"
 130          *       Code to create env variable not executed.
 131          * 4) give and invalid value and check to make sure JVM commented
 132          */
 133         String launcherPidString = "launcher.pid=";
 134         String envVarPidString = "TRACER_MARKER: NativeMemoryTracking: env var is NMT_LEVEL_";
 135         String NMT_Option_Value = "off";
 136         String myClassName = "helloworld";
 137         boolean haveLauncherPid = false;
 138 
 139         // === Run the tests ===
 140         // ---Test 1a
 141         tr = doExec(envMap, javaCmd, "-XX:NativeMemoryTracking=" + NMT_Option_Value,
 142                 "-version");
 143 
 144         // get the PID from the env var we set for the JVM
 145         String envVarPid = null;
 146         for (String line : tr.testOutput) {
 147             if (line.contains(envVarPidString)) {
 148                 int sindex = envVarPidString.length();
 149                 envVarPid = line.substring(sindex);
 150                 break;
 151             }
 152         }
 153         // did we find envVarPid?
 154         if (envVarPid == null) {
 155             System.out.println(tr);
 156             throw new RuntimeException("Error: failed to find env Var Pid in tracking info");
 157         }
 158         // we think we found the pid string.  min test, not "".
 159         if (envVarPid.length() < 1) {
 160             System.out.println(tr);
 161             throw new RuntimeException("Error: env Var Pid in tracking info is empty string");
 162         }
 163 
 164         /*
 165          * On Linux, Launcher Tracking will print the PID.  Use this info
 166          * to validate what we got as the PID in the Launcher itself.
 167          * Linux is the only one that prints this, and trying to get it
 168          * here for win is awful.  So let the linux test make sure we get
 169          * the valid pid, and for non-linux, just make sure pid string is
 170          * non-zero.
 171          */
 172         if (isLinux) {
 173             // get what the test says is the launcher pid
 174             String launcherPid = null;
 175             for (String line : tr.testOutput) {
 176                 int index = line.indexOf(launcherPidString);
 177                 if (index >= 0) {
 178                     int sindex = index + launcherPidString.length();
 179                     int tindex = sindex + line.substring(sindex).indexOf("'");
 180                     System.out.println("DEBUG INFO: sindex = " + sindex);
 181                     System.out.println("DEBUG INFO: searching substring: " + line.substring(sindex));
 182                     System.out.println("DEBUG INFO: tindex = " + tindex);
 183                     // DEBUG INFO
 184                     System.out.println(tr);
 185                     launcherPid = line.substring(sindex, tindex);
 186                     break;
 187                 }
 188             }
 189             if (launcherPid == null) {
 190                 System.out.println(tr);
 191                 throw new RuntimeException("Error: failed to find launcher Pid in launcher tracking info");
 192             }
 193 
 194             // did we create the env var with the correct pid?
 195             if (!launcherPid.equals(envVarPid)) {
 196                 System.out.println(tr);
 197                 System.out.println("Error: wrong pid in creating env var");
 198                 System.out.println("Error Info: launcherPid = " + launcherPid);
 199                 System.out.println("Error Info: envVarPid   = " + envVarPid);
 200                 throw new RuntimeException("Error: wrong pid in creating env var");
 201             }
 202         }
 203 
 204         // --- Test 1b
 205         if (!tr.contains("NativeMemoryTracking: got value " + NMT_Option_Value)) {
 206             System.out.println(tr);
 207             throw new RuntimeException("Error: Valid param failed to set env variable");
 208         }
 209 
 210         // --- Test 2
 211         tr = doExec(envMap, javaCmd, "-XX:NativeMemoryTracking=",
 212                 "-version");
 213         if (tr.contains("NativeMemoryTracking:")) {
 214             System.out.println(tr);
 215             throw new RuntimeException("Error: invalid param caused env variable to be erroneously created");
 216         }
 217         if (!tr.contains("Syntax error, expecting -XX:NativeMemoryTracking=")) {
 218             System.out.println(tr);
 219             throw new RuntimeException("Error: invalid param not checked by JVM");
 220         }
 221 
 222         // --- Test 3
 223         tr = doExec(envMap, javaCmd, "-XX:NativeMemoryTracking",
 224                 "-version");
 225         if (tr.contains("NativeMemoryTracking:")) {
 226             System.out.println(tr);
 227             throw new RuntimeException("Error: invalid param caused env variable to be erroneously created");
 228         }
 229         if (!tr.contains("Syntax error, expecting -XX:NativeMemoryTracking=")) {
 230             System.out.println(tr);
 231             throw new RuntimeException("Error: invalid param not checked by JVM");
 232         }
 233         // --- Test 4
 234         tr = doExec(envMap, javaCmd, "-XX:NativeMemoryTracking=BADVALUE",
 235                 "-version");
 236         if (!tr.contains("expecting -XX:NativeMemoryTracking")) {
 237             System.out.println(tr);
 238             throw new RuntimeException("Error: invalid param did not get JVM Syntax error message");
 239         }
 240     }
 241 
 242     @Test
 243     void testNMArgumentProcessing() throws FileNotFoundException {
 244         TestResult tr;
 245         // the direct invokers of the VM
 246         String options[] = {
 247             "-version", "-fullversion", "-help", "-?", "-X"
 248         };
 249         for (String option : options) {
 250             tr = doExec(javaCmd, option, "-XX:NativeMemoryTracking=summary");
 251             checkTestResult(tr);
 252         }
 253 
 254         // create a test jar
 255         File jarFile = new File("test.jar");
 256         createJar(jarFile, "public static void main(String... args){}");
 257 
 258         // ones that involve main-class of some sort
 259         tr = doExec(javaCmd, "-jar", jarFile.getName(),
 260                 "-XX:NativeMemoryTracking=summary");
 261         checkTestResult(tr);
 262 
 263         tr = doExec(javaCmd, "-cp", jarFile.getName(), "Foo",
 264                 "-XX:NativeMemoryTracking=summary");
 265         checkTestResult(tr);
 266 
 267         final Map<String, String> envMap = new HashMap<>();
 268         // checkwith CLASSPATH set ie. no -cp or -classpath
 269         envMap.put("CLASSPATH", ".");
 270         tr = doExec(envMap, javaCmd, "Foo", "-XX:NativeMemoryTracking=summary");
 271         checkTestResult(tr);
 272 
 273         // should accept with no warnings
 274         tr = doExec(javaCmd, "-cp", jarFile.getName(),
 275                     "-XX:NativeMemoryTracking=summary", "Foo");
 276         ensureNoWarnings(tr);
 277 
 278         // should accept with no warnings
 279         tr = doExec(javaCmd, "-classpath", jarFile.getName(),
 280                     "-XX:NativeMemoryTracking=summary", "Foo");
 281         ensureNoWarnings(tr);
 282 
 283         // make sure a missing class is handled correctly, because the class
 284         // resolution is performed by the JVM.
 285         tr = doExec(javaCmd, "AbsentClass", "-XX:NativeMemoryTracking=summary");
 286         if (!tr.contains("Error: Could not find or load main class AbsentClass")) {
 287             throw new RuntimeException("Test Fails");
 288         }
 289     }
 290 
 291     void ensureNoWarnings(TestResult tr) {
 292         checkTestResult(tr);
 293         if (tr.contains("warning: Native Memory Tracking")) {
 294             System.err.println(tr.toString());
 295             throw new RuntimeException("Test Fails");
 296         }
 297     }
 298 
 299     void checkTestResult(TestResult tr) {
 300         if (!tr.isOK()) {
 301             System.err.println(tr.toString());
 302             throw new RuntimeException("Test Fails");
 303         }
 304     }
 305 }