Add java_library tests (ignore-relnotes) PiperOrigin-RevId: 907592868 Change-Id: I95b3560ff3008b56d5d2d63dbbd7eb8f91d2911a
diff --git a/test/java/common/rules/common_launcher_java_library_tests.bzl b/test/java/common/rules/common_launcher_java_library_tests.bzl index 9690b2b..3b2a228 100644 --- a/test/java/common/rules/common_launcher_java_library_tests.bzl +++ b/test/java/common/rules/common_launcher_java_library_tests.bzl
@@ -1,13 +1,19 @@ """Parameterized tests for java_library with --java_launcher""" load("@bazel_features//:features.bzl", "bazel_features") +load("@rules_cc//cc:cc_library.bzl", "cc_library") load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:truth.bzl", "matching") load("@rules_testing//lib:util.bzl", "util") load("//java:java_import.bzl", "java_import") load("//java:java_library.bzl", "java_library") +load("//java:java_plugin.bzl", "java_plugin") +load("//java/toolchains:java_runtime.bzl", "java_runtime") +load("//java/toolchains:java_toolchain.bzl", "java_toolchain") 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_library_with_bootclasspath.bzl", "custom_bootclasspath") def _test_java_library_rule_outputs(name): util.helper_target( @@ -214,12 +220,397 @@ expected_compile = "{bin_path}/{package}/lib{test_name}/compile_dep-hjar.jar" javac_action_subject.of(env, target, "{package}/lib{name}.jar").classpath().contains_exactly([expected_compile]) +def _test_java_library_annotation_processing_using_javacopt(name): + util.helper_target( + java_library, + name = name + "/to_be_processed", + srcs = ["ToBeProcessed.java"], + javacopts = ["-processor com.google.process.Processor"], + ) + + analysis_test( + name = name, + impl = _test_java_library_annotation_processing_using_javacopt_impl, + target = name + "/to_be_processed", + ) + +def _test_java_library_annotation_processing_using_javacopt_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + javac_action.argv().contains("--generated_sources_output") + javac_action.generated_sources_output().contains("{bin_path}/{package}/lib{name}-gensrc.jar") + javac_action.javacopts().contains("-processor") + javac_action.javacopts().contains("com.google.process.Processor") + + # The compile action should have a gensrc jar output + javac_action.outputs().contains("{package}/lib{name}-gensrc.jar") + + # The gensrc jar should be an input to the source jar action + src_jar_action = env.expect.that_target(target).action_generating("{package}/lib{name}-src.jar") + src_jar_action.inputs().contains("{package}/lib{name}-gensrc.jar") + +def _test_java_library_javacopts_with_location_expansion(name): + util.helper_target( + java_library, + name = name + "/patch", + srcs = ["A.java"], + ) + util.helper_target( + java_library, + name = name + "/lib", + srcs = ["ToBeProcessed.java"], + javacopts = ["--patch $(execpath " + name + "/patch)"], + deps = [name + "/patch"], + ) + + analysis_test( + name = name, + impl = _test_java_library_javacopts_with_location_expansion_impl, + target = name + "/lib", + ) + +def _test_java_library_javacopts_with_location_expansion_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + javac_action.javacopts().contains_at_least([ + "--patch", + "{bin_path}/{package}/lib{test_name}/patch.jar", + ]) + +def _test_java_library_invalid_plugin(name): + util.helper_target( + java_library, + name = name + "/not_a_plugin", + srcs = ["NotAPlugin.java"], + ) + util.helper_target( + java_library, + name = name + "/lib", + srcs = ["Lib.java"], + plugins = [name + "/not_a_plugin"], + ) + + analysis_test( + name = name, + impl = _test_java_library_invalid_plugin_impl, + target = name + "/lib", + expect_failure = True, + ) + +def _test_java_library_invalid_plugin_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.contains("does not have mandatory providers: 'JavaPluginInfo'"), + ) + +def _test_java_library_plugin_with_runtime_deps(name): + util.helper_target( + java_library, + name = name + "/runtime_lib", + srcs = ["Runtime.java"], + ) + util.helper_target( + java_library, + name = name + "/lib", + srcs = ["Lib.java"], + runtime_deps = [name + "/runtime_lib"], + ) + util.helper_target( + java_plugin, + name = name + "/plugin", + srcs = ["Plugin.java"], + processor_class = "com.google.process.stuff", + deps = [name + "/lib"], + ) + util.helper_target( + java_library, + name = name + "/leaf_lib", + srcs = ["LeafLib.java"], + plugins = [name + "/plugin"], + ) + + analysis_test( + name = name, + impl = _test_java_library_plugin_with_runtime_deps_impl, + target = name + "/leaf_lib", + ) + +def _test_java_library_plugin_with_runtime_deps_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + javac_action.processorpath().contains_exactly_predicates([ + matching.str_matches("*/plugin.jar"), + matching.str_matches("*/lib.jar"), + matching.str_matches("*/runtime_lib.jar"), + ]) + +def _test_java_library_source_jar_without_annotation_processing(name): + util.helper_target( + java_library, + name = name + "/foo", + srcs = ["Foo.java"], + ) + + analysis_test( + name = name, + impl = _test_java_library_source_jar_without_annotation_processing_impl, + target = name + "/foo", + ) + +def _test_java_library_source_jar_without_annotation_processing_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + javac_action.argv().not_contains("--generated_sources_output") + javac_action.outputs().contains_exactly([ + "{package}/lib{name}.jar", + "{package}/lib{name}.jdeps", + "{package}/lib{name}-native-header.jar", + "{package}/lib{name}.jar_manifest_proto", + ]) + + src_jar_action = javac_action_subject.of(env, target, "{package}/lib{name}-src.jar") + src_jar_action.outputs().contains_exactly([ + "{package}/lib{name}-src.jar", + ]) + +def _test_java_library_source_jars_with_source_jars(name): + util.helper_target( + java_library, + name = name + "/beatit", + srcs = [ + "Plugin.java", + "Some.srcjar", + ], + ) + + analysis_test( + name = name, + impl = _test_java_library_source_jars_with_source_jars_impl, + target = name + "/beatit", + ) + +def _test_java_library_source_jars_with_source_jars_impl(env, target): + src_jar_action = javac_action_subject.of(env, target, "{package}/lib{name}-src.jar") + src_jar_action.inputs().contains_at_least([ + "{package}/Plugin.java", + "{package}/Some.srcjar", + ]) + src_jar_action.sources().contains_exactly([ + "{package}/Some.srcjar", + ]) + src_jar_action.resources().contains_predicate( + matching.str_matches("*/Plugin.java:*rules/Plugin.java"), + ) + +def _test_java_library_should_set_bootclasspath(name): + boot_jar = util.empty_file(name + "/boot.jar") + util.helper_target( + custom_bootclasspath, + name = name + "/mock_bootclasspath", + bootclasspath = [boot_jar], + ) + + util.helper_target( + java_runtime, + name = name + "/runtime", + ) + + util.helper_target( + java_toolchain, + name = name + "/mock_toolchain_impl", + bootclasspath = [name + "/mock_bootclasspath"], + genclass = name + "/genclass", + header_compiler = name + "/header_compiler", + header_compiler_direct = name + "/header_compiler_direct", + ijar = name + "/ijar", + java_runtime = name + "/runtime", + javabuilder = name + "/javabuilder", + singlejar = name + "/singlejar", + ) + util.helper_target( + native.toolchain, + name = name + "/toolchain", + toolchain = name + "/mock_toolchain_impl", + toolchain_type = "@bazel_tools//tools/jdk:toolchain_type", + ) + util.helper_target( + java_library, + name = name + "/test_lib", + srcs = ["A.java"], + ) + + analysis_test( + name = name, + impl = _test_java_library_should_set_bootclasspath_impl, + config_settings = { + "//command_line_option:extra_toolchains": [ + native.package_relative_label(name + "/toolchain"), + ], + }, + target = name + "/test_lib", + ) + +def _test_java_library_should_set_bootclasspath_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + + javac_action.bootclasspath().contains_exactly([ + "{bin_path}/{package}/test_java_library_should_set_bootclasspath/boot.jar", + ]) + +def _test_java_library_command_line_contains_target_label_and_rule_kind(name): + util.helper_target( + java_library, + name = name + "/test_lib", + srcs = ["A.java"], + ) + + analysis_test( + name = name, + impl = _test_java_library_command_line_contains_target_label_and_rule_kind_impl, + target = name + "/test_lib", + ) + +def _test_java_library_command_line_contains_target_label_and_rule_kind_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + javac_action.target_label().contains_exactly(["//{package}:{name}"]) + +def _test_java_library_propagates_native_libraries(name): + util.helper_target( + cc_library, + name = name + "/native_deps1.so", + srcs = ["a.cc"], + ) + util.helper_target( + java_library, + name = name + "/lib_deps", + srcs = ["B.java"], + deps = [name + "/native_deps1.so"], + ) + util.helper_target( + cc_library, + name = name + "/native_deps2.so", + srcs = ["b.cc"], + ) + util.helper_target( + cc_library, + name = name + "/native_rdeps1.so", + srcs = ["c.cc"], + ) + util.helper_target( + java_library, + name = name + "/lib_runtime_deps", + srcs = ["C.java"], + deps = [name + "/native_rdeps1.so"], + ) + util.helper_target( + cc_library, + name = name + "/native_rdeps2.so", + srcs = ["d.cc"], + ) + util.helper_target( + cc_library, + name = name + "/native_exports1.so", + srcs = ["e.cc"], + ) + util.helper_target( + java_library, + name = name + "/lib_exports", + srcs = ["D.java"], + deps = [name + "/native_exports1.so"], + ) + util.helper_target( + cc_library, + name = name + "/native_exports2.so", + srcs = ["f.cc"], + ) + util.helper_target( + cc_library, + name = name + "/native_data1.so", + srcs = ["g.cc"], + ) + util.helper_target( + java_library, + name = name + "/lib_data", + srcs = ["E.java"], + deps = [name + "/native_data1.so"], + ) + util.helper_target( + cc_library, + name = name + "/native_data2.so", + srcs = ["h.cc"], + ) + util.helper_target( + java_library, + name = name + "/top", + srcs = ["A.java"], + data = [ + name + "/lib_data", + name + "/native_data2.so", + ], + exports = [ + name + "/lib_exports", + name + "/native_exports2.so", + ], + runtime_deps = [ + name + "/lib_runtime_deps", + name + "/native_rdeps2.so", + ], + deps = [ + name + "/lib_deps", + name + "/native_deps2.so", + ], + ) + + analysis_test( + name = name, + impl = _test_java_library_propagates_native_libraries_impl, + target = name + "/top", + ) + +def _test_java_library_propagates_native_libraries_impl(env, target): + java_info_subject.from_target(env, target).transitive_native_libraries().static_libraries().contains_exactly_predicates([ + # Windows platforms use .lib extension for static libraries. + matching.is_in(["libnative_rdeps2.so.a", "native_rdeps2.so.lib"]), + matching.is_in(["libnative_exports2.so.a", "native_exports2.so.lib"]), + matching.is_in(["libnative_deps2.so.a", "native_deps2.so.lib"]), + matching.is_in(["libnative_rdeps1.so.a", "native_rdeps1.so.lib"]), + matching.is_in(["libnative_exports1.so.a", "native_exports1.so.lib"]), + matching.is_in(["libnative_deps1.so.a", "native_deps1.so.lib"]), + ]) + +def _test_java_library_gen_source_no_processor_names(name): + util.helper_target( + java_plugin, + name = name + "/plugin", + srcs = ["AnnotationProcessor.java"], + ) + util.helper_target( + java_library, + name = name + "/to_be_processed", + srcs = ["ToBeProcessed.java"], + plugins = [name + "/plugin"], + ) + + analysis_test( + name = name, + impl = _test_java_library_gen_source_no_processor_names_impl, + target = name + "/to_be_processed", + ) + +def _test_java_library_gen_source_no_processor_names_impl(env, target): + javac_action = javac_action_subject.of(env, target, "{package}/lib{name}.jar") + + # The compile action should not have a gensrc jar output even though it has a plugin, + # since the plugin doesn't define a processor. + javac_action.outputs().contains_exactly([ + "{package}/lib{name}.jar", + "{package}/lib{name}.jdeps", + "{package}/lib{name}-native-header.jar", + "{package}/lib{name}.jar_manifest_proto", + ]) + def _test_java_library_fix_deps_tool_written_to_params_file(name): if not bazel_features.rules.analysis_tests_can_transition_on_experimental_incompatible_flags: # Bazel 7 does not support transition on experimental_* flags. # Exit early because this test case would be a loading phase error otherwise. always_passes(name) return + util.helper_target( java_library, name = name + "/base", @@ -250,4 +641,14 @@ _test_java_library_runtime_deps_are_not_on_classpath, _test_java_library_runtime_deps_are_not_on_classpath_with_header_compilation, _test_java_library_fix_deps_tool_written_to_params_file, + _test_java_library_propagates_native_libraries, + _test_java_library_gen_source_no_processor_names, + _test_java_library_annotation_processing_using_javacopt, + _test_java_library_javacopts_with_location_expansion, + _test_java_library_invalid_plugin, + _test_java_library_plugin_with_runtime_deps, + _test_java_library_source_jar_without_annotation_processing, + _test_java_library_source_jars_with_source_jars, + _test_java_library_should_set_bootclasspath, + _test_java_library_command_line_contains_target_label_and_rule_kind, ]
diff --git a/test/java/testutil/javac_action_subject.bzl b/test/java/testutil/javac_action_subject.bzl index 057040b..3c40566 100644 --- a/test/java/testutil/javac_action_subject.bzl +++ b/test/java/testutil/javac_action_subject.bzl
@@ -25,9 +25,16 @@ # An unset --strict_java_deps is equivalent to "OFF". strict_java_deps = lambda: _create_subject_for_flag("--strict_java_deps", self.parsed_flags, self.meta, default = ["OFF"]), sources = lambda: _create_subject_for_flag("--sources", self.parsed_flags, self.meta), + resources = lambda: _create_subject_for_flag("--resources", self.parsed_flags, self.meta), classpath = lambda: _create_subject_for_flag("--classpath", self.parsed_flags, self.meta), + bootclasspath = lambda: _create_subject_for_flag("--bootclasspath", self.parsed_flags, self.meta), + system = lambda: _create_subject_for_flag("--system", self.parsed_flags, self.meta), + generated_sources_output = lambda: _create_subject_for_flag("--generated_sources_output", self.parsed_flags, self.meta), + processorpath = lambda: _create_subject_for_flag("--processorpath", self.parsed_flags, self.meta), + target_label = lambda: _create_subject_for_flag("--target_label", self.parsed_flags, self.meta), executable_file_name = lambda: subjects.str(action_subject.actual.argv[0], self.meta), inputs = action_subject.inputs, + outputs = lambda: subjects.collection([o.short_path for o in action_subject.actual.outputs.to_list()], self.meta.derive("outputs()"), format = True), argv = action_subject.argv, mnemonic = action_subject.mnemonic, )