• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2022 Google LLC. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the License);
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Kotlin kt_jvm_compile API test."""
16
17load("//kotlin:traverse_exports.bzl", "kt_traverse_exports")
18load("//kotlin:jvm_compile.bzl", "kt_jvm_compile")
19load("//kotlin:common.bzl", "common")
20load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_dir", "create_file")
21load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
22load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
23load("@bazel_skylib//rules:build_test.bzl", "build_test")
24load(":assert_failure_test.bzl", "assert_failure_test")
25load("//:visibility.bzl", "RULES_KOTLIN")
26
27def _impl(ctx):
28    # As additional capabilites need to be tested, this rule should support
29    # additional fields/attributes.
30    result = kt_jvm_compile(
31        ctx,
32        output = ctx.outputs.jar,
33        srcs = ctx.files.srcs,
34        common_srcs = ctx.files.common_srcs,
35        deps = ctx.attr.deps,
36        plugins = [],
37        exported_plugins = [],
38        runtime_deps = [],
39        exports = ctx.attr.exports,
40        javacopts = [],
41        kotlincopts = [],
42        neverlink = False,
43        testonly = False,
44                android_lint_plugins = [],
45        manifest = None,
46        merged_manifest = None,
47        resource_files = [],
48        rule_family = ctx.attr.rule_family,
49        kt_toolchain = kt_jvm_toolchains.get(ctx),
50        java_toolchain = java_toolchains.get(ctx),
51        disable_lint_checks = [],
52        r_java = ctx.attr.r_java[JavaInfo] if ctx.attr.r_java else None,
53    )
54    return [result.java_info]
55
56_kt_jvm_compile = rule(
57    implementation = _impl,
58    attrs = dict(
59        srcs = attr.label_list(
60            allow_files = True,
61        ),
62        common_srcs = attr.label_list(
63            allow_files = True,
64        ),
65        deps = attr.label_list(
66            aspects = [kt_traverse_exports.aspect],
67            providers = [JavaInfo],
68        ),
69        exports = attr.label_list(
70            aspects = [kt_traverse_exports.aspect],
71            providers = [JavaInfo],
72        ),
73        rule_family = attr.int(
74            default = common.RULE_FAMILY.UNKNOWN,
75        ),
76        r_java = attr.label(
77            providers = [JavaInfo],
78        ),
79        _java_toolchain = attr.label(
80            default = Label(
81                "@bazel_tools//tools/jdk:current_java_toolchain",
82            ),
83        ),
84    ),
85    fragments = ["java"],
86    outputs = dict(
87        jar = "lib%{name}.jar",
88    ),
89    toolchains = [kt_jvm_toolchains.type],
90)
91
92def _test_kt_jvm_compile_using_kt_jvm_compile_with_r_java():
93    test_name = "kt_jvm_compile_using_kt_jvm_compile_with_r_java_test"
94
95    native.java_library(
96        name = "foo_resources",
97        srcs = [create_file(
98            name = test_name + "/java/com/foo/R.java",
99            content = """
100package com.foo;
101
102public final class R {
103  public static final class string {
104    public static int a_string=0x00000001;
105    public static int b_string=0x00000002;
106  }
107}
108""",
109        )],
110    )
111
112    _kt_jvm_compile(
113        name = "kt_jvm_compile_with_r_java",
114        srcs = [create_file(
115            name = test_name + "/AString.kt",
116            content = """
117package test
118
119import com.foo.R.string.a_string
120
121fun aString(): String = "a_string=" + a_string
122""",
123        )],
124        r_java = ":foo_resources",
125    )
126
127    _kt_jvm_compile(
128        name = "kt_jvm_compile_using_kt_jvm_compile_with_r_java",
129        srcs = [create_file(
130            name = test_name + "/ABString.kt",
131            content = """
132package test
133
134import com.foo.R.string.b_string
135
136fun bString(): String = "b_string=" + b_string
137
138fun abString(): String = aString() + bString()
139""",
140        )],
141        deps = [":kt_jvm_compile_with_r_java"],
142    )
143
144    # If a failure occurs, it will be at build time.
145    build_test(
146        name = test_name,
147        targets = [":kt_jvm_compile_using_kt_jvm_compile_with_r_java"],
148    )
149    return test_name
150
151def _test_kt_jvm_compile_with_illegal_r_java():
152    test_name = "kt_jvm_compile_with_illegal_r_java_test"
153
154    native.java_library(
155        name = "foo",
156        srcs = [create_file(
157            name = test_name + "/java/com/foo/Foo.java",
158            content = """
159package com.foo;
160
161public class Foo {}
162""",
163        )],
164    )
165    _kt_jvm_compile(
166        name = "kt_jvm_compile_with_illegal_r_java",
167        srcs = [create_file(
168            name = test_name + "/AString.kt",
169            content = """
170package test
171
172import com.foo.Foo
173
174fun bar(): String = "Bar"
175""",
176        )],
177        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
178        r_java = ":foo",
179    )
180    assert_failure_test(
181        name = test_name,
182        target_under_test = ":kt_jvm_compile_with_illegal_r_java",
183        msg_contains = "illegal dependency provided for r_java",
184    )
185    return test_name
186
187def _test_kt_jvm_compile_with_r_java_as_first_dep():
188    test_name = "kt_jvm_compile_with_r_java_as_first_dep_test"
189
190    # Note: The R from an android_library must be the first dependency in
191    # the classpath to prevent another libraries R from being used for
192    # compilation. If the ordering is incorrect, compiletime failures will
193    # occur as the depot relies on this ordering.
194
195    native.java_library(
196        name = "foo_with_symbol_resources",
197        srcs = [create_file(
198            name = test_name + "/with_symbol/java/com/foo/R.java",
199            content = """
200package com.foo;
201
202public final class R {
203  public static final class string {
204    public static int a_string=0x00000001;
205  }
206}
207""",
208        )],
209    )
210
211    native.java_library(
212        name = "foo_without_symbol_resources",
213        srcs = [create_file(
214            name = test_name + "/without_symbol/java/com/foo/R.java",
215            content = """
216package com.foo;
217
218public final class R {
219  public static final class string {
220  }
221}
222""",
223        )],
224    )
225
226    _kt_jvm_compile(
227        name = "kt_jvm_compile_with_r_java_as_first_dep",
228        srcs = [create_file(
229            name = test_name + "/AString.kt",
230            content = """
231package test
232
233import com.foo.R.string.a_string
234
235fun aString(): String = "a_string=" + a_string
236""",
237        )],
238        r_java = ":foo_with_symbol_resources",
239        deps = [":foo_without_symbol_resources"],
240    )
241
242    # If a failure occurs, it will be at build time.
243    build_test(
244        name = test_name,
245        targets = [":kt_jvm_compile_with_r_java_as_first_dep"],
246    )
247    return test_name
248
249def _test_kt_jvm_compile_without_srcs_for_android():
250    test_name = "kt_jvm_compile_without_srcs_for_android_test"
251
252    # This is a common case for rules like android_library where Kotlin sources
253    # could be empty, due to the rule being used for resource processing. For
254    # this scenario, historically, rules continue to produce empty Jars.
255    _kt_jvm_compile(
256        name = "kt_jvm_compile_without_srcs_for_android",
257        rule_family = common.RULE_FAMILY.ANDROID_LIBRARY,
258    )
259
260    # If a failure occurs, it will be at build time.
261    build_test(
262        name = test_name,
263        targets = [":kt_jvm_compile_without_srcs_for_android"],
264    )
265    return test_name
266
267def _test_kt_jvm_compile_without_srcs_for_jvm():
268    test_name = "kt_jvm_compile_without_srcs_for_jvm_test"
269
270    _kt_jvm_compile(
271        name = "kt_jvm_compile_without_srcs_for_jvm",
272        srcs = [],
273        common_srcs = [],
274        exports = [],
275        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
276    )
277    assert_failure_test(
278        name = test_name,
279        target_under_test = ":kt_jvm_compile_without_srcs_for_jvm",
280        msg_contains = "Expected one of (srcs, common_srcs, exports) is not empty",
281    )
282    return test_name
283
284def _test_kt_jvm_compile_without_srcs_and_with_exports():
285    test_name = "kt_jvm_compile_without_srcs_and_with_exports_test"
286
287    _kt_jvm_compile(
288        name = "bar_lib",
289        srcs = [create_file(
290            name = test_name + "/Bar.kt",
291            content = """
292package test
293
294fun bar(): String = "Bar"
295""",
296        )],
297    )
298
299    _kt_jvm_compile(
300        name = "kt_jvm_compile_without_srcs_and_with_exports",
301        exports = [":bar_lib"],
302    )
303
304    _kt_jvm_compile(
305        name = "foo_bar_lib",
306        srcs = [create_file(
307            name = test_name + "/FooBar.kt",
308            content = """
309package test
310
311fun fooBar(): String = "Foo" + bar()
312""",
313        )],
314        deps = [":kt_jvm_compile_without_srcs_and_with_exports"],
315    )
316
317    # If a failure occurs, it will be at build time.
318    build_test(
319        name = test_name,
320        targets = [":foo_bar_lib"],
321    )
322    return test_name
323
324def _test_kt_jvm_compile_unsupported_src_artifacts():
325    test_name = "kt_jvm_compile_unsupported_src_artifacts_test"
326
327    kt_src = create_file(
328        name = test_name + "/src.kt",
329        content = "",
330    )
331    kt_dir = create_dir(
332        name = test_name + "/kotlin",
333        subdir = "",
334        srcs = [create_file(
335            name = test_name + "/dir.kt",
336            content = "",
337        )],
338    )
339    java_src = create_file(
340        name = test_name + "/src.java",
341        content = "",
342    )
343    java_dir = create_dir(
344        name = test_name + "/java",
345        subdir = "",
346        srcs = [create_file(
347            name = test_name + "/dir.java",
348            content = "",
349        )],
350    )
351    java_srcjar = create_file(
352        name = test_name + "/java.srcjar",
353        content = "",
354    )
355    _kt_jvm_compile(
356        name = test_name + "_expected_lib",
357        srcs = [kt_src, kt_dir, java_src, java_dir, java_srcjar],
358        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
359    )
360
361    unexpected_file = create_file(
362        name = test_name + "/src.unexpected",
363        content = "",
364    )
365    _kt_jvm_compile(
366        name = test_name + "_unexpected_lib",
367        srcs = [unexpected_file],
368        deps = [test_name + "_expected_lib"],
369        tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
370    )
371
372    assert_failure_test(
373        name = test_name,
374        target_under_test = test_name + "_unexpected_lib",
375        msg_contains = "/src.unexpected",
376    )
377    return test_name
378
379def test_suite(name = None):
380    native.test_suite(
381        name = name,
382        tests = [
383            _test_kt_jvm_compile_unsupported_src_artifacts(),
384            _test_kt_jvm_compile_using_kt_jvm_compile_with_r_java(),
385            _test_kt_jvm_compile_with_illegal_r_java(),
386            _test_kt_jvm_compile_with_r_java_as_first_dep(),
387            _test_kt_jvm_compile_without_srcs_for_android(),
388            _test_kt_jvm_compile_without_srcs_for_jvm(),
389            _test_kt_jvm_compile_without_srcs_and_with_exports(),
390        ],
391    )
392