1# Copyright 2023 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"""Helpers and utilities multiple tests re-use.""" 15 16load("@bazel_skylib//lib:structs.bzl", "structs") 17 18# Use this with is_windows() 19WINDOWS_ATTR = {"windows": attr.label(default = "@platforms//os:windows")} 20 21def _create_tests(tests, **kwargs): 22 test_names = [] 23 for func in tests: 24 test_name = _test_name_from_function(func) 25 func(name = test_name, **kwargs) 26 test_names.append(test_name) 27 return test_names 28 29def _test_name_from_function(func): 30 """Derives the name of the given rule implementation function. 31 32 Args: 33 func: the function whose name to extract 34 35 Returns: 36 The name of the given function. Note it will have leading and trailing 37 "_" stripped -- this allows passing a private function and having the 38 name of the test not start with "_". 39 """ 40 41 # Starlark currently stringifies a function as "<function NAME>", so we use 42 # that knowledge to parse the "NAME" portion out. 43 # NOTE: This is relying on an implementation detail of Bazel 44 func_name = str(func) 45 func_name = func_name.partition("<function ")[-1] 46 func_name = func_name.rpartition(">")[0] 47 func_name = func_name.partition(" ")[0] 48 return func_name.strip("_") 49 50def _struct_with(s, **kwargs): 51 struct_dict = structs.to_dict(s) 52 struct_dict.update(kwargs) 53 return struct(**struct_dict) 54 55def _is_bazel_6_or_higher(): 56 # Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a 57 # different object that isn't equal to any other. This is fixed in bazel 6+. 58 return testing.ExecutionInfo == testing.ExecutionInfo 59 60def _is_windows(env): 61 """Tell if the target platform is windows. 62 63 This assumes the `WINDOWS_ATTR` attribute was added. 64 65 Args: 66 env: The test env struct 67 Returns: 68 True if the target is Windows, False if not. 69 """ 70 constraint = env.ctx.attr.windows[platform_common.ConstraintValueInfo] 71 return env.ctx.target_platform_has_constraint(constraint) 72 73util = struct( 74 create_tests = _create_tests, 75 struct_with = _struct_with, 76 is_bazel_6_or_higher = _is_bazel_6_or_higher, 77 is_windows = _is_windows, 78) 79