Starlarkify many `JavaStarlarkApiTest` tests.

PiperOrigin-RevId: 879201973
Change-Id: I783eee85fb6f1beeb47781f7c163745c3c0b1984
diff --git a/test/java/common/java_common_tests.bzl b/test/java/common/java_common_tests.bzl
index c35f838..d75d4a5 100644
--- a/test/java/common/java_common_tests.bzl
+++ b/test/java/common/java_common_tests.bzl
@@ -1,6 +1,8 @@
 """Tests for java_common APIs"""
 
+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")
@@ -10,6 +12,7 @@
 load("//java/common:java_common.bzl", "java_common")
 load("//java/common:java_info.bzl", "JavaInfo")
 load("//java/common:java_plugin_info.bzl", "JavaPluginInfo")
+load("//java/toolchains:java_runtime.bzl", "java_runtime")
 load("//test/java/testutil:artifact_closure.bzl", "artifact_closure")
 load("//test/java/testutil:java_info_subject.bzl", "java_info_subject")
 load("//test/java/testutil:javac_action_subject.bzl", "javac_action_subject")
@@ -22,6 +25,8 @@
 load("//test/java/testutil:rules/custom_library_with_named_outputs.bzl", "custom_library_with_named_outputs")
 load("//test/java/testutil:rules/custom_library_with_sourcepaths.bzl", "custom_library_with_sourcepaths")
 load("//test/java/testutil:rules/custom_library_with_strict_deps.bzl", "custom_library_with_strict_deps")
+load("//test/java/testutil:rules/custom_library_with_strict_java_deps_provider.bzl", "StrictJavaDepsInfo", "custom_library_with_strict_java_deps_provider")
+load("//test/java/testutil:rules/custom_library_with_wrong_java_toolchain_type.bzl", "custom_library_with_wrong_java_toolchain_type")
 load("//test/java/testutil:rules/custom_library_with_wrong_plugins_type.bzl", "custom_library_with_wrong_plugins_type")
 
 def _test_compile_default_values(name):
@@ -878,6 +883,194 @@
     turbine_action_noproc.mnemonic().equals("Turbine")
     turbine_action_noproc.argv().not_contains("--processors")
 
