• 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_args rule."""
15
16load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo")
17load("//cc:cc_toolchain_config_lib.bzl", "flag_group", "variable_with_value")
18load(
19    "//cc/toolchains/impl:nested_args.bzl",
20    "FORMAT_ARGS_ERR",
21    "REQUIRES_EQUAL_ERR",
22    "REQUIRES_MUTUALLY_EXCLUSIVE_ERR",
23    "REQUIRES_NONE_ERR",
24    "format_args",
25    "nested_args_provider",
26)
27load("//tests/rule_based_toolchain:subjects.bzl", "result_fn_wrapper", "subjects")
28
29visibility("private")
30
31def _expect_that_nested(env, expr = None, **kwargs):
32    return env.expect.that_value(
33        expr = expr,
34        value = result_fn_wrapper(nested_args_provider)(
35            label = Label("//:args"),
36            **kwargs
37        ),
38        factory = subjects.result(subjects.NestedArgsInfo),
39    )
40
41def _expect_that_formatted(env, args, format, must_use = [], expr = None):
42    return env.expect.that_value(
43        result_fn_wrapper(format_args)(args, format, must_use = must_use),
44        factory = subjects.result(subjects.collection),
45        expr = expr or "format_args(%r, %r)" % (args, format),
46    )
47
48def _format_args_test(env, targets):
49    _expect_that_formatted(
50        env,
51        [
52            "a % b",
53            "a {{",
54            "}} b",
55            "a {{ b }}",
56        ],
57        {},
58    ).ok().contains_exactly([
59        "a %% b",
60        "a {",
61        "} b",
62        "a { b }",
63    ]).in_order()
64
65    _expect_that_formatted(
66        env,
67        ["{foo"],
68        {},
69    ).err().equals('Unmatched { in "{foo"')
70
71    _expect_that_formatted(
72        env,
73        ["foo}"],
74        {},
75    ).err().equals('Unexpected } in "foo}"')
76    _expect_that_formatted(
77        env,
78        ["{foo}"],
79        {},
80    ).err().contains('Unknown variable "foo" in format string "{foo}"')
81
82    _expect_that_formatted(
83        env,
84        [
85            "a {var}",
86            "b {directory}",
87            "c {file}",
88        ],
89        {
90            "directory": targets.directory,
91            "file": targets.bin_wrapper,
92            "var": targets.foo,
93        },
94    ).ok().contains_exactly([
95        "a %{foo}",
96        "b " + targets.directory[DirectoryInfo].path,
97        "c " + targets.bin_wrapper[DefaultInfo].files.to_list()[0].path,
98    ]).in_order()
99
100    _expect_that_formatted(
101        env,
102        ["{var}", "{var}"],
103        {"var": targets.foo},
104    ).ok().contains_exactly(["%{foo}", "%{foo}"])
105
106    _expect_that_formatted(
107        env,
108        [],
109        {"var": targets.foo},
110        must_use = ["var"],
111    ).err().contains('"var" was not used')
112
113    _expect_that_formatted(
114        env,
115        ["{var} {var}"],
116        {"var": targets.foo},
117    ).err().contains('"{var} {var}" contained multiple variables')
118
119    _expect_that_formatted(
120        env,
121        ["{foo} {bar}"],
122        {"bar": targets.foo, "foo": targets.foo},
123    ).err().contains('"{foo} {bar}" contained multiple variables')
124
125def _iterate_over_test(env, targets):
126    inner = _expect_that_nested(
127        env,
128        args = ["--foo"],
129    ).ok().actual
130    env.expect.that_str(inner.legacy_flag_group).equals(flag_group(flags = ["--foo"]))
131
132    nested = _expect_that_nested(
133        env,
134        nested = [inner],
135        iterate_over = targets.my_list,
136    ).ok()
137    nested.iterate_over().some().equals("my_list")
138    nested.legacy_flag_group().equals(flag_group(
139        iterate_over = "my_list",
140        flag_groups = [inner.legacy_flag_group],
141    ))
142    nested.requires_types().contains_exactly({})
143
144def _requires_types_test(env, targets):
145    _expect_that_nested(
146        env,
147        requires_not_none = "abc",
148        requires_none = "def",
149        args = ["--foo"],
150        expr = "mutually_exclusive",
151    ).err().equals(REQUIRES_MUTUALLY_EXCLUSIVE_ERR)
152
153    _expect_that_nested(
154        env,
155        requires_none = "var",
156        args = ["--foo"],
157        expr = "requires_none",
158    ).ok().requires_types().contains_exactly(
159        {"var": [struct(
160            msg = REQUIRES_NONE_ERR,
161            valid_types = ["option"],
162            after_option_unwrap = False,
163        )]},
164    )
165
166    _expect_that_nested(
167        env,
168        args = ["foo {foo} baz"],
169        format = {targets.foo: "foo"},
170        expr = "type_validation",
171    ).ok().requires_types().contains_exactly(
172        {"foo": [struct(
173            msg = FORMAT_ARGS_ERR,
174            valid_types = ["string", "file", "directory"],
175            after_option_unwrap = True,
176        )]},
177    )
178
179    nested = _expect_that_nested(
180        env,
181        requires_equal = "foo",
182        requires_equal_value = "value",
183        args = ["--foo={foo}"],
184        format = {targets.foo: "foo"},
185        expr = "type_and_requires_equal_validation",
186    ).ok()
187    nested.requires_types().contains_exactly(
188        {"foo": [
189            struct(
190                msg = REQUIRES_EQUAL_ERR,
191                valid_types = ["string"],
192                after_option_unwrap = True,
193            ),
194            struct(
195                msg = FORMAT_ARGS_ERR,
196                valid_types = ["string", "file", "directory"],
197                after_option_unwrap = True,
198            ),
199        ]},
200    )
201    nested.legacy_flag_group().equals(flag_group(
202        expand_if_equal = variable_with_value(name = "foo", value = "value"),
203        flags = ["--foo=%{foo}"],
204    ))
205
206TARGETS = [
207    ":foo",
208    ":my_list",
209    "//tests/rule_based_toolchain/testdata:directory",
210    "//tests/rule_based_toolchain/testdata:bin_wrapper",
211]
212
213TESTS = {
214    "format_args_test": _format_args_test,
215    "iterate_over_test": _iterate_over_test,
216    "requires_types_test": _requires_types_test,
217}
218