| # 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], |
| ) |
| |
| 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(), |
| ], |
| ) |