1# Copyright (C) 2022 The Android Open Source Project 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"""cc_test macro for building native tests with Bazel.""" 16 17load("//build/bazel/rules/cc:cc_library_common.bzl", "CcAndroidMkInfo") 18load("//build/bazel/rules/cc:stripped_cc_common.bzl", "CcUnstrippedInfo", "StrippedCcBinaryInfo") 19load("//build/bazel/rules/tradefed:tradefed.bzl", "tradefed_host_driven_test") 20load(":cc_binary.bzl", "cc_binary") 21 22# TODO(b/244559183): Keep this in sync with cc/test.go#linkerFlags 23_gtest_copts = select({ 24 "//build/bazel/platforms/os:linux_glibc": ["-DGTEST_OS_LINUX"], 25 "//build/bazel/platforms/os:darwin": ["-DGTEST_OS_MAC"], 26 "//build/bazel/platforms/os:windows": ["-DGTEST_OS_WINDOWS"], 27 "//conditions:default": ["-DGTEST_OS_LINUX_ANDROID"], 28}) + select({ 29 "//build/bazel/platforms/os:android": [], 30 "//conditions:default": ["-O0", "-g"], # here, default == host platform 31}) + [ 32 "-DGTEST_HAS_STD_STRING", 33 "-Wno-unused-result", # TODO(b/244433518): Figure out why this is necessary in the bazel compile action. 34] 35 36_gtest_deps = [ 37 "//external/googletest/googletest:libgtest_main", 38 "//external/googletest/googletest:libgtest", 39] 40 41_pass_through_providers = [ 42 CcInfo, 43 InstrumentedFilesInfo, 44 DebugPackageInfo, 45 OutputGroupInfo, 46 StrippedCcBinaryInfo, 47 CcUnstrippedInfo, 48 CcAndroidMkInfo, 49] 50 51def cc_test( 52 name, 53 copts = [], 54 deps = [], 55 dynamic_deps = [], 56 gtest = True, 57 isolated = True, # TODO(b/244432609): currently no-op. @unused 58 tags = [], 59 tidy = None, 60 tidy_checks = None, 61 tidy_checks_as_errors = None, 62 tidy_flags = None, 63 tidy_disabled_srcs = None, 64 tidy_timeout_srcs = None, 65 test_config = None, 66 template_test_config = None, 67 template_configs = [], 68 template_install_base = None, 69 **kwargs): 70 # NOTE: Keep this in sync with cc/test.go#linkerDeps 71 if gtest: 72 # TODO(b/244433197): handle ctx.useSdk() && ctx.Device() case to link against the ndk variants of the gtest libs. 73 # TODO(b/244432609): handle isolated = True to link against libgtest_isolated_main and liblog (dynamically) 74 deps = deps + _gtest_deps 75 copts = copts + _gtest_copts 76 77 # A cc_test is essentially the same as a cc_binary. Let's reuse the 78 # implementation for now and factor the common bits out as necessary. 79 test_binary_name = name + "__test_binary" 80 cc_binary( 81 name = test_binary_name, 82 copts = copts, 83 deps = deps, 84 dynamic_deps = dynamic_deps, 85 generate_cc_test = True, 86 tidy = tidy, 87 tidy_checks = tidy_checks, 88 tidy_checks_as_errors = tidy_checks_as_errors, 89 tidy_flags = tidy_flags, 90 tidy_disabled_srcs = tidy_disabled_srcs, 91 tidy_timeout_srcs = tidy_timeout_srcs, 92 tags = tags + ["manual"], 93 **kwargs 94 ) 95 96 # Host only test with no tradefed. 97 # Compatability is left out for now so as not to break mix build. 98 # which breaks when modules are skipped with --config=android 99 without_tradefed_test_name = name + "__without_tradefed_test" 100 cc_runner_test( 101 name = without_tradefed_test_name, 102 binary = test_binary_name, 103 test = test_binary_name, 104 tags = ["manual"], 105 ) 106 107 # Tradefed host driven test 108 tradefed_host_driven_test_name = name + "__tradefed_host_driven_test" 109 if not test_config and not template_test_config: 110 template_test_config = select({ 111 "//build/bazel/rules/tradefed:android_host_driven_tradefed_test": "//build/make/core:native_test_config_template.xml", 112 "//build/bazel/rules/tradefed:linux_host_driven_tradefed_test": "//build/make/core:native_host_test_config_template.xml", 113 "//conditions:default": "//build/make/core:native_test_config_template.xml", 114 }) 115 tradefed_host_driven_test( 116 name = tradefed_host_driven_test_name, 117 test_identifier = name, 118 test = test_binary_name, 119 test_config = test_config, 120 template_test_config = template_test_config, 121 template_configs = template_configs, 122 template_install_base = template_install_base, 123 tags = ["manual"], 124 ) 125 126 # TODO(b/264792912) update to use proper config/tags to determine which test to run. 127 cc_runner_test( 128 name = name, 129 binary = test_binary_name, 130 test = select({ 131 "//build/bazel/rules/tradefed:android_host_driven_tradefed_test": tradefed_host_driven_test_name, 132 "//build/bazel/rules/tradefed:linux_host_driven_tradefed_test": tradefed_host_driven_test_name, 133 "//conditions:default": without_tradefed_test_name, 134 }), 135 ) 136 137def _cc_runner_test_impl(ctx): 138 executable = ctx.actions.declare_file(ctx.attr.name + "__cc_runner_test") 139 ctx.actions.symlink( 140 output = executable, 141 target_file = ctx.attr.test.files_to_run.executable, 142 ) 143 144 # Gather runfiles. 145 runfiles = ctx.runfiles() 146 runfiles = runfiles.merge_all([ 147 ctx.attr.binary.default_runfiles, 148 ctx.attr.test.default_runfiles, 149 ]) 150 151 # Propagate providers of the included binary 152 # Those providers are used to populate attributes of the mixed build. 153 providers = collect_providers(ctx.attr.binary, _pass_through_providers) 154 return [DefaultInfo( 155 executable = executable, 156 runfiles = runfiles, 157 )] + providers 158 159cc_runner_test = rule( 160 doc = "A wrapper rule used to run a test and also propagates providers", 161 attrs = { 162 "binary": attr.label( 163 doc = "Binary that providers should be propagated to next rule // mix build.", 164 ), 165 "test": attr.label( 166 doc = "Test to run.", 167 ), 168 }, 169 test = True, 170 implementation = _cc_runner_test_impl, 171 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 172) 173 174def collect_providers(dep, provider_types): 175 """Returns list of providers from dependency that match the provider types""" 176 providers = [] 177 for provider in provider_types: 178 if provider in dep: 179 providers.append(dep[provider]) 180 return providers 181