1 # @test MultipleJRE.sh 2 # @bug 4811102 4953711 4955505 4956301 4991229 4998210 5018605 6387069 6733959 3 # @build PrintVersion 4 # @build UglyPrintVersion 5 # @build ZipMeUp 6 # @run shell MultipleJRE.sh 7 # @summary Verify Multiple JRE version support 8 # @author Joseph E. Kowalski 9 10 # 11 # Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. 12 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13 # 14 # This code is free software; you can redistribute it and/or modify it 15 # under the terms of the GNU General Public License version 2 only, as 16 # published by the Free Software Foundation. 17 # 18 # This code is distributed in the hope that it will be useful, but WITHOUT 19 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 20 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 21 # version 2 for more details (a copy is included in the LICENSE file that 22 # accompanied this code). 23 # 24 # You should have received a copy of the GNU General Public License version 25 # 2 along with this work; if not, write to the Free Software Foundation, 26 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 27 # 28 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 29 # or visit www.oracle.com if you need additional information or have any 30 # questions. 31 # 32 33 # Verify directory context variables are set 34 if [ "${TESTJAVA}" = "" ] 35 then 36 echo "TESTJAVA not set. Test cannot execute. Failed." 37 exit 1 38 fi 39 40 if [ "${TESTSRC}" = "" ] 41 then 42 echo "TESTSRC not set. Test cannot execute. Failed." 43 exit 1 44 fi 45 46 if [ "${TESTCLASSES}" = "" ] 47 then 48 echo "TESTCLASSES not set. Test cannot execute. Failed." 49 exit 1 50 fi 51 52 JAVAEXE="$TESTJAVA/bin/java ${TESTVMOPTS}" 53 JAVA="$TESTJAVA/bin/java ${TESTVMOPTS} -classpath $TESTCLASSES" 54 JAR="$TESTJAVA/bin/jar" 55 OS=`uname -s`; 56 57 # 58 # Tests whether we are on windows (true) or not. 59 # 60 IsWindows() { 61 case "$OS" in 62 Windows* | CYGWIN* ) 63 printf "true" 64 ;; 65 * ) 66 printf "false" 67 ;; 68 esac 69 } 70 71 # 72 # Shell routine to test for the proper rejection of syntactically incorrect 73 # version specifications. 74 # 75 TestSyntax() { 76 mess="`$JAVA -version:\"$1\" -version 2>&1`" 77 if [ $? -eq 0 ]; then 78 echo "Invalid version syntax $1 accepted" 79 exit 1 80 fi 81 prefix="`echo "$mess" | cut -d ' ' -f 1-3`" 82 if [ "$prefix" != "Error: Syntax error" ]; then 83 echo "Unexpected error message for invalid syntax $1" 84 exit 1 85 fi 86 } 87 88 # 89 # Just as the name says. We sprinkle these in the appropriate location 90 # in the test file system and they just say who they are pretending to be. 91 # 92 CreateMockVM() { 93 mkdir -p jdk/j2re$1/bin 94 echo "#!/bin/sh" > jdk/j2re$1/bin/java 95 echo "echo \"$1\"" >> jdk/j2re$1/bin/java 96 chmod +x jdk/j2re$1/bin/java 97 } 98 99 # 100 # Constructs the jar file needed by these tests. 101 # 102 CreateJar() { 103 mkdir -p META-INF 104 echo "Manifest-Version: 1.0" > META-INF/MANIFEST.MF 105 echo "Main-Class: PrintVersion" >> META-INF/MANIFEST.MF 106 if [ "$1" != "" ]; then 107 echo "JRE-Version: $1" >> META-INF/MANIFEST.MF 108 fi 109 cp $TESTCLASSES/PrintVersion.class . 110 $JAR $2cmf META-INF/MANIFEST.MF PrintVersion PrintVersion.class 111 } 112 113 # 114 # Constructs a jar file using zip. 115 # 116 CreateZippyJar() { 117 mkdir -p META-INF 118 echo "Manifest-Version: 1.0" > META-INF/MANIFEST.MF 119 echo "Main-Class: PrintVersion" >> META-INF/MANIFEST.MF 120 if [ "$1" != "" ]; then 121 echo "JRE-Version: $1" >> META-INF/MANIFEST.MF 122 fi 123 cp $TESTCLASSES/PrintVersion.class . 124 /usr/bin/zip $2 PrintVersion META-INF/MANIFEST.MF PrintVersion.class 125 } 126 127 # 128 # Constructs a jar file with a Main-Class attribute of greater than 129 # 80 characters to validate the continuation line processing. 130 # 131 # Make this just long enough to require two continuation lines. Longer 132 # paths take too much away from the restricted Windows maximum path length. 133 # Note: see the variable UGLYCLASS and its check for path length. 134 # 135 # Make sure that 5018605 remains fixed by including additional sections 136 # in the Manifest which contain the same names as those allowed in the 137 # main section. 138 # 139 PACKAGE=reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongpackagename 140 UGLYCLASS=$TESTCLASSES/$PACKAGE/UglyPrintVersion.class 141 CreateUglyJar() { 142 mkdir -p META-INF 143 echo "Manifest-Version: 1.0" > META-INF/MANIFEST.MF 144 echo "Main-Class: $PACKAGE.UglyPrintVersion" >> META-INF/MANIFEST.MF 145 if [ "$1" != "" ]; then 146 echo "JRE-Version: $1" >> META-INF/MANIFEST.MF 147 fi 148 echo "" >> META-INF/MANIFEST.MF 149 echo "Name: NotToBeFound.class" >> META-INF/MANIFEST.MF 150 echo "Main-Class: NotToBeFound" >> META-INF/MANIFEST.MF 151 mkdir -p $PACKAGE 152 cp $UGLYCLASS $PACKAGE 153 $JAR $2cmf META-INF/MANIFEST.MF PrintVersion \ 154 $PACKAGE/UglyPrintVersion.class 155 } 156 157 # 158 # Constructs a jar file with a fair number of "zip directory" entries and 159 # the MANIFEST.MF entry at or near the end of that directory to validate 160 # the ability to transverse that directory. 161 # 162 CreateFullJar() { 163 mkdir -p META-INF 164 echo "Manifest-Version: 1.0" > META-INF/MANIFEST.MF 165 echo "Main-Class: PrintVersion" >> META-INF/MANIFEST.MF 166 if [ "$1" != "" ]; then 167 echo "JRE-Version: $1" >> META-INF/MANIFEST.MF 168 fi 169 cp $TESTCLASSES/PrintVersion.class . 170 for i in 0 1 2 3 4 5 6 7 8 9 ; do 171 for j in 0 1 2 3 4 5 6 7 8 9 ; do 172 touch AfairlyLongNameEatsUpDirectorySpaceBetter$i$j 173 done 174 done 175 $JAR $2cMf PrintVersion PrintVersion.class AfairlyLong* 176 $JAR $2umf META-INF/MANIFEST.MF PrintVersion 177 rm -f AfairlyLong* 178 } 179 180 # 181 # Creates a jar file with the attributes which caused the failure 182 # described in 4991229. 183 # 184 # Generate a bunch of CENTAB entries, each of which is 64 bytes long 185 # which practically guarentees we will hit the appropriate power of 186 # two buffer (initially 1K). Note that due to the perversity of 187 # zip/jar files, the first entry gets extra stuff so it needs a 188 # shorter name to compensate. 189 # 190 CreateAlignedJar() { 191 mkdir -p META-INF 192 echo "Manifest-Version: 1.0" > META-INF/MANIFEST.MF 193 echo "Main-Class: PrintVersion" >> META-INF/MANIFEST.MF 194 if [ "$1" != "" ]; then 195 echo "JRE-Version: $1" >> META-INF/MANIFEST.MF 196 fi 197 cp $TESTCLASSES/PrintVersion.class . 198 touch 57BytesSpecial 199 for i in 0 1 2 3 4 5 6 7 8 9 ; do 200 for j in 0 1 2 3 4 5 6 7 8 9 ; do 201 touch 64BytesPerEntry-$i$j 202 done 203 done 204 $JAR $2cMf PrintVersion 57* 64* PrintVersion.class 205 $JAR $2umf META-INF/MANIFEST.MF PrintVersion 206 rm -f 57* 64* 207 } 208 209 # 210 # Adds comments to a jar/zip file. This serves two purposes: 211 # 212 # 1) Make sure zip file comments (both per file and per archive) are 213 # properly processed and ignored. 214 # 215 # 2) A long file comment creates a mondo "Central Directory" entry in 216 # the zip file. Such a "mondo" entry could also be due to a very 217 # long file name (path) or a long "Ext" entry, but adding the long 218 # comment is the easiest way. 219 # 220 CommentZipFile() { 221 file= 222 tail="is designed to take up space - lots and lots of space." 223 mv PrintVersion PrintVersion.zip 224 /usr/bin/zipnote PrintVersion.zip > zipout 225 while read ampersand line; do 226 if [ "$ampersand" = "@" ]; then 227 if [ "$line" = "(comment above this line)" ]; then 228 echo "File Comment Line." >> zipin 229 if [ "$file" = "$1" ]; then 230 for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do 231 for j in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do 232 echo "Mondo comment line $i$j $tail" >> zipin 233 done 234 done 235 fi 236 else 237 file=$line 238 fi 239 fi 240 echo "$ampersand $line" >> zipin 241 if [ "$ampersand" = "@" ]; then 242 if [ "$line" = "(zip file comment below this line)" ]; then 243 echo "Zip File Comment Line number 1" >> zipin 244 echo "Zip File Comment Line number 2" >> zipin 245 fi 246 fi 247 done < zipout 248 /usr/bin/zipnote -w PrintVersion.zip < zipin 249 mv PrintVersion.zip PrintVersion 250 rm zipout zipin 251 } 252 253 # 254 # Attempt to launch a vm using a version specifier and make sure the 255 # resultant launch (probably a "mock vm") is appropriate. 256 # 257 LaunchVM() { 258 if [ "$1" != "" ]; then 259 mess="`$JAVA -version:\"$1\" -jar PrintVersion 2>&1`" 260 else 261 mess="`$JAVA -jar PrintVersion 2>&1`" 262 fi 263 if [ $? -ne 0 ]; then 264 prefix=`echo "$mess" | cut -d ' ' -f 1-3` 265 if [ "$prefix" != "Unable to locate" ]; then 266 echo "$mess" 267 exit 1 268 fi 269 echo "Unexpected error in attempting to locate $1" 270 exit 1 271 fi 272 echo $mess | grep "$2" > /dev/null 2>&1 273 if [ $? != 0 ]; then 274 echo "Launched $mess, expected $2" 275 exit 1 276 fi 277 } 278 279 # Tests very long Main-Class attribute in the jar 280 TestLongMainClass() { 281 JVER=$1 282 if [ "$JVER" = "mklink" ]; then 283 JVER=XX 284 JDKXX=jdk/j2re$JVER 285 rm -rf jdk 286 mkdir jdk 287 ln -s $TESTJAVA $JDKXX 288 JAVA_VERSION_PATH="`pwd`/jdk" 289 export JAVA_VERSION_PATH 290 fi 291 $JAVAEXE -cp $TESTCLASSES ZipMeUp UglyBetty.jar 4097 292 message="`$JAVAEXE -version:$JVER -jar UglyBetty.jar 2>&1`" 293 echo $message | grep "Error: main-class: attribute exceeds system limits" > /dev/null 2>&1 294 if [ $? -ne 0 ]; then 295 printf "Long manifest test did not get expected error" 296 exit 1 297 fi 298 unset JAVA_VERSION_PATH 299 rm -rf jdk 300 } 301 302 # 303 # Main test sequence starts here 304 # 305 RELEASE=`$JAVA -version 2>&1 | head -n 1 | cut -d ' ' -f 3 | \ 306 sed -e "s/\"//g"` 307 BASE_RELEASE=`echo $RELEASE | sed -e "s/-.*//g"` 308 309 # 310 # Make sure that the generic jar/manifest reading code works. Test both 311 # compressed and "stored" jar files. 312 # 313 # The "Ugly" jar (long manifest line) tests are only run if the combination 314 # of the file name length restrictions and the length of the cwd allow it. 315 # 316 CreateJar "" "" 317 LaunchVM "" "${RELEASE}" 318 CreateJar "" "0" 319 LaunchVM "" "${RELEASE}" 320 if [ `IsWindows` = "true" ]; then 321 MAXIMUM_PATH=255; 322 else 323 MAXIMUM_PATH=1024; 324 fi 325 326 PATH_LENGTH=`printf "%s" "$UGLYCLASS" | wc -c` 327 if [ ${PATH_LENGTH} -lt ${MAXIMUM_PATH} ]; then 328 CreateUglyJar "" "" 329 LaunchVM "" "${RELEASE}" 330 CreateUglyJar "" "0" 331 LaunchVM "" "${RELEASE}" 332 else 333 printf "Warning: Skipped UglyJar test, path length exceeded, %d" $MAXIMUM_PATH 334 printf " allowed, the current path is %d\n" $PATH_LENGTH 335 fi 336 CreateAlignedJar "" "" 337 LaunchVM "" "${RELEASE}" 338 CreateFullJar "" "" 339 LaunchVM "" "${RELEASE}" 340 341 # 342 # 4998210 shows that some very strange behaviors are semi-supported. 343 # In this case, it's the ability to prepend any kind of stuff to the 344 # jar file and require that the jar file still work. Note that this 345 # "interface" isn't publically supported and we may choose to break 346 # it in the future, but this test guarantees that we won't break it 347 # without informed consent. We take advantage the fact that the 348 # "FullJar" we just tested is probably the best jar to begin with 349 # for this test. 350 # 351 echo "This is just meaningless bytes to prepend to the jar" > meaningless 352 mv PrintVersion meaningfull 353 cat meaningless meaningfull > PrintVersion 354 LaunchVM "" "${RELEASE}" 355 rm meaningless meaningfull 356 357 # 358 # Officially, one must use "the jar command to create a jar file. However, 359 # all the comments about jar commands **imply** that jar files and zip files 360 # are equivalent. (Note: this isn't true due to the "0xcafe" insertion.) 361 # On systems which have a command line zip, test the ability to use zip 362 # to construct a jar and then use it (6387069). 363 # 364 if [ -x /usr/bin/zip ]; then 365 CreateZippyJar "" "-q" 366 LaunchVM "" "${RELEASE}" 367 fi 368 369 # 370 # jar files shouldn't have comments, but it is possible that somebody added 371 # one by using zip -c, zip -z, zipnote or a similar utility. On systems 372 # that have "zipnote", verify this functionality. 373 # 374 # This serves a dual purpose of creating a very large "central directory 375 # entry" which validates to code to read such entries. 376 # 377 if [ -x /usr/bin/zipnote ]; then 378 CreateFullJar "" "" 379 CommentZipFile "AfairlyLongNameEatsUpDirectorySpaceBetter20" 380 LaunchVM "" "${RELEASE}" 381 fi 382 383 # 384 # Throw some syntactically challenged (illegal) version specifiers at 385 # the interface. Failure (of the launcher) is success for the test. 386 # 387 TestSyntax "1.2..3" # Two adjacent separators 388 TestSyntax "_1.2.3" # Begins with a separator 389 TestSyntax "1.2.3-" # Ends with a separator 390 TestSyntax "1.2+.3" # Embedded modifier 391 TestSyntax "1.2.4+&1.2*&1++" # Long and invalid 392 393 # On windows we see if there is another jre installed, usually 394 # there is, then we test using that, otherwise links are created 395 # to get through to SelectVersion. 396 if [ `IsWindows` = "false" ]; then 397 TestLongMainClass "mklink" 398 else 399 $JAVAEXE -version:1.0+ 400 if [ $? -eq 0 ]; then 401 TestLongMainClass "1.0+" 402 else 403 printf "Warning: TestLongMainClass skipped as there is no" 404 printf "viable MJRE installed.\n" 405 fi 406 fi 407 408 # 409 # Because scribbling in the registry can be rather destructive, only a 410 # subset of the tests are run on Windows. 411 # 412 if [ `IsWindows` = "true" ]; then 413 exit 0; 414 fi 415 416 # 417 # Additional version specifiers containing spaces. (Sigh, unable to 418 # figure out the glomming on Windows) 419 # 420 TestSyntax "1.2.3_99 1.3.2+ 1.2.4+&1.2*&1++" # Long and invalid 421 422 # 423 # Create a mock installation of a number of shell scripts named as though 424 # they were installed JREs. Then test to see if the launcher can cause 425 # the right shell scripts to be invoked. 426 # 427 # Note, that as a side effect, this test verifies that JAVA_VERSION_PATH 428 # works. 429 # 430 rm -rf jdk 431 JAVA_VERSION_PATH="`pwd`/jdk" 432 export JAVA_VERSION_PATH 433 434 CreateMockVM 1.10 435 CreateMockVM 1.11.3 436 CreateMockVM 1.11.3_03 437 CreateMockVM 1.11.4 438 CreateMockVM 1.12.3_03 439 CreateMockVM 1.12.3_03-lastweek 440 CreateMockVM 1.13.3_03 441 CreateMockVM 1.13.3_03-lastweek 442 CreateMockVM 1.13.3_03_lastweek 443 CreateMockVM 1.20.0 444 445 # 446 # Test extracting the version information from the jar file: 447 # 448 # Requested Expected 449 CreateJar "1.10+" "" 450 LaunchVM "" "1.20.0" 451 CreateJar "1.11.3_03+&1.11*" "" 452 LaunchVM "" "1.11.4" 453 CreateJar "1.12.3_03+&1.12.3*" "" 454 LaunchVM "" "1.12.3_03" 455 CreateJar "1.13.3_03+&1.13.3*" "" 456 LaunchVM "" "1.13.3_03_lastweek" # Strange but true 457 458 # 459 # Test obtaining the version information from the command line (and that 460 # it overrides the manifest). 461 # 462 CreateJar "${BASERELEASE}*" "" 463 LaunchVM "1.10+" "1.20.0" 464 LaunchVM "1.11.3_03+&1.11*" "1.11.4" 465 LaunchVM "1.12.3_03+&1.12.3*" "1.12.3_03" 466 LaunchVM "1.13.3_03+&1.13.3*" "1.13.3_03_lastweek" # Strange but true 467 468 [ -d jdk ] && rm -rf jdk 469 [ -d META_INF ] && rm -rf META_INF 470 471 exit 0