aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party
diff options
context:
space:
mode:
authorGravatar Damien Martin-Guillerez <dmarting@google.com>2015-05-04 14:45:47 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-05-04 17:51:58 +0000
commit497d35e06119c560cbf1198bf68ae11824094240 (patch)
treeb712369cd8511fc57c62cfb456f252b1524704a2 /third_party
parent4c67f31c1e22b27d74e563339d7a5003fa8db19e (diff)
Improved ijar shell tests
The ijar tests were a bit bloated so using our shell test framework to separate those tests into individual function and enable sharding. The ijar tests are still ~70s on a macbook with a SSD drive (compared to ~140s before). Those 70s are spent in tests that write big files and test ijar behavior with those big files. In those tests, disk IOs dominate time. Timing the various operation gave that jaring the 2.2Gb large file takes ~17s each time (operation we do twice). Simply creating that file takes approximatively 10s. Reducing the number of operations in that test would reduce significantly its duration. Unfortunately, that would reduce the coverage of the test. -- Change-Id: Idc817ab32b78b69bde8dd95ddedbcf6b9f12ee3f MOS_MIGRATED_REVID=92723971
Diffstat (limited to 'third_party')
-rw-r--r--third_party/ijar/test/BUILD3
-rwxr-xr-xthird_party/ijar/test/ijar_test.sh636
-rwxr-xr-xthird_party/ijar/test/testenv.sh38
3 files changed, 339 insertions, 338 deletions
diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD
index cb17830fc8..b46d742313 100644
--- a/third_party/ijar/test/BUILD
+++ b/third_party/ijar/test/BUILD
@@ -20,6 +20,8 @@ sh_test(
"zip",
],
data = [
+ "testenv.sh",
+ "//src/test/shell:bashunit",
"//third_party/ijar",
"A.java",
"B.java",
@@ -36,6 +38,7 @@ sh_test(
"//tools/defaults:jdk",
"//tools/jdk:langtools",
],
+ shard_count = 5,
)
java_library(
diff --git a/third_party/ijar/test/ijar_test.sh b/third_party/ijar/test/ijar_test.sh
index 9869969adf..f091144927 100755
--- a/third_party/ijar/test/ijar_test.sh
+++ b/third_party/ijar/test/ijar_test.sh
@@ -12,39 +12,37 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
-# TODO(bazel-team): this file is bloated, we should factor it.
-
-#### Inputs
-
-## TEST_TMPDIR
-if [ -z "${TEST_TMPDIR:-}" ]; then
- TEST_TMPDIR="$(mktemp -d ${TMPDIR:-/tmp}/ijar-test.XXXXXXXX)"
- trap "rm -fr ${TEST_TMPDIR}" EXIT
-fi
-
-## Mac OS X stat and MD5
-PLATFORM="$(uname -s | tr 'A-Z' 'a-z')"
-if [[ "$PLATFORM" = "darwin" ]]; then
- function statfmt() {
- stat -f "%z" $1
- }
- MD5SUM=/sbin/md5
-else
- function statfmt() {
- stat -c "%s" $1
- }
- MD5SUM=md5sum
-fi
+# TODO(bazel-team) test that modifying the source in a non-interface
+# changing way results in the same -interface.jar.
-## Tools
+
+DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
+
+## Inputs
JAVAC=$1
-JAVA=$2
-JAR=$3
-JAVAP=$4
-IJAR=$TEST_SRCDIR/$5
-LANGTOOLS8=$TEST_SRCDIR/$6
-UNZIP=$7
-ZIP=$8
+shift
+JAVA=$1
+shift
+JAR=$1
+shift
+JAVAP=$1
+shift
+IJAR=$TEST_SRCDIR/$1
+shift
+LANGTOOLS8=$TEST_SRCDIR/$1
+shift
+UNZIP=$1
+shift
+ZIP=$1
+shift
+
+## Test framework
+source ${DIR}/testenv.sh || { echo "testenv.sh not found!" >&2; exit 1; }
+
+
+## Tools
+# Ensure that javac is absolute
+[[ "$JAVAC" =~ ^/ ]] || JAVAC="$PWD/$JAVAC"
IJAR_SRCDIR=$(dirname ${IJAR})
A_JAR=$TEST_TMPDIR/A.jar
@@ -64,62 +62,6 @@ TYPEANN2_JAVA=$IJAR_SRCDIR/test/TypeAnnotationTest2.java
INVOKEDYNAMIC_JAR=$IJAR_SRCDIR/test/libinvokedynamic.jar
INVOKEDYNAMIC_IJAR=$TEST_TMPDIR/invokedynamic_interface.jar
-#### Testing framework
-# Print message in "$1" then exit with status "$2"
-die () {
- # second argument is optional, defaulting to 1
- local status_code=${2:-1}
- # Stop capturing stdout/stderr, and dump captured output
- if [ "$CAPTURED_STD_ERR" -ne 0 ]; then
- restore_outputs
- cat "${TEST_TMPDIR}/captured.err" 1>&2
- fi
-
- if [ -n "${1-}" ] ; then
- echo "$1" 1>&2
- fi
- if [ x"$status_code" != x -a x"$status_code" != x"0" ]; then
- exit "$status_code"
- else
- exit 1
- fi
-}
-
-# Die if "$1" == "$2", print $3 as death reason
-check_ne () {
- if [ "$1" = "$2" ]; then
- die "Check failed: '$1' != '$2' ${3:+ ($3)}"
- fi
-}
-
-# Die if "$1" != "$2", print $3 as death reason
-check_eq () {
- if [ ! "$1" = "$2" ]; then
- die "Check failed: '$1' = '$2' ${3:+ ($3)}"
- fi
-}
-
-CAPTURED_STD_ERR="${CAPTURED_STD_ERR:-0}"
-
-capture_test_stderr () {
- exec 6>&2 # Save stderr as fd 6
- exec 7>"${TEST_TMPDIR}/captured.err"
- exec 2>&7
- CAPTURED_STD_ERR=1
-}
-
-restore_outputs () {
- if [ "$CAPTURED_STD_ERR" -ne 0 ] ; then
- exec 2>&6
- fi
-}
-
-recapture_outputs () {
- if [ "$CAPTURED_STD_ERR" -ne 0 ] ; then
- exec 2>&7
- fi
-}
-
#### Setup
# set_file_length FILE SIZE
@@ -127,22 +69,9 @@ recapture_outputs () {
# Sets the file size for FILE, truncating if necessary, creating a
# sparse file if possible, preserving original contents if they fit.
function set_file_length() {
- perl -e 'open(FH, ">>$ARGV[0]") && truncate(FH, $ARGV[1]) or die $!' "$@" &&
+ perl -e 'open(FH, ">>$ARGV[0]") && truncate(FH, $ARGV[1]) or fail $!' "$@" &&
[[ "$(statfmt $1)" == "$2" ]] ||
- die "set_file_length failed"
-}
-
-# grep_test_stderr STRING MESSAGE
-#
-# Greps the captured stderr text for STRING. If not found, fails with MESSAGE.
-grep_test_stderr() {
- restore_outputs
- [ "$CAPTURED_STD_ERR" -ne 0 ] || \
- die "Must call capture_test_stderr before grep_test_stderr"
- grep -c "$1" ${TEST_TMPDIR}/captured.err >/dev/null || \
- die "Check failed: grep -c '$1' ${TEST_TMPDIR}/captured.err ${2:+ ($2)}"
- CAPTURED_STD_ERR=0
- recapture_outputs
+ fail "set_file_length failed"
}
# check_consistent_file_contents FILE
@@ -156,7 +85,7 @@ function check_consistent_file_contents() {
if $(echo "${expected_output}" | grep -q "^${filename} "); then
echo "${expected_output}" | grep -q "^${filename} ${actual}$" || {
ls -l "$1"
- die "output file contents differ"
+ fail "output file contents differ"
}
else
expected_output="$expected_output$filename $actual
@@ -164,254 +93,285 @@ function check_consistent_file_contents() {
fi
}
-# Tests that ijar does not crash when output ijar is bigger than the input jar
-rm -fr $TEST_TMPDIR/classes
-mkdir -p $TEST_TMPDIR/classes || die "mkdir $TEST_TMPDIR/classes failed"
-$JAVAC -g -d $TEST_TMPDIR/classes \
+function set_up() {
+ mkdir -p $TEST_TMPDIR/classes
+}
+
+function tear_down() {
+ rm -fr $TEST_TMPDIR/classes
+}
+
+#### Tests
+function test_output_bigger_than_input() {
+ # Tests that ijar does not crash when output ijar is bigger than the input jar
+ $JAVAC -g -d $TEST_TMPDIR/classes \
$IJAR_SRCDIR/test/WellCompressed*.java ||
- die "javac failed"
-$JAR cf $W_JAR -C $TEST_TMPDIR/classes . || die "jar failed"
-
-W_INTERFACE_JAR=$TEST_TMPDIR/W-interface.jar
-$IJAR $W_JAR $W_INTERFACE_JAR || die "ijar failed"
-
-mkdir -p $TEST_TMPDIR/java/lang
-cp $OBJECT_JAVA $TEST_TMPDIR/java/lang/.
-$JAVAC $TEST_TMPDIR/java/lang/Object.java || die "javac failed"
-$JAR cf $OBJECT_JAR -C $TEST_TMPDIR java/lang/Object.class || die "jar failed"
-
-# Tests that ijar can handle class bodies longer than 64K
-rm -fr $TEST_TMPDIR/classes
-mkdir -p $TEST_TMPDIR/classes || die "mkdir $TEST_TMPDIR/classes failed"
-# First, generate the input file
-BOTTLES_JAVA=$TEST_TMPDIR/BottlesOnTheWall.java
-echo "public class BottlesOnTheWall {" > $BOTTLES_JAVA
-for i in $(seq 1 16384); do
- echo " public int getBottleOnTheWall${i}() { return ${i}; }" >> $BOTTLES_JAVA
-done
-
-echo "}" >> $BOTTLES_JAVA
-
-$JAVAC -g -d $TEST_TMPDIR/classes $BOTTLES_JAVA || die "javac failed"
-BOTTLES_INTERFACE_JAR=$TEST_TMPDIR/bottles-interface.jar
-
-for flag0 in '' '0'; do
- $JAR c"${flag0}"f $BOTTLES_JAR -C $TEST_TMPDIR/classes . || die "jar failed"
- $IJAR $BOTTLES_JAR $BOTTLES_INTERFACE_JAR || die "ijar failed"
- check_consistent_file_contents $BOTTLES_INTERFACE_JAR
-done
-
-# Compiles A.java, builds A.jar and A-interface.jar
-rm -fr $TEST_TMPDIR/classes
-mkdir -p $TEST_TMPDIR/classes || die "mkdir $TEST_TMPDIR/classes failed"
-$JAVAC -g -d $TEST_TMPDIR/classes $IJAR_SRCDIR/test/A.java ||
- die "javac failed"
-
-for flag0 in '' '0'; do
-# Ensure input files larger than INITIAL_BUFFER_SIZE work.
-# TODO(martinrb): remove maximum .class file size limit (MAX_BUFFER_SIZE)
-for size in '' $((1024*1024)) $((15*1024*1024)); do
- if [[ -n "$size" ]]; then
- for file in $(find $TEST_TMPDIR/classes -name '*.class'); do
- set_file_length "$file" "$size"
- done
- fi
- $JAR c"${flag0}"f $A_JAR -C $TEST_TMPDIR/classes . || die "jar failed"
- $IJAR $A_JAR $A_INTERFACE_JAR || die "ijar failed."
- check_consistent_file_contents $A_INTERFACE_JAR
+ fail "javac failed"
+ $JAR cf $W_JAR -C $TEST_TMPDIR/classes . || fail "jar failed"
+
+ W_INTERFACE_JAR=$TEST_TMPDIR/W-interface.jar
+ $IJAR $W_JAR $W_INTERFACE_JAR || fail "ijar failed"
+ # Check that the interface jar is bigger than the original jar.
+ W_JAR_SIZE=$(statfmt $W_JAR)
+ W_INTERFACE_JAR_SIZE=$(statfmt $W_INTERFACE_JAR)
+ [[ $W_INTERFACE_JAR_SIZE -gt $W_JAR_SIZE ]] || fail "interface jar should be bigger"
+}
+
+function test_class_more_64k() {
+ # Tests that ijar can handle class bodies longer than 64K
+ # First, generate the input file
+ BOTTLES_JAVA=$TEST_TMPDIR/BottlesOnTheWall.java
+ echo "public class BottlesOnTheWall {" > $BOTTLES_JAVA
+ for i in $(seq 1 16384); do
+ echo " public int getBottleOnTheWall${i}() { return ${i}; }" >> $BOTTLES_JAVA
done
-done
-# Creates a huge (3Gb) input jar to test "large file" correctness
-set_file_length $TEST_TMPDIR/zeroes.data $((3*1024*1024*1024))
-for flag0 in '' '0'; do
- $JAR c"${flag0}"f $A_JAR -C $TEST_TMPDIR zeroes.data -C $TEST_TMPDIR/classes . || die "jar failed"
- $IJAR $A_JAR $A_INTERFACE_JAR || die "ijar failed."
- check_consistent_file_contents $A_INTERFACE_JAR
-done
+ echo "}" >> $BOTTLES_JAVA
-# Create an output jar with upper bound on size > 2GB
-DIR=$TEST_TMPDIR/ManyLargeClasses
-mkdir -p $DIR/classes
-for i in $(seq 200); do
- printf "class C${i} {}\n" > $DIR/C${i}.java
-done
-([[ "$JAVAC" =~ ^/ ]] || JAVAC="$PWD/$JAVAC"; cd $DIR && $JAVAC -d classes *.java)
-for i in $(seq 200); do
- set_file_length $DIR/classes/C${i}.class $((15*1024*1024))
-done
-$JAR cf $DIR/ManyLargeClasses.jar -C $DIR/classes . || die "jar failed"
-$IJAR $DIR/ManyLargeClasses.jar $DIR/ManyLargeClasses.ijar || die "ijar failed."
-
-#### Checks
-
-# Check that ijar can produce class files with a body longer than 64K by
-# calling ijar itself on the output file to make sure that it is valid
-BOTTLES_INTERFACE_INTERFACE_JAR=$TEST_TMPDIR/bottles-interface-interface.jar
-$IJAR $BOTTLES_INTERFACE_JAR $BOTTLES_INTERFACE_INTERFACE_JAR ||
- die "ijar cannot produce class files with body longer than 64K"
-
-# Check that the interface jar is bigger than the original jar.
-W_JAR_SIZE=$(statfmt $W_JAR)
-W_INTERFACE_JAR_SIZE=$(statfmt $W_INTERFACE_JAR)
-[[ $W_INTERFACE_JAR_SIZE -gt $W_JAR_SIZE ]] || die "interface jar should be bigger"
-
-# Check that the number of entries is 5:
-# A, A.PrivateInner, A.PublicInner, A.MyAnnotation,
-# A.RuntimeAnnotation
-# (Note: even private inner classes are retained, so we don't need to change
-# the types of members.)
-lines=$($JAR tvf $A_INTERFACE_JAR | wc -l)
-expected=5
-check_eq $expected $lines "Interface jar should have $expected entries!"
-
-
-# Check that no private class members are found:
-lines=$($JAVAP -private -classpath $A_JAR A | grep priv | wc -l)
-check_eq 2 $lines "Input jar should have 2 private members!"
-lines=$($JAVAP -private -classpath $A_INTERFACE_JAR A | grep priv | wc -l)
-check_eq 0 $lines "Interface jar should have no private members!"
-lines=$($JAVAP -private -classpath $A_INTERFACE_JAR A | grep clinit | wc -l)
-check_eq 0 $lines "Interface jar should have no class initializers!"
-
-
-# Check that no code is found:
-lines=$($JAVAP -c -private -classpath $A_JAR A | grep Code: | wc -l)
-check_eq 5 $lines "Input jar should have 5 method bodies!"
-lines=$($JAVAP -c -private -classpath $A_INTERFACE_JAR A | grep Code: | wc -l)
-check_eq 0 $lines "Interface jar should have no method bodies!"
-
-
-# Check that constants from code are no longer present:
-$JAVAP -c -private -classpath $A_JAR A | grep -sq foofoofoofoo ||
- die "Input jar should have code constants!"
-$JAVAP -c -private -classpath $A_INTERFACE_JAR A | grep -sq foofoofoofoo &&
- die "Interface jar should have no code constants!"
-
-
-# Check (important, this!) that the interface jar is still sufficient
-# for compiling:
-$JAVAC -Xlint -classpath $A_INTERFACE_JAR -g -d $TEST_TMPDIR/classes \
- $IJAR_SRCDIR/test/B.java 2>$TEST_TMPDIR/B.javac.err ||
- { cat $TEST_TMPDIR/B.javac.err >&2; die "Can't compile B!"; }
-
-
-# Test compilation of B yielded deprecation message:
-grep -sq 'deprecatedMethod.*in A has been deprecated' \
- $TEST_TMPDIR/B.javac.err || die "ijar has lost @Deprecated annotation!"
-
-
-# Check idempotence of ijar transformation:
-A_INTERFACE_INTERFACE_JAR=$TEST_TMPDIR/A-interface-interface.jar
-$IJAR $A_INTERFACE_JAR $A_INTERFACE_INTERFACE_JAR || die "ijar failed."
-cmp $A_INTERFACE_JAR $A_INTERFACE_INTERFACE_JAR ||
- die "ijar transformation is not idempotent"
-
-
-# Check that -interface.jar contains nothing but .class files:
-check_eq 0 $($JAR tf $A_INTERFACE_JAR | grep -v \\.class$ | wc -l) \
+ $JAVAC -g -d $TEST_TMPDIR/classes $BOTTLES_JAVA || fail "javac failed"
+ BOTTLES_INTERFACE_JAR=$TEST_TMPDIR/bottles-interface.jar
+
+ # Test ijar calls
+ for flag0 in '' '0'; do
+ $JAR c"${flag0}"f $BOTTLES_JAR -C $TEST_TMPDIR/classes . || fail "jar failed"
+ $IJAR $BOTTLES_JAR $BOTTLES_INTERFACE_JAR || fail "ijar failed"
+ check_consistent_file_contents $BOTTLES_INTERFACE_JAR
+ done
+
+ # Check that ijar can produce class files with a body longer than 64K by
+ # calling ijar itself on the output file to make sure that it is valid
+ BOTTLES_INTERFACE_INTERFACE_JAR=$TEST_TMPDIR/bottles-interface-interface.jar
+ $IJAR $BOTTLES_INTERFACE_JAR $BOTTLES_INTERFACE_INTERFACE_JAR ||
+ fail "ijar cannot produce class files with body longer than 64K"
+}
+
+function test_ijar_output() {
+ # Numerous check on the output created by ijar.
+
+ # Compiles A.java, builds A.jar and A-interface.jar
+ $JAVAC -g -d $TEST_TMPDIR/classes $IJAR_SRCDIR/test/A.java ||
+ fail "javac failed"
+ $JAR cf $A_JAR -C $TEST_TMPDIR/classes . || fail "jar failed"
+ $IJAR $A_JAR $A_INTERFACE_JAR || fail "ijar failed."
+
+ # Check that the number of entries is 5:
+ # A, A.PrivateInner, A.PublicInner, A.MyAnnotation,
+ # A.RuntimeAnnotation
+ # (Note: even private inner classes are retained, so we don't need to change
+ # the types of members.)
+ expected=5
+ lines=$($JAR tvf $A_INTERFACE_JAR | wc -l)
+ check_eq $expected $lines "Interface jar should have $expected entries!"
+
+ # Check that no private class members are found:
+ lines=$($JAVAP -private -classpath $A_JAR A | grep priv | wc -l)
+ check_eq 2 $lines "Input jar should have 2 private members!"
+ lines=$($JAVAP -private -classpath $A_INTERFACE_JAR A | grep priv | wc -l)
+ check_eq 0 $lines "Interface jar should have no private members!"
+ lines=$($JAVAP -private -classpath $A_INTERFACE_JAR A | grep clinit | wc -l)
+ check_eq 0 $lines "Interface jar should have no class initializers!"
+
+
+ # Check that no code is found:
+ lines=$($JAVAP -c -private -classpath $A_JAR A | grep Code: | wc -l)
+ check_eq 5 $lines "Input jar should have 5 method bodies!"
+ lines=$($JAVAP -c -private -classpath $A_INTERFACE_JAR A | grep Code: | wc -l)
+ check_eq 0 $lines "Interface jar should have no method bodies!"
+
+ # Check that constants from code are no longer present:
+ $JAVAP -c -private -classpath $A_JAR A | grep -sq foofoofoofoo ||
+ fail "Input jar should have code constants!"
+ $JAVAP -c -private -classpath $A_INTERFACE_JAR A | grep -sq foofoofoofoo &&
+ fail "Interface jar should have no code constants!"
+
+
+ # Check (important, this!) that the interface jar is still sufficient
+ # for compiling:
+ $JAVAC -Xlint -classpath $A_INTERFACE_JAR -g -d $TEST_TMPDIR/classes \
+ $IJAR_SRCDIR/test/B.java 2>$TEST_log || fail "Can't compile B!"
+
+ # Test compilation of B yielded deprecation message:
+ expect_log 'deprecatedMethod.*in A has been deprecated' \
+ "ijar has lost @Deprecated annotation!"
+
+ # Run the dynamic checks in B.main().
+ $JAVA -classpath $TEST_TMPDIR/classes B || exit 1
+
+ # Check idempotence of ijar transformation:
+ A_INTERFACE_INTERFACE_JAR=$TEST_TMPDIR/A-interface-interface.jar
+ $IJAR $A_INTERFACE_JAR $A_INTERFACE_INTERFACE_JAR || fail "ijar failed."
+ cmp $A_INTERFACE_JAR $A_INTERFACE_INTERFACE_JAR ||
+ fail "ijar transformation is not idempotent"
+
+
+ # Check that -interface.jar contains nothing but .class files:
+ check_eq 0 $($JAR tf $A_INTERFACE_JAR | grep -v \\.class$ | wc -l) \
"Interface jar should contain only .class files!"
-# Check that -interface.jar timestamps are all zeros:
-check_eq 0 $(TZ=UTC $JAR tvf $A_INTERFACE_JAR |
- grep -v 'Fri Nov 30 00:00:00 UTC 1979' | wc -l) \
- "Interface jar contained non-zero timestamps!"
+ # Check that -interface.jar timestamps are all zeros:
+ check_eq 0 $(TZ=UTC $JAR tvf $A_INTERFACE_JAR |
+ grep -v 'Fri Nov 30 00:00:00 UTC 1979' | wc -l) \
+ "Interface jar contained non-zero timestamps!"
+
+
+ # Check that compile-time constants in A are still annotated as such in ijar:
+ $JAVAP -classpath $TEST_TMPDIR/classes -c B | grep -sq ldc2_w.*123 ||
+ fail "ConstantValue not propagated to class B!"
-# Check that compile-time constants in A are still annotated as such in ijar:
-$JAVAP -classpath $TEST_TMPDIR/classes -c B | grep -sq ldc2_w.*123 ||
- die "ConstantValue not propagated to class B!"
+ # Check that a jar compressed with zip results in the same interface jar as a
+ # jar compressed with jar
+ rm -fr $TEST_TMPDIR/classes
+ mkdir -p $TEST_TMPDIR/classes || fail "mkdir $TEST_TMPDIR/classes failed"
+ $JAVAC -g -d $TEST_TMPDIR/classes $IJAR_SRCDIR/test/A.java ||
+ fail "javac failed"
+ $JAR cf $A_JAR $TEST_TMPDIR/classes/A.class || fail "jar failed"
+ $ZIP $A_ZIP_JAR $TEST_TMPDIR/classes/A.class || fail "zip failed"
-# Regression test for jar file without classes (javac doesn't like an empty ijar).
->$TEST_TMPDIR/empty
-$ZIP $TEST_TMPDIR/noclasses.jar $TEST_TMPDIR/empty >/dev/null 2>&1
-$IJAR $TEST_TMPDIR/noclasses.jar || die "ijar failed"
-$UNZIP -qql $TEST_TMPDIR/noclasses-interface.jar 2>/dev/null | grep -q . ||
- die "noclasses-interface.jar is completely empty!"
- $JAVAC -classpath $TEST_TMPDIR/noclasses-interface.jar \
+ $IJAR $A_JAR $A_INTERFACE_JAR || fail "ijar failed"
+ $IJAR $A_ZIP_JAR $A_ZIP_INTERFACE_JAR || fail "ijar failed"
+ cmp $A_INTERFACE_JAR $A_ZIP_INTERFACE_JAR || \
+ fail "ijars from jar and zip are different"
+}
+
+function do_test_large_file() {
+ # Compiles A.java, builds A.jar and A-interface.jar
+ $JAVAC -g -d $TEST_TMPDIR/classes $IJAR_SRCDIR/test/A.java ||
+ fail "javac failed"
+
+ # First a check without large file to have something to compare to.
+ for flag0 in '' '0'; do
+ $JAR c"${flag0}"f $A_JAR -C $TEST_TMPDIR/classes . || fail "jar failed"
+ $IJAR $A_JAR $A_INTERFACE_JAR || fail "ijar failed."
+ check_consistent_file_contents $A_INTERFACE_JAR
+ done
+
+ # Then create larges files
+ extra_args=""
+ if [[ -n "${1-}" ]]; then
+ for file in $(find $TEST_TMPDIR/classes -name '*.class'); do
+ set_file_length "$file" "$1"
+ done
+ fi
+ if [[ -n "${2-}" ]]; then
+ set_file_length $TEST_TMPDIR/zeroes.data "$2"
+ extra_args="-C $TEST_TMPDIR zeroes.data"
+ fi
+
+ for flag0 in '' '0'; do
+ $JAR c"${flag0}"f $A_JAR $extra_args -C $TEST_TMPDIR/classes . || fail "jar failed"
+ $IJAR $A_JAR $A_INTERFACE_JAR || fail "ijar failed."
+ check_consistent_file_contents $A_INTERFACE_JAR
+ done
+}
+
+function test_large_files() {
+ # Ensure input files larger than INITIAL_BUFFER_SIZE work.
+ # TODO(martinrb): remove maximum .class file size limit (MAX_BUFFER_SIZE)
+ for size in $((1024*1024)) $((15*1024*1024)); do
+ do_test_large_file $size
+ done
+}
+
+# Create a huge (~2.2Gb) input jar to test "large file" correctness
+function test_z_2gb_plus_data_file() {
+ # This is slow because only writing a 2.2Gb file on a SSD drive is >10s and
+ # jaring it takes >16s.
+ # The z letter in the function name is to ensure that method is last in the
+ # method list so it has more chance to be alone on a shard.
+ do_test_large_file '' $((22*102*1024*1024))
+}
+
+# Create an output jar with upper bound on size > 2GB
+function test_upper_bound_up_2gb() {
+ DIR=$TEST_TMPDIR/ManyLargeClasses
+ mkdir -p $DIR/classes
+ for i in $(seq 200); do
+ printf "class C${i} {}\n" > $DIR/C${i}.java
+ done
+ (cd $DIR && $JAVAC -d classes *.java)
+ for i in $(seq 200); do
+ set_file_length $DIR/classes/C${i}.class $((15*1024*1024))
+ done
+ $JAR cf $DIR/ManyLargeClasses.jar -C $DIR/classes . || fail "jar failed"
+ $IJAR $DIR/ManyLargeClasses.jar $DIR/ManyLargeClasses.ijar || fail "ijar failed."
+}
+
+function test_empty_jar() {
+ # Regression test for jar file without classes (javac doesn't like an empty ijar).
+ >$TEST_TMPDIR/empty
+ $ZIP $TEST_TMPDIR/noclasses.jar $TEST_TMPDIR/empty >/dev/null 2>&1
+ $IJAR $TEST_TMPDIR/noclasses.jar || fail "ijar failed"
+ $UNZIP -qql $TEST_TMPDIR/noclasses-interface.jar 2>/dev/null | grep -q . ||
+ fail "noclasses-interface.jar is completely empty!"
+ $JAVAC -classpath $TEST_TMPDIR/noclasses-interface.jar \
-d $TEST_TMPDIR/classes \
$IJAR_SRCDIR/test/A.java ||
- die "javac noclasses-interface.jar failed"
-rm $TEST_TMPDIR/{empty,noclasses.jar,noclasses-interface.jar}
+ fail "javac noclasses-interface.jar failed"
+ rm $TEST_TMPDIR/{empty,noclasses.jar,noclasses-interface.jar}
+}
+
+function test_wrong_centraldir() {
+ # Check that a JAR file can be parsed even if the central directory file count
+ # is wrong
+ $IJAR $JAR_WRONG_CENTRAL_DIR $IJAR_WRONG_CENTRAL_DIR || fail "ijar failed"
+ IJAR_FILES=$($UNZIP -qql $IJAR_WRONG_CENTRAL_DIR | wc -l | xargs echo)
+ if [[ $IJAR_FILES != 2 ]]; then
+ fail "ijar removed files"
+ fi
+}
+function test_type_annotation() {
+ # Check that constant pool references used by JSR308 type annotations are
+ # preserved
+ $IJAR $TYPEANN2_JAR $TYPEANN2_IJAR || fail "ijar failed"
+ $JAVAP -classpath $TYPEANN2_IJAR -v Util >& $TEST_log || fail "javap failed"
+ expect_log "RuntimeVisibleTypeAnnotations" "RuntimeVisibleTypeAnnotations not preserved!"
+ cp $TYPEANN2_JAVA $TEST_TMPDIR/TypeAnnotationTest2.java
+ $JAVAC -J-Xbootclasspath/p:$LANGTOOLS8 $TEST_TMPDIR/TypeAnnotationTest2.java -cp $TYPEANN2_IJAR ||
+ fail "javac failed"
+}
-# Run the dynamic checks in B.main().
-$JAVA -classpath $TEST_TMPDIR/classes B || exit 1
+function test_invokedynamic() {
+ # Check that ijar works on classes with invokedynamic
+ $IJAR $INVOKEDYNAMIC_JAR $INVOKEDYNAMIC_IJAR || fail "ijar failed"
+ lines=$($JAVAP -c -private -classpath $INVOKEDYNAMIC_JAR ClassWithLambda | grep Code: | wc -l)
+ check_eq 4 $lines "Input jar should have 4 method bodies!"
+ lines=$($JAVAP -c -private -classpath $INVOKEDYNAMIC_IJAR ClassWithLambda | grep Code: | wc -l)
+ check_eq 0 $lines "Interface jar should have no method bodies!"
+}
-# TODO(bazel-team) test that modifying the source in a non-interface
-# changing way results in the same -interface.jar.
+function test_object_class() {
+ # Check that Object.class can be processed
+ mkdir -p $TEST_TMPDIR/java/lang
+ cp $OBJECT_JAVA $TEST_TMPDIR/java/lang/.
+ $JAVAC $TEST_TMPDIR/java/lang/Object.java || fail "javac failed"
+ $JAR cf $OBJECT_JAR -C $TEST_TMPDIR java/lang/Object.class || fail "jar failed"
+
+ $IJAR $OBJECT_JAR $OBJECT_IJAR || fail "ijar failed"
+}
+
+function test_corrupted_end_of_centraldir() {
+ # Check that the tool detects and reports a corrupted end of central directory
+ # record condition
+ CORRUPTED_JAR=$TEST_TMPDIR/corrupted.jar
+
+ # First make the jar one byte longer
+ cp $JAR_WRONG_CENTRAL_DIR $CORRUPTED_JAR
+ chmod +w $CORRUPTED_JAR
+ echo >> $CORRUPTED_JAR
+ echo "Abort trap is expected" # Show on the log that we expect failure.
+ $IJAR $CORRUPTED_JAR 2> $TEST_log && fail "ijar should have failed" || status=$?
+ check_ne 0 $status
+ expect_log "missing end of central directory record"
+
+ # Then make the jar one byte shorter than the original one
+ let "NEW_SIZE = `statfmt $CORRUPTED_JAR` - 2"
+ set_file_length $CORRUPTED_JAR $NEW_SIZE
+ $IJAR $CORRUPTED_JAR 2> $TEST_log && fail "ijar should have failed" || status=$?
+ check_ne 0 $status
+ expect_log "missing end of central directory record"
+}
-# Check that a jar compressed with zip results in the same interface jar as a
-# jar compressed with jar
-rm -fr $TEST_TMPDIR/classes
-mkdir -p $TEST_TMPDIR/classes || die "mkdir $TEST_TMPDIR/classes failed"
-$JAVAC -g -d $TEST_TMPDIR/classes $IJAR_SRCDIR/test/A.java ||
- die "javac failed"
-$JAR cf $A_JAR $TEST_TMPDIR/classes/A.class || die "jar failed"
-$ZIP $A_ZIP_JAR $TEST_TMPDIR/classes/A.class || die "zip failed"
-
-$IJAR $A_JAR $A_INTERFACE_JAR || die "ijar failed"
-$IJAR $A_ZIP_JAR $A_ZIP_INTERFACE_JAR || die "ijar failed"
-cmp $A_INTERFACE_JAR $A_ZIP_INTERFACE_JAR || \
- die "ijars from jar and zip are different"
-
-
-# Check that a JAR file can be parsed even if the central directory file count
-# is wrong
-$IJAR $JAR_WRONG_CENTRAL_DIR $IJAR_WRONG_CENTRAL_DIR || die "ijar failed"
-IJAR_FILES=$($UNZIP -qql $IJAR_WRONG_CENTRAL_DIR | wc -l | xargs echo)
-if [[ $IJAR_FILES != 2 ]]; then
- die "ijar removed files"
-fi
-
-# Check that constant pool references used by JSR308 type annotations are
-# preserved
-$IJAR $TYPEANN2_JAR $TYPEANN2_IJAR || die "ijar failed"
-$JAVAP -classpath $TYPEANN2_IJAR -v Util |
- grep -sq RuntimeVisibleTypeAnnotations ||
- die "RuntimeVisibleTypeAnnotations not preserved!"
-set -x
-cp $TYPEANN2_JAVA $TEST_TMPDIR/TypeAnnotationTest2.java
-$JAVAC -J-Xbootclasspath/p:$LANGTOOLS8 $TEST_TMPDIR/TypeAnnotationTest2.java -cp $TYPEANN2_IJAR ||
- die "javac failed"
-set +x
-
-# Check that ijar works on classes with invokedynamic
-$IJAR $INVOKEDYNAMIC_JAR $INVOKEDYNAMIC_IJAR || die "ijar failed"
-lines=$($JAVAP -c -private -classpath $INVOKEDYNAMIC_JAR ClassWithLambda | grep Code: | wc -l)
-check_eq 4 $lines "Input jar should have 4 method bodies!"
-lines=$($JAVAP -c -private -classpath $INVOKEDYNAMIC_IJAR ClassWithLambda | grep Code: | wc -l)
-check_eq 0 $lines "Interface jar should have no method bodies!"
-
-# Check that Object.class can be processed
-$IJAR $OBJECT_JAR $OBJECT_IJAR || die "ijar failed"
-
-# Check that the tool detects and reports a corrupted end of central directory
-# record condition
-CORRUPTED_JAR=$TEST_TMPDIR/corrupted.jar
-# First make the jar one byte longer
-cp $JAR_WRONG_CENTRAL_DIR $CORRUPTED_JAR
-chmod +w $CORRUPTED_JAR
-echo >> $CORRUPTED_JAR
-set +e
-capture_test_stderr
-$IJAR $CORRUPTED_JAR && die "ijar should have failed"
-status=$?
-set -e
-check_ne 0 $status
-grep_test_stderr "missing end of central directory record"
-restore_outputs
-# Then make the jar one byte shorter than the original one
-let "NEW_SIZE = `statfmt $CORRUPTED_JAR` - 2"
-set_file_length $CORRUPTED_JAR $NEW_SIZE
-set +e
-capture_test_stderr
-$IJAR $CORRUPTED_JAR && die "ijar should have failed"
-status=$?
-set -e
-check_ne 0 $status
-grep_test_stderr "missing end of central directory record"
-restore_outputs
-
-echo "PASS"
+run_suite "ijar tests"
diff --git a/third_party/ijar/test/testenv.sh b/third_party/ijar/test/testenv.sh
new file mode 100755
index 0000000000..e14aadf7a1
--- /dev/null
+++ b/third_party/ijar/test/testenv.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#
+# Copyright 2015 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Setting up the environment for Bazel integration tests.
+#
+
+[ -z "$TEST_SRCDIR" ] && { echo "TEST_SRCDIR not set!" >&2; exit 1; }
+
+# Load the unit-testing framework
+source "${TEST_SRCDIR}/src/test/shell/unittest.bash" || \
+ { echo "Failed to source unittest.bash" >&2; exit 1; }
+
+## Mac OS X stat and MD5
+PLATFORM="$(uname -s | tr 'A-Z' 'a-z')"
+if [[ "$PLATFORM" = "darwin" ]]; then
+ function statfmt() {
+ stat -f "%z" $1
+ }
+ MD5SUM=/sbin/md5
+else
+ function statfmt() {
+ stat -c "%s" $1
+ }
+ MD5SUM=md5sum
+fi