+def _test_compile_direct_native_libraries(name):
+    target_name = name + "/custom"
+    util.helper_target(
+        cc_library,
+        name = target_name + "/native.so",
+        srcs = ["a.cc"],
+    )
+    util.helper_target(
+        custom_library,
+        name = target_name,
+        srcs = ["A.java"],
+        ccdeps = [target_name + "/native.so"],
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_compile_direct_native_libraries_impl,
+        target = target_name,
+    )
+
+def _test_compile_direct_native_libraries_impl(env, target):
+    assert_native_libs = java_info_subject.from_target(env, target).transitive_native_libraries()
+    assert_native_libs.static_libraries().contains_exactly_predicates([
+        matching.any(
+            matching.str_matches("libnative.so.a"),  # linux / mac
+            matching.str_matches("native.so.lib"),  # windows
+        ),
+    ])
+
+def _test_strict_java_deps_default(name):
+    util.helper_target(
+        custom_library,
+        name = name + "/unused",
+    )
+    analysis_test(
+        name = name,
+        target = name + "/unused",  # analysis_test requires setting a target.
+        impl = _test_strict_java_deps_default_impl,
+        fragments = ["java"],
+    )
+
+def _test_strict_java_deps_default_impl(env, _unused):
+    env.expect.that_str(env.ctx.fragments.java.strict_java_deps).equals("default")
+
+def _test_strict_java_deps_error(name):
+    util.helper_target(
+        custom_library_with_strict_java_deps_provider,
+        name = name + "_strict_java_deps_provider",
+    )
+
+    if not bazel_features.rules.analysis_tests_can_transition_on_experimental_incompatible_flags:
+        analysis_test(
+            name = name,
+            impl = lambda env, target: env.expect.that_bool(True).equals(True),
+            target = name + "_strict_java_deps_provider",
+        )
+    else:
+        analysis_test(
+            name = name,
+            target = name + "_strict_java_deps_provider",
+            impl = _test_strict_java_deps_error_impl,
+            fragments = ["java"],
+            config_settings = {"//command_line_option:experimental_strict_java_deps": "error"},
+        )
+
+def _test_strict_java_deps_error_impl(env, target):
+    env.expect.that_str(target[StrictJavaDepsInfo].strict_java_deps).equals("error")
+
+def _test_compile_output_jar_has_manifest_proto(name):
+    util.helper_target(
+        custom_library,
+        name = name + "/custom",
+        srcs = ["Main.java"],
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_compile_output_jar_has_manifest_proto_impl,
+        target = name + "/custom",
+    )
+
+def _test_compile_output_jar_has_manifest_proto_impl(env, target):
+    java_info_subject.from_target(env, target).java_outputs().singleton().manifest_proto().short_path_equals(
+        "{package}/lib{name}.jar_manifest_proto",
+    )
+
+def _test_compile_with_neverlink_deps(name):
+    target_name = name + "/custom"
+    util.helper_target(
+        java_library,
+        name = target_name + "/neverlink_dep",
+        srcs = ["B.java"],
+        neverlink = True,
+    )
+    util.helper_target(
+        custom_library,
+        name = target_name,
+        srcs = ["A.java"],
+        deps = [target_name + "/neverlink_dep"],
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_compile_with_neverlink_deps_impl,
+        target = target_name,
+    )
+
+def _test_compile_with_neverlink_deps_impl(env, target):
+    assert_java_info = java_info_subject.from_target(env, target)
+    assert_java_info.compilation_args().transitive_runtime_jars().contains_exactly([
+        "{package}/lib{name}.jar",
+    ])
+    assert_java_info.transitive_source_jars().contains_exactly([
+        "{package}/lib{name}-src.jar",
+        "{package}/lib{name}/neverlink_dep-src.jar",
+    ])
+    assert_java_info.compilation_args().transitive_compile_time_jars().contains_exactly([
+        "{package}/lib{name}-hjar.jar",
+        "{package}/lib{name}/neverlink_dep-hjar.jar",
+    ])
+
+def _test_compile_output_jar_not_in_runtime_path_without_sources_defined(name):
+    target_name = name + "/custom"
+    util.helper_target(
+        java_library,
+        name = target_name + "/export_dep",
+        srcs = ["B.java"],
+    )
+    util.helper_target(
+        custom_library,
+        name = target_name,
+        srcs = [],
+        exports = [target_name + "/export_dep"],
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_compile_output_jar_not_in_runtime_path_without_sources_defined_impl,
+        target = target_name,
+    )
+
+def _test_compile_output_jar_not_in_runtime_path_without_sources_defined_impl(env, target):
+    assert_java_info = java_info_subject.from_target(env, target)
+    assert_java_info.compilation_args().transitive_runtime_jars().contains_exactly([
+        "{package}/lib{name}/export_dep.jar",
+    ])
+    assert_java_info.compilation_args().transitive_compile_time_jars().contains_exactly([
+        "{package}/lib{name}/export_dep-hjar.jar",
+    ])
+    assert_java_info.java_outputs().singleton().class_jar().short_path_equals("{package}/lib{name}.jar")
+    assert_java_info.java_outputs().singleton().compile_jar().equals(None)
+
+def _test_java_runtime_provider_files(name):
+    # Create a rule that extracts JavaRuntimeInfo.files
+    util.helper_target(
+        java_runtime,
+        name = name + "/jvm",
+        srcs = ["a.txt"],
+        java_home = "foo/bar",
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_java_runtime_provider_files_impl,
+        target = name + "/jvm",
+    )
+
+def _test_java_runtime_provider_files_impl(env, target):
+    env.expect.that_target(target).default_outputs().contains_exactly(["{package}/a.txt"])
+
+def _test_custom_library_with_wrong_java_toolchain_type(name):
+    util.helper_target(
+        custom_library_with_wrong_java_toolchain_type,
+        name = name + "/custom",
+        srcs = ["a.java"],
+    )
+    analysis_test(
+        name = name,
+        impl = _test_custom_library_with_wrong_java_toolchain_type_impl,
+        target = name + "/custom",
+        expect_failure = True,
+    )
+
+def _test_custom_library_with_wrong_java_toolchain_type_impl(env, target):
+    env.expect.that_target(target).failures().contains_predicate(
+        matching.str_matches("got element of type ToolchainInfo, want JavaToolchainInfo"),
+    )
+
 def java_common_tests(name):
     test_suite(
         name = name,
@@ -909,5 +1102,13 @@
             _test_compile_strict_deps_enum,
             _test_java_library_collects_coverage_dependencies_from_resources,
             _test_skip_annotation_processing,
+            _test_compile_direct_native_libraries,
+            _test_strict_java_deps_default,
+            _test_strict_java_deps_error,
+            _test_compile_output_jar_has_manifest_proto,
+            _test_compile_with_neverlink_deps,
+            _test_compile_output_jar_not_in_runtime_path_without_sources_defined,
+            _test_java_runtime_provider_files,
+            _test_custom_library_with_wrong_java_toolchain_type,
         ],
     )
