• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2024 The Bazel Authors. 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"""Tests for the cc_toolchain_config rule."""
15
16load(
17    "//cc:cc_toolchain_config_lib.bzl",
18    legacy_action_config = "action_config",
19    legacy_env_entry = "env_entry",
20    legacy_env_set = "env_set",
21    legacy_feature = "feature",
22    legacy_flag_group = "flag_group",
23    legacy_flag_set = "flag_set",
24    legacy_tool = "tool",
25)
26load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeInfo", "ToolchainConfigInfo")
27load("//cc/toolchains/impl:legacy_converter.bzl", "convert_toolchain")
28load("//cc/toolchains/impl:toolchain_config_info.bzl", _toolchain_config_info = "toolchain_config_info")
29load("//tests/rule_based_toolchain:subjects.bzl", "result_fn_wrapper", "subjects")
30
31visibility("private")
32
33toolchain_config_info = result_fn_wrapper(_toolchain_config_info)
34
35_COLLECTED_CPP_COMPILE_FILES = [
36    # From :compile_config's tool
37    "tests/rule_based_toolchain/testdata/bin",
38    "tests/rule_based_toolchain/testdata/bin_wrapper",
39    # From :compile_feature's args
40    "tests/rule_based_toolchain/testdata/file2",
41]
42
43_COLLECTED_C_COMPILE_FILES = _COLLECTED_CPP_COMPILE_FILES + [
44    # From :c_compile_args
45    "tests/rule_based_toolchain/testdata/file1",
46]
47
48def _expect_that_toolchain(env, expr = None, **kwargs):
49    return env.expect.that_value(
50        value = toolchain_config_info(label = Label("//:toolchain"), **kwargs),
51        expr = expr,
52        factory = subjects.result(subjects.ToolchainConfigInfo),
53    )
54
55def _empty_toolchain_valid_test(env, _targets):
56    _expect_that_toolchain(env).ok()
57
58def _duplicate_feature_names_invalid_test(env, targets):
59    _expect_that_toolchain(
60        env,
61        features = [targets.simple_feature, targets.same_feature_name],
62        expr = "duplicate_feature_name",
63    ).err().contains_all_of([
64        "The feature name simple_feature was defined by",
65        targets.same_feature_name.label,
66        targets.simple_feature.label,
67    ])
68
69    # Overriding a feature gives it the same name. Ensure this isn't blocked.
70    _expect_that_toolchain(
71        env,
72        features = [targets.builtin_feature, targets.overrides_feature],
73        expr = "override_feature",
74    ).ok()
75
76def _duplicate_action_type_invalid_test(env, targets):
77    _expect_that_toolchain(
78        env,
79        features = [targets.simple_feature],
80        action_type_configs = [targets.compile_config, targets.c_compile_config],
81    ).err().contains_all_of([
82        "The action type %s is configured by" % targets.c_compile.label,
83        targets.compile_config.label,
84        targets.c_compile_config.label,
85    ])
86
87def _action_config_implies_missing_feature_invalid_test(env, targets):
88    _expect_that_toolchain(
89        env,
90        features = [targets.simple_feature],
91        action_type_configs = [targets.c_compile_config],
92        expr = "action_type_config_with_implies",
93    ).ok()
94
95    _expect_that_toolchain(
96        env,
97        features = [],
98        action_type_configs = [targets.c_compile_config],
99        expr = "action_type_config_missing_implies",
100    ).err().contains(
101        "%s implies the feature %s" % (targets.c_compile_config.label, targets.simple_feature.label),
102    )
103
104def _feature_config_implies_missing_feature_invalid_test(env, targets):
105    _expect_that_toolchain(
106        env,
107        expr = "feature_with_implies",
108        features = [targets.simple_feature, targets.implies_simple_feature],
109    ).ok()
110
111    _expect_that_toolchain(
112        env,
113        features = [targets.implies_simple_feature],
114        expr = "feature_missing_implies",
115    ).err().contains(
116        "%s implies the feature %s" % (targets.implies_simple_feature.label, targets.simple_feature.label),
117    )
118
119def _feature_missing_requirements_invalid_test(env, targets):
120    _expect_that_toolchain(
121        env,
122        features = [targets.requires_any_simple_feature, targets.simple_feature],
123        expr = "requires_any_simple_has_simple",
124    ).ok()
125    _expect_that_toolchain(
126        env,
127        features = [targets.requires_any_simple_feature, targets.simple_feature2],
128        expr = "requires_any_simple_has_simple2",
129    ).ok()
130    _expect_that_toolchain(
131        env,
132        features = [targets.requires_any_simple_feature],
133        expr = "requires_any_simple_has_none",
134    ).err().contains(
135        "It is impossible to enable %s" % targets.requires_any_simple_feature.label,
136    )
137
138    _expect_that_toolchain(
139        env,
140        features = [targets.requires_all_simple_feature, targets.simple_feature, targets.simple_feature2],
141        expr = "requires_all_simple_has_both",
142    ).ok()
143    _expect_that_toolchain(
144        env,
145        features = [targets.requires_all_simple_feature, targets.simple_feature],
146        expr = "requires_all_simple_has_simple",
147    ).err().contains(
148        "It is impossible to enable %s" % targets.requires_all_simple_feature.label,
149    )
150    _expect_that_toolchain(
151        env,
152        features = [targets.requires_all_simple_feature, targets.simple_feature2],
153        expr = "requires_all_simple_has_simple2",
154    ).err().contains(
155        "It is impossible to enable %s" % targets.requires_all_simple_feature.label,
156    )
157
158def _args_missing_requirements_invalid_test(env, targets):
159    _expect_that_toolchain(
160        env,
161        args = [targets.requires_all_simple_args],
162        features = [targets.simple_feature, targets.simple_feature2],
163        expr = "has_both",
164    ).ok()
165    _expect_that_toolchain(
166        env,
167        args = [targets.requires_all_simple_args],
168        features = [targets.simple_feature],
169        expr = "has_only_one",
170    ).err().contains(
171        "It is impossible to enable %s" % targets.requires_all_simple_args.label,
172    )
173
174def _tool_missing_requirements_invalid_test(env, targets):
175    _expect_that_toolchain(
176        env,
177        action_type_configs = [targets.requires_all_simple_action_type_config],
178        features = [targets.simple_feature, targets.simple_feature2],
179        expr = "has_both",
180    ).ok()
181    _expect_that_toolchain(
182        env,
183        action_type_configs = [targets.requires_all_simple_action_type_config],
184        features = [targets.simple_feature],
185        expr = "has_only_one",
186    ).err().contains(
187        "It is impossible to enable %s" % targets.requires_all_simple_tool.label,
188    )
189
190def _toolchain_collects_files_test(env, targets):
191    tc = env.expect.that_target(
192        targets.collects_files_toolchain_config,
193    ).provider(ToolchainConfigInfo)
194    tc.files().get(targets.c_compile[ActionTypeInfo]).contains_exactly(_COLLECTED_C_COMPILE_FILES)
195    tc.files().get(targets.cpp_compile[ActionTypeInfo]).contains_exactly(_COLLECTED_CPP_COMPILE_FILES)
196
197    env.expect.that_target(
198        targets.collects_files_c_compile,
199    ).default_outputs().contains_exactly(_COLLECTED_C_COMPILE_FILES)
200    env.expect.that_target(
201        targets.collects_files_cpp_compile,
202    ).default_outputs().contains_exactly(_COLLECTED_CPP_COMPILE_FILES)
203
204    legacy = convert_toolchain(tc.actual)
205    env.expect.that_collection(legacy.features).contains_exactly([
206        legacy_feature(
207            name = "compile_feature",
208            enabled = True,
209            flag_sets = [legacy_flag_set(
210                actions = ["c_compile", "cpp_compile"],
211                flag_groups = [
212                    legacy_flag_group(flags = ["compile_args"]),
213                ],
214            )],
215        ),
216        legacy_feature(
217            name = "implied_by_always_enabled",
218            enabled = True,
219            flag_sets = [legacy_flag_set(
220                actions = ["c_compile"],
221                flag_groups = [
222                    legacy_flag_group(flags = ["c_compile_args"]),
223                ],
224            )],
225        ),
226        legacy_feature(
227            name = "implied_by_cpp_compile",
228            enabled = False,
229            flag_sets = [legacy_flag_set(
230                actions = ["cpp_compile"],
231                flag_groups = [
232                    legacy_flag_group(flags = ["cpp_compile_args"]),
233                ],
234            )],
235            env_sets = [legacy_env_set(
236                actions = ["cpp_compile"],
237                env_entries = [legacy_env_entry(key = "CPP_COMPILE", value = "1")],
238            )],
239        ),
240    ]).in_order()
241
242    exe = tc.action_type_configs().get(
243        targets.c_compile[ActionTypeInfo],
244    ).actual.tools[0].exe
245    env.expect.that_collection(legacy.action_configs).contains_exactly([
246        legacy_action_config(
247            action_name = "c_compile",
248            enabled = True,
249            tools = [legacy_tool(tool = exe)],
250        ),
251        legacy_action_config(
252            action_name = "cpp_compile",
253            enabled = True,
254            tools = [legacy_tool(tool = exe)],
255            implies = ["implied_by_cpp_compile"],
256        ),
257    ]).in_order()
258
259TARGETS = [
260    "//tests/rule_based_toolchain/actions:c_compile",
261    "//tests/rule_based_toolchain/actions:cpp_compile",
262    ":builtin_feature",
263    ":compile_config",
264    ":collects_files_c_compile",
265    ":collects_files_cpp_compile",
266    ":collects_files_toolchain_config",
267    ":compile_feature",
268    ":c_compile_args",
269    ":c_compile_config",
270    ":implies_simple_feature",
271    ":overrides_feature",
272    ":requires_any_simple_feature",
273    ":requires_all_simple_feature",
274    ":requires_all_simple_args",
275    ":requires_all_simple_action_type_config",
276    ":requires_all_simple_tool",
277    ":simple_feature",
278    ":simple_feature2",
279    ":same_feature_name",
280]
281
282# @unsorted-dict-items
283TESTS = {
284    "empty_toolchain_valid_test": _empty_toolchain_valid_test,
285    "duplicate_feature_names_fail_validation_test": _duplicate_feature_names_invalid_test,
286    "duplicate_action_type_invalid_test": _duplicate_action_type_invalid_test,
287    "action_config_implies_missing_feature_invalid_test": _action_config_implies_missing_feature_invalid_test,
288    "feature_config_implies_missing_feature_invalid_test": _feature_config_implies_missing_feature_invalid_test,
289    "feature_missing_requirements_invalid_test": _feature_missing_requirements_invalid_test,
290    "args_missing_requirements_invalid_test": _args_missing_requirements_invalid_test,
291    "tool_missing_requirements_invalid_test": _tool_missing_requirements_invalid_test,
292    "toolchain_collects_files_test": _toolchain_collects_files_test,
293}
294