xref: /aosp_15_r20/external/bazelbuild-rules_rust/test/cc_common_link/unit/cc_common_link_test.bzl (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1"""Unittests for the --experimental_use_cc_common_link build setting."""
2
3load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
4load("@rules_cc//cc:defs.bzl", "cc_library")
5load(
6    "@rules_rust//rust:defs.bzl",
7    "rust_binary",
8    "rust_shared_library",
9    "rust_test",
10)
11
12DepActionsInfo = provider(
13    "Contains information about dependencies actions.",
14    fields = {"actions": "List[Action]"},
15)
16
17def _collect_dep_actions_aspect_impl(target, _ctx):
18    return [DepActionsInfo(actions = target.actions)]
19
20collect_dep_actions_aspect = aspect(
21    implementation = _collect_dep_actions_aspect_impl,
22)
23
24def _use_cc_common_link_transition_impl(_settings, _attr):
25    return {"@rules_rust//rust/settings:experimental_use_cc_common_link": True}
26
27use_cc_common_link_transition = transition(
28    inputs = [],
29    outputs = ["@rules_rust//rust/settings:experimental_use_cc_common_link"],
30    implementation = _use_cc_common_link_transition_impl,
31)
32
33def _use_cc_common_link_on_target_impl(ctx):
34    return [ctx.attr.target[0][DepActionsInfo]]
35
36use_cc_common_link_on_target = rule(
37    implementation = _use_cc_common_link_on_target_impl,
38    attrs = {
39        "target": attr.label(
40            cfg = use_cc_common_link_transition,
41            aspects = [collect_dep_actions_aspect],
42        ),
43        "_allowlist_function_transition": attr.label(
44            default = Label("@bazel_tools//tools/allowlists/function_transition_allowlist"),
45        ),
46    },
47)
48
49def _outputs_object_file(action):
50    object_files = [output for output in action.outputs.to_list() if output.extension in ("o", "obj")]
51    return len(object_files) > 0
52
53def _use_cc_common_link_test(ctx):
54    env = analysistest.begin(ctx)
55    tut = analysistest.target_under_test(env)
56    registered_actions = tut[DepActionsInfo].actions
57
58    # When --experimental_use_cc_common_link is enabled the compile+link Rustc action produces a
59    # .o/.obj file.
60    rustc_action = [action for action in registered_actions if action.mnemonic == "Rustc"][0]
61    asserts.true(env, _outputs_object_file(rustc_action), "Rustc action did not output an object file")
62
63    has_cpp_link_action = len([action for action in registered_actions if action.mnemonic == "CppLink"]) > 0
64    asserts.true(env, has_cpp_link_action, "Expected that the target registers a CppLink action")
65
66    return analysistest.end(env)
67
68use_cc_common_link_test = analysistest.make(_use_cc_common_link_test)
69
70def _custom_malloc_test(ctx):
71    env = analysistest.begin(ctx)
72    tut = analysistest.target_under_test(env)
73    registered_actions = tut[DepActionsInfo].actions
74    links = [action for action in registered_actions if action.mnemonic == "CppLink"]
75    cmdline = " ".join(links[0].argv)
76    asserts.true(env, "this_library_is_not_really_an_allocator" in cmdline, "expected to find custom malloc in linker invocation")
77    return analysistest.end(env)
78
79custom_malloc_test = analysistest.make(
80    _custom_malloc_test,
81    config_settings = {
82        "//command_line_option:custom_malloc": "@//unit:this_library_is_not_really_an_allocator",
83    },
84)
85
86def _cc_common_link_test_targets():
87    """Generate targets and tests."""
88
89    cc_library(
90        name = "this_library_is_not_really_an_allocator",
91        srcs = ["this_library_is_not_really_an_allocator.c"],
92    )
93
94    rust_binary(
95        name = "bin",
96        srcs = ["bin.rs"],
97        edition = "2018",
98    )
99
100    use_cc_common_link_on_target(
101        name = "bin_with_cc_common_link",
102        target = ":bin",
103    )
104
105    rust_shared_library(
106        name = "cdylib",
107        srcs = ["lib.rs"],
108        edition = "2018",
109    )
110
111    use_cc_common_link_on_target(
112        name = "cdylib_with_cc_common_link",
113        target = ":cdylib",
114    )
115
116    rust_test(
117        name = "test_with_srcs",
118        srcs = ["lib.rs"],
119        edition = "2018",
120    )
121
122    use_cc_common_link_on_target(
123        name = "test_with_cc_common_link",
124        target = ":test_with_srcs",
125        testonly = True,
126    )
127
128    rust_test(
129        name = "test-with-crate",
130        crate = "cdylib",
131        edition = "2018",
132    )
133
134    use_cc_common_link_on_target(
135        name = "crate_test_with_cc_common_link",
136        target = ":test-with-crate",
137        testonly = True,
138    )
139
140    use_cc_common_link_test(
141        name = "use_cc_common_link_on_binary",
142        target_under_test = ":bin_with_cc_common_link",
143    )
144
145    use_cc_common_link_test(
146        name = "use_cc_common_link_on_test",
147        target_under_test = ":test_with_cc_common_link",
148    )
149
150    use_cc_common_link_test(
151        name = "use_cc_common_link_on_crate_test",
152        target_under_test = ":crate_test_with_cc_common_link",
153    )
154
155    use_cc_common_link_test(
156        name = "use_cc_common_link_on_cdylib",
157        target_under_test = ":cdylib_with_cc_common_link",
158    )
159
160    custom_malloc_test(
161        name = "custom_malloc_on_binary_test",
162        target_under_test = ":bin_with_cc_common_link",
163    )
164
165def cc_common_link_test_suite(name):
166    """Entry-point macro called from the BUILD file.
167
168    Args:
169        name: Name of the macro.
170    """
171    _cc_common_link_test_targets()
172
173    native.test_suite(
174        name = name,
175        tests = [
176            "use_cc_common_link_on_binary",
177            "use_cc_common_link_on_test",
178            "use_cc_common_link_on_crate_test",
179            "use_cc_common_link_on_cdylib",
180            "custom_malloc_on_binary_test",
181        ],
182    )
183