#!/bin/bash # # Copyright 2016 The Bazel Authors. 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. # # These are end to end tests for building Java. CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${CURRENT_DIR}/../shell_utils.sh" \ || { echo "shell_utils.sh not found!" >&2; exit 1; } # Load the test setup defined in the parent directory source "${CURRENT_DIR}/../integration_test_setup.sh" \ || { echo "integration_test_setup.sh not found!" >&2; exit 1; } set -eu declare -r runfiles_relative_javabase="$1" add_to_bazelrc "build --package_path=%workspace%" #### HELPER FUNCTIONS ################################################## function setup_local_jdk() { local -r dest="$1" local -r src="${BAZEL_RUNFILES}/${runfiles_relative_javabase}" mkdir -p "$dest" || fail "mkdir -p $dest" cp -LR "${src}"/* "$dest" || fail "cp -LR \"${src}\"/* \"$dest\"" chmod -R ug+rwX "$dest" || fail "chmod -R ug+rwX \"$dest\"" } function write_hello_world_files() { local pkg="$1" mkdir -p $pkg/java/hello || fail "mkdir" cat >$pkg/java/hello/BUILD <$pkg/java/hello/Hello.java <$pkg/java/hello/BUILD <$pkg/java/hello/Hello.java < 1 && !keyValue[1].equals(value)) { System.err.println("Value for key '" + keyValue[0] + "' is '" + value + "' while it should be '" + keyValue[1] + "'"); printMap(properties); return; } } System.out.println("Hello, World!"); } } EOF } function write_hello_library_files() { local -r pkg="$1" mkdir -p $pkg/java/main || fail "mkdir" cat >$pkg/java/main/BUILD <$pkg/java/main/Main.java <$pkg/java/hello_library/BUILD <$pkg/java/hello_library/HelloLibrary.java <$pkg/java/hellosailor/BUILD <$pkg/java/hellosailor/HelloSailor.java < "$pkg/jvm/BUILD" <&"$TEST_log" \ || fail "Build failed" mkdir $pkg/ugly/ || fail "mkdir failed" # The stub script follows symlinks, so copy the files. cp ${PRODUCT_NAME}-bin/$pkg/java/hello/hello $pkg/ugly/ cp ${PRODUCT_NAME}-bin/$pkg/java/hello/hello_deploy.jar $pkg/ugly/ $pkg/ugly/hello build.target build.time build.timestamp \ main.class=hello.Hello "$expected_build_data" >> $TEST_log 2>&1 expect_log 'Hello, World!' } function test_singlejar_with_default_jdk_with_stamp() { local -r pkg="${FUNCNAME[0]}" assert_singlejar_works "$pkg" true "--stamp" "--embed_label=toto" \ "build.label=toto" } # Regression test for b/17658100, ensure that --nostamp generate correct # build-info.properties file. function test_singlejar_with_default_jdk_without_stamp() { local -r pkg="${FUNCNAME[0]}" assert_singlejar_works "$pkg" true "--nostamp" "--embed_label=" \ "build.timestamp.as.int=0" } # Regression test for b/3244955, to ensure that running the deploy jar works # even without the runfiles available. function test_singlejar_with_custom_jdk_with_stamp() { local -r pkg="${FUNCNAME[0]}" assert_singlejar_works "$pkg" false "--stamp" "--embed_label=toto" \ "build.label=toto" } function test_singlejar_with_custom_jdk_without_stamp() { local -r pkg="${FUNCNAME[0]}" assert_singlejar_works "$pkg" false "--nostamp" "--embed_label=" \ "build.timestamp.as.int=0" } # Regression test for b/18191163: ensure that the build is deterministic when # used with --nostamp. function test_deterministic_nostamp_build() { local -r pkg="${FUNCNAME[0]}" mkdir "$pkg" || fail "mkdir $pkg" write_hello_world_files "$pkg" bazel clean || fail "Clean failed" bazel build --nostamp //$pkg/java/hello:hello_deploy.jar \ || fail "Build failed" # TODO(bazel-team) .a files (C/C++ static library file generated by # archive tool) on darwin OS only are not deterministic. # https://github.com/bazelbuild/bazel/issues/3156 local -r first_run="$(md5_file $(find "${PRODUCT_NAME}-out/" -type f '!' \ -name build-changelist.txt -a '!' -name volatile-status.txt \ -a '!' -name 'stderr-*' -a '!' -name '*.a' \ -a '!' -name __xcodelocatorcache -a '!' -name __xcruncache \ | sort -u))" sleep 1 # Ensure the timestamp change between builds. bazel clean || fail "Clean failed" bazel build --nostamp //$pkg/java/hello:hello_deploy.jar \ || fail "Build failed" local -r second_run="$(md5_file $(find "${PRODUCT_NAME}-out/" -type f '!' \ -name build-changelist.txt -a '!' -name volatile-status.txt \ -a '!' -name 'stderr-*' -a '!' -name '*.a' \ -a '!' -name __xcodelocatorcache -a '!' -name __xcruncache \ | sort -u))" assert_equals "$first_run" "$second_run" } function test_compiles_hello_library() { local -r pkg="${FUNCNAME[0]}" mkdir "$pkg" || fail "mkdir $pkg" write_hello_library_files "$pkg" bazel clean bazel build //$pkg/java/main:main || fail "build failed" ${PRODUCT_NAME}-bin/$pkg/java/main/main \ | grep -q "Hello, Library!;Hello, World!" || fail "comparison failed" bazel run //$pkg/java/main:main -- --singlejar && fail "deploy jar should not exist" true # reset the last exit code so the test won't be considered failed } function test_compiles_hello_library_using_ijars() { local -r pkg="${FUNCNAME[0]}" mkdir "$pkg" || fail "mkdir $pkg" write_hello_library_files "$pkg" bazel clean bazel build --use_ijars //$pkg/java/main:main || fail "build failed" ${PRODUCT_NAME}-bin/$pkg/java/main/main \ | grep -q "Hello, Library!;Hello, World!" || fail "comparison failed" } function test_compiles_hello_library_from_deploy_jar() { local -r pkg="${FUNCNAME[0]}" mkdir "$pkg" || fail "mkdir $pkg" write_hello_library_files "$pkg" bazel build //$pkg/java/main:main_deploy.jar || fail "build failed" ${PRODUCT_NAME}-bin/$pkg/java/main/main --singlejar \ | grep -q "Hello, Library!;Hello, World!" || fail "comparison failed" unzip -p ${PRODUCT_NAME}-bin/$pkg/java/main/main_deploy.jar META-INF/MANIFEST.MF \ | grep -q "k1: v1" || fail "missing manifest lines" unzip -p ${PRODUCT_NAME}-bin/$pkg/java/main/main_deploy.jar META-INF/MANIFEST.MF \ | grep -q "k2: v2" || fail "missing manifest lines" } function test_building_deploy_jar_twice_does_not_rebuild() { local -r pkg="${FUNCNAME[0]}" mkdir "$pkg" || fail "mkdir $pkg" write_hello_library_files "$pkg" bazel build //$pkg/java/main:main_deploy.jar || fail "build failed" touch -r ${PRODUCT_NAME}-bin/$pkg/java/main/main_deploy.jar old bazel build //$pkg/java/main:main_deploy.jar || fail "build failed" find ${PRODUCT_NAME}-bin/$pkg/java/main/main_deploy.jar -newer old \ | grep -q . && fail "file was rebuilt" true # reset the last exit code so the test won't be considered failed } function test_does_not_create_executable_when_not_asked_for() { local -r pkg="${FUNCNAME[0]}" mkdir "$pkg" || fail "mkdir $pkg" write_hello_sailor_files "$pkg" bazel build //$pkg/java/hellosailor:hellosailor_deploy.jar \ || fail "build failed" if [[ ! -e ${PRODUCT_NAME}-bin/$pkg/java/hellosailor/hellosailor.jar ]]; then fail "output jar does not exist"; fi if [[ -e ${PRODUCT_NAME}-bin/$pkg/java/hellosailor/hellosailor ]]; then fail "output executable should not exist"; fi if [[ ! -e ${PRODUCT_NAME}-bin/$pkg/java/hellosailor/hellosailor_deploy.jar ]]; then fail "output deploy jar does not exist"; fi } # Assert that the a deploy jar can be a dependency of another java_binary. function test_building_deploy_jar_dependent_on_deploy_jar() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/deploy || fail "mkdir" cat > $pkg/java/deploy/BUILD <$pkg/java/deploy/Hello.java <$pkg/hello/BUILD echo "Some other File" >$pkg/hello/Test.txt bazel build //$pkg/java/deploy:Hello_deploy.jar || fail "build failed" unzip -p ${PRODUCT_NAME}-bin/$pkg/java/deploy/Hello_deploy.jar \ $pkg/hello/Test.txt | grep -q "Some other File" || fail "missing resource" } function test_wrapper_script_arg_handling() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/hello/ || fail "Expected success" cat > $pkg/java/hello/Test.java < $pkg/java/hello/BUILD <&$TEST_log || fail "Build failed" expect_log "Args: '' 'foo' '' '' 'bar quux' ''" } function test_srcjar_compilation() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/hello/ || fail "Expected success" cat > $pkg/java/hello/Test.java < $pkg/java/hello/BUILD <&$TEST_log || fail "Expected success" bazel run //$pkg/java/hello:hello -- --singlejar >&$TEST_log expect_log "Hello World!" } function test_private_initializers() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/hello/ || fail "Expected success" cat > $pkg/java/hello/A.java < $pkg/java/hello/B.java < $pkg/java/hello/C.java < $pkg/java/hello/App.java < $pkg/java/hello/BUILD <$pkg/java/test/processor/BUILD <$pkg/java/test/processor/TestAnnotation.java <$pkg/java/test/processor/ProcessorDep.java <$pkg/java/test/processor/Processor.java < annotations, RoundEnvironment roundEnv) { Filer filer = mainEnvironment.getFiler(); try { FileObject output = filer.createSourceFile("test.Generated"); Writer writer = output.openWriter(); writer.append(OUTFILE_CONTENT); writer.close(); } catch (IOException ex) { return false; } return true; } } EOF mkdir -p $pkg/java/test/client cat >$pkg/java/test/client/BUILD <$pkg/java/test/client/ProcessorClient.java < $TEST_log expect_log " test/Generated.class" "missing class file from annotation processing" bazel build //$pkg/java/test/client:libclient-src.jar --use_ijars \ || fail "build failed" unzip -l ${PRODUCT_NAME}-bin/$pkg/java/test/client/libclient-src.jar > $TEST_log expect_log " test/Generated.java" "missing source file from annotation processing" } function test_jvm_flags_are_passed_verbatim() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/com/google/jvmflags || fail "mkdir" cat >$pkg/java/com/google/jvmflags/BUILD <$pkg/java/com/google/jvmflags/Foo.java <$pkg/java/classpath/BUILD <$pkg/java/classpath/Classpath.java <<'EOF' package classpath; public class Classpath { public static void main(String[] args) { String cp = System.getProperty("java.class.path"); String[] jars = cp.split(":"); // TODO(bazel-team): this is ";" on Windows boolean singlejar = (args.length > 1 && args[1].equals("SINGLEJAR")); System.out.printf("CLASSPATH=%s%n", cp); if (jars.length != 2 && !singlejar) { throw new Error("Unexpected class path length"); } String jarRegex = args[0]; for (String jar : jars) { if (!jar.matches(jarRegex)) { throw new Error("No match for regex: " + jarRegex); } if (!new java.io.File(jar).exists()) { throw new Error("No such file: " + jar); } } } } EOF bazel clean bazel build //$pkg/java/classpath || fail "build failed" bazel run //$pkg/java/classpath -- \ "^$pkg/java/(classpath|hello_library)/.*\.jar\$" || fail "bazel run" local PROG="${PRODUCT_NAME}-bin/$pkg/java/classpath/classpath" function check_classpath_invocations() { "$PROG" "^${PRODUCT_NAME}-bin/.*\.jar\$" "$@" \ || fail "direct run relative classpath $*" "./$PROG" "^\./${PRODUCT_NAME}-bin/.*\.jar\$" "$@" \ || fail "direct run '.'-relative classpath $*" "$PWD/$PROG" "^${PRODUCT_NAME}-bin/.*\.jar\$" "$@" \ || fail "direct run absolute classpath $*" (PROG="$PWD/$PROG"; cd / && exec "$PROG" '^/.*\.jar$' "$@") \ || fail "direct run from / absolute classpath $*" } check_classpath_invocations # Test --singlejar and --wrapper_script_flag bazel build //$pkg/java/classpath:classpath_deploy.jar || fail "build failed" for prog in "$PROG" "./$PROG" "$PWD/$PROG"; do "$prog" --singlejar '.*_deploy.jar$' "SINGLEJAR" \ || fail "$prog --singlejar" "$prog" '.*_deploy.jar$' "SINGLEJAR" --wrapper_script_flag=--singlejar \ || fail "$prog --wrapper_script_flag=--singlejar" done } function test_java7() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/foo/ || fail "Expected success" cat > $pkg/java/foo/Foo.java < list = new ArrayList<>(); // In Java 7 language only System.out.println("Success!"); } } EOF cat > $pkg/java/foo/BUILD < $TEST_log expect_log " hello_library/HelloLibrary.class" \ "missing class file from header compilation" } function test_header_compilation_errors() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/test/ || fail "Expected success" cat > $pkg/java/test/A.java < $pkg/java/test/B.java < $pkg/java/test/BUILD <& "$TEST_log" && fail "Unexpected success" expect_log "package missing does not exist" } function test_java_import_with_empty_jars_attribute() { local -r pkg="${FUNCNAME[0]}" mkdir -p $pkg/java/hello/ || fail "Expected success" cat > $pkg/java/hello/Hello.java < $pkg/java/hello/BUILD <& "$TEST_log" \ || fail "Expected success" bazel run //$pkg/java/hello:hello -- --singlejar >& "$TEST_log" expect_log "Hello World!" } run_suite "Java integration tests"