diff --git a/test/java/common/java_info_tests.bzl b/test/java/common/java_info_tests.bzl
index 4f82d3e..daea048 100644
--- a/test/java/common/java_info_tests.bzl
+++ b/test/java/common/java_info_tests.bzl
@@ -1390,6 +1390,34 @@
         matching.str_matches("*native_dep*"),
     ])
 
+def _test_merge_runtime_output_jars(name):
+    util.helper_target(
+        java_library,
+        name = name + "/a",
+        srcs = ["A.java"],
+    )
+    util.helper_target(
+        java_library,
+        name = name + "/b",
+        srcs = ["B.java"],
+    )
+    util.helper_target(
+        java_info_merge_rule,
+        name = name + "/merged",
+        deps = [name + "/a", name + "/b"],
+    )
+    analysis_test(
+        name = name,
+        impl = _test_merge_runtime_output_jars_impl,
+        target = name + "/merged",
+    )
+
+def _test_merge_runtime_output_jars_impl(env, target):
+    java_info_subject.from_target(env, target).runtime_output_jars().contains_exactly([
+        "{package}/lib{test_name}/a.jar",
+        "{package}/lib{test_name}/b.jar",
+    ])
+
 def java_info_tests(name):
     test_suite(
         name = name,
@@ -1438,5 +1466,6 @@
             _java_common_merge_with_neverlink_test,
             _java_common_compile_with_neverlink_test,
             _java_common_compile_native_libraries_propagate_test,
+            _test_merge_runtime_output_jars,
         ],
     )
diff --git a/test/java/testutil/java_info_subject.bzl b/test/java/testutil/java_info_subject.bzl
index 8471706..f5ad9e9 100644
--- a/test/java/testutil/java_info_subject.bzl
+++ b/test/java/testutil/java_info_subject.bzl
@@ -98,6 +98,7 @@
         source_jars = lambda: subjects.depset_file(java_output.source_jars if hasattr(java_output.source_jars, "to_list") else depset(java_output.source_jars), meta.derive("source_jars")),
         jdeps = lambda: subjects.file(java_output.jdeps, meta.derive("jdeps")),
         compile_jdeps = lambda: subjects.file(java_output.compile_jdeps, meta.derive("compile_jdeps")),
+        manifest_proto = lambda: subjects.file(java_output.manifest_proto, meta.derive("manifest_proto")),
         native_headers_jar = lambda: subjects.file(java_output.native_headers_jar, meta.derive("native_headers_jar")),
     )
     return public
diff --git a/test/java/testutil/java_toolchain_info_subject.bzl b/test/java/testutil/java_toolchain_info_subject.bzl
index 2757bfc..31afe59 100644
--- a/test/java/testutil/java_toolchain_info_subject.bzl
+++ b/test/java/testutil/java_toolchain_info_subject.bzl
@@ -23,6 +23,11 @@
         header_compiler_builtin_processors = lambda: subjects.collection(info._header_compiler_builtin_processors.to_list(), meta.derive("_header_compiler_builtin_processors")),
         reduced_classpath_incompatible_processors = lambda: subjects.collection(info._reduced_classpath_incompatible_processors.to_list(), meta.derive("_reduced_classpath_incompatible_processors")),
         javabuilder = lambda: _new_java_builder_subject(info._javabuilder, meta.derive("_javabuilder")),
+        label = lambda: subjects.label(info.label, meta.derive("label")),
+        # TODO: hvd - Give label_subject predicate matching support so we don't need this str_subject variant.
+        label_str = lambda: subjects.str(str(info.label), meta.derive("label_str")),
+        default_javacopts = lambda: subjects.collection(info._javacopts_list, meta.derive("default_javacopts")),
+        default_javacopts_depset = lambda: subjects.collection(info._javacopts.to_list(), meta.derive("default_javacopts_depset")),
     )
     return public
 
