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