1 /* 2 * Copyright (c) 2009, 2013, 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 4780570 4731671 6354700 6367077 6670965 4882974 27 * @summary Checks for LD_LIBRARY_PATH and execution on *nixes 28 * @compile -XDignore.symbol.file ExecutionEnvironment.java 29 * @run main/othervm ExecutionEnvironment 30 */ 31 32 /* 33 * This tests for various things as follows: 34 * Ensures that: 35 * 1. uneccessary execs do not occur 36 * 2. the environment is pristine, users environment variable wrt. 37 * LD_LIBRARY_PATH if set are not modified in any way. 38 * 3. the correct vm is chosen with -server and -client options 39 * 4. the VM on Solaris correctly interprets the LD_LIBRARY_PATH32 40 * and LD_LIBRARY_PATH64 variables if set by the user, ie. 41 * i. on 32 bit systems: 42 * a. if LD_LIBRARY_PATH32 is set it will override LD_LIBRARY_PATH 43 * b. LD_LIBRARY_PATH64 is ignored if set 44 * ii. on 64 bit systems: 45 * a. if LD_LIBRARY_PATH64 is set it will override LD_LIBRARY_PATH 46 * b. LD_LIBRARY_PATH32 is ignored if set 47 * 5. no extra symlink exists on Solaris ie. 48 * jre/lib/$arch/libjvm.so -> client/libjvm.so 49 * 6. Since 32-bit Solaris is no longer supported we continue to ensure that 50 * the appropriate paths are ignored or used, additionally we also test to 51 * ensure the 64-bit isadir exists and contains appopriate links. 52 * TODO: 53 * a. perhaps we need to add a test to audit all environment variables are 54 * in pristine condition after the launch, there may be a few that the 55 * launcher may add as implementation details. 56 * b. add a pldd for solaris to ensure only one libjvm.so is linked 57 */ 58 import java.io.File; 59 import java.io.FileNotFoundException; 60 import java.io.IOException; 61 import java.nio.file.DirectoryStream; 62 import java.nio.file.Files; 63 import java.nio.file.Path; 64 import java.util.ArrayList; 65 import java.util.HashMap; 66 import java.util.List; 67 import java.util.Map; 68 import static java.nio.file.LinkOption.*; 69 70 71 public class ExecutionEnvironment extends TestHelper { 72 static final String LD_LIBRARY_PATH = TestHelper.isMacOSX 73 ? "DYLD_LIBRARY_PATH" 74 : "LD_LIBRARY_PATH"; 75 static final String LD_LIBRARY_PATH_32 = LD_LIBRARY_PATH + "_32"; 76 static final String LD_LIBRARY_PATH_64 = LD_LIBRARY_PATH + "_64"; 77 78 // Note: these paths need not exist on the filesytem 79 static final String LD_LIBRARY_PATH_VALUE = "/Bridge/On/The/River/Kwai"; 80 static final String LD_LIBRARY_PATH_32_VALUE = "/Lawrence/Of/Arabia"; 81 static final String LD_LIBRARY_PATH_64_VALUE = "/A/Passage/To/India"; 82 83 static final String[] LD_PATH_STRINGS = { 84 LD_LIBRARY_PATH + "=" + LD_LIBRARY_PATH_VALUE, 85 LD_LIBRARY_PATH_32 + "=" + LD_LIBRARY_PATH_32_VALUE, 86 LD_LIBRARY_PATH_64 + "=" + LD_LIBRARY_PATH_64_VALUE 87 }; 88 89 static final File testJarFile = new File("EcoFriendly.jar"); 90 91 static final String LIBJVM = TestHelper.isWindows 92 ? "jvm.dll" 93 : "libjvm" + (TestHelper.isMacOSX ? ".dylib" : ".so"); 94 95 public ExecutionEnvironment() { 96 createTestJar(); 97 } 98 99 static void createTestJar() { 100 try { 101 List<String> codeList = new ArrayList<>(); 102 codeList.add("static void printValue(String name, boolean property) {\n"); 103 codeList.add(" String value = (property) ? System.getProperty(name) : System.getenv(name);\n"); 104 codeList.add(" System.out.println(name + \"=\" + value);\n"); 105 codeList.add("}\n"); 106 codeList.add("public static void main(String... args) {\n"); 107 codeList.add(" System.out.println(\"Execute test:\");\n"); 108 codeList.add(" printValue(\"os.name\", true);\n"); 109 codeList.add(" printValue(\"os.arch\", true);\n"); 110 codeList.add(" printValue(\"os.version\", true);\n"); 111 codeList.add(" printValue(\"sun.arch.data.model\", true);\n"); 112 codeList.add(" printValue(\"java.library.path\", true);\n"); 113 codeList.add(" printValue(\"" + LD_LIBRARY_PATH + "\", false);\n"); 114 codeList.add(" printValue(\"" + LD_LIBRARY_PATH_32 + "\", false);\n"); 115 codeList.add(" printValue(\"" + LD_LIBRARY_PATH_64 + "\", false);\n"); 116 codeList.add("}\n"); 117 String[] clist = new String[codeList.size()]; 118 createJar(testJarFile, codeList.toArray(clist)); 119 } catch (FileNotFoundException fnfe) { 120 throw new RuntimeException(fnfe); 121 } 122 } 123 private void flagError(TestResult tr, String message) { 124 System.err.println(tr); 125 throw new RuntimeException(message); 126 } 127 /* 128 * tests if the launcher pollutes the LD_LIBRARY_PATH variables ie. there 129 * should not be any new variables or pollution/mutations of any kind, the 130 * environment should be pristine. 131 */ 132 @Test 133 void testEcoFriendly() { 134 TestResult tr = null; 135 136 Map<String, String> env = new HashMap<>(); 137 for (String x : LD_PATH_STRINGS) { 138 String pairs[] = x.split("="); 139 env.put(pairs[0], pairs[1]); 140 } 141 142 tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); 143 144 if (!tr.isNotZeroOutput()) { 145 flagError(tr, "Error: No output at all. Did the test execute ?"); 146 } 147 148 for (String x : LD_PATH_STRINGS) { 149 if (!tr.contains(x)) { 150 flagError(tr, "FAIL: did not get <" + x + ">"); 151 } 152 } 153 } 154 155 /* 156 * ensures that there are no execs as long as we are in the same 157 * data model 158 */ 159 @Test 160 void testNoExec() { 161 Map<String, String> env = new HashMap<>(); 162 env.put(JLDEBUG_KEY, "true"); 163 TestResult tr = doExec(env, javaCmd, "-version"); 164 if (tr.testOutput.contains(EXPECTED_MARKER)) { 165 flagError(tr, "testNoExec: found warning <" + EXPECTED_MARKER + 166 "> the process execing ?"); 167 } 168 } 169 170 /* 171 * This test ensures that LD_LIBRARY_PATH* values are interpreted by the VM 172 * and the expected java.library.path behaviour. 173 * For Generic platforms (All *nixes): 174 * * All LD_LIBRARY_PATH variable should be on java.library.path 175 * For Solaris 32-bit 176 * * The LD_LIBRARY_PATH_32 should override LD_LIBRARY_PATH if specified 177 * For Solaris 64-bit 178 * * The LD_LIBRARY_PATH_64 should override LD_LIBRARY_PATH if specified 179 */ 180 @Test 181 void testJavaLibraryPath() { 182 TestResult tr = null; 183 184 Map<String, String> env = new HashMap<>(); 185 186 if (TestHelper.isLinux || TestHelper.isMacOSX) { 187 for (String x : LD_PATH_STRINGS) { 188 String pairs[] = x.split("="); 189 env.put(pairs[0], pairs[1]); 190 } 191 192 tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); 193 verifyJavaLibraryPathGeneric(tr); 194 } else { 195 // no override 196 env.clear(); 197 env.put(LD_LIBRARY_PATH, LD_LIBRARY_PATH_VALUE); 198 tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); 199 verifyJavaLibraryPathGeneric(tr); 200 201 env.clear(); 202 for (String x : LD_PATH_STRINGS) { 203 String pairs[] = x.split("="); 204 env.put(pairs[0], pairs[1]); 205 } 206 207 // verify the override occurs for 64-bit system 208 tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); 209 verifyJavaLibraryPathOverride(tr, false); 210 } 211 } 212 213 private void verifyJavaLibraryPathGeneric(TestResult tr) { 214 if (!tr.matches("java.library.path=.*" + LD_LIBRARY_PATH_VALUE + ".*")) { 215 flagError(tr, "testJavaLibraryPath: java.library.path does not contain " + 216 LD_LIBRARY_PATH_VALUE); 217 } 218 } 219 220 private void verifyJavaLibraryPathOverride(TestResult tr, 221 boolean is32Bit) { 222 // make sure the 32/64 bit value exists 223 if (!tr.matches("java.library.path=.*" + 224 (is32Bit ? LD_LIBRARY_PATH_32_VALUE : LD_LIBRARY_PATH_64_VALUE) + ".*")) { 225 flagError(tr, "verifyJavaLibraryPathOverride: " + 226 " java.library.path does not contain " + 227 (is32Bit ? LD_LIBRARY_PATH_32_VALUE : LD_LIBRARY_PATH_64_VALUE)); 228 229 } 230 // make sure the generic value is absent 231 if (!tr.notMatches("java.library.path=.*" + LD_LIBRARY_PATH_VALUE + ".*")) { 232 flagError(tr, "verifyJavaLibraryPathOverride: " + 233 " java.library.path contains " + LD_LIBRARY_PATH_VALUE); 234 } 235 } 236 237 /* 238 * ensures we have indeed exec'ed the correct vm of choice, all VMs support 239 * -server, however 32-bit VMs support -client and -server. 240 */ 241 @Test 242 void testVmSelection() { 243 244 TestResult tr = null; 245 246 if (is32Bit) { 247 tr = doExec(javaCmd, "-client", "-version"); 248 if (!tr.matches(".*Client VM.*")) { 249 flagError(tr, "the expected vm -client did not launch"); 250 } 251 } 252 tr = doExec(javaCmd, "-server", "-version"); 253 if (!tr.matches(".*Server VM.*")) { 254 flagError(tr, "the expected vm -server did not launch"); 255 } 256 } 257 258 /* 259 * checks to see there is no extra libjvm.so than needed 260 */ 261 @Test 262 void testNoSymLink() { 263 if (is64Bit) { 264 return; 265 } 266 267 File symLink = null; 268 String libPathPrefix = isSDK ? "jre/lib" : "/lib"; 269 symLink = new File(JAVAHOME, libPathPrefix + 270 getJreArch() + "/" + LIBJVM); 271 if (symLink.exists()) { 272 throw new RuntimeException("symlink exists " + symLink.getAbsolutePath()); 273 } 274 } 275 276 /* 277 * verify if all the symlinks in the images are created correctly, 278 * only on solaris, this test works only on images. 279 */ 280 @Test 281 void testSymLinks() throws Exception { 282 if (!isSolaris) 283 return; 284 verifySymLinks(JAVA_BIN); 285 verifySymLinks(JAVA_JRE_BIN); 286 } 287 private void verifySymLinks(String bindir) throws IOException { 288 File binDir = new File(bindir); 289 System.err.println("verifying links in: " + bindir); 290 File isaDir = new File(binDir, getArch()).getAbsoluteFile(); 291 if (!isaDir.exists()) { 292 throw new RuntimeException("dir: " + isaDir + " does not exist"); 293 } 294 try (DirectoryStream<Path> ds = Files.newDirectoryStream(binDir.toPath())) { 295 for (Path p : ds) { 296 if (Files.isDirectory(p, NOFOLLOW_LINKS)) 297 continue; 298 Path link = new File(isaDir, p.getFileName().toString()).toPath(); 299 if (Files.isSymbolicLink(link)) { 300 Path target = Files.readSymbolicLink(link); 301 if (target.startsWith("..") && p.endsWith(target.getFileName())) 302 continue; 303 System.err.println("target:" + target); 304 System.err.println("file:" + p); 305 } 306 throw new RuntimeException("could not find link to " + p); 307 } 308 } 309 310 } 311 public static void main(String... args) throws Exception { 312 if (isWindows) { 313 System.err.println("Warning: test not applicable to windows"); 314 return; 315 } 316 ExecutionEnvironment ee = new ExecutionEnvironment(); 317 ee.run(args); 318 } 319 }