xref: /aosp_15_r20/external/bazelbuild-rules_python/tests/python/python_tests.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1*60517a1eSAndroid Build Coastguard Worker# Copyright 2024 The Bazel Authors. All rights reserved.
2*60517a1eSAndroid Build Coastguard Worker#
3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*60517a1eSAndroid Build Coastguard Worker#
7*60517a1eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*60517a1eSAndroid Build Coastguard Worker#
9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*60517a1eSAndroid Build Coastguard Worker# limitations under the License.
14*60517a1eSAndroid Build Coastguard Worker
15*60517a1eSAndroid Build Coastguard Worker""
16*60517a1eSAndroid Build Coastguard Worker
17*60517a1eSAndroid Build Coastguard Workerload("@rules_testing//lib:test_suite.bzl", "test_suite")
18*60517a1eSAndroid Build Coastguard Workerload("//python:versions.bzl", "MINOR_MAPPING")
19*60517a1eSAndroid Build Coastguard Workerload("//python/private:python.bzl", "parse_modules")  # buildifier: disable=bzl-visibility
20*60517a1eSAndroid Build Coastguard Worker
21*60517a1eSAndroid Build Coastguard Worker_tests = []
22*60517a1eSAndroid Build Coastguard Worker
23*60517a1eSAndroid Build Coastguard Workerdef _mock_mctx(*modules, environ = {}):
24*60517a1eSAndroid Build Coastguard Worker    return struct(
25*60517a1eSAndroid Build Coastguard Worker        os = struct(environ = environ),
26*60517a1eSAndroid Build Coastguard Worker        modules = [
27*60517a1eSAndroid Build Coastguard Worker            struct(
28*60517a1eSAndroid Build Coastguard Worker                name = modules[0].name,
29*60517a1eSAndroid Build Coastguard Worker                tags = modules[0].tags,
30*60517a1eSAndroid Build Coastguard Worker                is_root = modules[0].is_root,
31*60517a1eSAndroid Build Coastguard Worker            ),
32*60517a1eSAndroid Build Coastguard Worker        ] + [
33*60517a1eSAndroid Build Coastguard Worker            struct(
34*60517a1eSAndroid Build Coastguard Worker                name = mod.name,
35*60517a1eSAndroid Build Coastguard Worker                tags = mod.tags,
36*60517a1eSAndroid Build Coastguard Worker                is_root = False,
37*60517a1eSAndroid Build Coastguard Worker            )
38*60517a1eSAndroid Build Coastguard Worker            for mod in modules[1:]
39*60517a1eSAndroid Build Coastguard Worker        ],
40*60517a1eSAndroid Build Coastguard Worker    )
41*60517a1eSAndroid Build Coastguard Worker
42*60517a1eSAndroid Build Coastguard Workerdef _mod(*, name, toolchain = [], override = [], single_version_override = [], single_version_platform_override = [], is_root = True):
43*60517a1eSAndroid Build Coastguard Worker    return struct(
44*60517a1eSAndroid Build Coastguard Worker        name = name,
45*60517a1eSAndroid Build Coastguard Worker        tags = struct(
46*60517a1eSAndroid Build Coastguard Worker            toolchain = toolchain,
47*60517a1eSAndroid Build Coastguard Worker            override = override,
48*60517a1eSAndroid Build Coastguard Worker            single_version_override = single_version_override,
49*60517a1eSAndroid Build Coastguard Worker            single_version_platform_override = single_version_platform_override,
50*60517a1eSAndroid Build Coastguard Worker        ),
51*60517a1eSAndroid Build Coastguard Worker        is_root = is_root,
52*60517a1eSAndroid Build Coastguard Worker    )
53*60517a1eSAndroid Build Coastguard Worker
54*60517a1eSAndroid Build Coastguard Workerdef _toolchain(python_version, *, is_default = False, **kwargs):
55*60517a1eSAndroid Build Coastguard Worker    return struct(
56*60517a1eSAndroid Build Coastguard Worker        is_default = is_default,
57*60517a1eSAndroid Build Coastguard Worker        python_version = python_version,
58*60517a1eSAndroid Build Coastguard Worker        **kwargs
59*60517a1eSAndroid Build Coastguard Worker    )
60*60517a1eSAndroid Build Coastguard Worker
61*60517a1eSAndroid Build Coastguard Workerdef _override(
62*60517a1eSAndroid Build Coastguard Worker        auth_patterns = {},
63*60517a1eSAndroid Build Coastguard Worker        available_python_versions = [],
64*60517a1eSAndroid Build Coastguard Worker        base_url = "",
65*60517a1eSAndroid Build Coastguard Worker        ignore_root_user_error = False,
66*60517a1eSAndroid Build Coastguard Worker        minor_mapping = {},
67*60517a1eSAndroid Build Coastguard Worker        netrc = "",
68*60517a1eSAndroid Build Coastguard Worker        register_all_versions = False):
69*60517a1eSAndroid Build Coastguard Worker    return struct(
70*60517a1eSAndroid Build Coastguard Worker        auth_patterns = auth_patterns,
71*60517a1eSAndroid Build Coastguard Worker        available_python_versions = available_python_versions,
72*60517a1eSAndroid Build Coastguard Worker        base_url = base_url,
73*60517a1eSAndroid Build Coastguard Worker        ignore_root_user_error = ignore_root_user_error,
74*60517a1eSAndroid Build Coastguard Worker        minor_mapping = minor_mapping,
75*60517a1eSAndroid Build Coastguard Worker        netrc = netrc,
76*60517a1eSAndroid Build Coastguard Worker        register_all_versions = register_all_versions,
77*60517a1eSAndroid Build Coastguard Worker    )
78*60517a1eSAndroid Build Coastguard Worker
79*60517a1eSAndroid Build Coastguard Workerdef _single_version_override(
80*60517a1eSAndroid Build Coastguard Worker        python_version = "",
81*60517a1eSAndroid Build Coastguard Worker        sha256 = {},
82*60517a1eSAndroid Build Coastguard Worker        urls = [],
83*60517a1eSAndroid Build Coastguard Worker        patch_strip = 0,
84*60517a1eSAndroid Build Coastguard Worker        patches = [],
85*60517a1eSAndroid Build Coastguard Worker        strip_prefix = "python",
86*60517a1eSAndroid Build Coastguard Worker        distutils_content = "",
87*60517a1eSAndroid Build Coastguard Worker        distutils = None):
88*60517a1eSAndroid Build Coastguard Worker    if not python_version:
89*60517a1eSAndroid Build Coastguard Worker        fail("missing mandatory args: python_version ({})".format(python_version))
90*60517a1eSAndroid Build Coastguard Worker
91*60517a1eSAndroid Build Coastguard Worker    return struct(
92*60517a1eSAndroid Build Coastguard Worker        python_version = python_version,
93*60517a1eSAndroid Build Coastguard Worker        sha256 = sha256,
94*60517a1eSAndroid Build Coastguard Worker        urls = urls,
95*60517a1eSAndroid Build Coastguard Worker        patch_strip = patch_strip,
96*60517a1eSAndroid Build Coastguard Worker        patches = patches,
97*60517a1eSAndroid Build Coastguard Worker        strip_prefix = strip_prefix,
98*60517a1eSAndroid Build Coastguard Worker        distutils_content = distutils_content,
99*60517a1eSAndroid Build Coastguard Worker        distutils = distutils,
100*60517a1eSAndroid Build Coastguard Worker    )
101*60517a1eSAndroid Build Coastguard Worker
102*60517a1eSAndroid Build Coastguard Workerdef _single_version_platform_override(
103*60517a1eSAndroid Build Coastguard Worker        coverage_tool = None,
104*60517a1eSAndroid Build Coastguard Worker        patch_strip = 0,
105*60517a1eSAndroid Build Coastguard Worker        patches = [],
106*60517a1eSAndroid Build Coastguard Worker        platform = "",
107*60517a1eSAndroid Build Coastguard Worker        python_version = "",
108*60517a1eSAndroid Build Coastguard Worker        sha256 = "",
109*60517a1eSAndroid Build Coastguard Worker        strip_prefix = "python",
110*60517a1eSAndroid Build Coastguard Worker        urls = []):
111*60517a1eSAndroid Build Coastguard Worker    if not platform or not python_version:
112*60517a1eSAndroid Build Coastguard Worker        fail("missing mandatory args: platform ({}) and python_version ({})".format(platform, python_version))
113*60517a1eSAndroid Build Coastguard Worker
114*60517a1eSAndroid Build Coastguard Worker    return struct(
115*60517a1eSAndroid Build Coastguard Worker        sha256 = sha256,
116*60517a1eSAndroid Build Coastguard Worker        urls = urls,
117*60517a1eSAndroid Build Coastguard Worker        strip_prefix = strip_prefix,
118*60517a1eSAndroid Build Coastguard Worker        platform = platform,
119*60517a1eSAndroid Build Coastguard Worker        coverage_tool = coverage_tool,
120*60517a1eSAndroid Build Coastguard Worker        python_version = python_version,
121*60517a1eSAndroid Build Coastguard Worker        patch_strip = patch_strip,
122*60517a1eSAndroid Build Coastguard Worker        patches = patches,
123*60517a1eSAndroid Build Coastguard Worker    )
124*60517a1eSAndroid Build Coastguard Worker
125*60517a1eSAndroid Build Coastguard Workerdef _test_default(env):
126*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
127*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
128*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")]),
129*60517a1eSAndroid Build Coastguard Worker        ),
130*60517a1eSAndroid Build Coastguard Worker    )
131*60517a1eSAndroid Build Coastguard Worker
132*60517a1eSAndroid Build Coastguard Worker    # The value there should be consistent in bzlmod with the automatically
133*60517a1eSAndroid Build Coastguard Worker    # calculated value Please update the MINOR_MAPPING in //python:versions.bzl
134*60517a1eSAndroid Build Coastguard Worker    # when this part starts failing.
135*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.minor_mapping).contains_exactly(MINOR_MAPPING)
136*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.config.kwargs).has_size(0)
137*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.config.default.keys()).contains_exactly([
138*60517a1eSAndroid Build Coastguard Worker        "base_url",
139*60517a1eSAndroid Build Coastguard Worker        "ignore_root_user_error",
140*60517a1eSAndroid Build Coastguard Worker        "tool_versions",
141*60517a1eSAndroid Build Coastguard Worker    ])
142*60517a1eSAndroid Build Coastguard Worker    env.expect.that_bool(py.config.default["ignore_root_user_error"]).equals(False)
143*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.11")
144*60517a1eSAndroid Build Coastguard Worker
145*60517a1eSAndroid Build Coastguard Worker    want_toolchain = struct(
146*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
147*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
148*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
149*60517a1eSAndroid Build Coastguard Worker    )
150*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([want_toolchain])
151*60517a1eSAndroid Build Coastguard Worker
152*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default)
153*60517a1eSAndroid Build Coastguard Worker
154*60517a1eSAndroid Build Coastguard Workerdef _test_default_some_module(env):
155*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
156*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
157*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")], is_root = False),
158*60517a1eSAndroid Build Coastguard Worker        ),
159*60517a1eSAndroid Build Coastguard Worker    )
160*60517a1eSAndroid Build Coastguard Worker
161*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.11")
162*60517a1eSAndroid Build Coastguard Worker
163*60517a1eSAndroid Build Coastguard Worker    want_toolchain = struct(
164*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
165*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
166*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
167*60517a1eSAndroid Build Coastguard Worker    )
168*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([want_toolchain])
169*60517a1eSAndroid Build Coastguard Worker
170*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default_some_module)
171*60517a1eSAndroid Build Coastguard Worker
172*60517a1eSAndroid Build Coastguard Workerdef _test_default_with_patch_version(env):
173*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
174*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
175*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11.2")]),
176*60517a1eSAndroid Build Coastguard Worker        ),
177*60517a1eSAndroid Build Coastguard Worker    )
178*60517a1eSAndroid Build Coastguard Worker
179*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.11.2")
180*60517a1eSAndroid Build Coastguard Worker
181*60517a1eSAndroid Build Coastguard Worker    want_toolchain = struct(
182*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11_2",
183*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11.2",
184*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
185*60517a1eSAndroid Build Coastguard Worker    )
186*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([want_toolchain])
187*60517a1eSAndroid Build Coastguard Worker
188*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default_with_patch_version)
189*60517a1eSAndroid Build Coastguard Worker
190*60517a1eSAndroid Build Coastguard Workerdef _test_default_non_rules_python(env):
191*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
192*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
193*60517a1eSAndroid Build Coastguard Worker            # NOTE @aignas 2024-09-06: the first item in the module_ctx.modules
194*60517a1eSAndroid Build Coastguard Worker            # could be a non-root module, which is the case if the root module
195*60517a1eSAndroid Build Coastguard Worker            # does not make any calls to the extension.
196*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")], is_root = False),
197*60517a1eSAndroid Build Coastguard Worker        ),
198*60517a1eSAndroid Build Coastguard Worker    )
199*60517a1eSAndroid Build Coastguard Worker
200*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.11")
201*60517a1eSAndroid Build Coastguard Worker    rules_python_toolchain = struct(
202*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
203*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
204*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
205*60517a1eSAndroid Build Coastguard Worker    )
206*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([rules_python_toolchain])
207*60517a1eSAndroid Build Coastguard Worker
208*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default_non_rules_python)
209*60517a1eSAndroid Build Coastguard Worker
210*60517a1eSAndroid Build Coastguard Workerdef _test_default_non_rules_python_ignore_root_user_error(env):
211*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
212*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
213*60517a1eSAndroid Build Coastguard Worker            _mod(
214*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
215*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.12", ignore_root_user_error = True)],
216*60517a1eSAndroid Build Coastguard Worker            ),
217*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")]),
218*60517a1eSAndroid Build Coastguard Worker        ),
219*60517a1eSAndroid Build Coastguard Worker    )
220*60517a1eSAndroid Build Coastguard Worker
221*60517a1eSAndroid Build Coastguard Worker    env.expect.that_bool(py.config.default["ignore_root_user_error"]).equals(True)
222*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.12")
223*60517a1eSAndroid Build Coastguard Worker
224*60517a1eSAndroid Build Coastguard Worker    my_module_toolchain = struct(
225*60517a1eSAndroid Build Coastguard Worker        name = "python_3_12",
226*60517a1eSAndroid Build Coastguard Worker        python_version = "3.12",
227*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
228*60517a1eSAndroid Build Coastguard Worker    )
229*60517a1eSAndroid Build Coastguard Worker    rules_python_toolchain = struct(
230*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
231*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
232*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
233*60517a1eSAndroid Build Coastguard Worker    )
234*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
235*60517a1eSAndroid Build Coastguard Worker        rules_python_toolchain,
236*60517a1eSAndroid Build Coastguard Worker        my_module_toolchain,
237*60517a1eSAndroid Build Coastguard Worker    ]).in_order()
238*60517a1eSAndroid Build Coastguard Worker
239*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default_non_rules_python_ignore_root_user_error)
240*60517a1eSAndroid Build Coastguard Worker
241*60517a1eSAndroid Build Coastguard Workerdef _test_default_non_rules_python_ignore_root_user_error_override(env):
242*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
243*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
244*60517a1eSAndroid Build Coastguard Worker            _mod(
245*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
246*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.12")],
247*60517a1eSAndroid Build Coastguard Worker                override = [_override(ignore_root_user_error = True)],
248*60517a1eSAndroid Build Coastguard Worker            ),
249*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")]),
250*60517a1eSAndroid Build Coastguard Worker        ),
251*60517a1eSAndroid Build Coastguard Worker    )
252*60517a1eSAndroid Build Coastguard Worker
253*60517a1eSAndroid Build Coastguard Worker    env.expect.that_bool(py.config.default["ignore_root_user_error"]).equals(True)
254*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.12")
255*60517a1eSAndroid Build Coastguard Worker
256*60517a1eSAndroid Build Coastguard Worker    my_module_toolchain = struct(
257*60517a1eSAndroid Build Coastguard Worker        name = "python_3_12",
258*60517a1eSAndroid Build Coastguard Worker        python_version = "3.12",
259*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
260*60517a1eSAndroid Build Coastguard Worker    )
261*60517a1eSAndroid Build Coastguard Worker    rules_python_toolchain = struct(
262*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
263*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
264*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
265*60517a1eSAndroid Build Coastguard Worker    )
266*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
267*60517a1eSAndroid Build Coastguard Worker        rules_python_toolchain,
268*60517a1eSAndroid Build Coastguard Worker        my_module_toolchain,
269*60517a1eSAndroid Build Coastguard Worker    ]).in_order()
270*60517a1eSAndroid Build Coastguard Worker
271*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default_non_rules_python_ignore_root_user_error_override)
272*60517a1eSAndroid Build Coastguard Worker
273*60517a1eSAndroid Build Coastguard Workerdef _test_default_non_rules_python_ignore_root_user_error_non_root_module(env):
274*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
275*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
276*60517a1eSAndroid Build Coastguard Worker            _mod(name = "my_module", toolchain = [_toolchain("3.13")]),
277*60517a1eSAndroid Build Coastguard Worker            _mod(name = "some_module", toolchain = [_toolchain("3.12", ignore_root_user_error = True)]),
278*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")]),
279*60517a1eSAndroid Build Coastguard Worker        ),
280*60517a1eSAndroid Build Coastguard Worker    )
281*60517a1eSAndroid Build Coastguard Worker
282*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.13")
283*60517a1eSAndroid Build Coastguard Worker    env.expect.that_bool(py.config.default["ignore_root_user_error"]).equals(False)
284*60517a1eSAndroid Build Coastguard Worker
285*60517a1eSAndroid Build Coastguard Worker    my_module_toolchain = struct(
286*60517a1eSAndroid Build Coastguard Worker        name = "python_3_13",
287*60517a1eSAndroid Build Coastguard Worker        python_version = "3.13",
288*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
289*60517a1eSAndroid Build Coastguard Worker    )
290*60517a1eSAndroid Build Coastguard Worker    some_module_toolchain = struct(
291*60517a1eSAndroid Build Coastguard Worker        name = "python_3_12",
292*60517a1eSAndroid Build Coastguard Worker        python_version = "3.12",
293*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
294*60517a1eSAndroid Build Coastguard Worker    )
295*60517a1eSAndroid Build Coastguard Worker    rules_python_toolchain = struct(
296*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
297*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
298*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
299*60517a1eSAndroid Build Coastguard Worker    )
300*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
301*60517a1eSAndroid Build Coastguard Worker        some_module_toolchain,
302*60517a1eSAndroid Build Coastguard Worker        rules_python_toolchain,
303*60517a1eSAndroid Build Coastguard Worker        my_module_toolchain,  # this was the only toolchain, default to that
304*60517a1eSAndroid Build Coastguard Worker    ]).in_order()
305*60517a1eSAndroid Build Coastguard Worker
306*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_default_non_rules_python_ignore_root_user_error_non_root_module)
307*60517a1eSAndroid Build Coastguard Worker
308*60517a1eSAndroid Build Coastguard Workerdef _test_first_occurance_of_the_toolchain_wins(env):
309*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
310*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
311*60517a1eSAndroid Build Coastguard Worker            _mod(name = "my_module", toolchain = [_toolchain("3.12")]),
312*60517a1eSAndroid Build Coastguard Worker            _mod(name = "some_module", toolchain = [_toolchain("3.12", configure_coverage_tool = True)]),
313*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")]),
314*60517a1eSAndroid Build Coastguard Worker            environ = {
315*60517a1eSAndroid Build Coastguard Worker                "RULES_PYTHON_BZLMOD_DEBUG": "1",
316*60517a1eSAndroid Build Coastguard Worker            },
317*60517a1eSAndroid Build Coastguard Worker        ),
318*60517a1eSAndroid Build Coastguard Worker    )
319*60517a1eSAndroid Build Coastguard Worker
320*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.12")
321*60517a1eSAndroid Build Coastguard Worker
322*60517a1eSAndroid Build Coastguard Worker    my_module_toolchain = struct(
323*60517a1eSAndroid Build Coastguard Worker        name = "python_3_12",
324*60517a1eSAndroid Build Coastguard Worker        python_version = "3.12",
325*60517a1eSAndroid Build Coastguard Worker        # NOTE: coverage stays disabled even though `some_module` was
326*60517a1eSAndroid Build Coastguard Worker        # configuring something else.
327*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
328*60517a1eSAndroid Build Coastguard Worker    )
329*60517a1eSAndroid Build Coastguard Worker    rules_python_toolchain = struct(
330*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
331*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
332*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
333*60517a1eSAndroid Build Coastguard Worker    )
334*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
335*60517a1eSAndroid Build Coastguard Worker        rules_python_toolchain,
336*60517a1eSAndroid Build Coastguard Worker        my_module_toolchain,  # default toolchain is last
337*60517a1eSAndroid Build Coastguard Worker    ]).in_order()
338*60517a1eSAndroid Build Coastguard Worker
339*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.debug_info).contains_exactly({
340*60517a1eSAndroid Build Coastguard Worker        "toolchains_registered": [
341*60517a1eSAndroid Build Coastguard Worker            {"ignore_root_user_error": False, "module": {"is_root": True, "name": "my_module"}, "name": "python_3_12"},
342*60517a1eSAndroid Build Coastguard Worker            {"ignore_root_user_error": False, "module": {"is_root": False, "name": "rules_python"}, "name": "python_3_11"},
343*60517a1eSAndroid Build Coastguard Worker        ],
344*60517a1eSAndroid Build Coastguard Worker    })
345*60517a1eSAndroid Build Coastguard Worker
346*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_first_occurance_of_the_toolchain_wins)
347*60517a1eSAndroid Build Coastguard Worker
348*60517a1eSAndroid Build Coastguard Workerdef _test_auth_overrides(env):
349*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
350*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
351*60517a1eSAndroid Build Coastguard Worker            _mod(
352*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
353*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.12")],
354*60517a1eSAndroid Build Coastguard Worker                override = [
355*60517a1eSAndroid Build Coastguard Worker                    _override(
356*60517a1eSAndroid Build Coastguard Worker                        netrc = "/my/netrc",
357*60517a1eSAndroid Build Coastguard Worker                        auth_patterns = {"foo": "bar"},
358*60517a1eSAndroid Build Coastguard Worker                    ),
359*60517a1eSAndroid Build Coastguard Worker                ],
360*60517a1eSAndroid Build Coastguard Worker            ),
361*60517a1eSAndroid Build Coastguard Worker            _mod(name = "rules_python", toolchain = [_toolchain("3.11")]),
362*60517a1eSAndroid Build Coastguard Worker        ),
363*60517a1eSAndroid Build Coastguard Worker    )
364*60517a1eSAndroid Build Coastguard Worker
365*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.default).contains_at_least({
366*60517a1eSAndroid Build Coastguard Worker        "auth_patterns": {"foo": "bar"},
367*60517a1eSAndroid Build Coastguard Worker        "ignore_root_user_error": False,
368*60517a1eSAndroid Build Coastguard Worker        "netrc": "/my/netrc",
369*60517a1eSAndroid Build Coastguard Worker    })
370*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.12")
371*60517a1eSAndroid Build Coastguard Worker
372*60517a1eSAndroid Build Coastguard Worker    my_module_toolchain = struct(
373*60517a1eSAndroid Build Coastguard Worker        name = "python_3_12",
374*60517a1eSAndroid Build Coastguard Worker        python_version = "3.12",
375*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
376*60517a1eSAndroid Build Coastguard Worker    )
377*60517a1eSAndroid Build Coastguard Worker    rules_python_toolchain = struct(
378*60517a1eSAndroid Build Coastguard Worker        name = "python_3_11",
379*60517a1eSAndroid Build Coastguard Worker        python_version = "3.11",
380*60517a1eSAndroid Build Coastguard Worker        register_coverage_tool = False,
381*60517a1eSAndroid Build Coastguard Worker    )
382*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
383*60517a1eSAndroid Build Coastguard Worker        rules_python_toolchain,
384*60517a1eSAndroid Build Coastguard Worker        my_module_toolchain,
385*60517a1eSAndroid Build Coastguard Worker    ]).in_order()
386*60517a1eSAndroid Build Coastguard Worker
387*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_auth_overrides)
388*60517a1eSAndroid Build Coastguard Worker
389*60517a1eSAndroid Build Coastguard Workerdef _test_add_new_version(env):
390*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
391*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
392*60517a1eSAndroid Build Coastguard Worker            _mod(
393*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
394*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.13")],
395*60517a1eSAndroid Build Coastguard Worker                single_version_override = [
396*60517a1eSAndroid Build Coastguard Worker                    _single_version_override(
397*60517a1eSAndroid Build Coastguard Worker                        python_version = "3.13.0",
398*60517a1eSAndroid Build Coastguard Worker                        sha256 = {
399*60517a1eSAndroid Build Coastguard Worker                            "aarch64-unknown-linux-gnu": "deadbeef",
400*60517a1eSAndroid Build Coastguard Worker                        },
401*60517a1eSAndroid Build Coastguard Worker                        urls = ["example.org"],
402*60517a1eSAndroid Build Coastguard Worker                        patch_strip = 0,
403*60517a1eSAndroid Build Coastguard Worker                        patches = [],
404*60517a1eSAndroid Build Coastguard Worker                        strip_prefix = "prefix",
405*60517a1eSAndroid Build Coastguard Worker                        distutils_content = "",
406*60517a1eSAndroid Build Coastguard Worker                        distutils = None,
407*60517a1eSAndroid Build Coastguard Worker                    ),
408*60517a1eSAndroid Build Coastguard Worker                ],
409*60517a1eSAndroid Build Coastguard Worker                single_version_platform_override = [
410*60517a1eSAndroid Build Coastguard Worker                    _single_version_platform_override(
411*60517a1eSAndroid Build Coastguard Worker                        sha256 = "deadb00f",
412*60517a1eSAndroid Build Coastguard Worker                        urls = ["something.org", "else.org"],
413*60517a1eSAndroid Build Coastguard Worker                        strip_prefix = "python",
414*60517a1eSAndroid Build Coastguard Worker                        platform = "aarch64-unknown-linux-gnu",
415*60517a1eSAndroid Build Coastguard Worker                        coverage_tool = "specific_cov_tool",
416*60517a1eSAndroid Build Coastguard Worker                        python_version = "3.13.1",
417*60517a1eSAndroid Build Coastguard Worker                        patch_strip = 2,
418*60517a1eSAndroid Build Coastguard Worker                        patches = ["specific-patch.txt"],
419*60517a1eSAndroid Build Coastguard Worker                    ),
420*60517a1eSAndroid Build Coastguard Worker                ],
421*60517a1eSAndroid Build Coastguard Worker                override = [
422*60517a1eSAndroid Build Coastguard Worker                    _override(
423*60517a1eSAndroid Build Coastguard Worker                        base_url = "",
424*60517a1eSAndroid Build Coastguard Worker                        available_python_versions = ["3.12.4", "3.13.0", "3.13.1"],
425*60517a1eSAndroid Build Coastguard Worker                        minor_mapping = {
426*60517a1eSAndroid Build Coastguard Worker                            "3.13": "3.13.0",
427*60517a1eSAndroid Build Coastguard Worker                        },
428*60517a1eSAndroid Build Coastguard Worker                    ),
429*60517a1eSAndroid Build Coastguard Worker                ],
430*60517a1eSAndroid Build Coastguard Worker            ),
431*60517a1eSAndroid Build Coastguard Worker        ),
432*60517a1eSAndroid Build Coastguard Worker    )
433*60517a1eSAndroid Build Coastguard Worker
434*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.13")
435*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.config.default["tool_versions"].keys()).contains_exactly([
436*60517a1eSAndroid Build Coastguard Worker        "3.12.4",
437*60517a1eSAndroid Build Coastguard Worker        "3.13.0",
438*60517a1eSAndroid Build Coastguard Worker        "3.13.1",
439*60517a1eSAndroid Build Coastguard Worker    ])
440*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.default["tool_versions"]["3.13.0"]).contains_exactly({
441*60517a1eSAndroid Build Coastguard Worker        "sha256": {"aarch64-unknown-linux-gnu": "deadbeef"},
442*60517a1eSAndroid Build Coastguard Worker        "strip_prefix": {"aarch64-unknown-linux-gnu": "prefix"},
443*60517a1eSAndroid Build Coastguard Worker        "url": {"aarch64-unknown-linux-gnu": ["example.org"]},
444*60517a1eSAndroid Build Coastguard Worker    })
445*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.default["tool_versions"]["3.13.1"]).contains_exactly({
446*60517a1eSAndroid Build Coastguard Worker        "coverage_tool": {"aarch64-unknown-linux-gnu": "specific_cov_tool"},
447*60517a1eSAndroid Build Coastguard Worker        "patch_strip": {"aarch64-unknown-linux-gnu": 2},
448*60517a1eSAndroid Build Coastguard Worker        "patches": {"aarch64-unknown-linux-gnu": ["specific-patch.txt"]},
449*60517a1eSAndroid Build Coastguard Worker        "sha256": {"aarch64-unknown-linux-gnu": "deadb00f"},
450*60517a1eSAndroid Build Coastguard Worker        "strip_prefix": {"aarch64-unknown-linux-gnu": "python"},
451*60517a1eSAndroid Build Coastguard Worker        "url": {"aarch64-unknown-linux-gnu": ["something.org", "else.org"]},
452*60517a1eSAndroid Build Coastguard Worker    })
453*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.minor_mapping).contains_exactly({
454*60517a1eSAndroid Build Coastguard Worker        "3.13": "3.13.0",
455*60517a1eSAndroid Build Coastguard Worker    })
456*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
457*60517a1eSAndroid Build Coastguard Worker        struct(
458*60517a1eSAndroid Build Coastguard Worker            name = "python_3_13",
459*60517a1eSAndroid Build Coastguard Worker            python_version = "3.13",
460*60517a1eSAndroid Build Coastguard Worker            register_coverage_tool = False,
461*60517a1eSAndroid Build Coastguard Worker        ),
462*60517a1eSAndroid Build Coastguard Worker    ])
463*60517a1eSAndroid Build Coastguard Worker
464*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_add_new_version)
465*60517a1eSAndroid Build Coastguard Worker
466*60517a1eSAndroid Build Coastguard Workerdef _test_register_all_versions(env):
467*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
468*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
469*60517a1eSAndroid Build Coastguard Worker            _mod(
470*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
471*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.13")],
472*60517a1eSAndroid Build Coastguard Worker                single_version_override = [
473*60517a1eSAndroid Build Coastguard Worker                    _single_version_override(
474*60517a1eSAndroid Build Coastguard Worker                        python_version = "3.13.0",
475*60517a1eSAndroid Build Coastguard Worker                        sha256 = {
476*60517a1eSAndroid Build Coastguard Worker                            "aarch64-unknown-linux-gnu": "deadbeef",
477*60517a1eSAndroid Build Coastguard Worker                        },
478*60517a1eSAndroid Build Coastguard Worker                        urls = ["example.org"],
479*60517a1eSAndroid Build Coastguard Worker                    ),
480*60517a1eSAndroid Build Coastguard Worker                ],
481*60517a1eSAndroid Build Coastguard Worker                single_version_platform_override = [
482*60517a1eSAndroid Build Coastguard Worker                    _single_version_platform_override(
483*60517a1eSAndroid Build Coastguard Worker                        sha256 = "deadb00f",
484*60517a1eSAndroid Build Coastguard Worker                        urls = ["something.org"],
485*60517a1eSAndroid Build Coastguard Worker                        platform = "aarch64-unknown-linux-gnu",
486*60517a1eSAndroid Build Coastguard Worker                        python_version = "3.13.1",
487*60517a1eSAndroid Build Coastguard Worker                    ),
488*60517a1eSAndroid Build Coastguard Worker                ],
489*60517a1eSAndroid Build Coastguard Worker                override = [
490*60517a1eSAndroid Build Coastguard Worker                    _override(
491*60517a1eSAndroid Build Coastguard Worker                        base_url = "",
492*60517a1eSAndroid Build Coastguard Worker                        available_python_versions = ["3.12.4", "3.13.0", "3.13.1"],
493*60517a1eSAndroid Build Coastguard Worker                        register_all_versions = True,
494*60517a1eSAndroid Build Coastguard Worker                    ),
495*60517a1eSAndroid Build Coastguard Worker                ],
496*60517a1eSAndroid Build Coastguard Worker            ),
497*60517a1eSAndroid Build Coastguard Worker        ),
498*60517a1eSAndroid Build Coastguard Worker    )
499*60517a1eSAndroid Build Coastguard Worker
500*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.13")
501*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.config.default["tool_versions"].keys()).contains_exactly([
502*60517a1eSAndroid Build Coastguard Worker        "3.12.4",
503*60517a1eSAndroid Build Coastguard Worker        "3.13.0",
504*60517a1eSAndroid Build Coastguard Worker        "3.13.1",
505*60517a1eSAndroid Build Coastguard Worker    ])
506*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.minor_mapping).contains_exactly({
507*60517a1eSAndroid Build Coastguard Worker        # The mapping is calculated automatically
508*60517a1eSAndroid Build Coastguard Worker        "3.12": "3.12.4",
509*60517a1eSAndroid Build Coastguard Worker        "3.13": "3.13.1",
510*60517a1eSAndroid Build Coastguard Worker    })
511*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
512*60517a1eSAndroid Build Coastguard Worker        struct(
513*60517a1eSAndroid Build Coastguard Worker            name = name,
514*60517a1eSAndroid Build Coastguard Worker            python_version = version,
515*60517a1eSAndroid Build Coastguard Worker            register_coverage_tool = False,
516*60517a1eSAndroid Build Coastguard Worker        )
517*60517a1eSAndroid Build Coastguard Worker        for name, version in {
518*60517a1eSAndroid Build Coastguard Worker            "python_3_12": "3.12",
519*60517a1eSAndroid Build Coastguard Worker            "python_3_12_4": "3.12.4",
520*60517a1eSAndroid Build Coastguard Worker            "python_3_13": "3.13",
521*60517a1eSAndroid Build Coastguard Worker            "python_3_13_0": "3.13.0",
522*60517a1eSAndroid Build Coastguard Worker            "python_3_13_1": "3.13.1",
523*60517a1eSAndroid Build Coastguard Worker        }.items()
524*60517a1eSAndroid Build Coastguard Worker    ])
525*60517a1eSAndroid Build Coastguard Worker
526*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_register_all_versions)
527*60517a1eSAndroid Build Coastguard Worker
528*60517a1eSAndroid Build Coastguard Workerdef _test_add_patches(env):
529*60517a1eSAndroid Build Coastguard Worker    py = parse_modules(
530*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
531*60517a1eSAndroid Build Coastguard Worker            _mod(
532*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
533*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.13")],
534*60517a1eSAndroid Build Coastguard Worker                single_version_override = [
535*60517a1eSAndroid Build Coastguard Worker                    _single_version_override(
536*60517a1eSAndroid Build Coastguard Worker                        python_version = "3.13.0",
537*60517a1eSAndroid Build Coastguard Worker                        sha256 = {
538*60517a1eSAndroid Build Coastguard Worker                            "aarch64-apple-darwin": "deadbeef",
539*60517a1eSAndroid Build Coastguard Worker                            "aarch64-unknown-linux-gnu": "deadbeef",
540*60517a1eSAndroid Build Coastguard Worker                        },
541*60517a1eSAndroid Build Coastguard Worker                        urls = ["example.org"],
542*60517a1eSAndroid Build Coastguard Worker                        patch_strip = 1,
543*60517a1eSAndroid Build Coastguard Worker                        patches = ["common.txt"],
544*60517a1eSAndroid Build Coastguard Worker                        strip_prefix = "prefix",
545*60517a1eSAndroid Build Coastguard Worker                        distutils_content = "",
546*60517a1eSAndroid Build Coastguard Worker                        distutils = None,
547*60517a1eSAndroid Build Coastguard Worker                    ),
548*60517a1eSAndroid Build Coastguard Worker                ],
549*60517a1eSAndroid Build Coastguard Worker                single_version_platform_override = [
550*60517a1eSAndroid Build Coastguard Worker                    _single_version_platform_override(
551*60517a1eSAndroid Build Coastguard Worker                        sha256 = "deadb00f",
552*60517a1eSAndroid Build Coastguard Worker                        urls = ["something.org", "else.org"],
553*60517a1eSAndroid Build Coastguard Worker                        strip_prefix = "python",
554*60517a1eSAndroid Build Coastguard Worker                        platform = "aarch64-unknown-linux-gnu",
555*60517a1eSAndroid Build Coastguard Worker                        coverage_tool = "specific_cov_tool",
556*60517a1eSAndroid Build Coastguard Worker                        python_version = "3.13.0",
557*60517a1eSAndroid Build Coastguard Worker                        patch_strip = 2,
558*60517a1eSAndroid Build Coastguard Worker                        patches = ["specific-patch.txt"],
559*60517a1eSAndroid Build Coastguard Worker                    ),
560*60517a1eSAndroid Build Coastguard Worker                ],
561*60517a1eSAndroid Build Coastguard Worker                override = [
562*60517a1eSAndroid Build Coastguard Worker                    _override(
563*60517a1eSAndroid Build Coastguard Worker                        base_url = "",
564*60517a1eSAndroid Build Coastguard Worker                        available_python_versions = ["3.13.0"],
565*60517a1eSAndroid Build Coastguard Worker                        minor_mapping = {
566*60517a1eSAndroid Build Coastguard Worker                            "3.13": "3.13.0",
567*60517a1eSAndroid Build Coastguard Worker                        },
568*60517a1eSAndroid Build Coastguard Worker                    ),
569*60517a1eSAndroid Build Coastguard Worker                ],
570*60517a1eSAndroid Build Coastguard Worker            ),
571*60517a1eSAndroid Build Coastguard Worker        ),
572*60517a1eSAndroid Build Coastguard Worker    )
573*60517a1eSAndroid Build Coastguard Worker
574*60517a1eSAndroid Build Coastguard Worker    env.expect.that_str(py.default_python_version).equals("3.13")
575*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.default["tool_versions"]).contains_exactly({
576*60517a1eSAndroid Build Coastguard Worker        "3.13.0": {
577*60517a1eSAndroid Build Coastguard Worker            "coverage_tool": {"aarch64-unknown-linux-gnu": "specific_cov_tool"},
578*60517a1eSAndroid Build Coastguard Worker            "patch_strip": {"aarch64-apple-darwin": 1, "aarch64-unknown-linux-gnu": 2},
579*60517a1eSAndroid Build Coastguard Worker            "patches": {
580*60517a1eSAndroid Build Coastguard Worker                "aarch64-apple-darwin": ["common.txt"],
581*60517a1eSAndroid Build Coastguard Worker                "aarch64-unknown-linux-gnu": ["specific-patch.txt"],
582*60517a1eSAndroid Build Coastguard Worker            },
583*60517a1eSAndroid Build Coastguard Worker            "sha256": {"aarch64-apple-darwin": "deadbeef", "aarch64-unknown-linux-gnu": "deadb00f"},
584*60517a1eSAndroid Build Coastguard Worker            "strip_prefix": {"aarch64-apple-darwin": "prefix", "aarch64-unknown-linux-gnu": "python"},
585*60517a1eSAndroid Build Coastguard Worker            "url": {
586*60517a1eSAndroid Build Coastguard Worker                "aarch64-apple-darwin": ["example.org"],
587*60517a1eSAndroid Build Coastguard Worker                "aarch64-unknown-linux-gnu": ["something.org", "else.org"],
588*60517a1eSAndroid Build Coastguard Worker            },
589*60517a1eSAndroid Build Coastguard Worker        },
590*60517a1eSAndroid Build Coastguard Worker    })
591*60517a1eSAndroid Build Coastguard Worker    env.expect.that_dict(py.config.minor_mapping).contains_exactly({
592*60517a1eSAndroid Build Coastguard Worker        "3.13": "3.13.0",
593*60517a1eSAndroid Build Coastguard Worker    })
594*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(py.toolchains).contains_exactly([
595*60517a1eSAndroid Build Coastguard Worker        struct(
596*60517a1eSAndroid Build Coastguard Worker            name = "python_3_13",
597*60517a1eSAndroid Build Coastguard Worker            python_version = "3.13",
598*60517a1eSAndroid Build Coastguard Worker            register_coverage_tool = False,
599*60517a1eSAndroid Build Coastguard Worker        ),
600*60517a1eSAndroid Build Coastguard Worker    ])
601*60517a1eSAndroid Build Coastguard Worker
602*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_add_patches)
603*60517a1eSAndroid Build Coastguard Worker
604*60517a1eSAndroid Build Coastguard Workerdef _test_fail_two_overrides(env):
605*60517a1eSAndroid Build Coastguard Worker    errors = []
606*60517a1eSAndroid Build Coastguard Worker    parse_modules(
607*60517a1eSAndroid Build Coastguard Worker        module_ctx = _mock_mctx(
608*60517a1eSAndroid Build Coastguard Worker            _mod(
609*60517a1eSAndroid Build Coastguard Worker                name = "my_module",
610*60517a1eSAndroid Build Coastguard Worker                toolchain = [_toolchain("3.13")],
611*60517a1eSAndroid Build Coastguard Worker                override = [
612*60517a1eSAndroid Build Coastguard Worker                    _override(base_url = "foo"),
613*60517a1eSAndroid Build Coastguard Worker                    _override(base_url = "bar"),
614*60517a1eSAndroid Build Coastguard Worker                ],
615*60517a1eSAndroid Build Coastguard Worker            ),
616*60517a1eSAndroid Build Coastguard Worker        ),
617*60517a1eSAndroid Build Coastguard Worker        _fail = errors.append,
618*60517a1eSAndroid Build Coastguard Worker    )
619*60517a1eSAndroid Build Coastguard Worker    env.expect.that_collection(errors).contains_exactly([
620*60517a1eSAndroid Build Coastguard Worker        "Only a single 'python.override' can be present",
621*60517a1eSAndroid Build Coastguard Worker    ])
622*60517a1eSAndroid Build Coastguard Worker
623*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_fail_two_overrides)
624*60517a1eSAndroid Build Coastguard Worker
625*60517a1eSAndroid Build Coastguard Workerdef _test_single_version_override_errors(env):
626*60517a1eSAndroid Build Coastguard Worker    for test in [
627*60517a1eSAndroid Build Coastguard Worker        struct(
628*60517a1eSAndroid Build Coastguard Worker            overrides = [
629*60517a1eSAndroid Build Coastguard Worker                _single_version_override(python_version = "3.12.4", distutils_content = "foo"),
630*60517a1eSAndroid Build Coastguard Worker                _single_version_override(python_version = "3.12.4", distutils_content = "foo"),
631*60517a1eSAndroid Build Coastguard Worker            ],
632*60517a1eSAndroid Build Coastguard Worker            want_error = "Only a single 'python.single_version_override' can be present for '3.12.4'",
633*60517a1eSAndroid Build Coastguard Worker        ),
634*60517a1eSAndroid Build Coastguard Worker        struct(
635*60517a1eSAndroid Build Coastguard Worker            overrides = [
636*60517a1eSAndroid Build Coastguard Worker                _single_version_override(python_version = "3.12.4+3", distutils_content = "foo"),
637*60517a1eSAndroid Build Coastguard Worker            ],
638*60517a1eSAndroid Build Coastguard Worker            want_error = "The 'python_version' attribute needs to specify an 'X.Y.Z' semver-compatible version, got: '3.12.4+3'",
639*60517a1eSAndroid Build Coastguard Worker        ),
640*60517a1eSAndroid Build Coastguard Worker    ]:
641*60517a1eSAndroid Build Coastguard Worker        errors = []
642*60517a1eSAndroid Build Coastguard Worker        parse_modules(
643*60517a1eSAndroid Build Coastguard Worker            module_ctx = _mock_mctx(
644*60517a1eSAndroid Build Coastguard Worker                _mod(
645*60517a1eSAndroid Build Coastguard Worker                    name = "my_module",
646*60517a1eSAndroid Build Coastguard Worker                    toolchain = [_toolchain("3.13")],
647*60517a1eSAndroid Build Coastguard Worker                    single_version_override = test.overrides,
648*60517a1eSAndroid Build Coastguard Worker                ),
649*60517a1eSAndroid Build Coastguard Worker            ),
650*60517a1eSAndroid Build Coastguard Worker            _fail = errors.append,
651*60517a1eSAndroid Build Coastguard Worker        )
652*60517a1eSAndroid Build Coastguard Worker        env.expect.that_collection(errors).contains_exactly([test.want_error])
653*60517a1eSAndroid Build Coastguard Worker
654*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_single_version_override_errors)
655*60517a1eSAndroid Build Coastguard Worker
656*60517a1eSAndroid Build Coastguard Workerdef _test_single_version_platform_override_errors(env):
657*60517a1eSAndroid Build Coastguard Worker    for test in [
658*60517a1eSAndroid Build Coastguard Worker        struct(
659*60517a1eSAndroid Build Coastguard Worker            overrides = [
660*60517a1eSAndroid Build Coastguard Worker                _single_version_platform_override(python_version = "3.12.4", platform = "foo", coverage_tool = "foo"),
661*60517a1eSAndroid Build Coastguard Worker                _single_version_platform_override(python_version = "3.12.4", platform = "foo", coverage_tool = "foo"),
662*60517a1eSAndroid Build Coastguard Worker            ],
663*60517a1eSAndroid Build Coastguard Worker            want_error = "Only a single 'python.single_version_platform_override' can be present for '(\"3.12.4\", \"foo\")'",
664*60517a1eSAndroid Build Coastguard Worker        ),
665*60517a1eSAndroid Build Coastguard Worker        struct(
666*60517a1eSAndroid Build Coastguard Worker            overrides = [
667*60517a1eSAndroid Build Coastguard Worker                _single_version_platform_override(python_version = "3.12", platform = "foo"),
668*60517a1eSAndroid Build Coastguard Worker            ],
669*60517a1eSAndroid Build Coastguard Worker            want_error = "The 'python_version' attribute needs to specify an 'X.Y.Z' semver-compatible version, got: '3.12'",
670*60517a1eSAndroid Build Coastguard Worker        ),
671*60517a1eSAndroid Build Coastguard Worker        struct(
672*60517a1eSAndroid Build Coastguard Worker            overrides = [
673*60517a1eSAndroid Build Coastguard Worker                _single_version_platform_override(python_version = "3.12.1+my_build", platform = "foo"),
674*60517a1eSAndroid Build Coastguard Worker            ],
675*60517a1eSAndroid Build Coastguard Worker            want_error = "The 'python_version' attribute needs to specify an 'X.Y.Z' semver-compatible version, got: '3.12.1+my_build'",
676*60517a1eSAndroid Build Coastguard Worker        ),
677*60517a1eSAndroid Build Coastguard Worker    ]:
678*60517a1eSAndroid Build Coastguard Worker        errors = []
679*60517a1eSAndroid Build Coastguard Worker        parse_modules(
680*60517a1eSAndroid Build Coastguard Worker            module_ctx = _mock_mctx(
681*60517a1eSAndroid Build Coastguard Worker                _mod(
682*60517a1eSAndroid Build Coastguard Worker                    name = "my_module",
683*60517a1eSAndroid Build Coastguard Worker                    toolchain = [_toolchain("3.13")],
684*60517a1eSAndroid Build Coastguard Worker                    single_version_platform_override = test.overrides,
685*60517a1eSAndroid Build Coastguard Worker                ),
686*60517a1eSAndroid Build Coastguard Worker            ),
687*60517a1eSAndroid Build Coastguard Worker            _fail = errors.append,
688*60517a1eSAndroid Build Coastguard Worker        )
689*60517a1eSAndroid Build Coastguard Worker        env.expect.that_collection(errors).contains_exactly([test.want_error])
690*60517a1eSAndroid Build Coastguard Worker
691*60517a1eSAndroid Build Coastguard Worker_tests.append(_test_single_version_platform_override_errors)
692*60517a1eSAndroid Build Coastguard Worker
693*60517a1eSAndroid Build Coastguard Worker# TODO @aignas 2024-09-03: add failure tests:
694*60517a1eSAndroid Build Coastguard Worker# * incorrect platform failure
695*60517a1eSAndroid Build Coastguard Worker# * missing python_version failure
696*60517a1eSAndroid Build Coastguard Worker
697*60517a1eSAndroid Build Coastguard Workerdef python_test_suite(name):
698*60517a1eSAndroid Build Coastguard Worker    """Create the test suite.
699*60517a1eSAndroid Build Coastguard Worker
700*60517a1eSAndroid Build Coastguard Worker    Args:
701*60517a1eSAndroid Build Coastguard Worker        name: the name of the test suite
702*60517a1eSAndroid Build Coastguard Worker    """
703*60517a1eSAndroid Build Coastguard Worker    test_suite(name = name, basic_tests = _tests)
704