Merge remote-tracking branch 'aosp/upstream-main' into aosp am: fb2b420b89

Original change: https://android-review.googlesource.com/c/platform/external/bazelbuild-kotlin-rules/+/2795413

Change-Id: I3ebefa424fd41bb0a472a2e55fee10e4aaf03efb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/BUILD b/BUILD
index 5f9e261..2bbd42e 100644
--- a/BUILD
+++ b/BUILD
@@ -13,8 +13,13 @@
 # limitations under the License.
 
 load("//bazel:stubs.bzl", "integration_test_filegroup")
+load("@rules_license//rules:license.bzl", "license")
 load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
 
+package(
+    default_applicable_licenses = ["//:license"],
+)
+
 licenses(["notice"])
 
 exports_files(["LICENSE"])
@@ -25,3 +30,15 @@
         "//...",
     ],
 )
+
+bzl_library(
+    name = "visibility_bzl",
+    srcs = ["visibility.bzl"],
+    visibility = [":internal"],
+)
+
+license(
+    name = "license",
+    package_name = "rules_kotlin",
+    visibility = [":internal"],
+)
diff --git a/METADATA b/METADATA
index a499231..b1d1458 100644
--- a/METADATA
+++ b/METADATA
@@ -11,8 +11,8 @@
     type: GIT
     value: "https://team.googlesource.com/kotlin-rules/rules"
   }
-  version: "7a8fbedcfd9b4c1121d144329d9bf3e9a3184026"
-  last_upgrade_date { year: 2023 month: 10 day: 3}
+  version: "56d691d5d452654a36b5890992042e85137ad083"
+  last_upgrade_date { year: 2023 month: 10 day: 18}
   license_type: NOTICE
 }
 