diff --git a/test/java/testutil/rules/custom_library.bzl b/test/java/testutil/rules/custom_library.bzl
index ec3699c..5ef3ca0 100644
--- a/test/java/testutil/rules/custom_library.bzl
+++ b/test/java/testutil/rules/custom_library.bzl
@@ -1,5 +1,6 @@
 """Helper rule for testing compilation with default parameter values"""
 
+load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
 load("//java/common:java_common.bzl", "java_common")
 load("//java/common:java_info.bzl", "JavaInfo")
 load("//java/common:java_plugin_info.bzl", "JavaPluginInfo")
@@ -9,6 +10,7 @@
     output_jar = ctx.actions.declare_file("lib" + ctx.label.name + ".jar")
     deps = [dep[JavaInfo] for dep in ctx.attr.deps]
     runtime_deps = [dep[JavaInfo] for dep in ctx.attr.runtime_deps]
+    native_libraries = [dep[CcInfo] for dep in ctx.attr.ccdeps]
     compilation_provider = java_common.compile(
         ctx,
         source_files = ctx.files.srcs,
@@ -22,6 +24,7 @@
         javac_opts = ctx.attr.javac_opts,
         java_toolchain = semantics.find_java_toolchain(ctx),
         enable_annotation_processing = ctx.attr.enable_annotation_processing,
+        native_libraries = native_libraries,
     )
     return [DefaultInfo(files = depset([output_jar])), compilation_provider]
 
@@ -32,6 +35,7 @@
         "source_jars": attr.label_list(allow_files = [".jar"]),
         "deps": attr.label_list(),
         "runtime_deps": attr.label_list(),
+        "ccdeps": attr.label_list(providers = [CcInfo]),
         "exports": attr.label_list(),
         "plugins": attr.label_list(),
         "javac_opts": attr.string_list(),
diff --git a/test/java/testutil/rules/custom_library_with_strict_java_deps_provider.bzl b/test/java/testutil/rules/custom_library_with_strict_java_deps_provider.bzl
new file mode 100644
index 0000000..3a0f66a
--- /dev/null
+++ b/test/java/testutil/rules/custom_library_with_strict_java_deps_provider.bzl
@@ -0,0 +1,15 @@
+"""Custom libraty that reads --strict_java_deps and returns it from a provider."""
+
+StrictJavaDepsInfo = provider(
+    doc = "Provides args.strict_java_deps for testing",
+    fields = ["strict_java_deps"],
+)
+
+def _impl(ctx):
+    return [StrictJavaDepsInfo(strict_java_deps = ctx.fragments.java.strict_java_deps)]
+
+custom_library_with_strict_java_deps_provider = rule(
+    implementation = _impl,
+    attrs = {},
+    fragments = ["java"],
+)
diff --git a/test/java/testutil/rules/custom_library_with_wrong_java_toolchain_type.bzl b/test/java/testutil/rules/custom_library_with_wrong_java_toolchain_type.bzl
new file mode 100644
index 0000000..73b4a7f
--- /dev/null
+++ b/test/java/testutil/rules/custom_library_with_wrong_java_toolchain_type.bzl
@@ -0,0 +1,24 @@
+"""Custom rule to test java_common.compile(java_toolchain = ...) expects JavaToolchainInfo"""
+
+load("//java/common:java_common.bzl", "java_common")
+load("//java/common:java_semantics.bzl", "semantics")
+
+def _impl(ctx):
+    output_jar = ctx.actions.declare_file("lib" + ctx.label.name + ".jar")
+    return java_common.compile(
+        ctx,
+        source_files = ctx.files.srcs,
+        output = output_jar,
+        java_toolchain = ctx.attr._java_toolchain[platform_common.ToolchainInfo],
+    )
+
+custom_library_with_wrong_java_toolchain_type = rule(
+    implementation = _impl,
+    attrs = {
+        "srcs": attr.label_list(allow_files = [".java"]),
+        "deps": attr.label_list(),
+        "_java_toolchain": attr.label(default = semantics.JAVA_TOOLCHAIN_LABEL),
+    },
+    toolchains = [semantics.JAVA_TOOLCHAIN_TYPE],
+    fragments = ["java"],
+)
diff --git a/test/java/toolchains/BUILD b/test/java/toolchains/BUILD
index 4ebe1f2..1d7af21 100644
--- a/test/java/toolchains/BUILD
+++ b/test/java/toolchains/BUILD
@@ -6,3 +6,5 @@
 java_runtime_tests(name = "java_runtime_tests")
 
 java_toolchain_tests(name = "java_toolchain_tests")
