| """Tests for the java_library rule""" |
| |
| load("@bazel_features//:features.bzl", "bazel_features") |
| load("@rules_cc//cc:cc_binary.bzl", "cc_binary") |
| load("@rules_cc//cc:cc_library.bzl", "cc_library") |
| 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_library.bzl", "java_library") |
| load("//java:java_plugin.bzl", "java_plugin") |
| load("//java/common:java_info.bzl", "JavaInfo") |
| load("//test/java/common/rules:common_launcher_java_library_tests.bzl", "JAVA_LIBRARY_LAUNCHER_TESTS") |
| load("//test/java/testutil:helper.bzl", "always_passes") |
| load("//test/java/testutil:java_info_subject.bzl", "java_info_subject") |
| load("//test/java/testutil:javac_action_subject.bzl", "javac_action_subject") |
| load("//test/java/testutil:rules/custom_java_info_rule.bzl", "custom_java_info_rule") |
| load("//test/java/testutil:rules/forward_java_info.bzl", "java_info_forwarding_rule") |
| load("//test/java/testutil:rules/wrap_java_info.bzl", "JavaInfoWrappingInfo", "java_info_wrapping_rule") |
| |
| def _test_exposes_plugins(name): |
| target_name = name + "/library" |
| util.helper_target( |
| java_library, |
| name = target_name + "/plugin_dep1", |
| srcs = ["A.java"], |
| data = ["depfile1.dat"], |
| ) |
| util.helper_target( |
| java_library, |
| name = target_name + "/plugin_dep2", |
| srcs = ["B.java"], |
| data = ["depfile2.dat"], |
| ) |
| util.helper_target( |
| java_plugin, |
| name = target_name + "/plugin", |
| srcs = ["AnnotationProcessor1.java"], |
| data = ["pluginfile1.dat"], |
| processor_class = "com.google.process.stuff", |
| deps = [target_name + "/plugin_dep1"], |
| ) |
| util.helper_target( |
| java_plugin, |
| name = target_name + "/apiplugin", |
| srcs = ["AnnotationProcessor2.java"], |
| data = ["pluginfile2.dat"], |
| generates_api = True, |
| processor_class = "com.google.process.apistuff", |
| deps = [target_name + "/plugin_dep2"], |
| ) |
| util.helper_target( |
| java_library, |
| name = target_name, |
| exported_plugins = [ |
| target_name + "/plugin", |
| target_name + "/apiplugin", |
| ], |
| ) |
| |
| analysis_test( |
| name = name, |
| impl = _test_exposes_plugins_impl, |
| target = target_name, |
| ) |
| |
| def _test_exposes_plugins_impl(env, target): |
| assert_plugin_data = java_info_subject.from_target(env, target).plugins() |
| assert_plugin_data.processor_classes().contains_exactly([ |
| "com.google.process.stuff", |
| "com.google.process.apistuff", |
| ]) |
| assert_plugin_data.processor_jars().contains_exactly([ |
| "{package}/lib{name}/plugin.jar", |
| "{package}/lib{name}/plugin_dep1.jar", |
| "{package}/lib{name}/apiplugin.jar", |
| "{package}/lib{name}/plugin_dep2.jar", |
| ]) |
| assert_plugin_data.processor_data().contains_exactly([ |
| "{package}/pluginfile1.dat", |
| "{package}/pluginfile2.dat", |
| ]) |
| |
| assert_api_plugin_data = java_info_subject.from_target(env, target).api_generating_plugins() |
| assert_api_plugin_data.processor_classes().contains_exactly(["com.google.process.apistuff"]) |
| assert_api_plugin_data.processor_jars().contains_exactly([ |
| "{package}/lib{name}/apiplugin.jar", |
| "{package}/lib{name}/plugin_dep2.jar", |
| ]) |
| assert_api_plugin_data.processor_data().contains_exactly(["{package}/pluginfile2.dat"]) |
| |
| def _test_exposes_java_info(name): |
| util.helper_target( |
| java_library, |
| name = name + "/jl", |
| srcs = ["java/A.java"], |
| ) |
| util.helper_target( |
| java_info_wrapping_rule, |
| name = name + "/r", |
| dep = name + "/jl", |
| ) |
| analysis_test( |
| name = name, |
| impl = _test_exposes_java_info_impl, |
| targets = { |
| "r": name + "/r", |
| "jl": name + "/jl", |
| }, |
| ) |
| |
| def _test_exposes_java_info_impl(env, targets): |
| env.expect.that_bool( |
| targets.r[JavaInfoWrappingInfo].p == targets.jl[JavaInfo], |
| ).equals(True) |
| |
| def _test_java_info_propagation(name): |
| util.helper_target( |
| java_library, |
| name = name + "/jl", |
| srcs = ["java/A.java"], |
| ) |
| util.helper_target( |
| java_info_forwarding_rule, |
| name = name + "/r", |
| dep = name + "/jl", |
| ) |
| util.helper_target( |
| java_library, |
| name = name + "/jl_top", |
| srcs = ["java/C.java"], |
| deps = [name + "/r"], |
| ) |
| |
| analysis_test( |
| name = name, |
| impl = _test_java_info_propagation_impl, |
| targets = { |
| "r": name + "/r", |
| "jl": name + "/jl", |
| "jl_top": name + "/jl_top", |
| }, |
| ) |
| |
| def _test_java_info_propagation_impl(env, targets): |
| env.expect.that_bool(targets.r[JavaInfo] == targets.jl[JavaInfo]).equals(True) |
| _assert_depsets_have_the_same_parent( |
| env, |
| targets.jl[JavaInfo].transitive_compile_time_jars, |
| targets.jl_top[JavaInfo].transitive_compile_time_jars, |
| ) |
| _assert_depsets_have_the_same_parent( |
| env, |
| targets.jl[JavaInfo].transitive_runtime_jars, |
| targets.jl_top[JavaInfo].transitive_runtime_jars, |
| ) |
| |
| def _assert_depsets_have_the_same_parent(env, depset1, depset2): |
| elements = depset1.to_list() |
| other_elements = depset2.to_list() |
| |
| for e, other_e in zip(elements, other_elements): |
| env.expect.that_str(e.dirname).equals(other_e.dirname) |
| |
| def _test_java_library_attributes(name): |
| util.helper_target( |
| java_library, |
| name = name + "/jl_bottom_for_deps", |
| srcs = ["java/A.java"], |
| ) |
| util.helper_target( |
| java_library, |
| name = name + "/jl_bottom_for_exports", |
| srcs = ["java/A2.java"], |
| ) |
| util.helper_target( |
| java_library, |
| name = name + "/jl_bottom_for_runtime_deps", |
| srcs = ["java/A2.java"], |
| ) |
| util.helper_target( |
| java_info_forwarding_rule, |
| name = name + "/mya", |
| dep = name + "/jl_bottom_for_deps", |
| ) |
| util.helper_target( |
| java_info_forwarding_rule, |
| name = name + "/myb", |
| dep = name + "/jl_bottom_for_exports", |
| ) |
| util.helper_target( |
| java_info_forwarding_rule, |
| name = name + "/myc", |
| dep = name + "/jl_bottom_for_runtime_deps", |
| ) |
| util.helper_target( |
| java_library, |
| name = name + "/lib_exports", |
| srcs = ["java/B.java"], |
| exports = [name + "/myb"], |
| runtime_deps = [name + "/myc"], |
| deps = [name + "/mya"], |
| ) |
| util.helper_target( |
| java_library, |
| name = name + "/lib_interm", |
| srcs = ["java/C.java"], |
| deps = [name + "/lib_exports"], |
| ) |
| util.helper_target( |
| java_library, |
| name = name + "/lib_top", |
| srcs = ["java/D.java"], |
| deps = [name + "/lib_interm"], |
| ) |
| |
| analysis_test( |
| name = name, |
| impl = _test_java_library_attributes_impl, |
| targets = { |
| "exports": name + "/lib_exports", |
| "interm": name + "/lib_interm", |
| }, |
| ) |
| |
| def _test_java_library_attributes_impl(env, targets): |
| # all bottom jars are on the runtime classpath of lib_exports. |
| java_info_subject.from_target(env, targets.exports).compilation_args().transitive_runtime_jars().contains_at_least_predicates([ |
| matching.file_basename_equals("jl_bottom_for_deps.jar"), |
| matching.file_basename_equals("jl_bottom_for_runtime_deps.jar"), |
| matching.file_basename_equals("jl_bottom_for_exports.jar"), |
| ]) |
| |
| # jl_bottom_for_exports.jar is in the recursive java compilation args of lib_top. |
| java_info_subject.from_target(env, targets.interm).compilation_args().transitive_runtime_jars().contains_predicate( |
| matching.file_basename_equals("jl_bottom_for_exports.jar"), |
| ) |
| |
| def _test_propagates_direct_native_libraries(name): |
| target_name = name + "/jl_top" |
| util.helper_target( |
| cc_library, |
| name = target_name + "/native", |
| srcs = ["cc/x.cc"], |
| ) |
| util.helper_target( |
| java_library, |
| name = target_name + "/jl", |
| srcs = ["java/A.java"], |
| deps = [target_name + "/native"], |
| ) |
| util.helper_target( |
| cc_library, |
| name = target_name + "/ccl", |
| srcs = ["cc/x.cc"], |
| ) |
| util.helper_target( |
| custom_java_info_rule, |
| name = target_name + "/r", |
| output_jar = target_name + "-out.jar", |
| cc_dep = [target_name + "/ccl"], |
| dep = [target_name + "/jl"], |
| ) |
| util.helper_target( |
| java_library, |
| name = target_name, |
| srcs = ["java/C.java"], |
| deps = [target_name + "/r"], |
| ) |
| |
| analysis_test( |
| name = name, |
| impl = _test_propagates_direct_native_libraries_impl, |
| target = target_name, |
| ) |
| |
| def _test_propagates_direct_native_libraries_impl(env, target): |
| assert_transitive_native_libraries = java_info_subject.from_target(env, target).transitive_native_libraries() |
| assert_transitive_native_libraries.static_libraries().contains_exactly_predicates([ |
| matching.str_matches("*native*"), |
| matching.str_matches("*ccl*"), |
| ]).in_order() |
| |
| def _test_exposes_native_library_info(name): |
| target_name = name + "/jl" |
| util.helper_target( |
| cc_library, |
| name = target_name + "/mynativedep_lib", |
| srcs = ["cc/x.cc"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = target_name + "/mynativedep_bin", |
| srcs = ["cc/x.cc"], |
| linkshared = 1, |
| ) |
| util.helper_target( |
| java_library, |
| name = target_name, |
| srcs = ["java/A.java"], |
| deps = select({ |
| "@platforms//os:windows": [target_name + "/mynativedep_lib"], |
| "//conditions:default": [target_name + "/mynativedep_bin"], |
| }), |
| ) |
| analysis_test( |
| name = name, |
| impl = _test_exposes_native_library_info_impl, |
| target = target_name, |
| ) |
| |
| def _test_exposes_native_library_info_impl(env, target): |
| assert_lib = java_info_subject.from_target(env, target).transitive_native_libraries().singleton() |
| |
| assert_lib.dynamic_library().basename().contains("mynativedep") |
| |
| def _test_strict_java_deps(name, strict_java_deps): |
| if not bazel_features.rules.analysis_tests_can_transition_on_experimental_incompatible_flags: |
| always_passes(name) |
| return |
| |
| util.helper_target( |
| java_library, |
| name = name + "/jl", |
| srcs = ["A.java"], |
| ) |
| |
| analysis_test( |
| name = name, |
| impl = _test_strict_java_deps_impl, |
| target = name + "/jl", |
| config_settings = {"//command_line_option:experimental_strict_java_deps": strict_java_deps}, |
| attrs = {"expected_strict_java_deps": attr.string()}, |
| attr_values = {"expected_strict_java_deps": strict_java_deps}, |
| ) |
| |
| def _test_strict_java_deps_impl(env, target): |
| # Note that if --experimental_strict_java_deps=OFF, we may not set --strict_java_deps in the |
| # javac action's argv at all; the "OFF" value (which is equivalent to an unset flag) in that |
| # case is injected by javac_action_subject for convenience and canonicalization. |
| expect_that_javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") |
| expect_that_javac_action.strict_java_deps().contains_exactly([env.ctx.attr.expected_strict_java_deps]) |
| |
| def _test_strict_java_deps_off(name): |
| _test_strict_java_deps(name, "OFF") |
| |
| def _test_strict_java_deps_warn(name): |
| _test_strict_java_deps(name, "WARN") |
| |
| def _test_strict_java_deps_error(name): |
| _test_strict_java_deps(name, "ERROR") |
| |
| def java_library_tests(name): |
| test_suite( |
| name = "_basic_" + name, |
| tests = [ |
| _test_exposes_plugins, |
| _test_exposes_java_info, |
| _test_java_info_propagation, |
| _test_java_library_attributes, |
| _test_propagates_direct_native_libraries, |
| _test_exposes_native_library_info, |
| _test_strict_java_deps_off, |
| _test_strict_java_deps_warn, |
| _test_strict_java_deps_error, |
| ], |
| ) |
| |
| # TODO: unset --java_launcher explicitly |
| test_suite( |
| name = "_jdk_launcher_" + name, |
| tests = JAVA_LIBRARY_LAUNCHER_TESTS, |
| ) |
| |
| native.test_suite( |
| name = name, |
| tests = [ |
| "_basic_" + name, |
| "_jdk_launcher_" + name, |
| ], |
| ) |