1# Copyright 2023 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://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, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14 15import("//build_overrides/pigweed.gni") 16 17import("$dir_pw_build/python.gni") 18import("$dir_pw_build/test_info.gni") 19 20# Creates a Python action to use as a test and associated metadata. 21# 22# This template derives several additional targets: 23# - <target_name>.metadata produces the test metadata when included in a 24# `pw_test_group`. This metadata includes the Ninja target that runs the 25# test. 26# - <target_name>.script creates a `pw_python_action` to run the test and 27# wraps it as a standalone `pw_python_package`. 28# - <target_name>.group creates a `pw_python_group` in order to apply tools, 29# e.g. linters, to the standalone package. 30# - <target_name>.lib is an empty group for compatibility with 31# `pw_test_group`. 32# - <target_name>.run invokes the test. 33# 34# Targets defined using this template will produce test metadata with a 35# `test_type` of "action_test" and a `ninja_target` value that will invoke the 36# test when passed to Ninja, i.e. `ninja -C out <ninja_target>`. 37# 38# Args: 39# - The following args have the same meaning as for `pw_test`: 40# enable_if 41# envvars (may also use `environment`) 42# tags 43# extra_metadata 44# source_gen_deps 45# 46# - The following args have the same meaning as for `pw_python_action`: 47# script (may be omitted if `sources` has length=1) 48# args 49# deps 50# environment (may also use `envvars`) 51# working_directory 52# command_launcher 53# venv 54# 55# - The following args have the same meaning as for `pw_python_package`: 56# sources 57# python_deps 58# other_deps 59# inputs 60# static_analysis 61# pylintrc 62# mypy_ini 63# 64# - action: Optional string or scope. If a string, this should be a label to 65# a `pw_python_action` target that performs the test. If a scope, this 66# has the same meaning as for `pw_python_script`. 67template("pw_python_action_test") { 68 _test_target_name = target_name 69 _deps = [] 70 _run_deps = [] 71 _metadata = { 72 } 73 74 _test_is_enabled = !defined(invoker.enable_if) || invoker.enable_if 75 if (_test_is_enabled) { 76 # Metadata for this test when used as part of a pw_test_group target. 77 _test_metadata = "${target_name}.metadata" 78 _ninja_target = "$target_out_dir/$target_name.run.stamp" 79 _extra_metadata = { 80 forward_variables_from(invoker, [ "extra_metadata" ]) 81 ninja_target = rebase_path(_ninja_target, root_build_dir) 82 } 83 pw_test_info(_test_metadata) { 84 test_type = "action_test" 85 test_name = _test_target_name 86 forward_variables_from(invoker, [ "tags" ]) 87 extra_metadata = _extra_metadata 88 } 89 _deps += [ ":$_test_metadata" ] 90 _metadata = { 91 test_barrier = [ ":$_test_metadata" ] 92 } 93 94 if (defined(invoker.action) && invoker.action == "${invoker.action}") { 95 # `action` is a label to an existing Python action. 96 _run_deps = [ invoker.action ] 97 if (defined(invoker.deps)) { 98 _deps += invoker.deps 99 } 100 } else { 101 # Wrap the action in a Python script target for additional flexibility. 102 _test_script_name = _test_target_name + ".script" 103 104 _sources = [] 105 if (defined(invoker.script)) { 106 _sources += [ invoker.script ] 107 } 108 if (defined(invoker.sources)) { 109 _sources += invoker.sources 110 } 111 112 pw_python_script(_test_script_name) { 113 other_deps = [] 114 forward_variables_from(invoker, 115 [ 116 "action", 117 "python_deps", 118 "other_deps", 119 "inputs", 120 "static_analysis", 121 "testonly", 122 "pylintrc", 123 "mypy_ini", 124 ]) 125 sources = _sources 126 if (defined(invoker.source_gen_deps)) { 127 other_deps += invoker.source_gen_deps 128 } 129 if (!defined(pylintrc)) { 130 pylintrc = "$dir_pigweed/.pylintrc" 131 } 132 if (!defined(mypy_ini)) { 133 mypy_ini = "$dir_pigweed/.mypy.ini" 134 } 135 if (!defined(action)) { 136 action = { 137 environment = [] 138 forward_variables_from(invoker, 139 [ 140 "script", 141 "args", 142 "deps", 143 "environment", 144 "working_directory", 145 "command_launcher", 146 "venv", 147 ]) 148 if (defined(invoker.envvars)) { 149 environment += invoker.envvars 150 } 151 stamp = true 152 } 153 } 154 } 155 _deps += [ ":$_test_script_name" ] 156 _run_deps = [ ":$_test_script_name.action" ] 157 158 # Create a Python group in order to ensure the package is linted. 159 _test_python_group = _test_target_name + ".group" 160 pw_python_group(_test_python_group) { 161 python_deps = [ ":$_test_script_name" ] 162 } 163 _deps += [ ":$_test_python_group" ] 164 } 165 } else { 166 if (defined(invoker.source_gen_deps)) { 167 _deps += invoker.source_gen_deps 168 } 169 } 170 171 # For compatibility with `pw_test_group`. 172 group(_test_target_name + ".lib") { 173 forward_variables_from(invoker, [ "testonly" ]) 174 } 175 176 # For compatibility with `pw_test_group`. 177 group(_test_target_name + ".run") { 178 forward_variables_from(invoker, [ "testonly" ]) 179 deps = _run_deps 180 } 181 182 group(_test_target_name) { 183 forward_variables_from(invoker, [ "testonly" ]) 184 deps = _deps 185 metadata = _metadata 186 } 187} 188