+
+exports_files(["java_runtime.src"])
diff --git a/test/java/toolchains/java_toolchain_tests.bzl b/test/java/toolchains/java_toolchain_tests.bzl
index 7c95d0e..372b999 100644
--- a/test/java/toolchains/java_toolchain_tests.bzl
+++ b/test/java/toolchains/java_toolchain_tests.bzl
@@ -13,6 +13,7 @@
 load("//test/java/testutil:java_info_subject.bzl", "java_info_subject")
 load("//test/java/testutil:java_toolchain_info_subject.bzl", "java_toolchain_info_subject")
 load("//test/java/testutil:javac_action_subject.bzl", "javac_action_subject")
+load("//toolchains:java_toolchain_alias.bzl", "java_toolchain_alias")
 
 def _declare_java_toolchain(*, name, **kwargs):
     java_runtime_name = name + "/runtime"
@@ -595,6 +596,86 @@
         matching.str_matches("must declare *tools/jdk:toolchain_type' toolchain in order to use java_common"),
     )
 
+def _test_java_toolchain_flag_default(name):
+    util.helper_target(
+        java_toolchain_alias,
+        name = name + "/toolchain_alias",
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_java_toolchain_flag_default_impl,
+        target = name + "/toolchain_alias",
+    )
+
+def _test_java_toolchain_flag_default_impl(env, target):
+    assert_toolchain = java_toolchain_info_subject.from_target(env, target)
+    assert_toolchain.label_str().matches(
+        matching.any(
+            matching.str_endswith("jdk:remote_toolchain"),
+            matching.str_endswith("jdk:toolchain"),
+            matching.str_endswith("jdk:toolchain_host"),
+            # buildifier: disable=canonical-repository
+            matching.str_startswith("@@//toolchains:toolchain_java"),
+        ),
+    )
+
+def _test_java_toolchain_flag_set(name):
+    _declare_java_toolchain(name = name)
+    util.helper_target(
+        java_toolchain_alias,
+        name = name + "/toolchain_alias",
+    )
+
+    analysis_test(
+        name = name,
+        impl = _test_java_toolchain_flag_set_impl,
+        targets = {
+            "alias": name + "/toolchain_alias",
+            "toolchain": name + "/java_toolchain",
+        },
+        config_settings = {
+            "//command_line_option:extra_toolchains": [Label(name + "/toolchain")],
+        },
+    )
+
+def _test_java_toolchain_flag_set_impl(env, targets):
+    assert_toolchain = java_toolchain_info_subject.from_target(env, targets.alias)
+    assert_toolchain.label().equals(targets.toolchain.label)
+
+def _test_default_javac_opts_depset(name):
+    _declare_java_toolchain(name = name)
+
+    analysis_test(
+        name = name,
+        impl = _test_default_javac_opts_depset_impl,
+        target = name + "/java_toolchain",
+        attr_values = {"tags": ["min_bazel_8"]},
+    )
+
+def _test_default_javac_opts_depset_impl(env, target):
+    java_toolchain_info_subject.from_target(env, target).default_javacopts_depset().contains_exactly(
+        ["-source 6 -target 6 -Xlint:toto -Xmaxerrs 500"],
+    )
+
+def _test_default_javac_opts(name):
+    _declare_java_toolchain(name = name)
+
+    analysis_test(
+        name = name,
+        impl = _test_default_javac_opts_impl,
+        target = name + "/java_toolchain",
+        attr_values = {"tags": ["min_bazel_8"]},
+    )
+
+def _test_default_javac_opts_impl(env, target):
+    java_toolchain_info_subject.from_target(env, target).default_javacopts().contains_at_least([
+        "-source",
+        "6",
+        "-target",
+        "6",
+    ]).in_order()
+
 def java_toolchain_tests(name):
     test_suite(
         name = name,
@@ -619,5 +700,9 @@
             _test_java_compile_action_uses_tool_specific_jvm_opts,
             _test_javabuilder_location_expansion_with_multiple_artifacts,
             _test_java_common_without_toolchain_type_fails,
+            _test_java_toolchain_flag_default,
+            _test_java_toolchain_flag_set,
+            _test_default_javac_opts_depset,
+            _test_default_javac_opts,
         ],
     )