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