1"""Copyright (C) 2022 The Android Open Source Project 2 3Licensed under the Apache License, Version 2.0 (the "License"); 4you may not use this file except in compliance with the License. 5You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9Unless required by applicable law or agreed to in writing, software 10distributed under the License is distributed on an "AS IS" BASIS, 11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12See the License for the specific language governing permissions and 13limitations under the License. 14""" 15 16load("@bazel_skylib//lib:paths.bzl", "paths") 17load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 18load("//build/bazel/rules:hidl_file_utils.bzl", "INTERFACE_HEADER_PREFIXES", "TYPE_HEADER_PREFIXES") 19load("//build/bazel/rules/hidl:hidl_interface.bzl", "INTERFACE_SUFFIX") 20load("//build/bazel/rules/hidl:hidl_library.bzl", "hidl_library") 21load("//build/bazel/rules/hidl:hidl_package_root.bzl", "hidl_package_root") 22load(":cc_hidl_library.bzl", "CC_HEADER_SUFFIX", "cc_hidl_library") 23 24HIDL_GEN = "prebuilts/build-tools/linux-x86/bin/hidl-gen" 25 26SRC_TYPE_NAME_1 = "types_1.hal" 27GEN_TYPE_NAME_1 = "types_1.h" 28SRC_INTERFACE_NAME_1 = "IInterface_1.hal" 29GEN_INTERFACE_NAME_1 = "Interface_1.h" 30ROOT_1 = "android.hardware" 31ROOT_INTERFACE_FILE_LABEL_1 = "//hardware/interfaces:current.txt" 32ROOT_INTERFACE_FILE_1 = "hardware/interfaces/current.txt" 33ROOT_INTERFACE_PATH_1 = "hardware/interfaces" 34INTERFACE_PACKAGE_NAME_1 = "android.hardware.int1" 35ROOT_ARGUMENT_1 = "android.hardware:hardware/interfaces" 36 37SRC_TYPE_NAME_2 = "types_2.hal" 38SRC_INTERFACE_NAME_2 = "IInterface_2.hal" 39ROOT_2 = "android.hidl" 40ROOT_INTERFACE_FILE_LABEL_2 = "//system/libhidl/transport:current.txt" 41ROOT_INTERFACE_FILE_2 = "system/libhidl/transport/current.txt" 42ROOT_INTERFACE_PATH_2 = "system/libhidl/transport" 43ROOT_ARGUMENT_2 = "android.hidl:system/libhidl/transport" 44INTERFACE_PACKAGE_NAME_2 = "android.hidl.int2" 45 46INTERFACE_PACKAGE_NAME_CORE = "android.hidl.base" 47 48INTERFACE_VERSION_1_0 = "1.0" 49INTERFACE_VERSION_1_1 = "1.1" 50 51def _setup_roots(): 52 hidl_package_root( 53 name = ROOT_1, 54 current = ROOT_INTERFACE_FILE_LABEL_1, 55 path = ROOT_INTERFACE_PATH_1, 56 tags = ["manual"], 57 ) 58 59 hidl_package_root( 60 name = ROOT_2, 61 current = ROOT_INTERFACE_FILE_LABEL_2, 62 path = ROOT_INTERFACE_PATH_2, 63 tags = ["manual"], 64 ) 65 66def _cc_code_gen_test_impl(ctx): 67 env = analysistest.begin(ctx) 68 actions = analysistest.target_actions(env) 69 package_root = paths.dirname(ctx.build_file_path) 70 header_gen_actions = [a for a in actions if a.mnemonic == "HidlGenCcHeader"] 71 asserts.true( 72 env, 73 len(header_gen_actions) == 1, 74 "Cc header gen action not found: %s" % actions, 75 ) 76 77 header_gen_action = header_gen_actions[0] 78 79 asserts.equals( 80 env, 81 expected = sorted([ 82 paths.join(package_root, SRC_TYPE_NAME_1), 83 paths.join(package_root, SRC_INTERFACE_NAME_1), 84 paths.join(package_root, SRC_TYPE_NAME_2), 85 paths.join(package_root, SRC_INTERFACE_NAME_2), 86 ROOT_INTERFACE_FILE_1, 87 ROOT_INTERFACE_FILE_2, 88 paths.join(HIDL_GEN), 89 ]), 90 actual = sorted([ 91 file.short_path 92 for file in header_gen_action.inputs.to_list() 93 ]), 94 ) 95 96 path = paths.join(package_root, INTERFACE_PACKAGE_NAME_1.replace(".", "/"), INTERFACE_VERSION_1_0) 97 asserts.equals( 98 env, 99 expected = sorted( 100 [ 101 paths.join(path, prefix + GEN_TYPE_NAME_1) 102 for prefix in TYPE_HEADER_PREFIXES 103 ] + 104 [ 105 paths.join(path, prefix + GEN_INTERFACE_NAME_1) 106 for prefix in INTERFACE_HEADER_PREFIXES 107 ], 108 ), 109 actual = sorted([ 110 file.short_path 111 for file in header_gen_action.outputs.to_list() 112 ]), 113 ) 114 115 cmd = header_gen_action.argv 116 asserts.true( 117 env, 118 HIDL_GEN == cmd[0], 119 "hidl-gen is not called: %s" % cmd, 120 ) 121 122 asserts.true( 123 env, 124 "-R" in cmd, 125 "Calling hidl-gen without -R: %s" % cmd, 126 ) 127 128 index = cmd.index("-p") 129 asserts.true( 130 env, 131 index > 0, 132 "Calling hidl-gen without -p: %s" % cmd, 133 ) 134 135 asserts.true( 136 env, 137 cmd[index + 1] == ".", 138 ". needs to follow -p: %s" % cmd, 139 ) 140 141 index = cmd.index("-o") 142 asserts.true( 143 env, 144 index > 0, 145 "Calling hidl-gen without -o: %s" % cmd, 146 ) 147 148 asserts.true( 149 env, 150 cmd[index + 1].endswith(package_root), 151 "Incorrect output path: %s" % cmd, 152 ) 153 154 index = cmd.index("-L") 155 asserts.true( 156 env, 157 index > 0, 158 "Calling hidl-gen without -L: %s" % cmd, 159 ) 160 161 asserts.true( 162 env, 163 cmd[index + 1] == "c++-headers", 164 "Incorrect language: %s" % cmd, 165 ) 166 167 roots = [] 168 cmd_len = len(cmd) 169 for i in range(cmd_len): 170 if cmd[i] == "-r": 171 roots.append(cmd[i + 1]) 172 173 asserts.equals( 174 env, 175 expected = sorted([ 176 ROOT_ARGUMENT_1, 177 ROOT_ARGUMENT_2, 178 ]), 179 actual = sorted(roots), 180 ) 181 182 asserts.true( 183 env, 184 cmd[cmd_len - 1] == INTERFACE_PACKAGE_NAME_1 + "@" + INTERFACE_VERSION_1_0, 185 "The last arg should be the FQ name of the interface: %s" % cmd, 186 ) 187 188 return analysistest.end(env) 189 190cc_code_gen_test = analysistest.make( 191 _cc_code_gen_test_impl, 192) 193 194def _test_cc_code_gen(): 195 test_name = "cc_code_gen_test" 196 cc_name = INTERFACE_PACKAGE_NAME_1 + "@" + INTERFACE_VERSION_1_0 197 interface_name = cc_name + INTERFACE_SUFFIX 198 cc_name_dep = INTERFACE_PACKAGE_NAME_2 + "@" + INTERFACE_VERSION_1_0 199 interface_name_dep = cc_name_dep + INTERFACE_SUFFIX 200 201 hidl_library( 202 name = interface_name_dep, 203 root = ROOT_2, 204 fq_name = cc_name_dep, 205 srcs = [ 206 SRC_TYPE_NAME_2, 207 SRC_INTERFACE_NAME_2, 208 ], 209 tags = ["manual"], 210 ) 211 212 cc_hidl_library( 213 name = cc_name_dep, 214 interface = interface_name_dep, 215 tags = ["manual"], 216 ) 217 218 hidl_library( 219 name = interface_name, 220 deps = [interface_name_dep], 221 root = ROOT_1, 222 fq_name = cc_name, 223 srcs = [ 224 SRC_TYPE_NAME_1, 225 SRC_INTERFACE_NAME_1, 226 ], 227 tags = ["manual"], 228 ) 229 230 cc_hidl_library( 231 name = cc_name, 232 interface = interface_name, 233 dynamic_deps = [cc_name_dep], 234 tags = ["manual"], 235 ) 236 237 cc_code_gen_test( 238 name = test_name, 239 target_under_test = cc_name + CC_HEADER_SUFFIX, 240 ) 241 242 return test_name 243 244def _cc_interface_dep_test_impl(ctx): 245 env = analysistest.begin(ctx) 246 target_under_test = analysistest.target_under_test(env) 247 dynamic_deps = target_under_test[CcSharedLibraryInfo].dynamic_deps 248 249 dep_name = INTERFACE_PACKAGE_NAME_CORE + "@" + INTERFACE_VERSION_1_1 250 package_root = paths.dirname(ctx.build_file_path) 251 252 asserts.false( 253 env, 254 _find_dep(package_root, dep_name, dynamic_deps), 255 "Core package in the dependencies: %s %s" % (dep_name, dynamic_deps), 256 ) 257 258 dep_name = INTERFACE_PACKAGE_NAME_2 + "@" + INTERFACE_VERSION_1_1 259 asserts.true( 260 env, 261 _find_dep(package_root, dep_name, dynamic_deps), 262 "Missing valid dependency: %s %s" % (dep_name, dynamic_deps), 263 ) 264 265 return analysistest.end(env) 266 267def _find_dep(package_root, name, deps): 268 full_name = "@//" + package_root + ":" + name 269 for lists in deps.to_list(): 270 for dep in lists.exports: 271 if dep.startswith(full_name): 272 return True 273 274 return False 275 276cc_interface_dep_test = analysistest.make( 277 _cc_interface_dep_test_impl, 278) 279 280def _test_cc_interface_dep(): 281 test_name = "cc_interface_dep_test" 282 cc_name = INTERFACE_PACKAGE_NAME_1 + "@" + INTERFACE_VERSION_1_1 283 interface_name = cc_name + INTERFACE_SUFFIX 284 cc_name_dep = INTERFACE_PACKAGE_NAME_2 + "@" + INTERFACE_VERSION_1_1 285 interface_name_dep = cc_name_dep + INTERFACE_SUFFIX 286 cc_name_core = INTERFACE_PACKAGE_NAME_CORE + "@" + INTERFACE_VERSION_1_1 287 interface_name_core = cc_name_core + INTERFACE_SUFFIX 288 289 hidl_library( 290 name = interface_name_dep, 291 root = ROOT_2, 292 fq_name = cc_name_dep, 293 srcs = [ 294 SRC_TYPE_NAME_2, 295 SRC_INTERFACE_NAME_2, 296 ], 297 tags = ["manual"], 298 ) 299 300 cc_hidl_library( 301 name = cc_name_dep, 302 interface = interface_name_dep, 303 tags = ["manual"], 304 ) 305 306 hidl_library( 307 name = interface_name_core, 308 root = ROOT_2, 309 fq_name = cc_name_core, 310 srcs = [ 311 SRC_TYPE_NAME_2, 312 SRC_INTERFACE_NAME_2, 313 ], 314 tags = ["manual"], 315 ) 316 317 cc_hidl_library( 318 name = cc_name_core, 319 interface = interface_name_core, 320 tags = ["manual"], 321 ) 322 323 hidl_library( 324 name = interface_name, 325 deps = [interface_name_dep, interface_name_core], 326 root = ROOT_1, 327 fq_name = cc_name, 328 srcs = [ 329 SRC_TYPE_NAME_1, 330 SRC_INTERFACE_NAME_1, 331 ], 332 tags = ["manual"], 333 ) 334 335 cc_hidl_library( 336 name = cc_name, 337 interface = interface_name, 338 dynamic_deps = [cc_name_dep, cc_name_core], 339 tags = ["manual"], 340 ) 341 342 cc_interface_dep_test( 343 name = test_name, 344 target_under_test = cc_name, 345 ) 346 347 return test_name 348 349def cc_hidl_library_test_suite(name): 350 _setup_roots() 351 native.test_suite( 352 name = name, 353 tests = [ 354 _test_cc_code_gen(), 355 _test_cc_interface_dep(), 356 ], 357 ) 358