| #!/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 <<EOF |
| java_binary(name = 'hello', |
| srcs = ['Hello.java'], |
| main_class = 'hello.Hello') |
| EOF |
| |
| cat >$pkg/java/hello/Hello.java <<EOF |
| package hello; |
| public class Hello { |
| public static void main(String[] args) { |
| System.out.println("Hello, World!"); |
| } |
| } |
| EOF |
| } |
| |
| function write_hello_world_files_for_singlejar() { |
| local -r pkg="$1" |
| mkdir -p $pkg/java/hello || fail "mkdir" |
| cat >$pkg/java/hello/BUILD <<EOF |
| java_binary(name = 'hello', |
| srcs = ['Hello.java'], |
| main_class = 'hello.Hello') |
| EOF |
| |
| cat >$pkg/java/hello/Hello.java <<EOF |
| package hello; |
| import java.util.Properties; |
| public class Hello { |
| private static void printMap(Properties p) { |
| System.err.println("Available keys and values are:"); |
| for (Object key : p.keySet()) { |
| System.err.printf(" '%s': '%s'%n", key, p.get(key)); |
| } |
| } |
| |
| public static void main(String[] args) throws Exception { |
| Properties properties = new Properties(); |
| properties.load(Hello.class.getResourceAsStream("/build-data.properties")); |
| for (String arg : args) { |
| String[] keyValue = arg.split("=", 2); |
| Object value = properties.get(keyValue[0]); |
| if (value == null) { |
| System.err.println("Key '" + keyValue[0] + "' not found"); |
| printMap(properties); |
| return; |
| } |
| if (keyValue.length > 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 <<EOF |
| java_binary( |
| name = 'main', |
| deps = ['//$pkg/java/hello_library'], |
| srcs = ['Main.java'], |
| main_class = 'main.Main', |
| deploy_manifest_lines = ['k1: v1', 'k2: v2']) |
| EOF |
| |
| cat >$pkg/java/main/Main.java <<EOF |
| package main; |
| import hello_library.HelloLibrary; |
| public class Main { |
| public static void main(String[] args) { |
| HelloLibrary.funcHelloLibrary(); |
| System.out.println("Hello, World!"); |
| } |
| } |
| EOF |
| |
| mkdir -p $pkg/java/hello_library || fail "mkdir" |
| cat >$pkg/java/hello_library/BUILD <<EOF |
| package(default_visibility=['//visibility:public']) |
| java_library(name = 'hello_library', |
| srcs = ['HelloLibrary.java']); |
| EOF |
| |
| cat >$pkg/java/hello_library/HelloLibrary.java <<EOF |
| package hello_library; |
| public class HelloLibrary { |
| public static void funcHelloLibrary() { |
| System.out.print("Hello, Library!;"); |
| } |
| } |
| EOF |
| } |
| |
| function write_hello_sailor_files() { |
| local -r pkg="$1" |
| mkdir -p $pkg/java/hellosailor || fail "mkdir" |
| cat >$pkg/java/hellosailor/BUILD <<EOF |
| java_binary(name = 'hellosailor', |
| srcs = ['HelloSailor.java'], |
| create_executable = 0) |
| EOF |
| |
| cat >$pkg/java/hellosailor/HelloSailor.java <<EOF |
| package hellosailor; |
| public class HelloSailor { |
| public static int addtwoNumbers(int a, int b) { |
| return a + b; |
| } |
| } |
| EOF |
| } |
| |
| |
| #### TESTS ############################################################# |
| |
| # This test intentionally show some errors on the standard output. |
| function test_compiles_hello_world() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_world_files "$pkg" |
| |
| bazel clean |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello || fail "build failed" |
| ${PRODUCT_NAME}-bin/$pkg/java/hello/hello | grep -q 'Hello, World!' \ |
| || fail "comparison failed" |
| function check_deploy_jar_should_not_exist() { |
| "$@" && fail "deploy jar should not exist" |
| true # reset the last exit code so the test won't be considered failed |
| } |
| function check_arglists() { |
| check_deploy_jar_should_not_exist "$@" --singlejar |
| check_deploy_jar_should_not_exist "$@" --wrapper_script_flag=--singlejar |
| check_deploy_jar_should_not_exist "$@" REGULAR_ARG \ |
| --wrapper_script_flag=--singlejar |
| } |
| check_arglists bazel run //$pkg/java/hello:hello -- |
| check_arglists ${PRODUCT_NAME}-bin/$pkg/java/hello/hello |
| } |
| |
| function test_compiles_hello_world_remote_java_tools() { |
| test_compiles_hello_world \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_compiles_hello_world_from_deploy_jar() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_world_files "$pkg" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello_deploy.jar || fail "build failed" |
| |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello -- --singlejar | grep -q 'Hello, World!' \ |
| || fail "comparison failed" |
| ${PRODUCT_NAME}-bin/$pkg/java/hello/hello -- --singlejar | \ |
| grep -q 'Hello, World!' || fail "comparison failed" |
| |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello -- --wrapper_script_flag=--singlejar \ |
| | grep -q 'Hello, World!' || fail "comparison failed" |
| ${PRODUCT_NAME}-bin/$pkg/java/hello/hello -- \ |
| --wrapper_script_flag=--singlejar | grep -q 'Hello, World!' \ |
| || fail "comparison failed" |
| |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello -- REGULAR_ARG \ |
| --wrapper_script_flag=--singlejar | grep -q 'Hello, World!' \ |
| || fail "comparison failed" |
| ${PRODUCT_NAME}-bin/$pkg/java/hello/hello -- REGULAR_ARG \ |
| --wrapper_script_flag=--singlejar | grep -q 'Hello, World!' \ |
| || fail "comparison failed" |
| } |
| |
| function test_compiles_hello_world_from_deploy_jar_remote_java_tools() { |
| test_compiles_hello_world_from_deploy_jar \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_explicit_bogus_wrapper_args_are_rejected() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_world_files "$pkg" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello_deploy.jar || fail "build failed" |
| function check_arg_rejected() { |
| "$@" && fail "bogus arg should be rejected" |
| true # reset the last exit code so the test won't be considered failed |
| } |
| function check_arglists() { |
| check_arg_rejected "$@" --wrapper_script_flag=--bogus |
| check_arg_rejected "$@" REGULAR_ARG --wrapper_script_flag=--bogus |
| } |
| check_arglists bazel run //$pkg/java/hello:hello -- |
| check_arglists ${PRODUCT_NAME}-bin/$pkg/java/hello/hello |
| } |
| |
| function test_explicit_bogus_wrapper_args_are_rejected_remote_java_tools() { |
| test_explicit_bogus_wrapper_args_are_rejected \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| function assert_singlejar_works() { |
| local -r pkg="$1" |
| local -r copy_jdk="$2" |
| local -r stamp_arg="$3" |
| local -r embed_label="$4" |
| local -r expected_build_data="$5" |
| |
| write_hello_world_files_for_singlejar "$pkg" |
| |
| if "$copy_jdk"; then |
| local -r local_jdk="$pkg/my_jdk" |
| setup_local_jdk "$local_jdk" |
| |
| ln -s "my_jdk" "$pkg/my_jdk.symlink" |
| local -r javabase="$(get_real_path "$pkg/my_jdk.symlink")" |
| else |
| local -r javabase="${BAZEL_RUNFILES}/${runfiles_relative_javabase}" |
| fi |
| |
| mkdir -p "$pkg/jvm" |
| cat > "$pkg/jvm/BUILD" <<EOF |
| package(default_visibility=["//visibility:public"]) |
| java_runtime(name='runtime', java_home='$javabase') |
| EOF |
| |
| |
| # Set javabase to an absolute path. |
| bazel build //$pkg/java/hello:hello //$pkg/java/hello:hello_deploy.jar \ |
| "$stamp_arg" --javabase="//$pkg/jvm:runtime" "$embed_label" >&"$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() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_world_files "$pkg" |
| |
| bazel clean || fail "Clean failed" |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} --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_deterministic_nostamp_build_remote_java_tools() { |
| test_deterministic_nostamp_build \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_compiles_hello_library() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_library_files "$pkg" |
| |
| bazel clean |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$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 ${bazel_opts[@]+"${bazel_opts[@]}"} //$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_remote_java_tools() { |
| test_compiles_hello_library \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_compiles_hello_library_using_ijars() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_library_files "$pkg" |
| |
| bazel clean |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} --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_using_ijars_remote_java_tools() { |
| test_compiles_hello_library_using_ijars \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_compiles_hello_library_from_deploy_jar() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_library_files "$pkg" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$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_compiles_hello_library_from_deploy_jar_remote_java_tools() { |
| test_compiles_hello_library_from_deploy_jar \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_building_deploy_jar_twice_does_not_rebuild() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_library_files "$pkg" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/main:main_deploy.jar || fail "build failed" |
| touch -r ${PRODUCT_NAME}-bin/$pkg/java/main/main_deploy.jar old |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$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_building_deploy_jar_twice_does_not_rebuild_remote_java_tools() { |
| test_building_deploy_jar_twice_does_not_rebuild \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_does_not_create_executable_when_not_asked_for() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_sailor_files "$pkg" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$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 |
| } |
| |
| function test_does_not_create_executable_when_not_asked_for_remote_java_tools() { |
| test_does_not_create_executable_when_not_asked_for \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| # Assert that the a deploy jar can be a dependency of another java_binary. |
| function test_building_deploy_jar_dependent_on_deploy_jar() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/deploy || fail "mkdir" |
| cat > $pkg/java/deploy/BUILD <<EOF |
| java_binary(name = 'Hello', |
| srcs = ['Hello.java'], |
| deps = ['Other_deploy.jar'], |
| main_class = 'hello.Hello') |
| java_binary(name = 'Other', |
| resources = ['//$pkg/hello:Test.txt'], |
| main_class = 'none') |
| EOF |
| |
| cat >$pkg/java/deploy/Hello.java <<EOF |
| package deploy; |
| public class Hello { |
| public static void main(String[] args) { |
| System.out.println("Hello, World!"); |
| } |
| } |
| EOF |
| |
| mkdir -p $pkg/hello |
| echo "exports_files(['Test.txt'])" >$pkg/hello/BUILD |
| echo "Some other File" >$pkg/hello/Test.txt |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$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_building_deploy_jar_dependent_on_deploy_jar_remote_java_tools() { |
| test_building_deploy_jar_dependent_on_deploy_jar \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_wrapper_script_arg_handling() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/hello/ || fail "Expected success" |
| cat > $pkg/java/hello/Test.java <<EOF |
| package hello; |
| public class Test { |
| public static void main(String[] args) { |
| System.out.print("Args:"); |
| for (String arg : args) { |
| System.out.print(" '" + arg + "'"); |
| } |
| System.out.println(); |
| } |
| } |
| EOF |
| |
| cat > $pkg/java/hello/BUILD <<EOF |
| java_binary(name='hello', srcs=['Test.java'], main_class='hello.Test') |
| EOF |
| |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello -- '' foo '' '' 'bar quux' '' \ |
| >&$TEST_log || fail "Build failed" |
| expect_log "Args: '' 'foo' '' '' 'bar quux' ''" |
| } |
| |
| function test_wrapper_script_arg_handling_remote_java_tools() { |
| test_wrapper_script_arg_handling \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_srcjar_compilation() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/hello/ || fail "Expected success" |
| cat > $pkg/java/hello/Test.java <<EOF |
| package hello; |
| public class Test { |
| public static void main(String[] args) { |
| System.out.println("Hello World!"); |
| } |
| } |
| EOF |
| cd $pkg |
| zip -q java/hello/test.srcjar java/hello/Test.java || fail "zip failed" |
| cd .. |
| |
| cat > $pkg/java/hello/BUILD <<EOF |
| java_binary(name='hello', srcs=['test.srcjar'], main_class='hello.Test') |
| EOF |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello //$pkg/java/hello:hello_deploy.jar \ |
| >&$TEST_log || fail "Expected success" |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello -- --singlejar >&$TEST_log |
| expect_log "Hello World!" |
| } |
| |
| function test_srcjar_compilation_remote_java_tools() { |
| test_srcjar_compilation \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_private_initializers() { |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/hello/ || fail "Expected success" |
| |
| cat > $pkg/java/hello/A.java <<EOF |
| package hello; |
| public class A { private B b; } |
| EOF |
| |
| cat > $pkg/java/hello/B.java <<EOF |
| package hello; |
| public class B { private C c; } |
| EOF |
| |
| cat > $pkg/java/hello/C.java <<EOF |
| package hello; |
| public class C {} |
| EOF |
| |
| # This definition is only to make sure that A's interface is built. |
| cat > $pkg/java/hello/App.java <<EOF |
| package hello; |
| public class App { } |
| EOF |
| |
| cat > $pkg/java/hello/BUILD <<EOF |
| java_library(name = 'app', |
| srcs = ['App.java'], |
| deps = [':a']) |
| |
| java_library(name = 'a', |
| srcs = ['A.java'], |
| deps = [':b']) |
| |
| java_library(name = 'b', |
| srcs = ['B.java'], |
| deps = [':c']) |
| |
| java_library(name = 'c', |
| srcs = ['C.java']) |
| EOF |
| |
| bazel build //$pkg/java/hello:app || fail "Expected success" |
| } |
| |
| function test_java_plugin() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/test/processor || fail "mkdir" |
| |
| cat >$pkg/java/test/processor/BUILD <<EOF |
| package(default_visibility=['//visibility:public']) |
| |
| java_library(name = 'annotation', |
| srcs = [ 'TestAnnotation.java' ]) |
| |
| java_library(name = 'processor_dep', |
| srcs = [ 'ProcessorDep.java' ]) |
| |
| java_plugin(name = 'processor', |
| processor_class = 'test.processor.Processor', |
| deps = [ ':annotation', ':processor_dep' ], |
| srcs = [ 'Processor.java' ]) |
| EOF |
| |
| cat >$pkg/java/test/processor/TestAnnotation.java <<EOF |
| package test.processor; |
| import java.lang.annotation.*; |
| @Target(value = {ElementType.TYPE}) |
| |
| public @interface TestAnnotation { |
| } |
| EOF |
| |
| cat >$pkg/java/test/processor/ProcessorDep.java <<EOF |
| package test.processor; |
| |
| class ProcessorDep { |
| static String value = "DependencyValue"; |
| } |
| EOF |
| |
| cat >$pkg/java/test/processor/Processor.java <<EOF |
| package test.processor; |
| import java.util.*; |
| import java.io.*; |
| import javax.annotation.processing.*; |
| import javax.tools.*; |
| import javax.lang.model.*; |
| import javax.lang.model.element.*; |
| @SupportedAnnotationTypes(value= {"test.processor.TestAnnotation"}) |
| public class Processor extends AbstractProcessor { |
| private static final String OUTFILE_CONTENT = "package test;\n" |
| + "public class Generated {\n" |
| + " public static String value = \"" + ProcessorDep.value + "\";\n" |
| + "}"; |
| private ProcessingEnvironment mainEnvironment; |
| public void init(ProcessingEnvironment environment) { |
| mainEnvironment = environment; |
| } |
| public boolean process(Set<? extends TypeElement> 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 <<EOF |
| java_library(name = 'client', |
| srcs = [ 'ProcessorClient.java' ], |
| deps = [ '//$pkg/java/test/processor:annotation' ], |
| plugins = [ '//$pkg/java/test/processor:processor' ]) |
| EOF |
| |
| cat >$pkg/java/test/client/ProcessorClient.java <<EOF |
| package test.client; |
| import test.processor.TestAnnotation; |
| @TestAnnotation() |
| class ProcessorClient { } |
| EOF |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/test/client:client --use_ijars || fail "build failed" |
| unzip -l ${PRODUCT_NAME}-bin/$pkg/java/test/client/libclient.jar > $TEST_log |
| expect_log " test/Generated.class" "missing class file from annotation processing" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$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_java_plugin_remote_java_tools() { |
| test_java_plugin \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_jvm_flags_are_passed_verbatim() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/com/google/jvmflags || fail "mkdir" |
| cat >$pkg/java/com/google/jvmflags/BUILD <<EOF |
| java_binary( |
| name = 'foo', |
| srcs = ['Foo.java'], |
| main_class = 'com.google.jvmflags.Foo', |
| toolchains = ['${TOOLS_REPOSITORY}//tools/jdk:current_java_runtime'], |
| jvm_flags = [ |
| # test quoting |
| '--a=\\'single_single\\'', |
| '--b="single_double"', |
| "--c='double_single'", |
| "--d=\\"double_double\\"", |
| '--e=no_quotes', |
| # no escaping expected |
| '--f=stuff\$\$to"escape\\\\', |
| ], |
| ) |
| EOF |
| |
| cat >$pkg/java/com/google/jvmflags/Foo.java <<EOF |
| package com.google.jvmflags; |
| public class Foo { public static void main(String[] args) {} } |
| EOF |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/com/google/jvmflags:foo || fail "build failed" |
| |
| STUBSCRIPT=${PRODUCT_NAME}-bin/$pkg/java/com/google/jvmflags/foo |
| [ -e $STUBSCRIPT ] || fail "$STUBSCRIPT not found" |
| |
| for flag in \ |
| " --a='single_single' " \ |
| " --b=\"single_double\" " \ |
| " --c='double_single' " \ |
| " --d=\"double_double\" " \ |
| ' --e=no_quotes ' \ |
| ' --f=stuff$to"escape\\ ' \ |
| ; do |
| # NOTE: don't test the full path of the JDK, it's architecture-dependent. |
| assert_contains $flag $STUBSCRIPT |
| done |
| } |
| |
| function test_jvm_flags_are_passed_verbatim_remote_java_tools() { |
| test_jvm_flags_are_passed_verbatim \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_classpath_fiddling() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_library_files "$pkg" |
| |
| mkdir -p $pkg/java/classpath |
| cat >$pkg/java/classpath/BUILD <<EOF |
| java_binary(name = 'classpath', |
| deps = ['//$pkg/java/hello_library'], |
| srcs = ['Classpath.java'], |
| main_class = 'classpath.Classpath') |
| EOF |
| |
| cat >$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 ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/classpath || fail "build failed" |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$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 ${bazel_opts[@]+"${bazel_opts[@]}"} //$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_classpath_fiddling_remote_java_tools() { |
| test_classpath_fiddling \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_java7() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/foo/ || fail "Expected success" |
| cat > $pkg/java/foo/Foo.java <<EOF |
| package foo; |
| import java.lang.invoke.MethodHandle; // In Java 7 class library only |
| import java.util.ArrayList; |
| public class Foo { |
| public static void main(String[] args) { |
| ArrayList<Object> list = new ArrayList<>(); // In Java 7 language only |
| System.out.println("Success!"); |
| } |
| } |
| EOF |
| |
| cat > $pkg/java/foo/BUILD <<EOF |
| java_binary(name = 'foo', |
| srcs = ['Foo.java'], |
| main_class = 'foo.Foo') |
| EOF |
| |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/foo:foo | grep -q "Success!" || fail "Expected success" |
| } |
| |
| function test_java7_remote_java_tools() { |
| test_java7 \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_header_compilation() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir "$pkg" || fail "mkdir $pkg" |
| write_hello_library_files "$pkg" |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} -s --java_header_compilation=true \ |
| //$pkg/java/main:main || fail "build failed" |
| unzip -l ${PRODUCT_NAME}-bin/$pkg/java/hello_library/libhello_library-hjar.jar \ |
| > $TEST_log |
| expect_log " hello_library/HelloLibrary.class" \ |
| "missing class file from header compilation" |
| } |
| |
| function test_header_compilation_remote_java_tools() { |
| test_header_compilation \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_header_compilation_errors() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/test/ || fail "Expected success" |
| cat > $pkg/java/test/A.java <<EOF |
| package test; |
| public class A {} |
| EOF |
| cat > $pkg/java/test/B.java <<EOF |
| package test; |
| import missing.NoSuch; |
| @NoSuch |
| public class B {} |
| EOF |
| cat > $pkg/java/test/BUILD <<EOF |
| java_library( |
| name='a', |
| srcs=['A.java'], |
| deps=[':b'], |
| ) |
| java_library( |
| name='b', |
| srcs=['B.java'], |
| ) |
| EOF |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} --java_header_compilation=true \ |
| //$pkg/java/test:liba.jar >& "$TEST_log" && fail "Unexpected success" |
| expect_log "symbol not found missing.NoSuch" |
| } |
| |
| function test_header_compilation_errors_remote_java_tools() { |
| test_header_compilation_errors \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| function test_java_import_with_empty_jars_attribute() { |
| declare -a bazel_opts=("${@:+$@}") |
| local -r pkg="${FUNCNAME[0]}" |
| mkdir -p $pkg/java/hello/ || fail "Expected success" |
| cat > $pkg/java/hello/Hello.java <<EOF |
| package hello; |
| public class Hello { |
| public static void main(String[] args) { |
| System.out.println("Hello World!"); |
| } |
| } |
| EOF |
| cat > $pkg/java/hello/BUILD <<EOF |
| java_import( |
| name='empty_java_import', |
| jars=[] |
| ) |
| java_binary( |
| name='hello', |
| srcs=['Hello.java'], |
| deps=[':empty_java_import'], |
| main_class = 'hello.Hello' |
| ) |
| EOF |
| |
| bazel build ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello //$pkg/java/hello:hello_deploy.jar >& "$TEST_log" \ |
| || fail "Expected success" |
| bazel run ${bazel_opts[@]+"${bazel_opts[@]}"} //$pkg/java/hello:hello -- --singlejar >& "$TEST_log" |
| expect_log "Hello World!" |
| } |
| |
| function test_java_import_with_empty_jars_attribute_remote_java_tools() { |
| test_java_import_with_empty_jars_attribute \ |
| --incompatible_use_remote_host_java_toolchain \ |
| --incompatible_use_remote_java_toolchain |
| } |
| |
| |
| run_suite "Java integration tests" |