656 lines
19 KiB
Python
656 lines
19 KiB
Python
# 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("//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")
|
|
load("//:visibility.bzl", "RULES_KOTLIN")
|
|
|
|
_DEFAULT_LIST = ["__default__"]
|
|
|
|
def _test_impl(ctx):
|
|
env = analysistest.begin(ctx)
|
|
actions = analysistest.target_actions(env)
|
|
actual = ctx.attr.target_under_test
|
|
expected = ctx.attr.expected
|
|
|
|
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 "data" in expected:
|
|
expected_data = expected["data"]
|
|
actual_data = _extract_data_runfiles(actual)
|
|
|
|
asserts.new_set_equals(
|
|
env,
|
|
sets.make(expected_data),
|
|
sets.make(actual_data),
|
|
"""
|
|
FAIL: kt_jvm_library did not produce the expected data dependencies.
|
|
EXPECTED: %s
|
|
ACTUAL: %s
|
|
""" % (expected_data, actual_data),
|
|
)
|
|
|
|
expected_exports = []
|
|
for target in ctx.attr.expected_exports:
|
|
asserts.equals(
|
|
env,
|
|
1,
|
|
len(target[JavaInfo].full_compile_jars.to_list()),
|
|
"Not a single compile-time Jar: %s" % target.label,
|
|
)
|
|
expected_exports.extend(target[JavaInfo].full_compile_jars.to_list())
|
|
actual_exports = actual[JavaInfo].full_compile_jars.to_list()
|
|
|
|
# TODO: fail if there are *un*expected exports, maybe by making sure
|
|
# that the actual exports are exactly the expected ones plus the Jar(s)
|
|
# produced by this JavaInfo.
|
|
for expected_export in expected_exports:
|
|
asserts.true(
|
|
env,
|
|
expected_export in actual_exports,
|
|
"""
|
|
kt_jvm_library did not export %s
|
|
actual: %s
|
|
""" % (expected_export, actual_exports),
|
|
)
|
|
|
|
asserts.equals(
|
|
env,
|
|
ctx.attr.expected_exported_processor_classes,
|
|
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 = attr.string_list_dict(),
|
|
expected_exports = attr.label_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,
|
|
),
|
|
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 _extract_data_runfiles(target):
|
|
return [f.basename for f in target[DefaultInfo].data_runfiles.files.to_list()]
|
|
|
|
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_exports = [
|
|
":%s_exp" % test_name,
|
|
":%s_javaexp" % 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_exports = [":%s_exports_plugin" % 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_exports = [], # _exports_plugin has no compile/runtime Jars
|
|
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(),
|
|
],
|
|
)
|