xref: /aosp_15_r20/external/bazelbuild-kotlin-rules/kotlin/common/testing/testing_rules.bzl (revision 3a22c0a33dd99bcca39a024d43e6fbcc55c2806e)
1*3a22c0a3SAlix# Copyright 2022 Google LLC. All rights reserved.
2*3a22c0a3SAlix#
3*3a22c0a3SAlix# Licensed under the Apache License, Version 2.0 (the License);
4*3a22c0a3SAlix# you may not use this file except in compliance with the License.
5*3a22c0a3SAlix# You may obtain a copy of the License at
6*3a22c0a3SAlix#
7*3a22c0a3SAlix#     http://www.apache.org/licenses/LICENSE-2.0
8*3a22c0a3SAlix#
9*3a22c0a3SAlix# Unless required by applicable law or agreed to in writing, software
10*3a22c0a3SAlix# distributed under the License is distributed on an "AS IS" BASIS,
11*3a22c0a3SAlix# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*3a22c0a3SAlix# See the License for the specific language governing permissions and
13*3a22c0a3SAlix# limitations under the License.
14*3a22c0a3SAlix
15*3a22c0a3SAlix"""kt_testing_rules"""
16*3a22c0a3SAlix
17*3a22c0a3SAlixload("//:visibility.bzl", "RULES_KOTLIN")
18*3a22c0a3SAlixload("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
19*3a22c0a3SAlixload(":analysis.bzl", "kt_analysis")
20*3a22c0a3SAlix
21*3a22c0a3SAlixvisibility(RULES_KOTLIN)
22*3a22c0a3SAlix
23*3a22c0a3SAlix# Mark targets that's aren't expected to build, but are needed for analysis test assertions.
24*3a22c0a3SAlix_ONLY_FOR_ANALYSIS_TAGS = ["manual", "nobuilder", "notap"]
25*3a22c0a3SAlix
26*3a22c0a3SAlixdef _wrap_for_analysis(inner_rule):
27*3a22c0a3SAlix    """Wrap an existing rule to make it easier to use in analysis tests.
28*3a22c0a3SAlix
29*3a22c0a3SAlix    Args:
30*3a22c0a3SAlix        inner_rule: [rule|macro]
31*3a22c0a3SAlix
32*3a22c0a3SAlix    Returns:
33*3a22c0a3SAlix        [macro] Calls inner_rule with appropate tags, returning the target name
34*3a22c0a3SAlix    """
35*3a22c0a3SAlix
36*3a22c0a3SAlix    def wrapper(name, tags = [], **kwargs):
37*3a22c0a3SAlix        inner_rule(
38*3a22c0a3SAlix            name = name,
39*3a22c0a3SAlix            tags = tags + _ONLY_FOR_ANALYSIS_TAGS,
40*3a22c0a3SAlix            **kwargs
41*3a22c0a3SAlix        )
42*3a22c0a3SAlix        return name
43*3a22c0a3SAlix
44*3a22c0a3SAlix    return wrapper
45*3a22c0a3SAlix
46*3a22c0a3SAlix_assert_failure_test = analysistest.make(
47*3a22c0a3SAlix    impl = lambda ctx: _assert_failure_test_impl(ctx),
48*3a22c0a3SAlix    expect_failure = True,
49*3a22c0a3SAlix    attrs = dict(
50*3a22c0a3SAlix        msg_contains = attr.string(mandatory = True),
51*3a22c0a3SAlix    ),
52*3a22c0a3SAlix)
53*3a22c0a3SAlix
54*3a22c0a3SAlixdef _assert_failure_test_impl(ctx):
55*3a22c0a3SAlix    kt_analysis.check_endswith_test(ctx)
56*3a22c0a3SAlix
57*3a22c0a3SAlix    env = analysistest.begin(ctx)
58*3a22c0a3SAlix    asserts.expect_failure(env, ctx.attr.msg_contains)
59*3a22c0a3SAlix    return analysistest.end(env)
60*3a22c0a3SAlix
61*3a22c0a3SAlix_coverage_instrumentation_test = analysistest.make(
62*3a22c0a3SAlix    impl = lambda ctx: _coverage_instrumentation_test_impl(ctx),
63*3a22c0a3SAlix    attrs = dict(
64*3a22c0a3SAlix        expected_instrumented_file_names = attr.string_list(),
65*3a22c0a3SAlix    ),
66*3a22c0a3SAlix    config_settings = {
67*3a22c0a3SAlix        "//command_line_option:collect_code_coverage": "1",
68*3a22c0a3SAlix        "//command_line_option:instrument_test_targets": "1",
69*3a22c0a3SAlix        "//command_line_option:instrumentation_filter": "+",
70*3a22c0a3SAlix    },
71*3a22c0a3SAlix)
72*3a22c0a3SAlix
73*3a22c0a3SAlixdef _coverage_instrumentation_test_impl(ctx):
74*3a22c0a3SAlix    env = analysistest.begin(ctx)
75*3a22c0a3SAlix    target_under_test = analysistest.target_under_test(env)
76*3a22c0a3SAlix    instrumented_files_info = target_under_test[InstrumentedFilesInfo]
77*3a22c0a3SAlix    instrumented_files = instrumented_files_info.instrumented_files.to_list()
78*3a22c0a3SAlix    asserts.equals(
79*3a22c0a3SAlix        env,
80*3a22c0a3SAlix        ctx.attr.expected_instrumented_file_names,
81*3a22c0a3SAlix        [file.basename for file in instrumented_files],
82*3a22c0a3SAlix    )
83*3a22c0a3SAlix    return analysistest.end(env)
84*3a22c0a3SAlix
85*3a22c0a3SAlixdef _create_file(name, content = ""):
86*3a22c0a3SAlix    """Declare a generated file with optional content.
87*3a22c0a3SAlix
88*3a22c0a3SAlix    Args:
89*3a22c0a3SAlix        name: [string] The relative file path
90*3a22c0a3SAlix        content: [string]
91*3a22c0a3SAlix
92*3a22c0a3SAlix    Returns:
93*3a22c0a3SAlix        [File] The label of the file
94*3a22c0a3SAlix    """
95*3a22c0a3SAlix
96*3a22c0a3SAlix    if content.startswith("\n"):
97*3a22c0a3SAlix        content = content[1:-1]
98*3a22c0a3SAlix
99*3a22c0a3SAlix    native.genrule(
100*3a22c0a3SAlix        name = "gen_" + name,
101*3a22c0a3SAlix        outs = [name],
102*3a22c0a3SAlix        cmd = """
103*3a22c0a3SAlixcat > $@ <<EOF
104*3a22c0a3SAlix%s
105*3a22c0a3SAlixEOF
106*3a22c0a3SAlix""" % content,
107*3a22c0a3SAlix    )
108*3a22c0a3SAlix
109*3a22c0a3SAlix    return name
110*3a22c0a3SAlix
111*3a22c0a3SAlix_create_dir = rule(
112*3a22c0a3SAlix    implementation = lambda ctx: _create_dir_impl(ctx),
113*3a22c0a3SAlix    attrs = dict(
114*3a22c0a3SAlix        subdir = attr.string(),
115*3a22c0a3SAlix        srcs = attr.label_list(allow_files = True),
116*3a22c0a3SAlix    ),
117*3a22c0a3SAlix)
118*3a22c0a3SAlix
119*3a22c0a3SAlixdef _create_dir_impl(ctx):
120*3a22c0a3SAlix    dir = ctx.actions.declare_directory(ctx.attr.name)
121*3a22c0a3SAlix
122*3a22c0a3SAlix    command = "mkdir -p {0} " + ("&& cp {1} {0}" if ctx.files.srcs else "# {1}")
123*3a22c0a3SAlix    ctx.actions.run_shell(
124*3a22c0a3SAlix        command = command.format(
125*3a22c0a3SAlix            dir.path + "/" + ctx.attr.subdir,
126*3a22c0a3SAlix            " ".join([s.path for s in ctx.files.srcs]),
127*3a22c0a3SAlix        ),
128*3a22c0a3SAlix        inputs = ctx.files.srcs,
129*3a22c0a3SAlix        outputs = [dir],
130*3a22c0a3SAlix    )
131*3a22c0a3SAlix
132*3a22c0a3SAlix    return [DefaultInfo(files = depset([dir]))]
133*3a22c0a3SAlix
134*3a22c0a3SAlixkt_testing_rules = struct(
135*3a22c0a3SAlix    # go/keep-sorted start
136*3a22c0a3SAlix    ONLY_FOR_ANALYSIS_TAGS = _ONLY_FOR_ANALYSIS_TAGS,
137*3a22c0a3SAlix    assert_failure_test = _assert_failure_test,
138*3a22c0a3SAlix    coverage_instrumentation_test = _coverage_instrumentation_test,
139*3a22c0a3SAlix    create_dir = _wrap_for_analysis(_create_dir),
140*3a22c0a3SAlix    create_file = _create_file,
141*3a22c0a3SAlix    wrap_for_analysis = _wrap_for_analysis,
142*3a22c0a3SAlix    # go/keep-sorted end
143*3a22c0a3SAlix)
144