1# Copyright 2022 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 15"""This module contains the definition for the toolchains testing rules. 16""" 17 18load("//python:versions.bzl", "PLATFORMS", "TOOL_VERSIONS") 19 20_WINDOWS_RUNNER_TEMPLATE = """\ 21@ECHO OFF 22set PATHEXT=.COM;.EXE;.BAT 23powershell.exe -c "& ./{interpreter_path} {run_acceptance_test_py}" 24""" 25 26def _acceptance_test_impl(ctx): 27 workspace = ctx.actions.declare_file("/".join([ctx.attr.python_version, "WORKSPACE"])) 28 ctx.actions.expand_template( 29 template = ctx.file._workspace_tmpl, 30 output = workspace, 31 substitutions = {"%python_version%": ctx.attr.python_version}, 32 ) 33 34 build_bazel = ctx.actions.declare_file("/".join([ctx.attr.python_version, "BUILD.bazel"])) 35 ctx.actions.expand_template( 36 template = ctx.file._build_bazel_tmpl, 37 output = build_bazel, 38 substitutions = {"%python_version%": ctx.attr.python_version}, 39 ) 40 41 python_version_test = ctx.actions.declare_file("/".join([ctx.attr.python_version, "python_version_test.py"])) 42 ctx.actions.symlink( 43 target_file = ctx.file._python_version_test, 44 output = python_version_test, 45 ) 46 47 run_acceptance_test_py = ctx.actions.declare_file("/".join([ctx.attr.python_version, "run_acceptance_test.py"])) 48 ctx.actions.expand_template( 49 template = ctx.file._run_acceptance_test_tmpl, 50 output = run_acceptance_test_py, 51 substitutions = { 52 "%is_windows%": str(ctx.attr.is_windows), 53 "%python_version%": ctx.attr.python_version, 54 "%test_location%": "/".join([ctx.attr.test_location, ctx.attr.python_version]), 55 }, 56 ) 57 58 toolchain = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"] 59 py3_runtime = toolchain.py3_runtime 60 interpreter_path = py3_runtime.interpreter_path 61 if not interpreter_path: 62 interpreter_path = py3_runtime.interpreter.short_path 63 64 if ctx.attr.is_windows: 65 executable = ctx.actions.declare_file("run_test_{}.bat".format(ctx.attr.python_version)) 66 ctx.actions.write( 67 output = executable, 68 content = _WINDOWS_RUNNER_TEMPLATE.format( 69 interpreter_path = interpreter_path.replace("../", "external/"), 70 run_acceptance_test_py = run_acceptance_test_py.short_path, 71 ), 72 is_executable = True, 73 ) 74 else: 75 executable = ctx.actions.declare_file("run_test_{}.sh".format(ctx.attr.python_version)) 76 ctx.actions.write( 77 output = executable, 78 content = "exec '{interpreter_path}' '{run_acceptance_test_py}'".format( 79 interpreter_path = interpreter_path, 80 run_acceptance_test_py = run_acceptance_test_py.short_path, 81 ), 82 is_executable = True, 83 ) 84 85 files = [ 86 build_bazel, 87 executable, 88 python_version_test, 89 run_acceptance_test_py, 90 workspace, 91 ] + ctx.files._distribution 92 return [DefaultInfo( 93 executable = executable, 94 files = depset( 95 direct = files, 96 transitive = [py3_runtime.files], 97 ), 98 runfiles = ctx.runfiles( 99 files = files, 100 transitive_files = py3_runtime.files, 101 ), 102 )] 103 104_acceptance_test = rule( 105 implementation = _acceptance_test_impl, 106 doc = "A rule for the toolchain acceptance tests.", 107 attrs = { 108 "is_windows": attr.bool( 109 doc = "(Provided by the macro) Whether this is running under Windows or not.", 110 mandatory = True, 111 ), 112 "python_version": attr.string( 113 doc = "The Python version to be used when requesting the toolchain.", 114 mandatory = True, 115 ), 116 "test_location": attr.string( 117 doc = "(Provided by the macro) The value of native.package_name().", 118 mandatory = True, 119 ), 120 "_build_bazel_tmpl": attr.label( 121 doc = "The BUILD.bazel template.", 122 allow_single_file = True, 123 default = Label("//python/tests/toolchains/workspace_template:BUILD.bazel.tmpl"), 124 ), 125 "_distribution": attr.label( 126 doc = "The rules_python source distribution.", 127 default = Label("//:distribution"), 128 ), 129 "_python_version_test": attr.label( 130 doc = "The python_version_test.py used to test the Python version.", 131 allow_single_file = True, 132 default = Label("//python/tests/toolchains/workspace_template:python_version_test.py"), 133 ), 134 "_run_acceptance_test_tmpl": attr.label( 135 doc = "The run_acceptance_test.py template.", 136 allow_single_file = True, 137 default = Label("//python/tests/toolchains:run_acceptance_test.py.tmpl"), 138 ), 139 "_workspace_tmpl": attr.label( 140 doc = "The WORKSPACE template.", 141 allow_single_file = True, 142 default = Label("//python/tests/toolchains/workspace_template:WORKSPACE.tmpl"), 143 ), 144 }, 145 test = True, 146 toolchains = ["@bazel_tools//tools/python:toolchain_type"], 147) 148 149def acceptance_test(python_version, **kwargs): 150 _acceptance_test( 151 is_windows = select({ 152 "@bazel_tools//src/conditions:host_windows": True, 153 "//conditions:default": False, 154 }), 155 python_version = python_version, 156 test_location = native.package_name(), 157 **kwargs 158 ) 159 160# buildifier: disable=unnamed-macro 161def acceptance_tests(): 162 """Creates a matrix of acceptance_test targets for all the toolchains. 163 """ 164 for python_version in TOOL_VERSIONS.keys(): 165 for platform, meta in PLATFORMS.items(): 166 if platform not in TOOL_VERSIONS[python_version]["sha256"]: 167 continue 168 acceptance_test( 169 name = "python_{python_version}_{platform}_test".format( 170 python_version = python_version.replace(".", "_"), 171 platform = platform, 172 ), 173 python_version = python_version, 174 target_compatible_with = meta.compatible_with, 175 tags = ["acceptance-test"], 176 ) 177