• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Unittests for rust rules."""
2
3load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
4load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro", "rust_shared_library", "rust_static_library")
5
6def _is_dylib_on_windows(ctx):
7    return ctx.target_platform_has_constraint(ctx.attr._windows[platform_common.ConstraintValueInfo])
8
9def _assert_cc_info_has_library_to_link(env, tut, type, ccinfo_count):
10    asserts.true(env, CcInfo in tut, "rust_library should provide CcInfo")
11    cc_info = tut[CcInfo]
12    linker_inputs = cc_info.linking_context.linker_inputs.to_list()
13    asserts.equals(env, ccinfo_count, len(linker_inputs))
14    library_to_link = linker_inputs[0].libraries[0]
15    asserts.equals(env, False, library_to_link.alwayslink)
16
17    asserts.equals(env, [], library_to_link.lto_bitcode_files)
18    asserts.equals(env, [], library_to_link.pic_lto_bitcode_files)
19
20    asserts.equals(env, [], library_to_link.objects)
21    asserts.equals(env, [], library_to_link.pic_objects)
22
23    if type == "cdylib":
24        asserts.true(env, library_to_link.dynamic_library != None)
25        if _is_dylib_on_windows(env.ctx):
26            asserts.true(env, library_to_link.interface_library != None)
27            asserts.true(env, library_to_link.resolved_symlink_dynamic_library == None)
28        else:
29            asserts.equals(env, None, library_to_link.interface_library)
30            asserts.true(env, library_to_link.resolved_symlink_dynamic_library != None)
31        asserts.equals(env, None, library_to_link.resolved_symlink_interface_library)
32        asserts.equals(env, None, library_to_link.static_library)
33        asserts.equals(env, None, library_to_link.pic_static_library)
34    else:
35        asserts.equals(env, None, library_to_link.dynamic_library)
36        asserts.equals(env, None, library_to_link.interface_library)
37        asserts.equals(env, None, library_to_link.resolved_symlink_dynamic_library)
38        asserts.equals(env, None, library_to_link.resolved_symlink_interface_library)
39        asserts.true(env, library_to_link.static_library != None)
40        if type in ("rlib", "lib"):
41            asserts.true(env, library_to_link.static_library.basename.startswith("lib" + tut.label.name))
42        asserts.true(env, library_to_link.pic_static_library != None)
43        asserts.equals(env, library_to_link.static_library, library_to_link.pic_static_library)
44
45def _collect_user_link_flags(env, tut):
46    asserts.true(env, CcInfo in tut, "rust_library should provide CcInfo")
47    cc_info = tut[CcInfo]
48    linker_inputs = cc_info.linking_context.linker_inputs.to_list()
49    return [f for i in linker_inputs for f in i.user_link_flags]
50
51def _rlib_provides_cc_info_test_impl(ctx):
52    env = analysistest.begin(ctx)
53    tut = analysistest.target_under_test(env)
54    _assert_cc_info_has_library_to_link(env, tut, "rlib", 4)
55    return analysistest.end(env)
56
57def _rlib_with_dep_only_has_stdlib_linkflags_once_test_impl(ctx):
58    env = analysistest.begin(ctx)
59    tut = analysistest.target_under_test(env)
60    user_link_flags = _collect_user_link_flags(env, tut)
61    asserts.equals(
62        env,
63        depset(user_link_flags).to_list(),
64        user_link_flags,
65        "user_link_flags_should_not_have_duplicates_here",
66    )
67    return analysistest.end(env)
68
69def _bin_does_not_provide_cc_info_test_impl(ctx):
70    env = analysistest.begin(ctx)
71    tut = analysistest.target_under_test(env)
72    asserts.false(env, CcInfo in tut, "rust_binary should not provide CcInfo")
73    return analysistest.end(env)
74
75def _proc_macro_does_not_provide_cc_info_test_impl(ctx):
76    env = analysistest.begin(ctx)
77    tut = analysistest.target_under_test(env)
78    asserts.false(env, CcInfo in tut, "rust_proc_macro should not provide CcInfo")
79    return analysistest.end(env)
80
81def _cdylib_provides_cc_info_test_impl(ctx):
82    env = analysistest.begin(ctx)
83    tut = analysistest.target_under_test(env)
84    _assert_cc_info_has_library_to_link(env, tut, "cdylib", 2)
85    return analysistest.end(env)
86
87def _staticlib_provides_cc_info_test_impl(ctx):
88    env = analysistest.begin(ctx)
89    tut = analysistest.target_under_test(env)
90    _assert_cc_info_has_library_to_link(env, tut, "staticlib", 2)
91    return analysistest.end(env)
92
93rlib_provides_cc_info_test = analysistest.make(_rlib_provides_cc_info_test_impl)
94rlib_with_dep_only_has_stdlib_linkflags_once_test = analysistest.make(
95    _rlib_with_dep_only_has_stdlib_linkflags_once_test_impl,
96)
97bin_does_not_provide_cc_info_test = analysistest.make(_bin_does_not_provide_cc_info_test_impl)
98staticlib_provides_cc_info_test = analysistest.make(_staticlib_provides_cc_info_test_impl)
99cdylib_provides_cc_info_test = analysistest.make(_cdylib_provides_cc_info_test_impl, attrs = {
100    "_windows": attr.label(default = Label("@platforms//os:windows")),
101})
102proc_macro_does_not_provide_cc_info_test = analysistest.make(_proc_macro_does_not_provide_cc_info_test_impl)
103
104def _cc_info_test():
105    rust_library(
106        name = "rlib",
107        srcs = ["foo.rs"],
108        edition = "2018",
109    )
110
111    rust_library(
112        name = "rlib_with_dep",
113        srcs = ["foo.rs"],
114        edition = "2018",
115        deps = [":rlib"],
116    )
117
118    rust_binary(
119        name = "bin",
120        srcs = ["foo.rs"],
121        edition = "2018",
122    )
123
124    rust_static_library(
125        name = "staticlib",
126        srcs = ["foo.rs"],
127        edition = "2018",
128    )
129
130    rust_shared_library(
131        name = "cdylib",
132        srcs = ["foo.rs"],
133        edition = "2018",
134    )
135
136    rust_proc_macro(
137        name = "proc_macro",
138        srcs = ["proc_macro.rs"],
139        edition = "2018",
140        deps = ["//test/unit/native_deps:native_dep"],
141    )
142
143    rlib_provides_cc_info_test(
144        name = "rlib_provides_cc_info_test",
145        target_under_test = ":rlib",
146    )
147    rlib_with_dep_only_has_stdlib_linkflags_once_test(
148        name = "rlib_with_dep_only_has_stdlib_linkflags_once_test",
149        target_under_test = ":rlib_with_dep",
150    )
151    bin_does_not_provide_cc_info_test(
152        name = "bin_does_not_provide_cc_info_test",
153        target_under_test = ":bin",
154    )
155    cdylib_provides_cc_info_test(
156        name = "cdylib_provides_cc_info_test",
157        target_under_test = ":cdylib",
158    )
159    staticlib_provides_cc_info_test(
160        name = "staticlib_provides_cc_info_test",
161        target_under_test = ":staticlib",
162    )
163    proc_macro_does_not_provide_cc_info_test(
164        name = "proc_macro_does_not_provide_cc_info_test",
165        target_under_test = ":proc_macro",
166    )
167
168def cc_info_test_suite(name):
169    """Entry-point macro called from the BUILD file.
170
171    Args:
172        name: Name of the macro.
173    """
174    _cc_info_test()
175
176    native.test_suite(
177        name = name,
178        tests = [
179            ":rlib_provides_cc_info_test",
180            ":rlib_with_dep_only_has_stdlib_linkflags_once_test",
181            ":staticlib_provides_cc_info_test",
182            ":cdylib_provides_cc_info_test",
183            ":proc_macro_does_not_provide_cc_info_test",
184            ":bin_does_not_provide_cc_info_test",
185        ],
186    )
187