diff --git a/WORKSPACE b/WORKSPACE
index e7a7d09..1db6b76 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -47,6 +47,16 @@
 )
 
 http_archive(
+    name = "rules_license",
+    sha256 = "4531deccb913639c30e5c7512a054d5d875698daeb75d8cf90f284375fe7c360",
+    urls = [
+        "https://github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz",
+    ],
+)
+load("@rules_license//:deps.bzl", "rules_license_dependencies")
+rules_license_dependencies()
+
+http_archive(
     name = "rules_java",
     urls = [
       "https://mirror.bazel.build/github.com/bazelbuild/rules_java/releases/download/5.5.0/rules_java-5.5.0.tar.gz",
diff --git a/bazel/deploy_jar_freshness_golden_test.bzl b/bazel/deploy_jar_freshness_golden_test.bzl
index a6524eb..7c933ce 100644
--- a/bazel/deploy_jar_freshness_golden_test.bzl
+++ b/bazel/deploy_jar_freshness_golden_test.bzl
@@ -16,6 +16,8 @@
 
 load("//:visibility.bzl", "RULES_KOTLIN")
 
+visibility(RULES_KOTLIN)
+
 def _deploy_jar_freshness_golden_test_impl(ctx):
     test_command = """
       if ! cmp $1 $2 ; then
diff --git a/bazel/stubs.bzl b/bazel/stubs.bzl
index 4a6915d..c63ac76 100644
--- a/bazel/stubs.bzl
+++ b/bazel/stubs.bzl
@@ -15,16 +15,19 @@
 """Stubs"""
 
 load("//:visibility.bzl", "RULES_KOTLIN")
-load("@bazel_skylib//lib:sets.bzl", "sets")
+
+visibility(RULES_KOTLIN)
 
 def _empty_fn(*_args, **_kwargs):
     pass
 
 register_extension_info = _empty_fn
 
-FORBIDDEN_DEP_PACKAGES = sets.make([])
+is_forbidden_dep = _empty_fn
 
-EXEMPT_DEPS = sets.make([])
+is_exempt_dep = _empty_fn
+
+is_android_lint_exempt = _empty_fn
 
 DEFAULT_BUILTIN_PROCESSORS = [
     "com.google.android.apps.play.store.plugins.injectionentrypoint.InjectionEntryPointProcessor",
@@ -58,7 +61,7 @@
 def check_compiler_opt_allowlist(_label):
     pass
 
-def jspecify_flags(ctx):
+def jspecify_flags(_ctx):
     # Trust JSpecify nullness annotations
     # (see https://kotlinlang.org/docs/whatsnew1520.html#support-for-jspecify-nullness-annotations)
     return ["-Xjspecify-annotations=strict"]
diff --git a/copy.bara.sky b/copy.bara.sky
index 13546c4..616f41e 100644
--- a/copy.bara.sky
+++ b/copy.bara.sky
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-1486640829
\ No newline at end of file
+1660301306
\ No newline at end of file
diff --git a/kotlin/common.bzl b/kotlin/common.bzl
index 2279596..cabe9fa 100644
--- a/kotlin/common.bzl
+++ b/kotlin/common.bzl
@@ -15,17 +15,17 @@
 """Common Kotlin definitions."""
 
 load("//:visibility.bzl", "RULES_DEFS_THAT_COMPILE_KOTLIN")
-
-# go/keep-sorted start
-load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory")
-load("//kotlin/jvm/internal_do_not_use/util:srcjars.bzl", "kt_srcjars")
+load("//kotlin/jvm/util:file_factory.bzl", "FileFactory")
+load("//kotlin/jvm/util:srcjars.bzl", "kt_srcjars")
 load("//toolchains/kotlin_jvm:androidlint_toolchains.bzl", "androidlint_toolchains")
 load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
 load("@bazel_skylib//lib:sets.bzl", "sets")
 load("//bazel:stubs.bzl", "lint_actions")
 load("//bazel:stubs.bzl", "jspecify_flags")
+load("//bazel:stubs.bzl", "is_android_lint_exempt")
 load("//bazel:stubs.bzl", "BASE_JVMOPTS")
-# go/keep-sorted end
+
+visibility(RULES_DEFS_THAT_COMPILE_KOTLIN)
 
 # TODO: Remove the _ALLOWED_*_RULES lists to determine which rules
 # are accepted dependencies to Kotlin rules as the approach does not scale
@@ -204,7 +204,7 @@
         } if toolchain.is_profiling_enabled(ctx.label) else {
             "worker-key-mnemonic": "Kt2JavaCompile",
         },
-        toolchain = kt_jvm_toolchains.type,
+        toolchain = toolchain.toolchain_type,
     )
 
     return struct(
@@ -317,7 +317,7 @@
         outputs = [output_dir],
         mnemonic = "KtDeriveHeaders",
         progress_message = "Deriving %s: %s" % (output_dir.basename, _get_original_kt_target_label(ctx)),
-        toolchain = kt_jvm_toolchains.type,
+        toolchain = toolchain.toolchain_type,
     )
     return [output_dir]
 
@@ -388,7 +388,7 @@
         outputs = [output],
         mnemonic = "KtJaCoCoInstrument",
         progress_message = "Instrumenting Kotlin for coverage collection: %s" % _get_original_kt_target_label(ctx),
-        toolchain = kt_jvm_toolchains.type,
+        toolchain = toolchain.toolchain_type,
     )
 
     return output
@@ -443,7 +443,7 @@
         arguments = [args],
         mnemonic = "KtMergeJdeps",
         progress_message = "Merging jdeps files %{output}",
-        toolchain = kt_jvm_toolchains.type,
+        toolchain = kt_jvm_toolchain.toolchain_type,
     )
 
     return merged_jdeps_file
@@ -504,7 +504,6 @@
         common_srcs = [],
         coverage_srcs = [],
         java_android_lint_config = None,
-        force_android_lint = False,  # TODO Remove this param
         manifest = None,  # set for Android libs, otherwise None.
         merged_manifest = None,  # set for Android libs, otherwise None.
         resource_files = [],  # set for Android libs, otherwise empty.
@@ -576,24 +575,12 @@
     # Collect all plugin data, including processors to run and all plugin classpaths,
     # whether they have processors or not (b/120995492).
     # This may include go/errorprone plugin classpaths that kapt will ignore.
-    java_plugin_datas = kt_codegen_processing_env.get("java_plugin_data_set", depset()).to_list()
-    processors_for_java_srcs = kt_codegen_processing_env.get("processors_for_java_srcs", depset()).to_list()
+    java_plugin_datas = kt_codegen_processing_env.get("java_plugin_data_set", plugins.java_plugin_datas).to_list()
+    processors_for_java_srcs = kt_codegen_processing_env.get("processors_for_java_srcs", depset(transitive = [p.processor_classes for p in java_plugin_datas])).to_list()
     java_plugin_classpaths_for_java_srcs = depset(transitive = [p.processor_jars for p in java_plugin_datas])
-
-    out_jars = [
-        jar
-        for java_info in generative_deps
-        for jar in java_info.runtime_output_jars
-    ]
-
-    out_srcjars = [
-    ] if codegen_plugin_output else []
-
-    out_compilejars = [
-        jar
-        for java_info in generative_deps
-        for jar in java_info.compile_jars.to_list()
-    ]
+    out_jars = kt_codegen_processing_env.get("codegen_runtime_output_jars", [])
+    out_srcjars = kt_codegen_processing_env.get("codegen_source_jars", [])
+    out_compilejars = kt_codegen_processing_env.get("codegen_compile_jars", [])
 
     kt_hdrs = _derive_headers(
         ctx,
@@ -662,10 +649,8 @@
 
         javac_out = output if is_android_library_without_kt_srcs_without_generative_deps else file_factory.declare_file("-libjvm-java.jar")
 
-        annotation_plugins = list(plugins.java_plugin_infos)
-
-        # Enable annotation processing for java-only sources to enable data binding
-        enable_annotation_processing = True if processors_for_java_srcs else False
+        annotation_plugins = kt_codegen_processing_env.get("java_common_annotation_plugins", list(plugins.java_plugin_infos))
+        enable_annotation_processing = kt_codegen_processing_env.get("enable_java_common_annotation_processing", True)
 
         javac_java_info = java_common.compile(
             ctx,
@@ -691,14 +676,6 @@
             annotation_processor_additional_inputs = annotation_processor_additional_inputs,
         )
 
-        # Directly return the JavaInfo from java.compile() for java-only android_library targets
-        # to avoid creating a new JavaInfo. See b/239847857 for additional context.
-        if is_android_library_without_kt_srcs_without_generative_deps:
-            return struct(
-                java_info = javac_java_info,
-                validations = [],
-            )
-
         out_jars.append(javac_out)
         out_srcjars.extend(javac_java_info.source_jars)
         out_compilejars.extend(javac_java_info.compile_jars.to_list())  # unpack singleton depset
@@ -726,8 +703,7 @@
     # TODO: Remove the is_android_library_without_kt_srcs condition once KtAndroidLint
     # uses the same lint checks with AndroidLint
 
-    disable_lint_checks = disable_lint_checks + kt_codegen_processing_env.get("disabled_lint_checks", [])
-    if force_android_lint or not is_android_library_without_kt_srcs:
+    if (srcs or common_srcs or resource_files) and not is_android_lint_exempt(ctx):
         lint_flags = [
             "--java-language-level",  # b/159950410
             kt_toolchain.java_language_version,
@@ -763,10 +739,18 @@
             extra_input_depsets = [p.processor_data for p in java_plugin_datas],
             testonly = testonly,
             android_java8_libs = kt_toolchain.android_java8_apis_desugared,
-            mnemonic = "KtAndroidLint",  # so LSA extractor can distinguish Kotlin (b/189442586)
+            mnemonic = "AndroidLint" if is_android_library_without_kt_srcs else "KtAndroidLint",  # so LSA extractor can distinguish Kotlin (b/189442586)
         )
         blocking_action_outs.append(android_lint_out)
 
+    # Directly return the JavaInfo from java.compile() for java-only android_library targets
+    # to avoid creating a new JavaInfo. See b/239847857 for additional context.
+    if javac_java_info and is_android_library_without_kt_srcs_without_generative_deps:
+        return struct(
+            java_info = javac_java_info,
+            validations = blocking_action_outs,
+        )
+
     if output_srcjar == None:
         output_srcjar = file_factory.declare_file("-src.jar")
     compile_jar = file_factory.declare_file("-compile.jar")
diff --git a/kotlin/common/is_eligible_friend.bzl b/kotlin/common/is_eligible_friend.bzl
index 1e5e814..0cf15d7 100644
--- a/kotlin/common/is_eligible_friend.bzl
+++ b/kotlin/common/is_eligible_friend.bzl
@@ -16,6 +16,8 @@
 
 load("//:visibility.bzl", "RULES_DEFS_THAT_COMPILE_KOTLIN")
 
+visibility(RULES_DEFS_THAT_COMPILE_KOTLIN)
+
 def is_eligible_friend(target, friend):
     """
     Determines if `target` is allowed to use `internal` members of `friend`
diff --git a/tests/analysis/jvm_library/no_java_srcs/BUILD b/kotlin/common/testing/BUILD
similarity index 67%
rename from tests/analysis/jvm_library/no_java_srcs/BUILD
rename to kotlin/common/testing/BUILD
index f149c73..b3ed4eb 100644
--- a/tests/analysis/jvm_library/no_java_srcs/BUILD
+++ b/kotlin/common/testing/BUILD
@@ -12,21 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
 
 package(
     default_testonly = True,
+    default_visibility = ["//:internal"],
 )
 
 licenses(["notice"])
 
-jvm_library_test(
-    name = "no_java_srcs_test",
-    target_under_test = rules_for_test.kt_jvm_library(
-        name = "no_java_srcs",
-        srcs = [
-            "Input.kt",
-        ],
-    ),
+bzl_library(
+    name = "testing_bzl",
+    srcs = glob(["*.bzl"]),
+    visibility = [
+        "//:internal",
+    ],
+    deps = [
+        "//:visibility_bzl",
+        "@bazel_skylib//lib:unittest",
+    ],
 )
diff --git a/kotlin/common/testing/analysis.bzl b/kotlin/common/testing/analysis.bzl
new file mode 100644
index 0000000..34cbfae
--- /dev/null
+++ b/kotlin/common/testing/analysis.bzl
@@ -0,0 +1,114 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_analysis"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+
+visibility(RULES_KOTLIN)
+
+def _get_action(actions, mnemonic):
+    """Get a specific action
+
+    Args:
+        actions: [List[Action]]
+        mnemonic: [string] Identify the action whose args to search
+
+    Returns:
+        [Action|None] The arg value, or None if it couldn't be found
+    """
+    menmonic_actions = [a for a in actions if a.mnemonic == mnemonic]
+    if len(menmonic_actions) == 0:
+        return None
+    elif len(menmonic_actions) > 1:
+        fail("Expected a single '%s' action" % mnemonic)
+
+    return menmonic_actions[0]
+
+def _get_all_args(action, arg_name, style = "trim"):
+    """Gets values for all instances of an arg name from a specific action.
+
+    Args:
+        action: [Action|None]
+        arg_name: [string]
+        style: ["trim"|"next"|"list"] The style of commandline arg
+
+    Returns:
+        [list[string]|list[list[string]]|None] The list of matching arg values
+    """
+    if not action:
+        return []
+
+    args = action.argv
+    matches = [(i, a) for (i, a) in enumerate(args) if a.startswith(arg_name)]
+
+    result = []
+    for index, arg in matches:
+        if style == "trim":
+            result.append(arg[len(arg_name):])
+        elif style == "next":
+            result.append(args[index + 1])
+        elif style == "list":
+            sub_result = []
+            for i in range(index + 1, len(args)):
+                if args[i].startswith("--"):
+                    break
+                sub_result.append(args[i])
+            result.append(sub_result)
+        else:
+            fail("Unrecognized arg style '%s" % style)
+
+    return result
+
+def _get_arg(action, arg_name, style = "trim"):
+    """Gets values for exactly one instance of an arg name from a specific action.
+
+    Args:
+        action: [Action|None]
+        arg_name: [string]
+        style: ["trim"|"next"|"list"] The style of commandline arg
+
+    Returns:
+        [string|list[string]|None] The arg value, or None if it couldn't be found
+    """
+    results = _get_all_args(action, arg_name, style)
+
+    if len(results) == 0:
+        return None
+    elif len(results) == 1:
+        return results[0]
+    else:
+        fail("Expected a single '%s' arg" % arg_name)
+
+def _check_endswith_test(ctx):
+    name = ctx.label.name
+    for i in range(0, 10):
+        # TODO: Remove support for suffix digits
+        if name.endswith(str(i)):
+            name = name.removesuffix(str(i))
+            break
+    if name.endswith("_test"):
+        return
+
+    fail("Analysis test names must end in '_test'")
+
+kt_analysis = struct(
+    # go/keep-sorted start
+    DEFAULT_LIST = ["__default__"],
+    check_endswith_test = _check_endswith_test,
+    get_action = _get_action,
+    get_all_args = _get_all_args,
+    get_arg = _get_arg,
+    # go/keep-sorted end
+)
diff --git a/kotlin/common/testing/asserts.bzl b/kotlin/common/testing/asserts.bzl
new file mode 100644
index 0000000..d88796c
--- /dev/null
+++ b/kotlin/common/testing/asserts.bzl
@@ -0,0 +1,116 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_asserts"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("@bazel_skylib//lib:unittest.bzl", "asserts")
+
+visibility(RULES_KOTLIN)
+
+def _equals(a, b):
+    return a == b
+
+def _list_matching(left, right, matcher = None):
+    """Find the overlap between two lists.
+
+    Args:
+        left: [list[A]]
+        right: [list[B]]
+        matcher: [function(A,B):bool] A matcher on the two list types
+
+    Returns:
+        [(list[A], list[(A, B)], list[B])] The left-only, matching-pair, and right-only lists
+    """
+
+    matcher = matcher or _equals
+
+    left_only = []
+    matches = []
+    right_only = list(right)
+
+    def _process_left_ele(left_ele):
+        for index, right_ele in enumerate(right_only):
+            if matcher(left_ele, right_ele):
+                right_only.pop(index)
+                matches.append((left_ele, right_ele))
+                return
+
+        left_only.append(left_ele)
+
+    for left_ele in left:
+        _process_left_ele(left_ele)
+
+    return (left_only, matches, right_only)
+
+def _assert_list_matches(env, expected, actual, matcher = None, items_name = "items"):
+    """Assert two lists have an exact matching.
+
+    Args:
+        env: [unittest.env]
+        expected: [list[A]]
+        actual: [list[B]]
+        matcher: [function(A,B):bool]
+        items_name: [string] The plural noun describing the list items in an error message
+
+    Returns:
+        [None] Fails if assertion violated
+    """
+
+    extra_expected, _, extra_actual = _list_matching(expected, actual, matcher = matcher)
+    asserts.true(
+        env,
+        len(extra_actual) == 0 and len(extra_expected) == 0,
+        "Unmatched expected {name} {expected}\nUnmatched actual {name} {actual}".format(
+            name = items_name,
+            expected = extra_expected,
+            actual = extra_actual,
+        ),
+    )
+
+def _assert_required_mnemonic_counts(env, required_mnemonic_counts, actual_actions):
+    """Assert that some set of menemonics is present/absent within a set of Actions.
+
+    Args:
+        env: [unittest.env]
+        required_mnemonic_counts: [dict[string,string]] The menemonics to check -> expected count
+        actual_actions: [list[Action]]
+
+    Returns:
+        [None] Fails if assertion violated
+    """
+
+    considered_actual_mnemonics = [
+        x.mnemonic
+        for x in actual_actions
+        # Ignore any mnemonics not mentioned by the user
+        if (x.mnemonic in required_mnemonic_counts)
+    ]
+
+    required_mnemonics = []
+    for m, c in required_mnemonic_counts.items():
+        for _ in range(0, int(c)):
+            required_mnemonics.append(m)
+
+    _assert_list_matches(
+        env,
+        required_mnemonics,
+        considered_actual_mnemonics,
+        items_name = "mnemonics",
+    )
+
+kt_asserts = struct(
+    list_matches = _assert_list_matches,
+    required_mnemonic_counts = _assert_required_mnemonic_counts,
+)
diff --git a/kotlin/common/testing/testing_rules.bzl b/kotlin/common/testing/testing_rules.bzl
new file mode 100644
index 0000000..35359f7
--- /dev/null
+++ b/kotlin/common/testing/testing_rules.bzl
@@ -0,0 +1,143 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_testing_rules"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(":analysis.bzl", "kt_analysis")
+
+visibility(RULES_KOTLIN)
+
+# Mark targets that's aren't expected to build, but are needed for analysis test assertions.
+_ONLY_FOR_ANALYSIS_TAGS = ["manual", "nobuilder", "notap"]
+
+def _wrap_for_analysis(inner_rule):
+    """Wrap an existing rule to make it easier to use in analysis tests.
+
+    Args:
+        inner_rule: [rule|macro]
+
+    Returns:
+        [macro] Calls inner_rule with appropate tags, returning the target name
+    """
+
+    def wrapper(name, tags = [], **kwargs):
+        inner_rule(
+            name = name,
+            tags = tags + _ONLY_FOR_ANALYSIS_TAGS,
+            **kwargs
+        )
+        return name
+
+    return wrapper
+
+_assert_failure_test = analysistest.make(
+    impl = lambda ctx: _assert_failure_test_impl(ctx),
+    expect_failure = True,
+    attrs = dict(
+        msg_contains = attr.string(mandatory = True),
+    ),
+)
+
+def _assert_failure_test_impl(ctx):
+    kt_analysis.check_endswith_test(ctx)
+
+    env = analysistest.begin(ctx)
+    asserts.expect_failure(env, ctx.attr.msg_contains)
+    return analysistest.end(env)
+
+_coverage_instrumentation_test = analysistest.make(
+    impl = lambda ctx: _coverage_instrumentation_test_impl(ctx),
+    attrs = dict(
+        expected_instrumented_file_names = attr.string_list(),
+    ),
+    config_settings = {
+        "//command_line_option:collect_code_coverage": "1",
+        "//command_line_option:instrument_test_targets": "1",
+        "//command_line_option:instrumentation_filter": "+",
+    },
+)
+
+def _coverage_instrumentation_test_impl(ctx):
+    env = analysistest.begin(ctx)
+    target_under_test = analysistest.target_under_test(env)
+    instrumented_files_info = target_under_test[InstrumentedFilesInfo]
+    instrumented_files = instrumented_files_info.instrumented_files.to_list()
+    asserts.equals(
+        env,
+        ctx.attr.expected_instrumented_file_names,
+        [file.basename for file in instrumented_files],
+    )
+    return analysistest.end(env)
+
+def _create_file(name, content = ""):
+    """Declare a generated file with optional content.
+
+    Args:
+        name: [string] The relative file path
+        content: [string]
+
+    Returns:
+        [File] The label of the file
+    """
+
+    if content.startswith("\n"):
+        content = content[1:-1]
+
+    native.genrule(
+        name = "gen_" + name,
+        outs = [name],
+        cmd = """
+cat > $@ <<EOF
+%s
+EOF
+""" % content,
+    )
+
+    return name
+
+_create_dir = rule(
+    implementation = lambda ctx: _create_dir_impl(ctx),
+    attrs = dict(
+        subdir = attr.string(),
+        srcs = attr.label_list(allow_files = True),
+    ),
+)
+
+def _create_dir_impl(ctx):
+    dir = ctx.actions.declare_directory(ctx.attr.name)
+
+    command = "mkdir -p {0} " + ("&& cp {1} {0}" if ctx.files.srcs else "# {1}")
+    ctx.actions.run_shell(
+        command = command.format(
+            dir.path + "/" + ctx.attr.subdir,
+            " ".join([s.path for s in ctx.files.srcs]),
+        ),
+        inputs = ctx.files.srcs,
+        outputs = [dir],
+    )
+
+    return [DefaultInfo(files = depset([dir]))]
+
+kt_testing_rules = struct(
+    # go/keep-sorted start
+    ONLY_FOR_ANALYSIS_TAGS = _ONLY_FOR_ANALYSIS_TAGS,
+    assert_failure_test = _assert_failure_test,
+    coverage_instrumentation_test = _coverage_instrumentation_test,
+    create_dir = _wrap_for_analysis(_create_dir),
+    create_file = _create_file,
+    wrap_for_analysis = _wrap_for_analysis,
+    # go/keep-sorted end
+)
diff --git a/kotlin/common/testing/unittest_suites.bzl b/kotlin/common/testing/unittest_suites.bzl
new file mode 100644
index 0000000..b1895bf
--- /dev/null
+++ b/kotlin/common/testing/unittest_suites.bzl
@@ -0,0 +1,205 @@
+# Copyright 2022 Google LLC. 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.
+
+"""A framework for writing tests of Starlark code with minimal overhead.
+
+Test cases are written as Starlark functions that will eventually be executed as
+individual test targets. Two types of tests are supported: those including their
+own assertions, and those expected to call 'fail()'.
+
+Basic usage looks like:
+```
+# unittests.bzl
+load("//kotlin/common/testing:unittest_suites.bzl", "kt_unittest_suites")
+load("@bazel_skylib//lib:unittest.bzl", "asserts")
+
+unittests = kt_unittest_suite.create() # Create a new suite in this file.
+
+def _some_test_case(ctx, env):
+    # Test logic here
+    asserts.true(env, 1 == 1)
+    return [] # Return any declared files
+    
+unittests.expect_finish(_some_test_case) # Include the test case in the suite
+
+def _some_fail_case(ctx):
+    # No assertions are allowed in fail cases
+    _some_logic_that_should_call_fail(ctx)
+    
+unittests.expect_fail(_some_fail_case, "fail message substring") # Expect this case to call fail
+
+# Generate a pair of rules that will be used for test targets
+_test, _fail = unittests.close()  # @unused
+```
+
+```
+// BUILD
+load(":unittests.bzl", "unittests")
+
+# Render each test case as a target in this package
+unittests.render(
+    name = "unittests"
+)
+```
+"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("@bazel_skylib//lib:unittest.bzl", "unittest")
+load(":testing_rules.bzl", "kt_testing_rules")
+
+visibility(RULES_KOTLIN)
+
+def _create():
+    """Create a new test suite.
+
+    Returns:
+        [kt_unittest_suite] An object representing the suite under construction
+    """
+
+    test_cases = dict()
+    rule_holder = []  # Use a list rather than separate vars becase captured vars are final
+
+    def expect_fail(test_case, msg_contains):
+        """Add a test case to the suite which is expected to call fail.
+
+        Args:
+            test_case: [function(ctx)]
+            msg_contains: [string] A substring expected in the failure message
+        """
+
+        if rule_holder:
+            fail("Test suite is closed")
+
+        test_case_name = _fn_name(test_case)
+        if not test_case_name.startswith("_"):
+            fail("Test cases must be private '%s'" % test_case_name)
+        if test_case_name in test_cases:
+            fail("Existing test case named '%s'" % test_case_name)
+
+        test_cases[test_case_name] = struct(
+            impl = test_case,
+            msg_contains = msg_contains,
+        )
+
+    def expect_finish(test_case):
+        """Add a test case to the suite.
+
+        Args:
+            test_case: [function(ctx,unittest.env):None|list[File]]
+        """
+
+        expect_fail(test_case, None)
+
+    def close():
+        """Close the suite from expect_finishing new tests.
+
+        The return value must be assigned to '_test, _fail' with an '# @unused' suppression.
+
+        Returns:
+            [(rule, rule)]
+        """
+
+        if rule_holder:
+            fail("Test suite is closed")
+
+        def test_impl(ctx):
+            env = unittest.begin(ctx)
+
+            output_files = test_cases[ctx.attr.case_name].impl(ctx, env) or []
+            if output_files:
+                ctx.actions.run_shell(
+                    outputs = output_files,
+                    command = "exit 1",
+                )
+
+            return unittest.end(env) + [OutputGroupInfo(_file_sink = depset(output_files))]
+
+        test_rule = unittest.make(
+            impl = test_impl,
+            attrs = dict(case_name = attr.string()),
+        )
+        rule_holder.append(test_rule)
+
+        def fail_impl(ctx):
+            test_cases[ctx.attr.case_name].impl(ctx)
+            return []
+
+        fail_rule = rule(
+            implementation = fail_impl,
+            attrs = dict(case_name = attr.string()),
+        )
+        rule_holder.append(fail_rule)
+
+        # Rules must be assigned to top-level Starlark vars before being called
+        return test_rule, fail_rule
+
+    def render(name, tags = [], **kwargs):
+        """Render the test suite into targets.
+
+        Args:
+            name: [string]
+            tags: [list[string]]
+            **kwargs: Generic rule kwargs
+        """
+
+        if not rule_holder:
+            fail("Test suite is not closed")
+        test_rule = rule_holder[0]
+        fail_rule = rule_holder[1]
+
+        test_targets = []
+        for test_case_name, test_case_data in test_cases.items():
+            target_name = test_case_name.removeprefix("_") + "_test"
+            test_targets.append(target_name)
+
+            if test_case_data.msg_contains == None:
+                test_rule(
+                    name = target_name,
+                    tags = tags,
+                    case_name = test_case_name,
+                    **kwargs
+                )
+            else:
+                fail_rule(
+                    name = test_case_name,
+                    tags = tags + kt_testing_rules.ONLY_FOR_ANALYSIS_TAGS,
+                    case_name = test_case_name,
+                    **kwargs
+                )
+                kt_testing_rules.assert_failure_test(
+                    name = target_name,
+                    target_under_test = test_case_name,
+                    msg_contains = test_case_data.msg_contains,
+                )
+
+        native.test_suite(
+            name = name,
+            tests = test_targets,
+            **kwargs
+        )
+
+    return struct(
+        expect_finish = expect_finish,
+        expect_fail = expect_fail,
+        close = close,
+        render = render,
+    )
+
+def _fn_name(rule_or_fn):
+    parts = str(rule_or_fn).removeprefix("<").removesuffix(">").split(" ")
+    return parts[0] if (len(parts) == 1) else parts[1]
+
+kt_unittest_suites = struct(
+    create = _create,
+)
diff --git a/kotlin/compiler_plugin.bzl b/kotlin/compiler_plugin.bzl
index 5df6e68..e1854e4 100644
--- a/kotlin/compiler_plugin.bzl
+++ b/kotlin/compiler_plugin.bzl
@@ -16,6 +16,8 @@
 
 load("//:visibility.bzl", "RULES_KOTLIN")
 
+visibility(RULES_KOTLIN)
+
 KtCompilerPluginInfo, _make_kt_compiler_plugin_info = provider(
     doc = "Info for running a plugin that directly registers itself to kotlinc extension points",
     fields = dict(
diff --git a/kotlin/jvm/testing/BUILD b/kotlin/jvm/testing/BUILD
new file mode 100644
index 0000000..59bd24c
--- /dev/null
+++ b/kotlin/jvm/testing/BUILD
@@ -0,0 +1,38 @@
+# Copyright 2022 Google LLC. 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.
+
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+    default_visibility = ["//:internal"],
+)
+
+licenses(["notice"])
+
+bzl_library(
+    name = "testing_bzl",
+    srcs = glob(["*.bzl"]),
+    visibility = [
+        "//:internal",
+    ],
+    deps = [
+        "//:visibility_bzl",
+        "//kotlin:rules_bzl",
+        "//kotlin/common/testing:testing_bzl",
+        "@bazel_skylib//lib:sets",
+        "@bazel_skylib//lib:unittest",
+    ],
+)
diff --git a/kotlin/jvm/testing/for_analysis.bzl b/kotlin/jvm/testing/for_analysis.bzl
new file mode 100644
index 0000000..1ba4fcd
--- /dev/null
+++ b/kotlin/jvm/testing/for_analysis.bzl
@@ -0,0 +1,35 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_for_analysis"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
+load("//kotlin:jvm_import.bzl", "kt_jvm_import")
+load("//kotlin:jvm_library.bzl", "kt_jvm_library")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+
+visibility(RULES_KOTLIN)
+
+kt_for_analysis = struct(
+    # go/keep-sorted start
+    java_binary = kt_testing_rules.wrap_for_analysis(native.java_binary),
+    java_import = kt_testing_rules.wrap_for_analysis(native.java_import),
+    java_library = kt_testing_rules.wrap_for_analysis(native.java_library),
+    java_plugin = kt_testing_rules.wrap_for_analysis(native.java_plugin),
+    kt_compiler_plugin = kt_testing_rules.wrap_for_analysis(kt_compiler_plugin),
+    kt_jvm_import = kt_testing_rules.wrap_for_analysis(kt_jvm_import),
+    kt_jvm_library = kt_testing_rules.wrap_for_analysis(kt_jvm_library),
+    # go/keep-sorted end
+)
diff --git a/kotlin/jvm/testing/jvm_compile_stubs.bzl b/kotlin/jvm/testing/jvm_compile_stubs.bzl
new file mode 100644
index 0000000..0d5a573
--- /dev/null
+++ b/kotlin/jvm/testing/jvm_compile_stubs.bzl
@@ -0,0 +1,128 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_jvm_compile_stubs"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("//kotlin:common.bzl", "common")
+load("//kotlin:jvm_compile.bzl", "kt_jvm_compile")
+load("//kotlin:traverse_exports.bzl", "kt_traverse_exports")
+load("//kotlin/common/testing:analysis.bzl", "kt_analysis")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
+load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+
+visibility(RULES_KOTLIN)
+
+_kt_jvm_compile_stub_rule = rule(
+    implementation = lambda ctx: _kt_jvm_compile_stub_rule_impl(ctx),
+    attrs = dict(
+        srcs = attr.label_list(
+            allow_files = True,
+        ),
+        common_srcs = attr.label_list(
+            allow_files = True,
+        ),
+        deps = attr.label_list(
+            aspects = [kt_traverse_exports.aspect],
+            providers = [JavaInfo],
+        ),
+        exports = attr.label_list(
+            aspects = [kt_traverse_exports.aspect],
+            providers = [JavaInfo],
+        ),
+        rule_family = attr.int(
+            default = common.RULE_FAMILY.UNKNOWN,
+        ),
+        r_java = attr.label(
+            providers = [JavaInfo],
+        ),
+        _java_toolchain = attr.label(
+            default = Label(
+                "@bazel_tools//tools/jdk:current_java_toolchain",
+            ),
+        ),
+    ),
+    fragments = ["java"],
+    outputs = dict(
+        jar = "lib%{name}.jar",
+    ),
+    toolchains = [kt_jvm_toolchains.type, "@bazel_tools//tools/jdk:toolchain_type"],
+)
+
+def _kt_jvm_compile_stub_rule_impl(ctx):
+    # As additional capabilites need to be tested, this rule should support
+    # additional fields/attributes.
+    result = kt_jvm_compile(
+        ctx,
+        output = ctx.outputs.jar,
+        srcs = ctx.files.srcs,
+        common_srcs = ctx.files.common_srcs,
+        deps = ctx.attr.deps,
+        plugins = [],
+        exported_plugins = [],
+        runtime_deps = [],
+        exports = ctx.attr.exports,
+        javacopts = [],
+        kotlincopts = [],
+        neverlink = False,
+        testonly = False,
+                android_lint_plugins = [],
+        manifest = None,
+        merged_manifest = None,
+        resource_files = [],
+        rule_family = ctx.attr.rule_family,
+        kt_toolchain = kt_jvm_toolchains.get(ctx),
+        java_toolchain = java_toolchains.get(ctx),
+        disable_lint_checks = [],
+        r_java = ctx.attr.r_java[JavaInfo] if ctx.attr.r_java else None,
+    )
+    return [result.java_info]
+
+_kt_jvm_compile_stub_analysis_test = analysistest.make(
+    impl = lambda ctx: _kt_jvm_compile_stub_analysis_test_impl(ctx),
+    attrs = dict(
+        expected_kotlinc_classpath_names = attr.string_list(default = kt_analysis.DEFAULT_LIST),
+    ),
+)
+
+def _kt_jvm_compile_stub_analysis_test_impl(ctx):
+    kt_analysis.check_endswith_test(ctx)
+
+    env = analysistest.begin(ctx)
+
+    actions = analysistest.target_actions(env)
+    kotlinc_action = kt_analysis.get_action(actions, "Kt2JavaCompile")
+
+    asserts.true(
+        env,
+        JavaInfo in ctx.attr.target_under_test,
+        "Did not produce JavaInfo provider.",
+    )
+
+    if ctx.attr.expected_kotlinc_classpath_names != kt_analysis.DEFAULT_LIST:
+        kotlinc_classpath = kt_analysis.get_arg(kotlinc_action, "-cp", style = "next").split(":")
+        asserts.equals(
+            env,
+            ctx.attr.expected_kotlinc_classpath_names,
+            [file.rsplit("/", 1)[1] for file in kotlinc_classpath],
+        )
+
+    return analysistest.end(env)
+
+kt_jvm_compile_stubs = struct(
+    rule = kt_testing_rules.wrap_for_analysis(_kt_jvm_compile_stub_rule),
+    analysis_test = _kt_jvm_compile_stub_analysis_test,
+)
diff --git a/kotlin/jvm/testing/jvm_import_analysis_test.bzl b/kotlin/jvm/testing/jvm_import_analysis_test.bzl
new file mode 100644
index 0000000..55df268
--- /dev/null
+++ b/kotlin/jvm/testing/jvm_import_analysis_test.bzl
@@ -0,0 +1,39 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_jvm_import_analysis_test"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+
+visibility(RULES_KOTLIN)
+
+kt_jvm_import_analysis_test = analysistest.make(
+    impl = lambda ctx: _kt_jvm_import_analysis_test_impl(ctx),
+    attrs = dict(),
+)
+
+def _kt_jvm_import_analysis_test_impl(ctx):
+    env = analysistest.begin(ctx)
+    asserts.true(
+        env,
+        JavaInfo in ctx.attr.target_under_test,
+        "kt_jvm_import did not produce JavaInfo provider.",
+    )
+    asserts.true(
+        env,
+        ProguardSpecProvider in ctx.attr.target_under_test,
+        "kt_jvm_import did not produce ProguardSpecProvider provider.",
+    )
+    return analysistest.end(env)
diff --git a/kotlin/jvm/testing/jvm_library_analysis_test.bzl b/kotlin/jvm/testing/jvm_library_analysis_test.bzl
new file mode 100644
index 0000000..6e05b28
--- /dev/null
+++ b/kotlin/jvm/testing/jvm_library_analysis_test.bzl
@@ -0,0 +1,155 @@
+# Copyright 2022 Google LLC. 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.
+
+"""kt_jvm_library_analysis_test"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("//kotlin/common/testing:analysis.bzl", "kt_analysis")
+load("//kotlin/common/testing:asserts.bzl", "kt_asserts")
+load("@bazel_skylib//lib:sets.bzl", "sets")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+
+visibility(RULES_KOTLIN)
+
+kt_jvm_library_analysis_test = analysistest.make(
+    impl = lambda ctx: _kt_jvm_library_analysis_test_impl(ctx),
+    attrs = dict(
+        expected_al_ruleset_names = attr.string_list(
+            doc = "Android Lint rule JARs reported as run on the given target",
+            default = kt_analysis.DEFAULT_LIST,
+        ),
+        expected_compile_jar_names = attr.string_list(
+            doc = "Names of all JavaInfo::compile_jars for the given target",
+            default = kt_analysis.DEFAULT_LIST,
+        ),
+        expected_exported_processor_jar_names = attr.string_list(
+            doc = "Names of all JavaInfo::plugins JARs returned by the given target",
+            default = kt_analysis.DEFAULT_LIST,
+        ),
+        expected_exported_processor_classes = attr.string_list(
+            doc = "Annotation processors reported as to be run on depending targets",
+        ),
+        expected_processor_classes = attr.string_list(
+            doc = "Annotation processors reported as run on the given target",
+        ),
+        expected_kotlinc_plugin_jar_names = attr.string_list(
+            doc = "Names of all -Xplugin= JARs",
+            default = kt_analysis.DEFAULT_LIST,
+        ),
+        expected_friend_jar_names = attr.string_list(
+            doc = "Names of all -Xfriend-paths= JARs",
+            default = kt_analysis.DEFAULT_LIST,
+        ),
+        expected_runfile_names = attr.string_list(
+            doc = "Names of all runfiles",
+            default = kt_analysis.DEFAULT_LIST,
+        ),
+        expect_jdeps = attr.bool(default = True),
+        expect_processor_classpath = attr.bool(),
+        expect_neverlink = attr.bool(),
+        required_mnemonic_counts = attr.string_dict(
+            doc = "Expected mnemonics to expected action count; unlisted mnemonics are ignored",
+        ),
+    ),
+)
+
+def _kt_jvm_library_analysis_test_impl(ctx):
+    kt_analysis.check_endswith_test(ctx)
+
+    env = analysistest.begin(ctx)
+    actual = ctx.attr.target_under_test
+
+    actions = analysistest.target_actions(env)
+    kt_al_action = kt_analysis.get_action(actions, "KtAndroidLint")
+
+    asserts.true(
+        env,
+        JavaInfo in actual,
+        "kt_jvm_library did not produce JavaInfo provider.",
+    )
+    asserts.true(
+        env,
+        ProguardSpecProvider in actual,
+        "Expected a ProguardSpecProvider provider.",
+    )
+
+    if ctx.attr.expected_runfile_names != kt_analysis.DEFAULT_LIST:
+        asserts.set_equals(
+            env,
+            sets.make(ctx.attr.expected_runfile_names),
+            sets.make([
+                f.basename
+                for f in actual[DefaultInfo].data_runfiles.files.to_list()
+            ]),
+        )
+
+    if ctx.attr.expected_compile_jar_names != kt_analysis.DEFAULT_LIST:
+        asserts.set_equals(
+            env,
+            sets.make(ctx.attr.expected_compile_jar_names),
+            sets.make([f.basename for f in actual[JavaInfo].compile_jars.to_list()]),
+            "kt_jvm_library JavaInfo::compile_jars",
+        )
+
+    if ctx.attr.expected_exported_processor_jar_names != kt_analysis.DEFAULT_LIST:
+        asserts.set_equals(
+            env,
+            sets.make(ctx.attr.expected_exported_processor_jar_names),
+            sets.make([f.basename for f in actual[JavaInfo].plugins.processor_jars.to_list()]),
+        )
+
+    asserts.set_equals(
+        env,
+        sets.make(ctx.attr.expected_exported_processor_classes),
+        sets.make(actual[JavaInfo].plugins.processor_classes.to_list()),
+    )
+
+    kt_2_java_compile = kt_analysis.get_action(actions, "Kt2JavaCompile")
+
+    if kt_2_java_compile:
+        asserts.true(
+            env,
+            kt_2_java_compile.outputs.to_list()[0].basename.endswith(".jar"),
+            "Expected first output to be a JAR (this affects the param file name).",
+        )
+
+    if ctx.attr.expected_friend_jar_names != kt_analysis.DEFAULT_LIST:
+        friend_paths_arg = kt_analysis.get_arg(kt_2_java_compile, "-Xfriend-paths=")
+        kt_asserts.list_matches(
+            env,
+            expected = ["/" + x for x in ctx.attr.expected_friend_jar_names],
+            actual = friend_paths_arg.split(",") if friend_paths_arg else [],
+            matcher = lambda expected, actual: actual.endswith(expected),
+            items_name = "friend JARs",
+        )
+
+    if ctx.attr.expected_kotlinc_plugin_jar_names != kt_analysis.DEFAULT_LIST:
+        kt_asserts.list_matches(
+            env,
+            expected = ["/" + x for x in ctx.attr.expected_kotlinc_plugin_jar_names],
+            actual = kt_analysis.get_all_args(kt_2_java_compile, "-Xplugin="),
+            matcher = lambda expected, actual: actual.endswith(expected),
+            items_name = "kotlinc plugin JARs",
+        )
+
+    asserts.equals(
+        env,
+        ctx.attr.expect_neverlink,
+        len(actual[JavaInfo].transitive_runtime_jars.to_list()) == 0,
+        "Mismatch: Expected transitive_runtime_jars iff (neverlink == False)",
+    )
+
+    kt_asserts.required_mnemonic_counts(env, ctx.attr.required_mnemonic_counts, actions)
+
+    return analysistest.end(env)
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/BUILD b/kotlin/jvm/traverse_exports/BUILD
similarity index 100%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/BUILD
rename to kotlin/jvm/traverse_exports/BUILD
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/compiler_plugin.bzl b/kotlin/jvm/traverse_exports/compiler_plugin.bzl
similarity index 97%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/compiler_plugin.bzl
rename to kotlin/jvm/traverse_exports/compiler_plugin.bzl
index a5c65c4..4a52cb5 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/compiler_plugin.bzl
+++ b/kotlin/jvm/traverse_exports/compiler_plugin.bzl
@@ -17,6 +17,8 @@
 load("//:visibility.bzl", "RULES_KOTLIN")
 load("//kotlin:compiler_plugin.bzl", "KtCompilerPluginInfo")
 
+visibility(RULES_KOTLIN)
+
 def _get_exported_plugins(_target, ctx_rule):
     return [
         t[KtCompilerPluginInfo]
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/direct_jdeps.bzl b/kotlin/jvm/traverse_exports/direct_jdeps.bzl
similarity index 97%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/direct_jdeps.bzl
rename to kotlin/jvm/traverse_exports/direct_jdeps.bzl
index 8bbb75f..75e2a15 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/direct_jdeps.bzl
+++ b/kotlin/jvm/traverse_exports/direct_jdeps.bzl
@@ -16,6 +16,8 @@
 
 load("//:visibility.bzl", "RULES_KOTLIN")
 
+visibility(RULES_KOTLIN)
+
 def _get_jdeps(target, _ctx_rule):
     return [
         out.compile_jdeps
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/forbidden_deps.bzl b/kotlin/jvm/traverse_exports/forbidden_deps.bzl
similarity index 82%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/forbidden_deps.bzl
rename to kotlin/jvm/traverse_exports/forbidden_deps.bzl
index fa1db86..570b260 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/forbidden_deps.bzl
+++ b/kotlin/jvm/traverse_exports/forbidden_deps.bzl
@@ -20,21 +20,19 @@
   - targets exporting other forbidden targets
 """
 
-load("@bazel_skylib//lib:sets.bzl", "sets")
-load("//bazel:stubs.bzl", "EXEMPT_DEPS", "FORBIDDEN_DEP_PACKAGES")
 load("//:visibility.bzl", "RULES_KOTLIN")
+load("//bazel:stubs.bzl", "is_exempt_dep", "is_forbidden_dep")
+
+visibility(RULES_KOTLIN)
 
 def _error(target, msg):
     return (str(target.label), msg)
 
-def _is_exempt(target):
-    return sets.contains(EXEMPT_DEPS, str(target.label))
-
 def _check_forbidden(target, ctx_rule):
-    if _is_exempt(target):
+    if is_exempt_dep(target):
         return []
 
-    if sets.contains(FORBIDDEN_DEP_PACKAGES, target.label.package):
+    if is_forbidden_dep(target):
         return [_error(target, "Forbidden package")]
 
     # Identify nano protos using tag (b/122083175)
@@ -45,7 +43,7 @@
     return []
 
 def _if_not_checked(target):
-    return [] if _is_exempt(target) else [_error(target, "Not checked")]
+    return [] if is_exempt_dep(target) else [_error(target, "Not checked")]
 
 def _validate_deps(error_set):
     if not error_set:
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/friend_jars.bzl b/kotlin/jvm/traverse_exports/friend_jars.bzl
similarity index 96%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/friend_jars.bzl
rename to kotlin/jvm/traverse_exports/friend_jars.bzl
index 3f89905..4d34abd 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/friend_jars.bzl
+++ b/kotlin/jvm/traverse_exports/friend_jars.bzl
@@ -14,10 +14,10 @@
 
 """kt_friend_jars_visitor"""
 
-# go/keep-sorted start
-load("//kotlin/common:is_eligible_friend.bzl", "is_eligible_friend")
 load("//:visibility.bzl", "RULES_KOTLIN")
-# go/keep-sorted end
+load("//kotlin/common:is_eligible_friend.bzl", "is_eligible_friend")
+
+visibility(RULES_KOTLIN)
 
 def _get_output_jars(target, _ctx_rule):
     # We can't simply use `JavaInfo.compile_jars` because we only want the JARs directly created by
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/friend_labels.bzl b/kotlin/jvm/traverse_exports/friend_labels.bzl
similarity index 95%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/friend_labels.bzl
rename to kotlin/jvm/traverse_exports/friend_labels.bzl
index ef0aacd..c91340c 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/friend_labels.bzl
+++ b/kotlin/jvm/traverse_exports/friend_labels.bzl
@@ -14,10 +14,10 @@
 
 """kt_friend_labels_visitor"""
 
-# go/keep-sorted start
-load("//kotlin/common:is_eligible_friend.bzl", "is_eligible_friend")
 load("//:visibility.bzl", "RULES_KOTLIN")
-# go/keep-sorted end
+load("//kotlin/common:is_eligible_friend.bzl", "is_eligible_friend")
+
+visibility(RULES_KOTLIN)
 
 def _get_output_labels(target, _):
     return [target.label]
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/java_plugin.bzl b/kotlin/jvm/traverse_exports/java_plugin.bzl
similarity index 97%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/java_plugin.bzl
rename to kotlin/jvm/traverse_exports/java_plugin.bzl
index b993b75..3ee38ef 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/java_plugin.bzl
+++ b/kotlin/jvm/traverse_exports/java_plugin.bzl
@@ -21,6 +21,8 @@
 
 load("//:visibility.bzl", "RULES_KOTLIN")
 
+visibility(RULES_KOTLIN)
+
 def _get_java_plugins(_target, ctx_rule):
     return [
         t[JavaPluginInfo].plugins
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/traverse_exports.bzl b/kotlin/jvm/traverse_exports/traverse_exports.bzl
similarity index 98%
rename from kotlin/jvm/internal_do_not_use/traverse_exports/traverse_exports.bzl
rename to kotlin/jvm/traverse_exports/traverse_exports.bzl
index edf2a10..c32f3a4 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/traverse_exports.bzl
+++ b/kotlin/jvm/traverse_exports/traverse_exports.bzl
@@ -14,7 +14,6 @@
 
 """Combined aspect for all rules_kotlin behaviours that need to traverse exports."""
 
-# go/keep-sorted start
 load("//:visibility.bzl", "RULES_KOTLIN")
 load(":compiler_plugin.bzl", "kt_compiler_plugin_visitor")
 load(":direct_jdeps.bzl", "kt_direct_jdeps_visitor")
@@ -22,7 +21,8 @@
 load(":friend_jars.bzl", "kt_friend_jars_visitor")
 load(":friend_labels.bzl", "kt_friend_labels_visitor")
 load(":java_plugin.bzl", "java_plugin_visitor")
-# go/keep-sorted end
+
+visibility(RULES_KOTLIN)
 
 # java_xxx_proto_library don't populate java_outputs but we can get them through
 # required_aspect_providers from their proto_library deps.
diff --git a/kotlin/jvm/internal_do_not_use/util/BUILD b/kotlin/jvm/util/BUILD
similarity index 100%
rename from kotlin/jvm/internal_do_not_use/util/BUILD
rename to kotlin/jvm/util/BUILD
diff --git a/kotlin/jvm/internal_do_not_use/util/file_factory.bzl b/kotlin/jvm/util/file_factory.bzl
similarity index 96%
rename from kotlin/jvm/internal_do_not_use/util/file_factory.bzl
rename to kotlin/jvm/util/file_factory.bzl
index 2e076c3..49791f7 100644
--- a/kotlin/jvm/internal_do_not_use/util/file_factory.bzl
+++ b/kotlin/jvm/util/file_factory.bzl
@@ -16,6 +16,8 @@
 
 load("//:visibility.bzl", "RULES_KOTLIN")
 
+visibility(RULES_KOTLIN)
+
 def FileFactory(ctx, base):
     """Creates files with names derived from some base file or prefix
 
@@ -31,7 +33,7 @@
         FileFactory
     """
 
-    if type(base) == "File":
+    if type(base) != "string":
         base = _scrub_base_file(ctx, base)
 
     def declare_directory(suffix):
diff --git a/kotlin/jvm/internal_do_not_use/util/run_deploy_jar.bzl b/kotlin/jvm/util/run_deploy_jar.bzl
similarity index 98%
rename from kotlin/jvm/internal_do_not_use/util/run_deploy_jar.bzl
rename to kotlin/jvm/util/run_deploy_jar.bzl
index 14c784b..d4d087a 100644
--- a/kotlin/jvm/internal_do_not_use/util/run_deploy_jar.bzl
+++ b/kotlin/jvm/util/run_deploy_jar.bzl
@@ -19,6 +19,8 @@
 load("//bazel:stubs.bzl", "BASE_JVMOPTS")
 # go/keep-sorted end
 
+visibility(RULES_KOTLIN)
+
 def kt_run_deploy_jar(
         ctx,
         java_runtime,
diff --git a/kotlin/jvm/internal_do_not_use/util/srcjars.bzl b/kotlin/jvm/util/srcjars.bzl
similarity index 99%
rename from kotlin/jvm/internal_do_not_use/util/srcjars.bzl
rename to kotlin/jvm/util/srcjars.bzl
index becf573..01618d9 100644
--- a/kotlin/jvm/internal_do_not_use/util/srcjars.bzl
+++ b/kotlin/jvm/util/srcjars.bzl
@@ -19,6 +19,8 @@
 load(":run_deploy_jar.bzl", "kt_run_deploy_jar")
 # go/keep-sorted end
 
+visibility(RULES_KOTLIN)
+
 def _zip(
         ctx,
         kt_jvm_toolchain,
diff --git a/kotlin/jvm_compile.bzl b/kotlin/jvm_compile.bzl
index 58a2818..be5fda0 100644
--- a/kotlin/jvm_compile.bzl
+++ b/kotlin/jvm_compile.bzl
@@ -20,6 +20,8 @@
 load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
 load(":traverse_exports.bzl", "kt_traverse_exports")
 
+visibility(RULES_DEFS_THAT_COMPILE_KOTLIN)
+
 _RULE_FAMILY = common.RULE_FAMILY
 
 def kt_jvm_compile(
@@ -39,7 +41,6 @@
         resource_files,
         exported_plugins,
         java_android_lint_config = None,
-        force_android_lint = False,  # TODO Remove this param
         manifest = None,
         merged_manifest = None,
         classpath_resources = [],
@@ -75,7 +76,6 @@
       resource_files: List of Files. The list of Android Resource files.
       exported_plugins: List of exported javac/kotlinc plugins
       java_android_lint_config: Android Lint XML config file to use if there are no Kotlin srcs
-      force_android_lint: Force AndroidLint action
       manifest: A File. The raw Android manifest. Optional.
       merged_manifest: A File. The merged Android manifest. Optional.
       classpath_resources: List of Files. The list of classpath resources (kt_jvm_library only).
@@ -116,7 +116,7 @@
     if classpath_resources and rule_family != _RULE_FAMILY.JVM_LIBRARY:
         fail("resources attribute only allowed for jvm libraries")
 
-    if type(java_toolchain) != "JavaToolchainInfo":
+    if type(java_toolchain) == "Target":
         # Allow passing either a target or a provider until all callers are updated
         java_toolchain = java_toolchain[java_common.JavaToolchainInfo]
 
@@ -187,7 +187,6 @@
             ),
         ),
         java_android_lint_config = java_android_lint_config,
-        force_android_lint = force_android_lint,
         resource_files = resource_files,
         runtime_deps = [d[JavaInfo] for d in runtime_deps if JavaInfo in d],
         srcs = srcs,
diff --git a/kotlin/jvm_import.bzl b/kotlin/jvm_import.bzl
index 72b5f6e..cfdb474 100644
--- a/kotlin/jvm_import.bzl
+++ b/kotlin/jvm_import.bzl
@@ -14,13 +14,15 @@
 
 """Kotlin kt_jvm_import rule."""
 
-load(":common.bzl", "common")
-load(":traverse_exports.bzl", "kt_traverse_exports")
-load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
-load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
-load("@bazel_skylib//lib:dicts.bzl", "dicts")
-load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
 load("//:visibility.bzl", "RULES_KOTLIN")
+load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
+load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
+load("@bazel_skylib//lib:dicts.bzl", "dicts")
+load(":common.bzl", "common")
+load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
+load(":traverse_exports.bzl", "kt_traverse_exports")
+
+visibility(RULES_KOTLIN)
 
 def _kt_jvm_import_impl(ctx):
     kt_jvm_toolchain = kt_jvm_toolchains.get(ctx)
diff --git a/kotlin/jvm_library.bzl b/kotlin/jvm_library.bzl
index ad77dbd..816ea25 100644
--- a/kotlin/jvm_library.bzl
+++ b/kotlin/jvm_library.bzl
@@ -22,6 +22,8 @@
 load("//bazel:stubs.bzl", "registry_checks_for_package")
 load(":jvm_library.internal.bzl", "kt_jvm_library_helper")
 
+visibility(RULES_KOTLIN)
+
 def kt_jvm_library(
         name,
         srcs = None,
diff --git a/kotlin/jvm_test.bzl b/kotlin/jvm_test.bzl
index 2a85a66..8c9ca84 100644
--- a/kotlin/jvm_test.bzl
+++ b/kotlin/jvm_test.bzl
@@ -14,9 +14,11 @@
 
 """Kotlin macro for building and running tests on a JVM."""
 
-load(":jvm_library.bzl", "kt_jvm_library")
 load("//bazel:stubs.bzl", "register_extension_info")
 load("//:visibility.bzl", "RULES_KOTLIN")
+load(":jvm_library.bzl", "kt_jvm_library")
+
+visibility(RULES_KOTLIN)
 
 def _lib_name(name):
     return "%s_DO_NOT_DEPEND_LIB" % name
diff --git a/kotlin/traverse_exports.bzl b/kotlin/traverse_exports.bzl
index 8157ec1..bb8b81d 100644
--- a/kotlin/traverse_exports.bzl
+++ b/kotlin/traverse_exports.bzl
@@ -14,7 +14,9 @@
 
 """Combined aspect for all rules_kotlin behaviours that need to traverse exports."""
 
-load("//kotlin/jvm/internal_do_not_use/traverse_exports:traverse_exports.bzl", _kt_traverse_exports = "kt_traverse_exports")
 load("//:visibility.bzl", "RULES_DEFS_THAT_COMPILE_KOTLIN")
+load("//kotlin/jvm/traverse_exports:traverse_exports.bzl", _kt_traverse_exports = "kt_traverse_exports")
+
+visibility(RULES_DEFS_THAT_COMPILE_KOTLIN)
 
 kt_traverse_exports = _kt_traverse_exports
diff --git a/tests/analysis/BUILD b/tests/analysis/BUILD
deleted file mode 100644
index 0533e13..0000000
--- a/tests/analysis/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-# Analysis Tests
-
-load("//tests/analysis:jvm_compile_test.bzl", jvm_compile_test_suite = "test_suite")
-load("//tests/analysis:jvm_import_test.bzl", jvm_import_test_suite = "test_suite")
-load("//tests/analysis:jvm_library_test.bzl", jvm_library_test_suite = "test_suite")
-load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-
-licenses(["notice"])
-
-jvm_compile_test_suite(name = "jvm_compile_tests")
-
-jvm_library_test_suite(name = "jvm_library_tests")
-
-jvm_import_test_suite(name = "jvm_import_tests")
diff --git a/tests/analysis/assert_failure_test.bzl b/tests/analysis/assert_failure_test.bzl
deleted file mode 100644
index 2a742c3..0000000
--- a/tests/analysis/assert_failure_test.bzl
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""An assertion for analysis failure."""
-
-load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _assert_failure_test_impl(ctx):
-    env = analysistest.begin(ctx)
-    asserts.expect_failure(env, ctx.attr.msg_contains)
-    return analysistest.end(env)
-
-assert_failure_test = analysistest.make(
-    _assert_failure_test_impl,
-    expect_failure = True,
-    attrs = dict(
-        msg_contains = attr.string(mandatory = True),
-    ),
-)
diff --git a/tests/analysis/compiler_plugin/BUILD b/tests/analysis/compiler_plugin/BUILD
deleted file mode 100644
index 0c1f9b6..0000000
--- a/tests/analysis/compiler_plugin/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-licenses(["notice"])
-
-genrule(
-    name = "empty_jar",
-    outs = ["empty.jar"],
-    cmd = """$(location @bazel_tools//tools/zip:zipper) c $@ "assets/_empty=" """,
-    tools = ["@bazel_tools//tools/zip:zipper"],
-    visibility = ["//tests/analysis/compiler_plugin:__subpackages__"],
-)
diff --git a/tests/analysis/compiler_plugin/forbidden_target/BUILD b/tests/analysis/compiler_plugin/forbidden_target/BUILD
deleted file mode 100644
index 9f751fa..0000000
--- a/tests/analysis/compiler_plugin/forbidden_target/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-load("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
-load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
-
-licenses(["notice"])
diff --git a/tests/analysis/compiler_plugin/propagation/BUILD b/tests/analysis/compiler_plugin/propagation/BUILD
deleted file mode 100644
index 0c6fe19..0000000
--- a/tests/analysis/compiler_plugin/propagation/BUILD
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-load("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
-load(":assert_propagation_test.bzl", "assert_propagation_test")
-
-licenses(["notice"])
-
-assert_propagation_test(
-    name = "f",
-    expected_plugin_ids = ["1"],
-    deps = [":e"],
-)
-
-assert_propagation_test(
-    name = "e",
-    expected_plugin_ids = [],
-    exports = [":a"],
-)
-
-assert_propagation_test(
-    name = "d",
-    expected_plugin_ids = [
-        "1",
-        "2",
-    ],
-    deps = [
-        ":a",
-        ":b",
-    ],
-)
-
-assert_propagation_test(
-    name = "c",
-    expected_plugin_ids = ["2"],
-    deps = [":b"],
-)
-
-assert_propagation_test(
-    name = "b",
-    expected_plugin_ids = ["1"],
-    exported_plugins = [":2"],
-    deps = [":a"],
-)
-
-assert_propagation_test(
-    name = "a",
-    expected_plugin_ids = [],
-    exported_plugins = [":1"],
-)
-
-kt_compiler_plugin(
-    name = "1",
-    jar = "//tests/analysis/compiler_plugin:empty_jar",
-    plugin_id = "1",
-)
-
-kt_compiler_plugin(
-    name = "2",
-    jar = "//tests/analysis/compiler_plugin:empty_jar",
-    plugin_id = "2",
-)
-
-kt_compiler_plugin(
-    name = "3",
-    jar = "//tests/analysis/compiler_plugin:empty_jar",
-    plugin_id = "3",
-)
diff --git a/tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl b/tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl
deleted file mode 100644
index 0c1b02a..0000000
--- a/tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Rule for asserting plugin propagation."""
-
-load("@bazel_skylib//lib:sets.bzl", "sets")
-load("@bazel_skylib//rules:build_test.bzl", "build_test")
-load("//kotlin:traverse_exports.bzl", "kt_traverse_exports")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _assert_propagation_impl(ctx):
-    expected_ids = sets.make(ctx.attr.expected_plugin_ids)
-    actual_ids = sets.make([
-        p.plugin_id
-        for p in kt_traverse_exports.expand_compiler_plugins(ctx.attr.deps).to_list()
-    ])
-
-    if not sets.is_equal(expected_ids, actual_ids):
-        fail("Expected IDs %s, actual IDs %s" % (sets.to_list(expected_ids), sets.to_list(actual_ids)))
-
-    return [
-        # Needed for kt_traverse_exports.aspect
-        JavaInfo(
-            compile_jar = ctx.file._empty_jar,
-            output_jar = ctx.file._empty_jar,
-        ),
-    ]
-
-_assert_propagation = rule(
-    implementation = _assert_propagation_impl,
-    attrs = dict(
-        exports = attr.label_list(),
-        exported_plugins = attr.label_list(),
-        expected_plugin_ids = attr.string_list(),
-        deps = attr.label_list(aspects = [kt_traverse_exports.aspect]),
-        _empty_jar = attr.label(
-            allow_single_file = True,
-            default = "//tests/analysis/compiler_plugin:empty_jar",
-        ),
-    ),
-)
-
-def assert_propagation_test(name, **kwargs):
-    _assert_propagation(name = name, **kwargs)
-
-    build_test(name = name + "_build", targets = [name])
diff --git a/tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl b/tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl
deleted file mode 100644
index 194025d..0000000
--- a/tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""A fake impl of kt_compiler_plugin."""
-
-load("//kotlin:compiler_plugin.bzl", "KtCompilerPluginInfo")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _kt_fake_compiler_plugin_impl(ctx):
-    return [
-        KtCompilerPluginInfo(
-            plugin_id = "fake",
-            jar = ctx.file._jar,
-            args = [],
-        ),
-    ]
-
-kt_fake_compiler_plugin = rule(
-    implementation = _kt_fake_compiler_plugin_impl,
-    attrs = dict(
-        _jar = attr.label(
-            allow_single_file = True,
-            default = "//tests/analysis/compiler_plugin:empty_jar",
-        ),
-    ),
-    provides = [KtCompilerPluginInfo],
-)
diff --git a/tests/analysis/compiler_plugin/provider_output/BUILD b/tests/analysis/compiler_plugin/provider_output/BUILD
deleted file mode 100644
index 4769965..0000000
--- a/tests/analysis/compiler_plugin/provider_output/BUILD
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-load("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
-load("//tests/analysis:util.bzl", "create_file")
-load("@bazel_skylib//rules:build_test.bzl", "build_test")
-load(":assert_compiler_plugin_test.bzl", "assert_compiler_plugin_test")
-
-licenses(["notice"])
-
-assert_compiler_plugin_test(
-    name = "example_plugin_test",
-    expected_args = [
-        "plugin:com.google.example:key=value",
-    ],
-    expected_id = "com.google.example",
-    expected_jar = "//tests/analysis/compiler_plugin:empty_jar",
-    target_under_test = ":example_plugin",
-)
-
-build_test(
-    name = "example_plugin_in_java_library_build_test",
-    targets = [
-        ":example_plugin_in_java_library",
-    ],
-)
-
-java_library(
-    name = "example_plugin_in_java_library",
-    srcs = [create_file(
-        name = "Tmp.java",
-        content = """
-          @SuppressWarnings("DefaultPackage")
-          class Tmp { }
-        """,
-    )],
-    plugins = [":example_plugin"],
-)
-
-kt_compiler_plugin(
-    name = "example_plugin",
-    args = {
-        "key": "value",
-    },
-    jar = "//tests/analysis/compiler_plugin:empty_jar",
-    plugin_id = "com.google.example",
-)
diff --git a/tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl b/tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl
deleted file mode 100644
index f4e1849..0000000
--- a/tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""An assertion on kt_compiler_plugin analysis."""
-
-load("//kotlin:compiler_plugin.bzl", "KtCompilerPluginInfo")
-load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _test_impl(ctx):
-    env = analysistest.begin(ctx)
-    info = ctx.attr.target_under_test[KtCompilerPluginInfo]
-
-    asserts.equals(env, info.plugin_id, ctx.attr.expected_id)
-    asserts.equals(env, info.jar, ctx.file.expected_jar)
-    asserts.equals(env, info.args, ctx.attr.expected_args)
-
-    return analysistest.end(env)
-
-assert_compiler_plugin_test = analysistest.make(
-    impl = _test_impl,
-    attrs = dict(
-        expected_id = attr.string(),
-        expected_jar = attr.label(allow_single_file = True, cfg = "exec"),
-        expected_args = attr.string_list(),
-    ),
-)
diff --git a/tests/analysis/for_test.bzl b/tests/analysis/for_test.bzl
deleted file mode 100644
index 2a75726..0000000
--- a/tests/analysis/for_test.bzl
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Rules for test."""
-
-load("//kotlin:jvm_library.bzl", "kt_jvm_library")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _kt_jvm_library_for_test(name, **kwargs):
-    kt_jvm_library(
-        name = name,
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-        **kwargs
-    )
-    return name
-
-def _java_library_for_test(name, **kwargs):
-    native.java_library(
-        name = name,
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-        **kwargs
-    )
-    return name
-
-rules_for_test = struct(
-    kt_jvm_library = _kt_jvm_library_for_test,
-    java_library = _java_library_for_test,
-)
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/BUILD b/tests/analysis/internal_do_not_use/util/file_factory/BUILD
deleted file mode 100644
index d92e379..0000000
--- a/tests/analysis/internal_do_not_use/util/file_factory/BUILD
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-load(":happy_test.bzl", "file_factory_happy_test")
-load(":check_base_file_valid.bzl", "check_base_file_valid")
-load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
-
-licenses(["notice"])
-
-file_factory_happy_test(
-    name = "happy_test",
-)
-
-assert_failure_test(
-    name = "base_without_extension_test",
-    msg_contains = "file must have an extension",
-    target_under_test = check_base_file_valid(
-        name = "base_without_extension",
-        base_file = "BUILD",
-    ),
-)
-
-assert_failure_test(
-    name = "base_from_other_package_test",
-    msg_contains = "file must be from ctx package",
-    target_under_test = check_base_file_valid(
-        name = "base_from_other_package",
-        base_file = "//tests/analysis/internal_do_not_use/util/file_factory/sub",
-    ),
-)
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl b/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl
deleted file mode 100644
index 9ca1f05..0000000
--- a/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Happy tests for FileFactory."""
-
-load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _check_base_file_valid_impl(ctx):
-    FileFactory(ctx, ctx.file.base_file)
-    return []
-
-_check_base_file_valid = rule(
-    implementation = _check_base_file_valid_impl,
-    attrs = dict(
-        base_file = attr.label(allow_single_file = True, mandatory = True),
-    ),
-)
-
-def check_base_file_valid(name, tags = [], **kwargs):
-    _check_base_file_valid(
-        name = name,
-        tags = tags + ONLY_FOR_ANALYSIS_TEST_TAGS,
-        **kwargs
-    )
-    return name
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl b/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl
deleted file mode 100644
index 1a2a655..0000000
--- a/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""file_factory_happy_test"""
-
-load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _test_base_from_file(ctx, pkg_path):
-    base_file = ctx.actions.declare_file("file/base.txt")
-    factory = FileFactory(ctx, base_file)
-
-    _assert_equals(pkg_path + "/file/base", factory.base_as_path)
-
-    return [base_file]
-
-def _test_declare(ctx, pkg_path):
-    factory = FileFactory(ctx, "string/base")
-
-    _assert_equals(pkg_path + "/string/base", factory.base_as_path)
-
-    a_file = factory.declare_file("a.txt")
-    _assert_equals(pkg_path + "/string/basea.txt", a_file.path)
-
-    b_dir = factory.declare_directory("b_dir")
-    _assert_equals(pkg_path + "/string/baseb_dir", b_dir.path)
-
-    return [a_file, b_dir]
-
-def _test_derive(ctx, pkg_path):
-    factory = FileFactory(ctx, "")
-
-    # Once
-    factory_once = factory.derive("once")
-    _assert_equals(pkg_path + "/once", factory_once.base_as_path)
-
-    # Twice
-    factory_twice = factory_once.derive("/twice")
-    _assert_equals(pkg_path + "/once/twice", factory_twice.base_as_path)
-
-def _assert_equals(expected, actual):
-    if expected != actual:
-        fail("Expected '%s' but was '%s'" % (expected, actual))
-
-def _file_factory_happy_test_impl(ctx):
-    pkg_path = ctx.bin_dir.path + "/" + ctx.label.package
-    all_files = []
-
-    all_files.extend(_test_base_from_file(ctx, pkg_path))
-    all_files.extend(_test_declare(ctx, pkg_path))
-    _test_derive(ctx, pkg_path)
-
-    ctx.actions.run_shell(
-        outputs = all_files,
-        command = "exit 1",
-    )
-
-    test_script = ctx.actions.declare_file(ctx.label.name + "_test.sh")
-    ctx.actions.write(test_script, "#!/bin/bash", True)
-    return [
-        DefaultInfo(executable = test_script),
-    ]
-
-file_factory_happy_test = rule(
-    implementation = _file_factory_happy_test_impl,
-    test = True,
-)
diff --git a/tests/analysis/jvm_compile_test.bzl b/tests/analysis/jvm_compile_test.bzl
deleted file mode 100644
index 83e722c..0000000
--- a/tests/analysis/jvm_compile_test.bzl
+++ /dev/null
@@ -1,391 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Kotlin kt_jvm_compile API test."""
-
-load("//kotlin:traverse_exports.bzl", "kt_traverse_exports")
-load("//kotlin:jvm_compile.bzl", "kt_jvm_compile")
-load("//kotlin:common.bzl", "common")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_dir", "create_file")
-load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
-load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
-load("@bazel_skylib//rules:build_test.bzl", "build_test")
-load(":assert_failure_test.bzl", "assert_failure_test")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _impl(ctx):
-    # As additional capabilites need to be tested, this rule should support
-    # additional fields/attributes.
-    result = kt_jvm_compile(
-        ctx,
-        output = ctx.outputs.jar,
-        srcs = ctx.files.srcs,
-        common_srcs = ctx.files.common_srcs,
-        deps = ctx.attr.deps,
-        plugins = [],
-        exported_plugins = [],
-        runtime_deps = [],
-        exports = ctx.attr.exports,
-        javacopts = [],
-        kotlincopts = [],
-        neverlink = False,
-        testonly = False,
-                android_lint_plugins = [],
-        manifest = None,
-        merged_manifest = None,
-        resource_files = [],
-        rule_family = ctx.attr.rule_family,
-        kt_toolchain = kt_jvm_toolchains.get(ctx),
-        java_toolchain = java_toolchains.get(ctx),
-        disable_lint_checks = [],
-        r_java = ctx.attr.r_java[JavaInfo] if ctx.attr.r_java else None,
-    )
-    return [result.java_info]
-
-_kt_jvm_compile = rule(
-    implementation = _impl,
-    attrs = dict(
-        srcs = attr.label_list(
-            allow_files = True,
-        ),
-        common_srcs = attr.label_list(
-            allow_files = True,
-        ),
-        deps = attr.label_list(
-            aspects = [kt_traverse_exports.aspect],
-            providers = [JavaInfo],
-        ),
-        exports = attr.label_list(
-            aspects = [kt_traverse_exports.aspect],
-            providers = [JavaInfo],
-        ),
-        rule_family = attr.int(
-            default = common.RULE_FAMILY.UNKNOWN,
-        ),
-        r_java = attr.label(
-            providers = [JavaInfo],
-        ),
-        _java_toolchain = attr.label(
-            default = Label(
-                "@bazel_tools//tools/jdk:current_java_toolchain",
-            ),
-        ),
-    ),
-    fragments = ["java"],
-    outputs = dict(
-        jar = "lib%{name}.jar",
-    ),
-    toolchains = [kt_jvm_toolchains.type, "@bazel_tools//tools/jdk:toolchain_type"],
-)
-
-def _test_kt_jvm_compile_using_kt_jvm_compile_with_r_java():
-    test_name = "kt_jvm_compile_using_kt_jvm_compile_with_r_java_test"
-
-    native.java_library(
-        name = "foo_resources",
-        srcs = [create_file(
-            name = test_name + "/java/com/foo/R.java",
-            content = """
-package com.foo;
-
-public final class R {
-  public static final class string {
-    public static int a_string=0x00000001;
-    public static int b_string=0x00000002;
-  }
-}
-""",
-        )],
-    )
-
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_with_r_java",
-        srcs = [create_file(
-            name = test_name + "/AString.kt",
-            content = """
-package test
-
-import com.foo.R.string.a_string
-
-fun aString(): String = "a_string=" + a_string
-""",
-        )],
-        r_java = ":foo_resources",
-    )
-
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_using_kt_jvm_compile_with_r_java",
-        srcs = [create_file(
-            name = test_name + "/ABString.kt",
-            content = """
-package test
-
-import com.foo.R.string.b_string
-
-fun bString(): String = "b_string=" + b_string
-
-fun abString(): String = aString() + bString()
-""",
-        )],
-        deps = [":kt_jvm_compile_with_r_java"],
-    )
-
-    # If a failure occurs, it will be at build time.
-    build_test(
-        name = test_name,
-        targets = [":kt_jvm_compile_using_kt_jvm_compile_with_r_java"],
-    )
-    return test_name
-
-def _test_kt_jvm_compile_with_illegal_r_java():
-    test_name = "kt_jvm_compile_with_illegal_r_java_test"
-
-    native.java_library(
-        name = "foo",
-        srcs = [create_file(
-            name = test_name + "/java/com/foo/Foo.java",
-            content = """
-package com.foo;
-
-public class Foo {}
-""",
-        )],
-    )
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_with_illegal_r_java",
-        srcs = [create_file(
-            name = test_name + "/AString.kt",
-            content = """
-package test
-
-import com.foo.Foo
-
-fun bar(): String = "Bar"
-""",
-        )],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-        r_java = ":foo",
-    )
-    assert_failure_test(
-        name = test_name,
-        target_under_test = ":kt_jvm_compile_with_illegal_r_java",
-        msg_contains = "illegal dependency provided for r_java",
-    )
-    return test_name
-
-def _test_kt_jvm_compile_with_r_java_as_first_dep():
-    test_name = "kt_jvm_compile_with_r_java_as_first_dep_test"
-
-    # Note: The R from an android_library must be the first dependency in
-    # the classpath to prevent another libraries R from being used for
-    # compilation. If the ordering is incorrect, compiletime failures will
-    # occur as the depot relies on this ordering.
-
-    native.java_library(
-        name = "foo_with_symbol_resources",
-        srcs = [create_file(
-            name = test_name + "/with_symbol/java/com/foo/R.java",
-            content = """
-package com.foo;
-
-public final class R {
-  public static final class string {
-    public static int a_string=0x00000001;
-  }
-}
-""",
-        )],
-    )
-
-    native.java_library(
-        name = "foo_without_symbol_resources",
-        srcs = [create_file(
-            name = test_name + "/without_symbol/java/com/foo/R.java",
-            content = """
-package com.foo;
-
-public final class R {
-  public static final class string {
-  }
-}
-""",
-        )],
-    )
-
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_with_r_java_as_first_dep",
-        srcs = [create_file(
-            name = test_name + "/AString.kt",
-            content = """
-package test
-
-import com.foo.R.string.a_string
-
-fun aString(): String = "a_string=" + a_string
-""",
-        )],
-        r_java = ":foo_with_symbol_resources",
-        deps = [":foo_without_symbol_resources"],
-    )
-
-    # If a failure occurs, it will be at build time.
-    build_test(
-        name = test_name,
-        targets = [":kt_jvm_compile_with_r_java_as_first_dep"],
-    )
-    return test_name
-
-def _test_kt_jvm_compile_without_srcs_for_android():
-    test_name = "kt_jvm_compile_without_srcs_for_android_test"
-
-    # This is a common case for rules like android_library where Kotlin sources
-    # could be empty, due to the rule being used for resource processing. For
-    # this scenario, historically, rules continue to produce empty Jars.
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_without_srcs_for_android",
-        rule_family = common.RULE_FAMILY.ANDROID_LIBRARY,
-    )
-
-    # If a failure occurs, it will be at build time.
-    build_test(
-        name = test_name,
-        targets = [":kt_jvm_compile_without_srcs_for_android"],
-    )
-    return test_name
-
-def _test_kt_jvm_compile_without_srcs_for_jvm():
-    test_name = "kt_jvm_compile_without_srcs_for_jvm_test"
-
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_without_srcs_for_jvm",
-        srcs = [],
-        common_srcs = [],
-        exports = [],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    )
-    assert_failure_test(
-        name = test_name,
-        target_under_test = ":kt_jvm_compile_without_srcs_for_jvm",
-        msg_contains = "Expected one of (srcs, common_srcs, exports) is not empty",
-    )
-    return test_name
-
-def _test_kt_jvm_compile_without_srcs_and_with_exports():
-    test_name = "kt_jvm_compile_without_srcs_and_with_exports_test"
-
-    _kt_jvm_compile(
-        name = "bar_lib",
-        srcs = [create_file(
-            name = test_name + "/Bar.kt",
-            content = """
-package test
-
-fun bar(): String = "Bar"
-""",
-        )],
-    )
-
-    _kt_jvm_compile(
-        name = "kt_jvm_compile_without_srcs_and_with_exports",
-        exports = [":bar_lib"],
-    )
-
-    _kt_jvm_compile(
-        name = "foo_bar_lib",
-        srcs = [create_file(
-            name = test_name + "/FooBar.kt",
-            content = """
-package test
-
-fun fooBar(): String = "Foo" + bar()
-""",
-        )],
-        deps = [":kt_jvm_compile_without_srcs_and_with_exports"],
-    )
-
-    # If a failure occurs, it will be at build time.
-    build_test(
-        name = test_name,
-        targets = [":foo_bar_lib"],
-    )
-    return test_name
-
-def _test_kt_jvm_compile_unsupported_src_artifacts():
-    test_name = "kt_jvm_compile_unsupported_src_artifacts_test"
-
-    kt_src = create_file(
-        name = test_name + "/src.kt",
-        content = "",
-    )
-    kt_dir = create_dir(
-        name = test_name + "/kotlin",
-        subdir = "",
-        srcs = [create_file(
-            name = test_name + "/dir.kt",
-            content = "",
-        )],
-    )
-    java_src = create_file(
-        name = test_name + "/src.java",
-        content = "",
-    )
-    java_dir = create_dir(
-        name = test_name + "/java",
-        subdir = "",
-        srcs = [create_file(
-            name = test_name + "/dir.java",
-            content = "",
-        )],
-    )
-    java_srcjar = create_file(
-        name = test_name + "/java.srcjar",
-        content = "",
-    )
-    _kt_jvm_compile(
-        name = test_name + "_expected_lib",
-        srcs = [kt_src, kt_dir, java_src, java_dir, java_srcjar],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    )
-
-    unexpected_file = create_file(
-        name = test_name + "/src.unexpected",
-        content = "",
-    )
-    _kt_jvm_compile(
-        name = test_name + "_unexpected_lib",
-        srcs = [unexpected_file],
-        deps = [test_name + "_expected_lib"],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    )
-
-    assert_failure_test(
-        name = test_name,
-        target_under_test = test_name + "_unexpected_lib",
-        msg_contains = "/src.unexpected",
-    )
-    return test_name
-
-def test_suite(name = None):
-    native.test_suite(
-        name = name,
-        tests = [
-            _test_kt_jvm_compile_unsupported_src_artifacts(),
-            _test_kt_jvm_compile_using_kt_jvm_compile_with_r_java(),
-            _test_kt_jvm_compile_with_illegal_r_java(),
-            _test_kt_jvm_compile_with_r_java_as_first_dep(),
-            _test_kt_jvm_compile_without_srcs_for_android(),
-            _test_kt_jvm_compile_without_srcs_for_jvm(),
-            _test_kt_jvm_compile_without_srcs_and_with_exports(),
-        ],
-    )
diff --git a/tests/analysis/jvm_import_test.bzl b/tests/analysis/jvm_import_test.bzl
deleted file mode 100644
index 6e56c02..0000000
--- a/tests/analysis/jvm_import_test.bzl
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Kotlin kt_jvm_import rule tests."""
-
-load("//kotlin:jvm_import.bzl", "kt_jvm_import")
-load("//kotlin:jvm_library.bzl", "kt_jvm_library")
-load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_file")
-load(":assert_failure_test.bzl", "assert_failure_test")
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-def _impl(ctx):
-    env = analysistest.begin(ctx)
-    asserts.true(
-        env,
-        JavaInfo in ctx.attr.target_under_test,
-        "kt_jvm_import did not produce JavaInfo provider.",
-    )
-    asserts.true(
-        env,
-        ProguardSpecProvider in ctx.attr.target_under_test,
-        "kt_jvm_import did not produce ProguardSpecProvider provider.",
-    )
-    return analysistest.end(env)
-
-_test = analysistest.make(_impl)
-
-def _test_kt_jvm_import():
-    test_name = "kt_jvm_import_test"
-    native.java_library(
-        name = "jar1",
-        srcs = [],
-    )
-    kt_jvm_import(
-        name = test_name + "_tut",
-        jars = [
-            "libjar1.jar",
-        ],
-        srcjar = "libjar1-src.jar",
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _test_kt_jvm_import_no_srcjar():
-    test_name = "kt_jvm_import_no_srcjar_test"
-    native.java_library(
-        name = "jar3",
-        srcs = [],
-    )
-    kt_jvm_import(
-        name = test_name + "_tut",
-        jars = [
-            "libjar3.jar",
-        ],
-            )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _test_kt_jvm_import_with_srcjar_ext():
-    test_name = "kt_jvm_import_test_with_srcjar_ext"
-    native.java_library(
-        name = "jar2",
-        srcs = [],
-    )
-    native.genrule(
-        name = "gen_jar2_srcjar",
-        cmd = "touch $@",
-        outs = ["libjar2.srcjar"],
-    )
-    kt_jvm_import(
-        name = test_name + "_tut",
-        jars = [
-            "libjar2.jar",
-        ],
-        srcjar = ":libjar2.srcjar",
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _test_kt_jvm_import_with_runtime_deps():
-    test_name = "kt_jvm_import_with_runtime_deps"
-    native.java_library(
-        name = test_name + "_dep",
-        srcs = [],
-    )
-    kt_jvm_import(
-        name = test_name + "_tut",
-        jars = [
-            "lib%s_dep.jar" % test_name,
-        ],
-        runtime_deps = [
-            test_name + "_dep",
-        ],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _test_kt_jvm_import_with_proguard_specs():
-    test_name = "kt_jvm_import_with_proguard_specs"
-    native.java_library(
-        name = test_name + "_jar",
-        srcs = [],
-    )
-
-    kt_jvm_import(
-        name = test_name + "_tut",
-        jars = [
-            "lib%s_jar.jar" % test_name,
-        ],
-        proguard_specs = [
-            create_file(
-                name = test_name + "/salutations.pgcfg",
-                content = """
--keep class * {
-  *** greeting();
-}
-""",
-            ),
-        ],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _mock_jar(test_name, i):
-    """Creates a Jar named after the given inputs and returns its name."""
-    native.java_library(
-        name = "%s_mock%s" % (test_name, i),
-        srcs = [],
-    )
-    return "lib%s_mock%s.jar" % (test_name, i)
-
-def test_suite(name = None):
-    native.test_suite(
-        name = name,
-        tests = [
-            _test_kt_jvm_import(),
-            _test_kt_jvm_import_with_srcjar_ext(),
-            _test_kt_jvm_import_no_srcjar(),
-            _test_kt_jvm_import_with_runtime_deps(),
-            _test_kt_jvm_import_with_proguard_specs(),
-        ],
-    )
diff --git a/tests/analysis/jvm_library/deps/Input.kt b/tests/analysis/jvm_library/deps/Input.kt
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/deps/Input.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library/no_java_srcs/Input.kt b/tests/analysis/jvm_library/no_java_srcs/Input.kt
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/no_java_srcs/Input.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library/no_kt_srcs/BUILD b/tests/analysis/jvm_library/no_kt_srcs/BUILD
deleted file mode 100644
index d5aafcd..0000000
--- a/tests/analysis/jvm_library/no_kt_srcs/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
-
-package(
-    default_testonly = True,
-)
-
-licenses(["notice"])
-
-jvm_library_test(
-    name = "no_kt_srcs_test",
-    target_under_test = rules_for_test.kt_jvm_library(
-        name = "no_kt_srcs",
-        srcs = [
-            "Input.java",
-        ],
-    ),
-)
diff --git a/tests/analysis/jvm_library/nodeps/Input.java b/tests/analysis/jvm_library/nodeps/Input.java
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/nodeps/Input.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library/nodeps/Input.kt b/tests/analysis/jvm_library/nodeps/Input.kt
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/nodeps/Input.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library/only_common_srcs/Input.kt b/tests/analysis/jvm_library/only_common_srcs/Input.kt
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/only_common_srcs/Input.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library/runtime_deps/Input.kt b/tests/analysis/jvm_library/runtime_deps/Input.kt
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/runtime_deps/Input.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library/treeartifacts_srcs/Input.kt b/tests/analysis/jvm_library/treeartifacts_srcs/Input.kt
deleted file mode 100644
index e675bc1..0000000
--- a/tests/analysis/jvm_library/treeartifacts_srcs/Input.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
diff --git a/tests/analysis/jvm_library_test.bzl b/tests/analysis/jvm_library_test.bzl
deleted file mode 100644
index 1627c5f..0000000
--- a/tests/analysis/jvm_library_test.bzl
+++ /dev/null
@@ -1,660 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Kotlin kt_jvm_library rule tests."""
-
-load("//:visibility.bzl", "RULES_KOTLIN")
-load("//kotlin:jvm_library.bzl", "kt_jvm_library")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_file", "get_action", "get_arg")
-load("@bazel_skylib//lib:sets.bzl", "sets")
-load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
-load(":assert_failure_test.bzl", "assert_failure_test")
-
-_DEFAULT_LIST = ["__default__"]
-
-def _test_impl(ctx):
-    env = analysistest.begin(ctx)
-    actual = ctx.attr.target_under_test
-
-    actions = analysistest.target_actions(env)
-    kt_al_action = get_action(actions, "KtAndroidLint")
-
-    asserts.true(
-        env,
-        JavaInfo in actual,
-        "kt_jvm_library did not produce JavaInfo provider.",
-    )
-    asserts.true(
-        env,
-        ProguardSpecProvider in actual,
-        "Expected a ProguardSpecProvider provider.",
-    )
-
-    if ctx.attr.expected_runfile_names != _DEFAULT_LIST:
-        asserts.set_equals(
-            env,
-            sets.make(ctx.attr.expected_runfile_names),
-            sets.make([
-                f.basename
-                for f in actual[DefaultInfo].data_runfiles.files.to_list()
-            ]),
-        )
-
-    if ctx.attr.expected_compile_jar_names != _DEFAULT_LIST:
-        asserts.set_equals(
-            env,
-            sets.make(ctx.attr.expected_compile_jar_names),
-            sets.make([f.basename for f in actual[JavaInfo].compile_jars.to_list()]),
-            "kt_jvm_library JavaInfo::compile_jars",
-        )
-
-    if ctx.attr.expected_exported_processor_jar_names != _DEFAULT_LIST:
-        asserts.set_equals(
-            env,
-            sets.make(ctx.attr.expected_exported_processor_jar_names),
-            sets.make([f.basename for f in actual[JavaInfo].plugins.processor_jars.to_list()]),
-        )
-
-    asserts.set_equals(
-        env,
-        sets.make(ctx.attr.expected_exported_processor_classes),
-        sets.make(actual[JavaInfo].plugins.processor_classes.to_list()),
-    )
-
-    kt_2_java_compile = get_action(actions, "Kt2JavaCompile")
-
-    if kt_2_java_compile:
-        asserts.true(
-            env,
-            kt_2_java_compile.outputs.to_list()[0].basename.endswith(".jar"),
-            "Expected first output to be a JAR (this affects the param file name).",
-        )
-
-    if ctx.attr.expected_friend_jar_names != _DEFAULT_LIST:
-        friend_paths_arg = get_arg(kt_2_java_compile, "-Xfriend-paths=")
-        friend_jar_names = [p.rsplit("/", 1)[1] for p in friend_paths_arg.split(",")] if friend_paths_arg else []
-        asserts.set_equals(env, sets.make(ctx.attr.expected_friend_jar_names), sets.make(friend_jar_names))
-
-    asserts.equals(
-        env,
-        ctx.attr.expect_neverlink,
-        len(actual[JavaInfo].transitive_runtime_jars.to_list()) == 0,
-        "Mismatch: Expected transitive_runtime_jars iff (neverlink == False)",
-    )
-
-    return analysistest.end(env)
-
-_test = analysistest.make(
-    impl = _test_impl,
-    attrs = dict(
-        expected_al_ruleset_names = attr.string_list(
-            doc = "Android Lint rule JARs reported as run on the given target",
-            default = _DEFAULT_LIST,
-        ),
-        expected_compile_jar_names = attr.string_list(
-            doc = "Names of all JavaInfo::compile_jars for the given target",
-            default = _DEFAULT_LIST,
-        ),
-        expected_exported_processor_jar_names = attr.string_list(
-            doc = "Names of all JavaInfo.plugins JARs returned by the given target",
-            default = _DEFAULT_LIST,
-        ),
-        expected_exported_processor_classes = attr.string_list(
-            doc = "Annotation processors reported as to be run on depending targets",
-        ),
-        expected_processor_classes = attr.string_list(
-            doc = "Annotation processors reported as run on the given target",
-        ),
-        expected_friend_jar_names = attr.string_list(
-            doc = "Names of all -Xfriend-paths= JARs",
-            default = _DEFAULT_LIST,
-        ),
-        expected_runfile_names = attr.string_list(
-            doc = "Names of all runfiles",
-            default = _DEFAULT_LIST,
-        ),
-        expect_processor_classpath = attr.bool(),
-        expect_neverlink = attr.bool(),
-    ),
-)
-
-jvm_library_test = _test
-
-def _coverage_test_impl(ctx):
-    env = analysistest.begin(ctx)
-    target_under_test = analysistest.target_under_test(env)
-    instrumented_files_info = target_under_test[InstrumentedFilesInfo]
-    instrumented_files = instrumented_files_info.instrumented_files.to_list()
-    asserts.equals(
-        env,
-        ctx.attr.expected_instrumented_file_basenames,
-        [file.basename for file in instrumented_files],
-    )
-    return analysistest.end(env)
-
-_coverage_test = analysistest.make(
-    impl = _coverage_test_impl,
-    attrs = {
-        "expected_instrumented_file_basenames": attr.string_list(),
-    },
-    config_settings = {
-        "//command_line_option:collect_code_coverage": "1",
-        "//command_line_option:instrument_test_targets": "1",
-        "//command_line_option:instrumentation_filter": "+tests/analysis[:/]",
-    },
-)
-
-def _test_kt_jvm_library_with_proguard_specs():
-    test_name = "kt_jvm_library_with_proguard_specs_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    create_file(
-        name = test_name + "/salutations.pgcfg",
-        content = """
--keep class * {
-  *** greeting();
-}
-""",
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        proguard_specs = [
-            test_name + "/salutations.pgcfg",
-        ],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_resources():
-    test_name = "kt_jvm_library_with_resources_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    create_file(
-        name = test_name + "/salutations.txt",
-        content = """
-Hi!
-""",
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-            "testinputs/Foo.java",
-        ],
-        resources = [
-            test_name + "/salutations.txt",
-        ],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_plugin():
-    test_name = "kt_jvm_library_with_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        # Need a working plugin so it can run for the test.
-        plugins = ["//bazel:auto_value_plugin"],
-    )
-
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_processor_classes = ["com.google.auto.value.processor.AutoValueProcessor"],
-        expect_processor_classpath = True,
-    )
-    return test_name
-
-def _test_kt_jvm_library_no_kt_srcs_with_plugin():
-    test_name = "kt_jvm_library_no_kt_srcs_with_plugin_test"
-    native.java_plugin(
-        name = "%s_plugin" % test_name,
-        processor_class = test_name,
-        srcs = ["testinputs/Foo.java"],  # induce processor_classpath
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = ["testinputs/Bar.java"],
-        plugins = [":%s_plugin" % test_name],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_processor_classes = [test_name],
-        expect_processor_classpath = True,
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_non_processor_plugin():
-    test_name = "kt_jvm_library_with_non_processor_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-
-    native.java_plugin(
-        # no processor_class
-        name = "%s_plugin" % test_name,
-        srcs = ["testinputs/Foo.java"],
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        plugins = [":%s_plugin" % test_name],
-    )
-
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_processor_classes = [],  # no processor class so no processing
-        expect_processor_classpath = True,  # expect java_plugin's Jar
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_exported_plugin():
-    test_name = "kt_jvm_library_with_exported_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    native.java_plugin(
-        name = "%s_plugin" % test_name,
-        processor_class = test_name,
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        exported_plugins = [":%s_plugin" % test_name],
-    )
-
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_exported_processor_classes = [test_name],
-        expected_processor_classes = [],  # exported plugin should *not* run on _tut itself
-    )
-    return test_name
-
-def _test_kt_jvm_library_dep_on_exported_plugin():
-    test_name = "kt_jvm_library_dep_on_exported_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-
-    native.java_plugin(
-        name = "%s_plugin" % test_name,
-        processor_class = test_name,
-        srcs = ["testinputs/Foo.java"],  # induce processor_classpath
-    )
-    kt_jvm_library(
-        name = "%s_exports_plugin" % test_name,
-        srcs = [test_name + "/Salutations.kt"],
-        exported_plugins = [":%s_plugin" % test_name],
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        deps = [":%s_exports_plugin" % test_name],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    )
-
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_processor_classes = [test_name],
-        expect_processor_classpath = True,
-    )
-    return test_name
-
-def _test_kt_jvm_library_java_dep_on_exported_plugin():
-    test_name = "kt_jvm_library_java_dep_on_exported_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    native.java_plugin(
-        name = "%s_plugin" % test_name,
-        processor_class = test_name,
-        srcs = ["testinputs/Foo.java"],  # induce processor_classpath
-    )
-    native.java_library(
-        name = "%s_exports_plugin" % test_name,
-        exported_plugins = [":%s_plugin" % test_name],
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        deps = [":%s_exports_plugin" % test_name],
-        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    )
-
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_processor_classes = [test_name],
-        expect_processor_classpath = True,
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_exports():
-    test_name = "kt_jvm_library_with_exports_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    kt_jvm_library(
-        name = test_name + "_exp",
-        srcs = [test_name + "/Salutations.kt"],
-    )
-    native.java_library(
-        name = test_name + "_javaexp",
-        srcs = ["testinputs/Foo.java"],  # need file here so we get a Jar
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        exports = [
-            ":%s_exp" % test_name,
-            ":%s_javaexp" % test_name,
-        ],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_compile_jar_names = [
-            "lib%s_tut-compile.jar" % test_name,
-            "lib%s_exp-compile.jar" % test_name,
-            "lib%s_javaexp-hjar.jar" % test_name,
-        ],
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_export_that_exports_plugin():
-    test_name = "kt_jvm_library_with_export_that_exports_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    native.java_plugin(
-        name = "%s_plugin" % test_name,
-        processor_class = test_name,
-        srcs = ["testinputs/Foo.java"],  # induce processor_classpath
-    )
-    kt_jvm_library(
-        name = "%s_exports_plugin" % test_name,
-        exported_plugins = [":%s_plugin" % test_name],
-        srcs = [test_name + "/Salutations.kt"],
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        exports = [":%s_exports_plugin" % test_name],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_compile_jar_names = [
-            "lib%s_tut-compile.jar" % test_name,
-            "lib%s_exports_plugin-compile.jar" % test_name,
-        ],
-        expected_exported_processor_classes = [test_name],
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_java_export_that_exports_plugin():
-    test_name = "kt_jvm_library_with_java_export_that_exports_plugin_test"
-    create_file(
-        name = test_name + "/Salutations.kt",
-        content = """
-package test
-
-fun greeting(): String = "Hello World!"
-""",
-    )
-    native.java_plugin(
-        name = "%s_plugin" % test_name,
-        processor_class = test_name,
-        srcs = ["testinputs/Foo.java"],  # induce processor_classpath
-    )
-    native.java_library(
-        name = "%s_exports_plugin" % test_name,
-        exported_plugins = [":%s_plugin" % test_name],
-    )
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [
-            test_name + "/Salutations.kt",
-        ],
-        exports = [":%s_exports_plugin" % test_name],
-    )
-    _test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_compile_jar_names = [
-            # _exports_plugin has no compile/runtime Jars
-            "lib%s_tut-compile.jar" % test_name,
-        ],
-        expected_exported_processor_classes = [test_name],
-    )
-    return test_name
-
-def _test_forbidden_nano_dep():
-    test_name = "kt_jvm_library_forbidden_nano_test"
-
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [test_name + "/Ignored.kt"],
-        deps = [test_name + "_fake_nano_proto_lib"],
-                tags = [
-            "manual",
-            "nobuilder",
-        ],
-    )
-    native.java_library(
-        name = test_name + "_fake_nano_proto_lib",
-        srcs = [],
-                tags = ["nano_proto_library"],
-    )
-    assert_failure_test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        msg_contains = test_name + "_fake_nano_proto_lib : nano_proto_library",
-    )
-    return test_name
-
-def _test_forbidden_nano_export():
-    test_name = "kt_jvm_library_forbidden_nano_export_test"
-
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = [test_name + "/Ignored.kt"],
-        deps = [test_name + "_export"],
-                tags = [
-            "manual",
-            "nobuilder",
-        ],
-    )
-    native.java_library(
-        name = test_name + "_export",
-        exports = [test_name + "_fake_nano_proto_lib"],
-            )
-    native.java_library(
-        name = test_name + "_fake_nano_proto_lib",
-        srcs = [],
-                tags = ["nano_proto_library"],
-    )
-    assert_failure_test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        msg_contains = test_name + "_fake_nano_proto_lib : nano_proto_library",
-    )
-    return test_name
-
-def _test_kt_jvm_library_with_no_sources():
-    test_name = "kt_jvm_library_with_no_sources_test"
-
-    kt_jvm_library(
-        name = test_name + "_tut",
-        tags = [
-            "manual",
-            "nobuilder",
-        ],
-    )
-    tut_label = str(Label("//tests/analysis:kt_jvm_library_with_no_sources_test_tut"))
-    assert_failure_test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        msg_contains = "One of {srcs, common_srcs, exports, exported_plugins} of target " + tut_label + " must be non empty",
-    )
-    return test_name
-
-def _test_kt_jvm_library_coverage():
-    test_name = "kt_jvm_library_coverage"
-    kt_jvm_library(
-        name = test_name + "_tut",
-        srcs = ["testinputs/Srcs.kt"],
-        common_srcs = ["testinputs/CommonSrcs.kt"],
-        deps = [":{}_deps".format(test_name)],
-        runtime_deps = [":{}_runtime_deps".format(test_name)],
-        data = [":{}_data".format(test_name)],
-        resources = [":{}_resources".format(test_name)],
-        testonly = True,
-    )
-    native.java_library(
-        name = test_name + "_deps",
-        srcs = ["testinputs/Deps.java"],
-        testonly = True,
-    )
-    native.java_library(
-        name = test_name + "_runtime_deps",
-        srcs = ["testinputs/RuntimeDeps.java"],
-        testonly = True,
-    )
-    native.java_binary(
-        name = test_name + "_data",
-        main_class = "Data",
-        srcs = ["testinputs/Data.java"],
-        testonly = True,
-    )
-    native.java_binary(
-        name = test_name + "_resources",
-        main_class = "Resources",
-        srcs = ["testinputs/Resources.java"],
-        testonly = True,
-    )
-    _coverage_test(
-        name = test_name,
-        target_under_test = test_name + "_tut",
-        expected_instrumented_file_basenames = [
-            "Data.java",
-            "Deps.java",
-            "Resources.java",
-            "RuntimeDeps.java",
-            "Srcs.kt",
-            "CommonSrcs.kt",
-        ],
-    )
-    return test_name
-
-def test_suite(name):
-    native.test_suite(
-        name = name,
-        tests = [
-            _test_forbidden_nano_dep(),
-            _test_forbidden_nano_export(),
-            _test_kt_jvm_library_dep_on_exported_plugin(),
-            _test_kt_jvm_library_java_dep_on_exported_plugin(),
-            _test_kt_jvm_library_no_kt_srcs_with_plugin(),
-            _test_kt_jvm_library_with_export_that_exports_plugin(),
-            _test_kt_jvm_library_with_exported_plugin(),
-            _test_kt_jvm_library_with_exports(),
-            _test_kt_jvm_library_with_java_export_that_exports_plugin(),
-            _test_kt_jvm_library_with_no_sources(),
-            _test_kt_jvm_library_with_non_processor_plugin(),
-            _test_kt_jvm_library_with_plugin(),
-            _test_kt_jvm_library_with_proguard_specs(),
-            _test_kt_jvm_library_with_resources(),
-            _test_kt_jvm_library_coverage(),
-        ],
-    )
diff --git a/tests/analysis/testinputs/Bar.java b/tests/analysis/testinputs/Bar.java
deleted file mode 100644
index c69a114..0000000
--- a/tests/analysis/testinputs/Bar.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs;
-
-public class Bar {
-  public Bar() {}
-}
diff --git a/tests/analysis/testinputs/CommonSrcs.kt b/tests/analysis/testinputs/CommonSrcs.kt
deleted file mode 100644
index 932e704..0000000
--- a/tests/analysis/testinputs/CommonSrcs.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs
-
-class CommonSrcs
diff --git a/tests/analysis/testinputs/Data.java b/tests/analysis/testinputs/Data.java
deleted file mode 100644
index d8e161f..0000000
--- a/tests/analysis/testinputs/Data.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs;
-
-final class Data {
-  private Data() {}
-}
diff --git a/tests/analysis/testinputs/Deps.java b/tests/analysis/testinputs/Deps.java
deleted file mode 100644
index 7f5237f..0000000
--- a/tests/analysis/testinputs/Deps.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs;
-
-final class Deps {
-  private Deps() {}
-}
diff --git a/tests/analysis/testinputs/Foo.java b/tests/analysis/testinputs/Foo.java
deleted file mode 100644
index 249811a..0000000
--- a/tests/analysis/testinputs/Foo.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs;
-
-public class Foo {
-  public Foo() {}
-}
diff --git a/tests/analysis/testinputs/Resources.java b/tests/analysis/testinputs/Resources.java
deleted file mode 100644
index cbf6e7c..0000000
--- a/tests/analysis/testinputs/Resources.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs;
-
-final class Resources {
-  private Resources() {}
-}
diff --git a/tests/analysis/testinputs/RuntimeDeps.java b/tests/analysis/testinputs/RuntimeDeps.java
deleted file mode 100644
index 5515a7a..0000000
--- a/tests/analysis/testinputs/RuntimeDeps.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs;
-
-final class RuntimeDeps {
-  private RuntimeDeps() {}
-}
diff --git a/tests/analysis/testinputs/Srcs.kt b/tests/analysis/testinputs/Srcs.kt
deleted file mode 100644
index 89ca40c..0000000
--- a/tests/analysis/testinputs/Srcs.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * * Copyright 2022 Google LLC. 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.
- */
-
-package testinputs
-
-class Srcs
diff --git a/tests/analysis/util.bzl b/tests/analysis/util.bzl
deleted file mode 100644
index 653843b..0000000
--- a/tests/analysis/util.bzl
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright 2022 Google LLC. 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.
-
-"""Some utils"""
-
-load("//:visibility.bzl", "RULES_KOTLIN")
-
-# Mark targets that's aren't expected to build, but are needed for analysis test assertions.
-ONLY_FOR_ANALYSIS_TEST_TAGS = ["manual", "nobuilder", "only_for_analysis_test"]
-
-def create_file(name, content):
-    if content.startswith("\n"):
-        content = content[1:-1]
-
-    native.genrule(
-        name = "gen_" + name,
-        outs = [name],
-        cmd = """
-cat > $@ <<EOF
-%s
-EOF
-""" % content,
-    )
-
-    return name
-
-def _create_dir_impl(ctx):
-    dir = ctx.actions.declare_directory(ctx.attr.name)
-
-    command = "mkdir -p {0} " + ("&& cp {1} {0}" if ctx.files.srcs else "# {1}")
-    ctx.actions.run_shell(
-        command = command.format(
-            dir.path + "/" + ctx.attr.subdir,
-            " ".join([s.path for s in ctx.files.srcs]),
-        ),
-        inputs = ctx.files.srcs,
-        outputs = [dir],
-    )
-
-    return [DefaultInfo(files = depset([dir]))]
-
-_create_dir = rule(
-    implementation = _create_dir_impl,
-    attrs = dict(
-        subdir = attr.string(),
-        srcs = attr.label_list(allow_files = True),
-    ),
-)
-
-def create_dir(
-        name,
-        subdir = None,
-        srcs = None):
-    _create_dir(
-        name = name,
-        subdir = subdir,
-        srcs = srcs,
-    )
-    return name
-
-def get_action(actions, mnemonic):
-    """Get a specific action
-
-    Args:
-      actions: [List[Action]]
-      mnemonic: [string] Identify the action whose args to search
-
-    Returns:
-      [Optional[action]] The arg value, or None if it couldn't be found
-    """
-    menmonic_actions = [a for a in actions if a.mnemonic == mnemonic]
-    if len(menmonic_actions) == 0:
-        return None
-    elif len(menmonic_actions) > 1:
-        fail("Expected a single '%s' action" % mnemonic)
-
-    return menmonic_actions[0]
-
-def get_arg(action, arg_name, style = "trim"):
-    """Get a named arg from a specific action
-
-    Args:
-      action: [Optional[Action]]
-      arg_name: [string]
-      style: [Optional[string]] The style of commandline arg
-
-    Returns:
-      [Optional[string]] The arg value, or None if it couldn't be found
-    """
-    if not action:
-        return None
-
-    args = action.argv
-    matches = [(i, a) for (i, a) in enumerate(args) if a.startswith(arg_name)]
-    if len(matches) == 0:
-        return None
-    elif len(matches) > 1:
-        fail("Expected a single '%s' arg" % arg_name)
-    (index, arg) = matches[0]
-
-    if style == "trim":
-        return arg[len(arg_name):]
-    elif style == "next":
-        return args[index + 1]
-    elif style == "list":
-        result = []
-        for i in range(index + 1, len(args)):
-            if args[i].startswith("--"):
-                break
-            result.append(args[i])
-        return result
-
-    else:
-        fail("Unrecognized arg style '%s" % style)
diff --git a/tests/analysis/compiler_plugin/provider_ctor/BUILD b/tests/common/testing/unittest_suites/BUILD
similarity index 67%
copy from tests/analysis/compiler_plugin/provider_ctor/BUILD
copy to tests/common/testing/unittest_suites/BUILD
index fb5acbc..ace4d76 100644
--- a/tests/analysis/compiler_plugin/provider_ctor/BUILD
+++ b/tests/common/testing/unittest_suites/BUILD
@@ -12,8 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
-load(":fake_compiler_plugin.bzl", "kt_fake_compiler_plugin")
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+load(":unittests.bzl", "unittests")
+
+package(
+    default_testonly = True,
+)
 
 licenses(["notice"])
+
+unittests.render(
+    name = "unittests",
+)
+
+bzl_library(
+    name = "unittests_bzl",
+    srcs = ["unittests.bzl"],
+    deps = ["//kotlin/common/testing:testing_bzl"],
+)
diff --git a/tests/common/testing/unittest_suites/unittests.bzl b/tests/common/testing/unittest_suites/unittests.bzl
new file mode 100644
index 0000000..6fae083
--- /dev/null
+++ b/tests/common/testing/unittest_suites/unittests.bzl
@@ -0,0 +1,97 @@
+# Copyright 2022 Google LLC. 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.
+
+"""unittests"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("//kotlin/common/testing:unittest_suites.bzl", "kt_unittest_suites")
+
+visibility(RULES_KOTLIN)
+
+unittests = kt_unittest_suites.create()
+
+def _add_private_test_case(_ctx, _env):
+    under_test = kt_unittest_suites.create()
+
+    def _some_test():
+        pass
+
+    under_test.expect_finish(_some_test)
+
+unittests.expect_finish(_add_private_test_case)
+
+def _add_private_fail_case(_ctx, _env):
+    under_test = kt_unittest_suites.create()
+
+    def _some_test():
+        pass
+
+    under_test.expect_fail(_some_test, "")
+
+unittests.expect_finish(_add_private_fail_case)
+
+def _add_public_test_case(_ctx):
+    under_test = kt_unittest_suites.create()
+
+    def some_test():
+        pass
+
+    under_test.expect_finish(some_test)
+
+unittests.expect_fail(_add_public_test_case, "private")
+
+def _add_public_fail_case(_ctx):
+    under_test = kt_unittest_suites.create()
+
+    def some_test():
+        pass
+
+    under_test.expect_fail(some_test, "")
+
+unittests.expect_fail(_add_public_fail_case, "private")
+
+def _add_duplicate_test_case(_ctx):
+    under_test = kt_unittest_suites.create()
+
+    def _some_test():
+        pass
+
+    under_test.expect_finish(_some_test)
+    under_test.expect_finish(_some_test)
+
+unittests.expect_fail(_add_duplicate_test_case, "Existing")
+
+def _add_duplicate_fail_case(_ctx):
+    under_test = kt_unittest_suites.create()
+
+    def _some_test():
+        pass
+
+    under_test.expect_fail(_some_test, "")
+    under_test.expect_fail(_some_test, "")
+
+unittests.expect_fail(_add_duplicate_fail_case, "Existing")
+
+def _add_duplicate_test_fail_case(_ctx):
+    under_test = kt_unittest_suites.create()
+
+    def _some_test():
+        pass
+
+    under_test.expect_finish(_some_test)
+    under_test.expect_fail(_some_test, "")
+
+unittests.expect_fail(_add_duplicate_test_fail_case, "Existing")
+
+_test, _fail = unittests.close()  # @unused
diff --git a/tests/analysis/compiler_plugin/provider_ctor/BUILD b/tests/jvm/analysis/compiler_plugin/forbidden_target/BUILD
similarity index 72%
rename from tests/analysis/compiler_plugin/provider_ctor/BUILD
rename to tests/jvm/analysis/compiler_plugin/forbidden_target/BUILD
index fb5acbc..d21f27c 100644
--- a/tests/analysis/compiler_plugin/provider_ctor/BUILD
+++ b/tests/jvm/analysis/compiler_plugin/forbidden_target/BUILD
@@ -12,8 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
-load(":fake_compiler_plugin.bzl", "kt_fake_compiler_plugin")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
 
 licenses(["notice"])
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD b/tests/jvm/analysis/compiler_plugin/provider_ctor/BUILD
similarity index 78%
rename from tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD
rename to tests/jvm/analysis/compiler_plugin/provider_ctor/BUILD
index db873cf..0ba8b21 100644
--- a/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD
+++ b/tests/jvm/analysis/compiler_plugin/provider_ctor/BUILD
@@ -12,11 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load(":unittests.bzl", "unittests")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
 licenses(["notice"])
 
-genrule(
-    name = "sub",
-    outs = ["sub.txt"],
-    cmd = "touch $(OUTS)",
-    visibility = ["//tests/analysis/internal_do_not_use/util/file_factory:__pkg__"],
-)
+unittests.render(name = "unittests")
diff --git a/kotlin/jvm/internal_do_not_use/traverse_exports/compiler_plugin.bzl b/tests/jvm/analysis/compiler_plugin/provider_ctor/unittests.bzl
similarity index 61%
copy from kotlin/jvm/internal_do_not_use/traverse_exports/compiler_plugin.bzl
copy to tests/jvm/analysis/compiler_plugin/provider_ctor/unittests.bzl
index a5c65c4..e43744f 100644
--- a/kotlin/jvm/internal_do_not_use/traverse_exports/compiler_plugin.bzl
+++ b/tests/jvm/analysis/compiler_plugin/provider_ctor/unittests.bzl
@@ -12,22 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""kt_compiler_plugin_visitor"""
+"""unittests"""
 
 load("//:visibility.bzl", "RULES_KOTLIN")
 load("//kotlin:compiler_plugin.bzl", "KtCompilerPluginInfo")
+load("//kotlin/common/testing:unittest_suites.bzl", "kt_unittest_suites")
 
-def _get_exported_plugins(_target, ctx_rule):
-    return [
-        t[KtCompilerPluginInfo]
-        for t in getattr(ctx_rule.attr, "exported_plugins", [])
-        if (KtCompilerPluginInfo in t)
-    ]
+visibility(RULES_KOTLIN)
 
-kt_compiler_plugin_visitor = struct(
-    name = "compiler_plugins",
-    visit_target = _get_exported_plugins,
-    filter_edge = None,
-    finish_expansion = None,
-    process_unvisited_target = None,
-)
+unittests = kt_unittest_suites.create()
+
+def _cannot_construct_provider(ctx):
+    KtCompilerPluginInfo(
+        plugin_id = "fake",
+        jar = ctx.actions.declare_file("fake.jar"),
+        args = [],
+    )
+
+unittests.expect_fail(_cannot_construct_provider, "Error in fail")
+
+_test, _fail = unittests.close()  # @unused
diff --git a/tests/jvm/analysis/jvm_compile/no_srcs/BUILD b/tests/jvm/analysis/jvm_compile/no_srcs/BUILD
new file mode 100644
index 0000000..6de9ffb
--- /dev/null
+++ b/tests/jvm/analysis/jvm_compile/no_srcs/BUILD
@@ -0,0 +1,63 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin:common.bzl", "common")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_compile_stubs.bzl", "kt_jvm_compile_stubs")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_jvm_compile_stubs.analysis_test(
+    name = "no_srcs_android_family_test",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "no_srcs_android_family",
+        srcs = [],
+        common_srcs = [],
+        rule_family = common.RULE_FAMILY.ANDROID_LIBRARY,
+    ),
+)
+
+kt_testing_rules.assert_failure_test(
+    name = "no_srcs_jvm_family_test",
+    msg_contains = "Expected one of (srcs, common_srcs, exports) is not empty",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "no_srcs_jvm_family",
+        srcs = [],
+        common_srcs = [],
+        rule_family = common.RULE_FAMILY.JVM_LIBRARY,
+        exports = [],
+    ),
+)
+
+kt_jvm_compile_stubs.analysis_test(
+    name = "no_srcs_jvm_family_with_exports_test",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "no_srcs_jvm_family_with_exports",
+        srcs = [],
+        common_srcs = [],
+        rule_family = common.RULE_FAMILY.ANDROID_LIBRARY,
+        exports = [
+            ktfa.java_library(
+                name = "no_srcs_jvm_family_export",
+                srcs = [],
+            ),
+        ],
+    ),
+)
diff --git a/tests/jvm/analysis/jvm_compile/r_java/BUILD b/tests/jvm/analysis/jvm_compile/r_java/BUILD
new file mode 100644
index 0000000..70ef77c
--- /dev/null
+++ b/tests/jvm/analysis/jvm_compile/r_java/BUILD
@@ -0,0 +1,61 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_compile_stubs.bzl", "kt_jvm_compile_stubs")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_jvm_compile_stubs.analysis_test(
+    name = "has_r_java_named_resources_test",
+    expected_kotlinc_classpath_names = [
+        "platformclasspath.jar",  # bootclasspath
+        "libjava_library_resources-hjar.jar",  # r_java
+        "libjava_library-hjar.jar",  # deps
+        "kotlin-stdlib-ijar.jar",  # stdlibs
+        "annotations-13.0-ijar.jar",  # stdlibs
+    ],
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "has_r_java_named_resources",
+        srcs = ["Input.kt"],
+        r_java = ":java_library_resources",
+        deps = [":java_library"],
+    ),
+)
+
+kt_testing_rules.assert_failure_test(
+    name = "has_r_java_not_named_resources_test",
+    msg_contains = "illegal dependency provided for r_java",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "has_r_java_not_named_resources",
+        srcs = ["Input.kt"],
+        r_java = ":java_library",
+    ),
+)
+
+ktfa.java_library(
+    name = "java_library_resources",
+    srcs = ["Input.java"],
+)
+
+ktfa.java_library(
+    name = "java_library",
+    srcs = ["Input.java"],
+)
diff --git a/tests/analysis/jvm_library/deps/Input.java b/tests/jvm/analysis/jvm_compile/r_java/Input.java
similarity index 100%
copy from tests/analysis/jvm_library/deps/Input.java
copy to tests/jvm/analysis/jvm_compile/r_java/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_compile/r_java/Input.kt
similarity index 99%
rename from tests/analysis/jvm_library/data/Input.kt
rename to tests/jvm/analysis/jvm_compile/r_java/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_compile/r_java/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/jvm/analysis/jvm_compile/src_artifacts/BUILD b/tests/jvm/analysis/jvm_compile/src_artifacts/BUILD
new file mode 100644
index 0000000..348c629
--- /dev/null
+++ b/tests/jvm/analysis/jvm_compile/src_artifacts/BUILD
@@ -0,0 +1,61 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:jvm_compile_stubs.bzl", "kt_jvm_compile_stubs")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_jvm_compile_stubs.analysis_test(
+    name = "has_allowed_aritfacts_test",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "has_allowed_artifacts",
+        srcs = [
+            # go/keep-sorted start
+            kt_testing_rules.create_dir(name = "has_allowed_artifacts/java"),
+            kt_testing_rules.create_dir(name = "has_allowed_artifacts/kotlin"),
+            kt_testing_rules.create_file(name = "has_allowed_artifacts/java.srcjar"),
+            kt_testing_rules.create_file(name = "has_allowed_artifacts/src.java"),
+            kt_testing_rules.create_file(name = "has_allowed_artifacts/src.kt"),
+            # go/keep-sorted end
+        ],
+    ),
+)
+
+kt_testing_rules.assert_failure_test(
+    name = "has_unexpected_file_type_test",
+    msg_contains = "/src.unexpected",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "has_unexpected_file_type",
+        srcs = [
+            kt_testing_rules.create_file(name = "has_unexpected_file_type/src.unexpected"),
+        ],
+    ),
+)
+
+kt_testing_rules.assert_failure_test(
+    name = "has_unexpected_dir_ending_test",
+    msg_contains = "/kotlin/unexpected",
+    target_under_test = kt_jvm_compile_stubs.rule(
+        name = "has_unexpected_dir_ending",
+        srcs = [
+            kt_testing_rules.create_dir(name = "has_unexpected_dir_ending_test/kotlin/unexpected"),
+        ],
+    ),
+)
diff --git a/tests/jvm/analysis/jvm_import/jars/BUILD b/tests/jvm/analysis/jvm_import/jars/BUILD
new file mode 100644
index 0000000..38b0b62
--- /dev/null
+++ b/tests/jvm/analysis/jvm_import/jars/BUILD
@@ -0,0 +1,45 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_import_analysis_test.bzl", "kt_jvm_import_analysis_test")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_jvm_import_analysis_test(
+    name = "one_jar_test",
+    target_under_test = kt_for_analysis.kt_jvm_import(
+        name = "one_jar",
+        jars = [
+            kt_testing_rules.create_file(name = "one_jar.jar"),
+        ],
+    ),
+)
+
+kt_jvm_import_analysis_test(
+    name = "many_jar_test",
+    target_under_test = kt_for_analysis.kt_jvm_import(
+        name = "many_jar",
+        jars = [
+            kt_testing_rules.create_file(name = "many_jar_0.jar"),
+            kt_testing_rules.create_file(name = "many_jar_2.jar"),
+        ],
+    ),
+)
diff --git a/tests/analysis/jvm_library/runtime_deps/BUILD b/tests/jvm/analysis/jvm_import/runtime_deps/BUILD
similarity index 64%
copy from tests/analysis/jvm_library/runtime_deps/BUILD
copy to tests/jvm/analysis/jvm_import/runtime_deps/BUILD
index 85f8b55..a6692cc 100644
--- a/tests/analysis/jvm_library/runtime_deps/BUILD
+++ b/tests/jvm/analysis/jvm_import/runtime_deps/BUILD
@@ -12,29 +12,31 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_import_analysis_test.bzl", "kt_jvm_import_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-rules_for_test.java_library(
-    name = "runtime_deps_test_dep",
-    srcs = [],
-)
-
-jvm_library_test(
+kt_jvm_import_analysis_test(
     name = "runtime_deps_test",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = kt_for_analysis.kt_jvm_import(
         name = "runtime_deps",
-        srcs = [
-            "Input.kt",
+        jars = [
+            kt_testing_rules.create_file(name = "runtime_deps.jar"),
         ],
         runtime_deps = [
             ":runtime_deps_test_dep",
         ],
     ),
 )
+
+kt_for_analysis.java_library(
+    name = "runtime_deps_test_dep",
+    srcs = [],
+)
diff --git a/tests/jvm/analysis/jvm_import/srcjar/BUILD b/tests/jvm/analysis/jvm_import/srcjar/BUILD
new file mode 100644
index 0000000..ea1b23c
--- /dev/null
+++ b/tests/jvm/analysis/jvm_import/srcjar/BUILD
@@ -0,0 +1,35 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_import_analysis_test.bzl", "kt_jvm_import_analysis_test")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_jvm_import_analysis_test(
+    name = "has_srcjar_test",
+    target_under_test = kt_for_analysis.kt_jvm_import(
+        name = "has_srcjar",
+        jars = [
+            kt_testing_rules.create_file(name = "has_srcjar.jar"),
+        ],
+        srcjar = kt_testing_rules.create_file(name = "has_srcjar.srcjar"),
+    ),
+)
diff --git a/tests/jvm/analysis/jvm_library/coverage/BUILD b/tests/jvm/analysis/jvm_library/coverage/BUILD
new file mode 100644
index 0000000..284a7a8
--- /dev/null
+++ b/tests/jvm/analysis/jvm_library/coverage/BUILD
@@ -0,0 +1,66 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_testing_rules.coverage_instrumentation_test(
+    name = "has_coverage_test",
+    expected_instrumented_file_names = [
+        "Data.java",
+        "Dep.java",
+        "Resource.java",
+        "RuntimeDep.java",
+        "Src.kt",
+        "CommonSrc.kt",
+    ],
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_coverage",
+        srcs = ["Src.kt"],
+        common_srcs = ["CommonSrc.kt"],
+        data = [":data"],
+        resources = [":resource"],
+        runtime_deps = [":runtime_dep"],
+        deps = [":dep"],
+    ),
+)
+
+ktfa.java_library(
+    name = "dep",
+    srcs = ["Dep.java"],
+)
+
+ktfa.java_library(
+    name = "runtime_dep",
+    srcs = ["RuntimeDep.java"],
+)
+
+ktfa.java_binary(
+    name = "data",
+    srcs = ["Data.java"],
+    main_class = "Data",
+)
+
+ktfa.java_binary(
+    name = "resource",
+    srcs = ["Resource.java"],
+    main_class = "Resources",
+)
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/coverage/CommonSrc.kt
similarity index 98%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/coverage/CommonSrc.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/coverage/CommonSrc.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/deps/Foo.java b/tests/jvm/analysis/jvm_library/coverage/Data.java
similarity index 100%
copy from tests/analysis/jvm_library/deps/Foo.java
copy to tests/jvm/analysis/jvm_library/coverage/Data.java
diff --git a/tests/analysis/jvm_library/deps/Foo.java b/tests/jvm/analysis/jvm_library/coverage/Dep.java
similarity index 100%
rename from tests/analysis/jvm_library/deps/Foo.java
rename to tests/jvm/analysis/jvm_library/coverage/Dep.java
diff --git a/tests/analysis/jvm_library/deps/Foo.java b/tests/jvm/analysis/jvm_library/coverage/Resource.java
similarity index 100%
copy from tests/analysis/jvm_library/deps/Foo.java
copy to tests/jvm/analysis/jvm_library/coverage/Resource.java
diff --git a/tests/analysis/jvm_library/deps/Foo.java b/tests/jvm/analysis/jvm_library/coverage/RuntimeDep.java
similarity index 100%
copy from tests/analysis/jvm_library/deps/Foo.java
copy to tests/jvm/analysis/jvm_library/coverage/RuntimeDep.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/coverage/Src.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/coverage/Src.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/coverage/Src.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/data/BUILD b/tests/jvm/analysis/jvm_library/data/BUILD
similarity index 76%
rename from tests/analysis/jvm_library/data/BUILD
rename to tests/jvm/analysis/jvm_library/data/BUILD
index e92a2e8..92350c0 100644
--- a/tests/analysis/jvm_library/data/BUILD
+++ b/tests/jvm/analysis/jvm_library/data/BUILD
@@ -12,23 +12,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "data_test",
     expected_runfile_names = [
         "data.txt",
         # libX.jar is always in data_runfiles as well - just append it.
         "libdata.jar",
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = kt_for_analysis.kt_jvm_library(
         name = "data",
         srcs = [
             "Input.kt",
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/data/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/data/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/data/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/jvm/analysis/jvm_library/data/data.txt b/tests/jvm/analysis/jvm_library/data/data.txt
new file mode 100644
index 0000000..d146a73
--- /dev/null
+++ b/tests/jvm/analysis/jvm_library/data/data.txt
@@ -0,0 +1,27 @@
+# Copyright 2022 Google LLC. 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.
+
+# Copyright 2022 Google LLC. 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.
\ No newline at end of file
diff --git a/tests/analysis/jvm_library/deps/BUILD b/tests/jvm/analysis/jvm_library/deps/BUILD
similarity index 62%
rename from tests/analysis/jvm_library/deps/BUILD
rename to tests/jvm/analysis/jvm_library/deps/BUILD
index 6db53bd..fb01c01 100644
--- a/tests/analysis/jvm_library/deps/BUILD
+++ b/tests/jvm/analysis/jvm_library/deps/BUILD
@@ -12,35 +12,33 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-rules_for_test.kt_jvm_library(
-    name = "deps_test_kt_dep",
-    srcs = [
-        "Input.kt",
-    ],
+kt_jvm_library_analysis_test(
+    name = "no_deps_test",
+    target_under_test = kt_for_analysis.kt_jvm_library(
+        name = "no_deps",
+        srcs = [
+            "Input.java",
+            "Input.kt",
+        ],
+    ),
 )
 
-rules_for_test.java_library(
-    name = "deps_test_java_dep",
-    srcs = [
-        "Input.java",
-    ],
-)
-
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "deps_test",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = kt_for_analysis.kt_jvm_library(
         name = "deps",
         srcs = [
-            "Foo.java",
+            "Input.java",
         ],
         deps = [
             ":deps_test_java_dep",
@@ -48,3 +46,17 @@
         ],
     ),
 )
+
+kt_for_analysis.kt_jvm_library(
+    name = "deps_test_kt_dep",
+    srcs = [
+        "Input.kt",
+    ],
+)
+
+kt_for_analysis.java_library(
+    name = "deps_test_java_dep",
+    srcs = [
+        "Input.java",
+    ],
+)
diff --git a/tests/analysis/jvm_library/deps/Input.java b/tests/jvm/analysis/jvm_library/deps/Input.java
similarity index 100%
rename from tests/analysis/jvm_library/deps/Input.java
rename to tests/jvm/analysis/jvm_library/deps/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/deps/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/deps/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/deps/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/jvm/analysis/jvm_library/exports/BUILD b/tests/jvm/analysis/jvm_library/exports/BUILD
new file mode 100644
index 0000000..b2bb9c7
--- /dev/null
+++ b/tests/jvm/analysis/jvm_library/exports/BUILD
@@ -0,0 +1,66 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_jvm_library_analysis_test(
+    name = "has_exports_test",
+    expected_compile_jar_names = [
+        # go/keep-sorted start
+        "libexports_transitive-compile.jar",
+        "libhas_exports-compile.jar",
+        "libjava_library-hjar.jar",
+        "libkt_jvm_library-compile.jar",
+        "libtransitive-compile.jar",
+        # go/keep-sorted end
+    ],
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_exports",
+        srcs = ["Input.kt"],
+        exports = [
+            ":exports_transitive",
+            ":java_library",
+            ":kt_jvm_library",
+        ],
+    ),
+)
+
+ktfa.kt_jvm_library(
+    name = "exports_transitive",
+    srcs = ["Input.kt"],
+    exports = [
+        ktfa.kt_jvm_library(
+            name = "transitive",
+            srcs = ["Input.kt"],
+        ),
+    ],
+)
+
+ktfa.kt_jvm_library(
+    name = "kt_jvm_library",
+    srcs = ["Input.kt"],
+)
+
+ktfa.java_library(
+    name = "java_library",
+    srcs = ["Input.java"],  # need file here so we get a Jar
+)
diff --git a/tests/analysis/jvm_library/deps/Input.java b/tests/jvm/analysis/jvm_library/exports/Input.java
similarity index 100%
copy from tests/analysis/jvm_library/deps/Input.java
copy to tests/jvm/analysis/jvm_library/exports/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/exports/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/exports/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/exports/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/jvm/analysis/jvm_library/forbidden_deps/BUILD b/tests/jvm/analysis/jvm_library/forbidden_deps/BUILD
new file mode 100644
index 0000000..5fcc02f
--- /dev/null
+++ b/tests/jvm/analysis/jvm_library/forbidden_deps/BUILD
@@ -0,0 +1,54 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_testing_rules.assert_failure_test(
+    name = "has_forbidden_nano_dep_test",
+    msg_contains = "fake_nano_proto_lib",
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_forbidden_nano_dep",
+        srcs = ["Inputs.kt"],
+        deps = [":fake_nano_proto_lib"],
+    ),
+)
+
+kt_testing_rules.assert_failure_test(
+    name = "dep_on_has_forbidden_nano_export_test",
+    msg_contains = "fake_nano_proto_lib",
+    target_under_test = ktfa.kt_jvm_library(
+        name = "dep_on_has_forbidden_nano_export",
+        srcs = ["Input.kt"],
+        deps = [
+            ktfa.java_library(
+                name = "has_forbidden_nano_export",
+                exports = [":fake_nano_proto_lib"],
+            ),
+        ],
+    ),
+)
+
+ktfa.java_library(
+    name = "fake_nano_proto_lib",
+    srcs = [],
+    tags = ["nano_proto_library"],
+)
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/forbidden_deps/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/forbidden_deps/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/forbidden_deps/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/friends/BUILD b/tests/jvm/analysis/jvm_library/friends/BUILD
similarity index 67%
rename from tests/analysis/jvm_library/friends/BUILD
rename to tests/jvm/analysis/jvm_library/friends/BUILD
index 538bdce..f2454f4 100644
--- a/tests/analysis/jvm_library/friends/BUILD
+++ b/tests/jvm/analysis/jvm_library/friends/BUILD
@@ -12,103 +12,99 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//kotlin:rules.bzl", "kt_jvm_library")
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
-    default_visibility = ["//tests/analysis/jvm_library/friends:__subpackages__"],
+    default_visibility = ["//tests/jvm/analysis/jvm_library/friends:__subpackages__"],
 )
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_kt_exported_friend_cross_package_test",
     expected_friend_jar_names = [],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_kt_exported_friend_cross_package",
         srcs = ["Input.kt"],
         deps = [
             # Exports :friend from this package
-            "//tests/analysis/jvm_library/friends/sub:kt_exports_friend",
+            "//tests/jvm/analysis/jvm_library/friends/sub:kt_exports_friend",
         ],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "has_java_exported_friend_in_package_test",
     expected_friend_jar_names = [
         "libjava_exports_friend-hjar.jar",
         "libfriend-compile.jar",
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "has_java_exported_friend_in_package",
         srcs = ["Input.kt"],
         deps = [":java_exports_friend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "has_kt_exported_friend_in_package_test",
     expected_friend_jar_names = [
         "libkt_exports_friend-compile.jar",
         "libfriend-compile.jar",
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "has_kt_exported_friend_in_package",
         srcs = ["Input.kt"],
         deps = [":kt_exports_friend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_direct_friend_testing_package_test",
     expected_friend_jar_names = [],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_direct_friend_testing_package",
         srcs = ["Input.kt"],
-        deps = ["//tests/analysis/jvm_library/friends/testing:testingfriend"],
+        deps = ["//tests/jvm/analysis/jvm_library/friends/testing:testingfriend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_direct_friend_subpackage_test",
     expected_friend_jar_names = [],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_direct_friend_subpackage",
         srcs = ["Input.kt"],
-        deps = ["//tests/analysis/jvm_library/friends/sub:subfriend"],
+        deps = ["//tests/jvm/analysis/jvm_library/friends/sub:subfriend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "has_direct_friend_in_package_test",
     expected_friend_jar_names = ["libfriend-compile.jar"],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "has_direct_friend_in_package",
         srcs = ["Input.kt"],
         deps = [":friend"],
     ),
 )
 
-java_library(
+ktfa.java_library(
     name = "java_exports_friend",
     srcs = ["Input.java"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
     exports = [":friend"],
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "kt_exports_friend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
     exports = [":friend"],
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "friend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
 )
diff --git a/tests/analysis/jvm_library/friends/Input.java b/tests/jvm/analysis/jvm_library/friends/Input.java
similarity index 100%
rename from tests/analysis/jvm_library/friends/Input.java
rename to tests/jvm/analysis/jvm_library/friends/Input.java
diff --git a/tests/analysis/jvm_library/friends/Input.kt b/tests/jvm/analysis/jvm_library/friends/Input.kt
similarity index 100%
rename from tests/analysis/jvm_library/friends/Input.kt
rename to tests/jvm/analysis/jvm_library/friends/Input.kt
diff --git a/tests/analysis/jvm_library/friends/sub/BUILD b/tests/jvm/analysis/jvm_library/friends/sub/BUILD
similarity index 64%
rename from tests/analysis/jvm_library/friends/sub/BUILD
rename to tests/jvm/analysis/jvm_library/friends/sub/BUILD
index e7c619f..7f4a38e 100644
--- a/tests/analysis/jvm_library/friends/sub/BUILD
+++ b/tests/jvm/analysis/jvm_library/friends/sub/BUILD
@@ -12,50 +12,47 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//kotlin:rules.bzl", "kt_jvm_library")
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
-    default_visibility = ["//tests/analysis/jvm_library/friends:__subpackages__"],
+    default_visibility = ["//tests/jvm/analysis/jvm_library/friends:__subpackages__"],
 )
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_kt_exported_friend_cross_package_test",
     expected_friend_jar_names = [
         "libkt_exports_friend-compile.jar",
         # Absent # "libfriend-compile.jar"
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_kt_exported_friend_cross_package",
         srcs = ["Input.kt"],
         deps = [":kt_exports_friend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_direct_friend_cross_package_test",
     expected_friend_jar_names = [],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_direct_friend_cross_package",
         srcs = ["Input.kt"],
-        deps = ["//tests/analysis/jvm_library/friends:friend"],
+        deps = ["//tests/jvm/analysis/jvm_library/friends:friend"],
     ),
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "kt_exports_friend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    exports = ["//tests/analysis/jvm_library/friends:friend"],
+    exports = ["//tests/jvm/analysis/jvm_library/friends:friend"],
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "subfriend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
 )
diff --git a/tests/analysis/jvm_library/friends/sub/Input.kt b/tests/jvm/analysis/jvm_library/friends/sub/Input.kt
similarity index 100%
rename from tests/analysis/jvm_library/friends/sub/Input.kt
rename to tests/jvm/analysis/jvm_library/friends/sub/Input.kt
diff --git a/tests/analysis/jvm_library/friends/testing/BUILD b/tests/jvm/analysis/jvm_library/friends/testing/BUILD
similarity index 64%
rename from tests/analysis/jvm_library/friends/testing/BUILD
rename to tests/jvm/analysis/jvm_library/friends/testing/BUILD
index 827aa30..0ab1bba 100644
--- a/tests/analysis/jvm_library/friends/testing/BUILD
+++ b/tests/jvm/analysis/jvm_library/friends/testing/BUILD
@@ -12,82 +12,78 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//kotlin:rules.bzl", "kt_jvm_library")
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
-load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
-    default_visibility = ["//tests/analysis/jvm_library/friends:__subpackages__"],
+    default_visibility = ["//tests/jvm/analysis/jvm_library/friends:__subpackages__"],
 )
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "has_kt_exported_friend_impl_package_test",
     expected_friend_jar_names = [
         "libkt_exports_friend-compile.jar",
         "libfriend-compile.jar",
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "has_kt_exported_friend_impl_package",
         srcs = ["Input.kt"],
         deps = [":kt_exports_friend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "has_direct_friend_impl_package_test",
     expected_friend_jar_names = [
         "libfriend-compile.jar",
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "has_direct_friend_impl_package",
         srcs = ["Input.kt"],
-        deps = ["//tests/analysis/jvm_library/friends:friend"],
+        deps = ["//tests/jvm/analysis/jvm_library/friends:friend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_kt_exported_friend_sibling_package_test",
     expected_friend_jar_names = [
         "libkt_exports_subfriend-compile.jar",
         # Absent # "subfriend-compile.jar"
     ],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_kt_exported_friend_sibling_package",
         srcs = ["Input.kt"],
         deps = [":kt_exports_subfriend"],
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "no_direct_friend_sibling_package_test",
     expected_friend_jar_names = [],
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "no_direct_friend_sibling_package",
         srcs = ["Input.kt"],
-        deps = ["//tests/analysis/jvm_library/friends/sub:subfriend"],
+        deps = ["//tests/jvm/analysis/jvm_library/friends/sub:subfriend"],
     ),
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "kt_exports_subfriend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    exports = ["//tests/analysis/jvm_library/friends/sub:subfriend"],
+    exports = ["//tests/jvm/analysis/jvm_library/friends/sub:subfriend"],
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "kt_exports_friend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
-    exports = ["//tests/analysis/jvm_library/friends:friend"],
+    exports = ["//tests/jvm/analysis/jvm_library/friends:friend"],
 )
 
-kt_jvm_library(
+ktfa.kt_jvm_library(
     name = "testingfriend",
     srcs = ["Input.kt"],
-    tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
 )
diff --git a/tests/analysis/jvm_library/friends/testing/Input.kt b/tests/jvm/analysis/jvm_library/friends/testing/Input.kt
similarity index 100%
rename from tests/analysis/jvm_library/friends/testing/Input.kt
rename to tests/jvm/analysis/jvm_library/friends/testing/Input.kt
diff --git a/tests/jvm/analysis/jvm_library/no_srcs/BUILD b/tests/jvm/analysis/jvm_library/no_srcs/BUILD
new file mode 100644
index 0000000..004d160
--- /dev/null
+++ b/tests/jvm/analysis/jvm_library/no_srcs/BUILD
@@ -0,0 +1,69 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+kt_testing_rules.assert_failure_test(
+    name = "no_srcs_test",
+    msg_contains = "Expected a source-bearing or an export-oriented target",
+    target_under_test = ktfa.kt_jvm_library(
+        name = "no_srcs",
+        srcs = [],
+    ),
+)
+
+kt_jvm_library_analysis_test(
+    name = "no_srcs_with_exports_test",
+    expect_jdeps = False,
+    required_mnemonic_counts = {"KtAndroidLint": "0"},
+    target_under_test = ktfa.kt_jvm_library(
+        name = "no_srcs_with_exports",
+        srcs = [],
+        exports = [
+            ktfa.kt_jvm_library(
+                name = "no_srcs_with_exports_export",
+                srcs = ["Input.kt"],
+            ),
+        ],
+    ),
+)
+
+kt_jvm_library_analysis_test(
+    name = "only_kt_srcs_test",
+    target_under_test = ktfa.kt_jvm_library(
+        name = "only_kt_srcs",
+        srcs = [
+            "Input.kt",
+        ],
+    ),
+)
+
+kt_jvm_library_analysis_test(
+    name = "only_java_srcs_test",
+    target_under_test = ktfa.kt_jvm_library(
+        name = "only_java_srcs",
+        srcs = [
+            "Input.java",
+        ],
+    ),
+)
diff --git a/tests/analysis/jvm_library/no_kt_srcs/Input.java b/tests/jvm/analysis/jvm_library/no_srcs/Input.java
similarity index 100%
rename from tests/analysis/jvm_library/no_kt_srcs/Input.java
rename to tests/jvm/analysis/jvm_library/no_srcs/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/no_srcs/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/no_srcs/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/no_srcs/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/only_common_srcs/BUILD b/tests/jvm/analysis/jvm_library/only_common_srcs/BUILD
similarity index 73%
rename from tests/analysis/jvm_library/only_common_srcs/BUILD
rename to tests/jvm/analysis/jvm_library/only_common_srcs/BUILD
index aae3068..a91cff7 100644
--- a/tests/analysis/jvm_library/only_common_srcs/BUILD
+++ b/tests/jvm/analysis/jvm_library/only_common_srcs/BUILD
@@ -12,18 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "only_common_srcs_test",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = kt_for_analysis.kt_jvm_library(
         name = "only_common_srcs",
         common_srcs = [
             "Input.kt",
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/only_common_srcs/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/only_common_srcs/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/only_common_srcs/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/jvm/analysis/jvm_library/plugins/BUILD b/tests/jvm/analysis/jvm_library/plugins/BUILD
new file mode 100644
index 0000000..3694233
--- /dev/null
+++ b/tests/jvm/analysis/jvm_library/plugins/BUILD
@@ -0,0 +1,153 @@
+# Copyright 2022 Google LLC. 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.
+
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
+
+package(
+    default_applicable_licenses = ["//:license"],
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+DEFAULT_KOTLINC_PLUGINS = [
+    "jvm-abi-gen.jar",
+]
+
+kt_jvm_library_analysis_test(
+    name = "has_plugin_and_only_kt_srcs_test",
+    expect_processor_classpath = True,
+    expected_exported_processor_classes = [],
+    expected_kotlinc_plugin_jar_names = DEFAULT_KOTLINC_PLUGINS + ["kt_compiler_plugin.jar"],
+    expected_processor_classes = ["java.plugin.class"],
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_plugin_and_only_kt_srcs",
+        srcs = ["Input.kt"],
+        plugins = [
+            ":java_plugin",
+            ":kt_compiler_plugin",
+        ],
+    ),
+)
+
+kt_jvm_library_analysis_test(
+    name = "has_plugin_and_only_java_srcs_test",
+    expect_processor_classpath = True,
+    expected_exported_processor_classes = [],
+    expected_kotlinc_plugin_jar_names = [],  # No kotlinc action
+    expected_processor_classes = ["java.plugin.class"],
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_plugin_and_only_java_srcs",
+        srcs = ["Input.java"],
+        plugins = [
+            ":java_plugin",
+            ":kt_compiler_plugin",
+        ],
+    ),
+)
+
+kt_jvm_library_analysis_test(
+    name = "has_plugin_without_processor_class_test",
+    expect_processor_classpath = True,
+    expected_exported_processor_classes = [],
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_plugin_without_processor_class",
+        srcs = ["Input.java"],
+        plugins = [
+            ktfa.java_plugin(
+                name = "java_plugin_without_processor_class",
+                srcs = ["Input.java"],
+            ),
+        ],
+    ),
+)
+
+[
+    kt_jvm_library_analysis_test(
+        name = "dep_on_" + exporter + "_test",
+        expect_processor_classpath = True,
+        expected_kotlinc_plugin_jar_names = DEFAULT_KOTLINC_PLUGINS + ["kt_compiler_plugin.jar"],
+        expected_processor_classes = ["java.plugin.class"],
+        target_under_test = ktfa.kt_jvm_library(
+            name = "dep_on_" + exporter,
+            srcs = ["Input.kt"],
+            deps = [exporter],
+        ),
+    )
+    for exporter in [
+        "java_library_with_exported_plugin",
+        "kt_jvm_library_with_exported_plugin",
+    ] + [
+        "kt_jvm_library_exporting_java_library_with_exported_plugin",
+        "kt_jvm_library_exporting_kt_jvm_library_with_exported_plugin",
+    ]
+]
+
+[
+    kt_jvm_library_analysis_test(
+        name = "kt_jvm_library_exporting_" + export + "_test",
+        expect_processor_classpath = False,
+        expected_exported_processor_classes = ["java.plugin.class"],
+        expected_kotlinc_plugin_jar_names = DEFAULT_KOTLINC_PLUGINS,
+        expected_processor_classes = [],
+        target_under_test = ktfa.kt_jvm_library(
+            name = "kt_jvm_library_exporting_" + export,
+            srcs = ["Input.kt"],
+            exports = [export],
+        ),
+    )
+    for export in [
+        "java_library_with_exported_plugin",
+        "kt_jvm_library_with_exported_plugin",
+    ]
+]
+
+ktfa.java_library(
+    name = "java_library_with_exported_plugin",
+    srcs = ["Input.java"],
+    exported_plugins = [
+        ":java_plugin",
+        ":kt_compiler_plugin",
+    ],
+)
+
+kt_jvm_library_analysis_test(
+    name = "kt_jvm_library_with_exported_plugin_test",
+    expect_processor_classpath = False,
+    expected_exported_processor_classes = ["java.plugin.class"],
+    expected_kotlinc_plugin_jar_names = DEFAULT_KOTLINC_PLUGINS,
+    expected_processor_classes = [],  # exported plugin should *not* run on exporter itself
+    target_under_test = ktfa.kt_jvm_library(
+        name = "kt_jvm_library_with_exported_plugin",
+        srcs = ["Input.kt"],
+        exported_plugins = [
+            ":java_plugin",
+            ":kt_compiler_plugin",
+        ],
+    ),
+)
+
+ktfa.java_plugin(
+    name = "java_plugin",
+    srcs = ["Input.java"],
+    processor_class = "java.plugin.class",
+)
+
+ktfa.kt_compiler_plugin(
+    name = "kt_compiler_plugin",
+    jar = kt_testing_rules.create_file(name = "kt_compiler_plugin.jar"),
+    plugin_id = "kt.plugin",
+)
diff --git a/tests/analysis/jvm_library/deps/Input.java b/tests/jvm/analysis/jvm_library/plugins/Input.java
similarity index 100%
copy from tests/analysis/jvm_library/deps/Input.java
copy to tests/jvm/analysis/jvm_library/plugins/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/plugins/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/plugins/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/plugins/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/nodeps/BUILD b/tests/jvm/analysis/jvm_library/resources/BUILD
similarity index 61%
rename from tests/analysis/jvm_library/nodeps/BUILD
rename to tests/jvm/analysis/jvm_library/resources/BUILD
index f2ae73b..1c4797f 100644
--- a/tests/analysis/jvm_library/nodeps/BUILD
+++ b/tests/jvm/analysis/jvm_library/resources/BUILD
@@ -12,22 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-jvm_library_test(
-    name = "nodeps_test",
-    target_under_test = rules_for_test.kt_jvm_library(
-        name = "nodeps",
-        srcs = [
-            "Input.java",
-            "Input.kt",
-        ],
+kt_jvm_library_analysis_test(
+    name = "has_resources_test",
+    target_under_test = ktfa.kt_jvm_library(
+        name = "has_resources",
+        srcs = ["Input.kt"],
+        resources = ["resource.txt"],
     ),
 )
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/resources/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/resources/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/resources/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/data/data.txt b/tests/jvm/analysis/jvm_library/resources/resource.txt
similarity index 98%
rename from tests/analysis/jvm_library/data/data.txt
rename to tests/jvm/analysis/jvm_library/resources/resource.txt
index e3ba5e8..b986da2 100644
--- a/tests/analysis/jvm_library/data/data.txt
+++ b/tests/jvm/analysis/jvm_library/resources/resource.txt
@@ -10,4 +10,5 @@
 # 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.
\ No newline at end of file
+# limitations under the License.
+
diff --git a/tests/analysis/jvm_library/runtime_deps/BUILD b/tests/jvm/analysis/jvm_library/runtime_deps/BUILD
similarity index 73%
rename from tests/analysis/jvm_library/runtime_deps/BUILD
rename to tests/jvm/analysis/jvm_library/runtime_deps/BUILD
index 85f8b55..aaea117 100644
--- a/tests/analysis/jvm_library/runtime_deps/BUILD
+++ b/tests/jvm/analysis/jvm_library/runtime_deps/BUILD
@@ -12,23 +12,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-rules_for_test.java_library(
+kt_for_analysis.java_library(
     name = "runtime_deps_test_dep",
     srcs = [],
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "runtime_deps_test",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = kt_for_analysis.kt_jvm_library(
         name = "runtime_deps",
         srcs = [
             "Input.kt",
diff --git a/tests/analysis/jvm_library/runtime_deps/Input.java b/tests/jvm/analysis/jvm_library/runtime_deps/Input.java
similarity index 100%
rename from tests/analysis/jvm_library/runtime_deps/Input.java
rename to tests/jvm/analysis/jvm_library/runtime_deps/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/runtime_deps/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/runtime_deps/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/runtime_deps/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/treeartifacts_srcs/BUILD b/tests/jvm/analysis/jvm_library/treeartifacts_srcs/BUILD
similarity index 69%
rename from tests/analysis/jvm_library/treeartifacts_srcs/BUILD
rename to tests/jvm/analysis/jvm_library/treeartifacts_srcs/BUILD
index 2ba8ecf..6151a43 100644
--- a/tests/analysis/jvm_library/treeartifacts_srcs/BUILD
+++ b/tests/jvm/analysis/jvm_library/treeartifacts_srcs/BUILD
@@ -12,23 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
-load("//tests/analysis:util.bzl", "create_dir")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
+load("//kotlin/jvm/testing:for_analysis.bzl", ktfa = "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = True,
 )
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "treeartifact_basename_kotlin_test",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "treeartifact_basename_kotlin",
         srcs = [
-            create_dir(
+            kt_testing_rules.create_dir(
                 name = "treeartifact_extension/kotlin",
                 srcs = [
                     "Input.java",  # TODO: Reject this source
@@ -38,12 +38,12 @@
     ),
 )
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "treeartifact_basename_java_test",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "treeartifact_basename_java",
         srcs = [
-            create_dir(
+            kt_testing_rules.create_dir(
                 name = "treeartifact_extension/java",
                 srcs = [
                     "Input.kt",  # TODO: Reject this source
@@ -53,52 +53,52 @@
     ),
 )
 
-assert_failure_test(
+kt_testing_rules.assert_failure_test(
     name = "treeartifact_extension_kt_test",
     msg_contains = "/treeartifact_extension.kt",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "treeartifact_extension_kt",
         srcs = [
-            create_dir(
+            kt_testing_rules.create_dir(
                 name = "treeartifact_extension.kt",
             ),
         ],
     ),
 )
 
-assert_failure_test(
+kt_testing_rules.assert_failure_test(
     name = "treeartifact_extension_java_test",
     msg_contains = "/treeartifact_extension.java",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "treeartifact_extension_java",
         srcs = [
-            create_dir(
+            kt_testing_rules.create_dir(
                 name = "treeartifact_extension.java",
             ),
         ],
     ),
 )
 
-assert_failure_test(
+kt_testing_rules.assert_failure_test(
     name = "treeartifact_extension_srcjar_test",
     msg_contains = "/treeartifact_extension.srcjar",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "treeartifact_extension_srcjar",
         srcs = [
-            create_dir(
+            kt_testing_rules.create_dir(
                 name = "treeartifact_extension.srcjar",
             ),
         ],
     ),
 )
 
-assert_failure_test(
+kt_testing_rules.assert_failure_test(
     name = "treeartifact_no_extension_test",
     msg_contains = "/treeartifact_no_extension",
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = ktfa.kt_jvm_library(
         name = "treeartifact_no_extension",
         srcs = [
-            create_dir(
+            kt_testing_rules.create_dir(
                 name = "treeartifact_no_extension_dir",
             ),
         ],
diff --git a/tests/analysis/jvm_library/treeartifacts_srcs/Input.java b/tests/jvm/analysis/jvm_library/treeartifacts_srcs/Input.java
similarity index 100%
rename from tests/analysis/jvm_library/treeartifacts_srcs/Input.java
rename to tests/jvm/analysis/jvm_library/treeartifacts_srcs/Input.java
diff --git a/tests/analysis/jvm_library/data/Input.kt b/tests/jvm/analysis/jvm_library/treeartifacts_srcs/Input.kt
similarity index 99%
copy from tests/analysis/jvm_library/data/Input.kt
copy to tests/jvm/analysis/jvm_library/treeartifacts_srcs/Input.kt
index e675bc1..963d749 100644
--- a/tests/analysis/jvm_library/data/Input.kt
+++ b/tests/jvm/analysis/jvm_library/treeartifacts_srcs/Input.kt
@@ -14,3 +14,4 @@
  * limitations under the License.
  */
 
+
diff --git a/tests/analysis/jvm_library/data/data.txt b/tests/jvm/analysis/util/file_factory/BUILD
similarity index 79%
copy from tests/analysis/jvm_library/data/data.txt
copy to tests/jvm/analysis/util/file_factory/BUILD
index e3ba5e8..3a0b592 100644
--- a/tests/analysis/jvm_library/data/data.txt
+++ b/tests/jvm/analysis/util/file_factory/BUILD
@@ -10,4 +10,16 @@
 # 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.
\ No newline at end of file
+# limitations under the License.
+
+load(":unittests.bzl", "unittests")
+
+package(
+    default_testonly = True,
+)
+
+licenses(["notice"])
+
+unittests.render(
+    name = "unittests",
+)
diff --git a/tests/jvm/analysis/util/file_factory/unittests.bzl b/tests/jvm/analysis/util/file_factory/unittests.bzl
new file mode 100644
index 0000000..cf7a2a4
--- /dev/null
+++ b/tests/jvm/analysis/util/file_factory/unittests.bzl
@@ -0,0 +1,85 @@
+# Copyright 2022 Google LLC. 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.
+
+"""unittests"""
+
+load("//:visibility.bzl", "RULES_KOTLIN")
+load("//kotlin/common/testing:unittest_suites.bzl", "kt_unittest_suites")
+load("//kotlin/jvm/util:file_factory.bzl", "FileFactory")
+load("@bazel_skylib//lib:unittest.bzl", "asserts")
+
+visibility(RULES_KOTLIN)
+
+unittests = kt_unittest_suites.create()
+
+def _base_from_file(ctx, env):
+    base_file = ctx.actions.declare_file("file/base.txt")
+    factory = FileFactory(ctx, base_file)
+
+    _assert_path_equals(ctx, env, "/file/base", factory.base_as_path)
+
+    return [base_file]
+
+unittests.expect_finish(_base_from_file)
+
+def _declare(ctx, env):
+    factory = FileFactory(ctx, "string/base")
+
+    _assert_path_equals(ctx, env, "/string/base", factory.base_as_path)
+
+    a_file = factory.declare_file("a.txt")
+    _assert_path_equals(ctx, env, "/string/basea.txt", a_file.path)
+
+    b_dir = factory.declare_directory("b_dir")
+    _assert_path_equals(ctx, env, "/string/baseb_dir", b_dir.path)
+
+    return [a_file, b_dir]
+
+unittests.expect_finish(_declare)
+
+def _derive(ctx, env):
+    factory = FileFactory(ctx, "")
+
+    # Once
+    factory_once = factory.derive("once")
+    _assert_path_equals(ctx, env, "/once", factory_once.base_as_path)
+
+    # Twice
+    factory_twice = factory_once.derive("/twice")
+    _assert_path_equals(ctx, env, "/once/twice", factory_twice.base_as_path)
+
+unittests.expect_finish(_derive)
+
+def _base_file_without_extension(ctx):
+    base_file = ctx.actions.declare_file(ctx.label.name + "/BUILD")
+    FileFactory(ctx, base_file)
+
+unittests.expect_fail(_base_file_without_extension, "file must have an extension")
+
+def _base_file_from_different_pkg(ctx):
+    mock_file = struct(owner = struct(package = ctx.label.package + "/sub"), extension = "txt")
+    FileFactory(ctx, mock_file)
+
+unittests.expect_fail(_base_file_from_different_pkg, "file must be from ctx package")
+
+def _assert_path_equals(ctx, env, expected, actual):
+    pkg_path = ctx.bin_dir.path + "/" + ctx.label.package
+
+    asserts.equals(
+        env,
+        pkg_path + expected,
+        actual,
+    )
+
+_test, _fail = unittests.close()  # @unused
diff --git a/tests/jvm/java/neverlink/BUILD b/tests/jvm/java/neverlink/BUILD
index c6daa08..a25ac73 100644
--- a/tests/jvm/java/neverlink/BUILD
+++ b/tests/jvm/java/neverlink/BUILD
@@ -12,15 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//tests/analysis:for_test.bzl", "rules_for_test")
-load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//kotlin/jvm/testing:for_analysis.bzl", "kt_for_analysis")
+load("//kotlin/jvm/testing:jvm_library_analysis_test.bzl", "kt_jvm_library_analysis_test")
 
 licenses(["notice"])
 
-jvm_library_test(
+kt_jvm_library_analysis_test(
     name = "neverlinked_input_library_test",
     expect_neverlink = True,
-    target_under_test = rules_for_test.kt_jvm_library(
+    target_under_test = kt_for_analysis.kt_jvm_library(
         name = "neverlinked_input_library",
         srcs = ["Input.kt"],
         neverlink = True,
diff --git a/tests/jvm/java/srcartifacts/BUILD b/tests/jvm/java/srcartifacts/BUILD
index 9d51c82..e974d73 100644
--- a/tests/jvm/java/srcartifacts/BUILD
+++ b/tests/jvm/java/srcartifacts/BUILD
@@ -13,10 +13,11 @@
 # limitations under the License.
 
 load("//kotlin:rules.bzl", "kt_jvm_library", "kt_jvm_test")
-load("//tests/analysis:util.bzl", "create_dir", "create_file")
+load("//kotlin/common/testing:testing_rules.bzl", "kt_testing_rules")
 load("@bazel_skylib//rules:build_test.bzl", "build_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = 1,
 )
 
@@ -43,7 +44,7 @@
     ],
 )
 
-create_dir(
+kt_testing_rules.create_dir(
     name = "dir/java",
     srcs = [
         "JavaInJavaDir.java",
@@ -51,7 +52,7 @@
     subdir = "srcartifacts",
 )
 
-create_dir(
+kt_testing_rules.create_dir(
     name = "dir/kotlin",
     srcs = [
         "KtInKotlinDir.kt",
@@ -59,16 +60,16 @@
     subdir = "srcartifacts",
 )
 
-create_dir(
+kt_testing_rules.create_dir(
     name = "dir/empty",
     srcs = [],
     subdir = "srcartifacts/empty",
 )
 
-create_dir(
+kt_testing_rules.create_dir(
     name = "dir/resources",
     srcs = [
-        create_file(
+        kt_testing_rules.create_file(
             name = "resources_in_resources_dir.txt",
             content = "Test resource content.",
         ),
@@ -92,7 +93,7 @@
 kt_jvm_library(
     name = "empty_java_tree_artifact",
     srcs = [
-        create_dir(
+        kt_testing_rules.create_dir(
             name = "dir/empty_java/java",
             srcs = [],
             subdir = "srcartifacts",
@@ -103,7 +104,7 @@
 kt_jvm_library(
     name = "empty_kotlin_tree_artifact",
     srcs = [
-        create_dir(
+        kt_testing_rules.create_dir(
             name = "dir/empty_kotlin/kotlin",
             srcs = [],
             subdir = "srcartifacts",
diff --git a/toolchains/kotlin_jvm/BUILD b/toolchains/kotlin_jvm/BUILD
index 66056a7..de24049 100644
--- a/toolchains/kotlin_jvm/BUILD
+++ b/toolchains/kotlin_jvm/BUILD
@@ -55,7 +55,6 @@
 
 kt_jvm_toolchains.declare(
     name = "kt_jvm_toolchain_no_turbine_darwin_jdk",
-    enable_turbine_direct = False,
 )
 
 # Turn on profiling of Kotlin/JVM actions
diff --git a/toolchains/kotlin_jvm/androidlint_toolchains.bzl b/toolchains/kotlin_jvm/androidlint_toolchains.bzl
index b4c2208..eb61fcb 100644
--- a/toolchains/kotlin_jvm/androidlint_toolchains.bzl
+++ b/toolchains/kotlin_jvm/androidlint_toolchains.bzl
@@ -14,8 +14,10 @@
 
 """Android Lint toolchain for Kotlin."""
 
-load("//bazel:stubs.bzl", "lint_actions")
 load("//:visibility.bzl", "RULES_KOTLIN")
+load("//bazel:stubs.bzl", "lint_actions")
+
+visibility(RULES_KOTLIN)
 
 _ATTRS = dict(
     _android_lint_baseline_file = attr.label(
diff --git a/toolchains/kotlin_jvm/java_toolchains.bzl b/toolchains/kotlin_jvm/java_toolchains.bzl
index 74095de..0b7a6a5 100644
--- a/toolchains/kotlin_jvm/java_toolchains.bzl
+++ b/toolchains/kotlin_jvm/java_toolchains.bzl
@@ -16,6 +16,8 @@
 
 load("//:visibility.bzl", "RULES_DEFS_THAT_COMPILE_KOTLIN")
 
+visibility(RULES_DEFS_THAT_COMPILE_KOTLIN)
+
 _ATTRS = dict(
     _java_toolchain = attr.label(
         default = Label(
diff --git a/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl b/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl
index 16f8ac2..42784ac 100644
--- a/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl
+++ b/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl
@@ -62,9 +62,6 @@
         proguard_whitelister = ctx.attr.proguard_whitelister[DefaultInfo].files_to_run,
         source_jar_zipper = ctx.file.source_jar_zipper,
         toolchain_type = None if ctx.attr.toolchain_type == None else str(ctx.attr.toolchain_type.label),
-        turbine = ctx.file.turbine,
-        turbine_direct = _opt_for_test(ctx.attr.turbine_direct, lambda x: x[DefaultInfo].files_to_run),
-        turbine_java_runtime = ctx.attr.turbine_java_runtime,
         # go/keep-sorted end
     )
     return [
@@ -100,11 +97,6 @@
         coverage_runtime = attr.label(
             default = "@maven//:org_jacoco_org_jacoco_agent",
         ),
-        enable_turbine_direct = attr.bool(
-            # If disabled, the value of turbine_direct will be ignored.
-            # Starlark doesn't allow None to override default-valued attributes:
-            default = True,
-        ),
         genclass = attr.label(
             default = "@bazel_tools//tools/jdk:GenClass_deploy.jar",
             cfg = "exec",
@@ -188,19 +180,6 @@
             cfg = "exec",
             allow_single_file = [".jar"],
         ),
-        turbine = attr.label(
-            default = "@bazel_tools//tools/jdk:turbine_direct",
-            cfg = "exec",
-            allow_single_file = True,
-        ),
-        turbine_direct = attr.label(
-            executable = True,
-            cfg = "exec",
-            allow_single_file = True,
-        ),
-        turbine_java_runtime = attr.label(
-            cfg = "exec",
-        ),
         toolchain_type = attr.label(),
     ),
     provides = [platform_common.ToolchainInfo],
diff --git a/visibility.bzl b/visibility.bzl
index bb0710e..a881c3e 100644
--- a/visibility.bzl
+++ b/visibility.bzl
@@ -18,10 +18,13 @@
     "//...",
 ]
 
+visibility(RULES_KOTLIN)
+
 TOOLS_KOTLIN = [
 ]
 
 # bzl files in these packages have access to internal parts of rules_kotlin, so think carefully
 # before expanding the list.
 RULES_DEFS_THAT_COMPILE_KOTLIN = RULES_KOTLIN + [
+    "public",
 ]