| """Tests for the Bazel java_binary rule""" | |
| load("@bazel_features//private:util.bzl", _bazel_version_ge = "ge") | |
| load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") | |
| load("@rules_testing//lib:truth.bzl", "matching") | |
| load("@rules_testing//lib:util.bzl", "util") | |
| load("//java:java_binary.bzl", "java_binary") | |
| load("//test/java/testutil:helper.bzl", "always_passes") | |
| load("//test/java/testutil:java_info_subject.bzl", "java_info_subject") | |
| load("//test/java/testutil:rules/template_var_info_rule.bzl", "template_var_info_rule") | |
| def _test_java_binary_cross_compilation_to_unix(name): | |
| # A Unix platform that: | |
| # - has a JDK | |
| # - does not require a launcher | |
| # - is not supported by the default C++ toolchain | |
| util.helper_target( | |
| native.platform, | |
| name = name + "_platform", | |
| constraint_values = [ | |
| "@platforms//os:linux", | |
| "@platforms//cpu:s390x", | |
| ], | |
| ) | |
| util.helper_target( | |
| java_binary, | |
| name = name + "/bin", | |
| srcs = ["java/C.java"], | |
| main_class = "C", | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_cross_compilation_to_unix_impl, | |
| target = name + "/bin", | |
| config_settings = { | |
| "//command_line_option:platforms": [Label(name + "_platform")], | |
| }, | |
| # Requires the launcher_maker toolchain. | |
| attr_values = {"tags": ["min_bazel_9"]}, | |
| ) | |
| def _test_java_binary_cross_compilation_to_unix_impl(env, target): | |
| # The main assertion is that analysis succeeds, but verify the absence of a | |
| # binary launcher for good measure. We do this by checking that the output | |
| # executable is the stub script, and not a bespoke launcher | |
| executable = target[DefaultInfo].files_to_run.executable.short_path | |
| assert_action = env.expect.that_target(target).action_generating(executable) | |
| assert_action.mnemonic().equals("TemplateExpand") | |
| assert_action.substitutions().keys().contains("%jvm_flags%") | |
| assert_action.inputs().contains_exactly(["java/bazel/rules/java_stub_template.txt"]) | |
| def _test_java_binary_excludes_build_data(name): | |
| if not _bazel_version_ge("8.0.0"): | |
| always_passes(name) | |
| return | |
| util.helper_target( | |
| java_binary, | |
| name = name + "/bin", | |
| srcs = ["Main.java"], | |
| exclude_build_data = True, | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_excludes_build_data_impl, | |
| target = name + "/bin", | |
| attr_values = {"tags": ["min_bazel_8"]}, | |
| ) | |
| def _test_java_binary_excludes_build_data_impl(env, target): | |
| assert_deploy_jar_action = env.expect.that_target(target).action_generating( | |
| "{package}/{name}_deploy.jar", | |
| ) | |
| assert_deploy_jar_action.argv().contains("--normalize") | |
| assert_deploy_jar_action.argv().contains("--exclude_build_data") | |
| assert_deploy_jar_action.argv().not_contains("--build_info_file") | |
| assert_deploy_jar_action.inputs().not_contains_predicate( | |
| matching.file_basename_equals("non_volatile_file.properties"), | |
| ) | |
| assert_deploy_jar_action.inputs().not_contains_predicate( | |
| matching.file_basename_equals("redacted_file.properties"), | |
| ) | |
| def _test_java_binary_stamping_enabled_build_data_excluded_fails(name): | |
| if not _bazel_version_ge("8.0.0"): | |
| always_passes(name) | |
| return | |
| util.helper_target( | |
| java_binary, | |
| name = name + "/bin", | |
| srcs = ["Main.java"], | |
| exclude_build_data = True, | |
| stamp = 1, | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_stamping_enabled_build_data_excluded_fails_impl, | |
| target = name + "/bin", | |
| expect_failure = True, | |
| attr_values = {"tags": ["min_bazel_8"]}, | |
| ) | |
| def _test_java_binary_stamping_enabled_build_data_excluded_fails_impl(env, target): | |
| env.expect.that_target(target).failures().contains_predicate( | |
| matching.str_matches("Enabling stamping has no effect with exclude_build_data enabled"), | |
| ) | |
| def _test_java_binary_javacopts_make_variable_expansion(name): | |
| util.helper_target( | |
| template_var_info_rule, | |
| name = name + "/vars", | |
| vars = { | |
| "MY_CUSTOM_OPT": "MY_OPT_VALUE", | |
| }, | |
| ) | |
| util.helper_target( | |
| java_binary, | |
| name = name + "/bin", | |
| srcs = ["java/A.java"], | |
| javacopts = ["$(MY_CUSTOM_OPT)"], | |
| toolchains = [name + "/vars"], | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_javacopts_make_variable_expansion_impl, | |
| target = name + "/bin", | |
| # Broken by Starlarkification in the embedded rules in Bazel 7 | |
| attr_values = {"tags": ["min_bazel_8"]}, | |
| ) | |
| def _test_java_binary_javacopts_make_variable_expansion_impl(env, target): | |
| assert_java_info = java_info_subject.from_target(env, target) | |
| assert_java_info.compilation_info().javac_options().not_contains("$(MY_CUSTOM_OPT)") | |
| assert_java_info.compilation_info().javac_options().contains("MY_OPT_VALUE") | |
| def _test_java_binary_javacopts_location_expansion(name): | |
| util.helper_target( | |
| java_binary, | |
| name = name + "/bin", | |
| srcs = ["A.java"], | |
| javacopts = ["-XepOpt:foo=$(location :A.java)"], | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_javacopts_location_expansion_impl, | |
| target = name + "/bin", | |
| ) | |
| def _test_java_binary_javacopts_location_expansion_impl(env, target): | |
| assert_java_info = java_info_subject.from_target(env, target) | |
| assert_java_info.compilation_info().javac_options().contains( | |
| "-XepOpt:foo={package}/A.java", | |
| ) | |
| def _test_java_binary_resource_strip_prefix(name): | |
| util.helper_target( | |
| java_binary, | |
| name = name + "/bin", | |
| srcs = ["Foo.java"], | |
| main_class = "Foo", | |
| resource_strip_prefix = native.package_name() + "/path/to/strip", | |
| resources = ["path/to/strip/bar.props"], | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_resource_strip_prefix_impl, | |
| target = name + "/bin", | |
| ) | |
| def _test_java_binary_resource_strip_prefix_impl(env, target): | |
| env.expect.that_target(target).action_generating("{package}/{name}.jar").contains_flag_values([ | |
| ("--resources", "{package}/path/to/strip/bar.props:bar.props"), | |
| ]) | |
| def _test_java_binary_empty_srcs(name): | |
| analysis_test( | |
| name = name, | |
| impl = _test_java_binary_empty_srcs_impl, | |
| target = "//test/bazel:bin_without_srcs", # need a target not under a `/java/` segment | |
| expect_failure = True, | |
| ) | |
| def _test_java_binary_empty_srcs_impl(env, target): | |
| env.expect.that_target(target).failures().contains_predicate(matching.str_matches( | |
| "need at least one of 'main_class' or Java source files", | |
| )) | |
| def java_binary_tests(name): | |
| test_suite( | |
| name = name, | |
| tests = [ | |
| _test_java_binary_cross_compilation_to_unix, | |
| _test_java_binary_excludes_build_data, | |
| _test_java_binary_stamping_enabled_build_data_excluded_fails, | |
| _test_java_binary_javacopts_make_variable_expansion, | |
| _test_java_binary_javacopts_location_expansion, | |
| _test_java_binary_resource_strip_prefix, | |
| _test_java_binary_empty_srcs, | |
| ], | |
| ) |