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