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 15load("@bazel_skylib//lib:new_sets.bzl", "sets") 16load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 17load( 18 "//build/bazel/rules/test_common:args.bzl", 19 "get_all_args_with_prefix", 20 "get_single_arg_with_prefix", 21) 22load("//build/bazel/rules/test_common:rules.bzl", "expect_failure_test") 23load(":cc_library_static.bzl", "cc_library_static") 24load(":clang_tidy.bzl", "generate_clang_tidy_actions") 25 26_PACKAGE_HEADER_FILTER = "^build/bazel/rules/cc/" 27_DEFAULT_GLOBAL_CHECKS = [ 28 "android-*", 29 "bugprone-*", 30 "cert-*", 31 "clang-diagnostic-unused-command-line-argument", 32 "google-build-explicit-make-pair", 33 "google-build-namespaces", 34 "google-runtime-operator", 35 "google-upgrade-*", 36 "misc-*", 37 "performance-*", 38 "portability-*", 39 "-bugprone-assignment-in-if-condition", 40 "-bugprone-easily-swappable-parameters", 41 "-bugprone-narrowing-conversions", 42 "-misc-const-correctness", 43 "-misc-no-recursion", 44 "-misc-non-private-member-variables-in-classes", 45 "-misc-unused-parameters", 46 "-performance-no-int-to-ptr", 47 "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling", 48] 49_DEFAULT_CHECKS = [ 50 "-misc-no-recursion", 51 "-readability-function-cognitive-complexity", 52 "-bugprone-unchecked-optional-access", 53 "-bugprone-reserved-identifier*", 54 "-cert-dcl51-cpp", 55 "-cert-dcl37-c", 56 "-readability-qualified-auto", 57 "-bugprone-implicit-widening-of-multiplication-result", 58 "-bugprone-easily-swappable-parameters", 59 "-cert-err33-c", 60 "-bugprone-unchecked-optional-access", 61 "-misc-use-anonymous-namespace", 62] 63_DEFAULT_CHECKS_AS_ERRORS = [ 64 "-bugprone-assignment-in-if-condition", 65 "-bugprone-branch-clone", 66 "-bugprone-signed-char-misuse", 67 "-misc-const-correctness", 68] 69_EXTRA_ARGS_BEFORE = [ 70 "-D__clang_analyzer__", 71 "-Xclang", 72 "-analyzer-config", 73 "-Xclang", 74 "c++-temp-dtor-inlining=false", 75] 76 77def _clang_tidy_impl(ctx): 78 tidy_outs = generate_clang_tidy_actions( 79 ctx, 80 ctx.attr.copts, 81 ctx.attr.deps, 82 ctx.files.srcs, 83 ctx.files.hdrs, 84 ctx.attr.language, 85 ctx.attr.tidy_flags, 86 ctx.attr.tidy_checks, 87 ctx.attr.tidy_checks_as_errors, 88 ctx.attr.tidy_timeout_srcs, 89 ) 90 return [ 91 DefaultInfo(files = depset(tidy_outs)), 92 ] 93 94_clang_tidy = rule( 95 implementation = _clang_tidy_impl, 96 attrs = { 97 "srcs": attr.label_list(allow_files = True), 98 "deps": attr.label_list(), 99 "copts": attr.string_list(), 100 "hdrs": attr.label_list(allow_files = True), 101 "language": attr.string(values = ["c++", "c"], default = "c++"), 102 "tidy_checks": attr.string_list(), 103 "tidy_checks_as_errors": attr.string_list(), 104 "tidy_flags": attr.string_list(), 105 "tidy_timeout_srcs": attr.label_list(allow_files = True), 106 "_clang_tidy_sh": attr.label( 107 default = Label("@//prebuilts/clang/host/linux-x86:clang-tidy.sh"), 108 allow_single_file = True, 109 executable = True, 110 cfg = "exec", 111 doc = "The clang tidy shell wrapper", 112 ), 113 "_clang_tidy": attr.label( 114 default = Label("@//prebuilts/clang/host/linux-x86:clang-tidy"), 115 allow_single_file = True, 116 executable = True, 117 cfg = "exec", 118 doc = "The clang tidy executable", 119 ), 120 "_clang_tidy_real": attr.label( 121 default = Label("@//prebuilts/clang/host/linux-x86:clang-tidy.real"), 122 allow_single_file = True, 123 executable = True, 124 cfg = "exec", 125 ), 126 "_with_tidy": attr.label( 127 default = "//build/bazel/flags/cc/tidy:with_tidy", 128 ), 129 "_allow_local_tidy_true": attr.label( 130 default = "//build/bazel/flags/cc/tidy:allow_local_tidy_true", 131 ), 132 "_with_tidy_flags": attr.label( 133 default = "//build/bazel/flags/cc/tidy:with_tidy_flags", 134 ), 135 "_default_tidy_header_dirs": attr.label( 136 default = "//build/bazel/flags/cc/tidy:default_tidy_header_dirs", 137 ), 138 "_tidy_timeout": attr.label( 139 default = "//build/bazel/flags/cc/tidy:tidy_timeout", 140 ), 141 "_product_variables": attr.label( 142 default = "//build/bazel/product_config:product_vars", 143 ), 144 }, 145 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 146 fragments = ["cpp"], 147) 148 149def _get_all_arg(env, actions, argname): 150 args = get_all_args_with_prefix(actions[0].argv, argname) 151 asserts.false(env, args == [], "could not arguments that start with `{}`".format(argname)) 152 return args 153 154def _get_single_arg(actions, argname): 155 return get_single_arg_with_prefix(actions[0].argv, argname) 156 157def _checks_test_impl(ctx): 158 env = analysistest.begin(ctx) 159 actions = analysistest.target_actions(env) 160 161 checks = _get_single_arg(actions, "-checks=").split(",") 162 asserts.set_equals(env, sets.make(ctx.attr.expected_checks), sets.make(checks)) 163 if len(ctx.attr.unexpected_checks) > 0: 164 for c in ctx.attr.unexpected_checks: 165 asserts.false(env, c in checks, "found unexpected check in -checks flag: %s" % c) 166 167 checks_as_errors = _get_single_arg(actions, "-warnings-as-errors=").split(",") 168 asserts.set_equals(env, sets.make(ctx.attr.expected_checks_as_errors), sets.make(checks_as_errors)) 169 170 return analysistest.end(env) 171 172_checks_test = analysistest.make( 173 _checks_test_impl, 174 attrs = { 175 "expected_checks": attr.string_list(mandatory = True), 176 "expected_checks_as_errors": attr.string_list(mandatory = True), 177 "unexpected_checks": attr.string_list(), 178 }, 179) 180 181def _copts_test_impl(ctx): 182 env = analysistest.begin(ctx) 183 actions = analysistest.target_actions(env) 184 185 args = actions[0].argv 186 clang_flags = [] 187 for i, a in enumerate(args): 188 if a == "--" and len(args) > i + 1: 189 clang_flags = args[i + 1:] 190 break 191 asserts.true( 192 env, 193 len(clang_flags) > 0, 194 "no flags passed to clang; all arguments: %s" % args, 195 ) 196 197 for expected_arg in ctx.attr.expected_copts: 198 asserts.true( 199 env, 200 expected_arg in clang_flags, 201 "expected `%s` not present in clang flags" % expected_arg, 202 ) 203 204 return analysistest.end(env) 205 206_copts_test = analysistest.make( 207 _copts_test_impl, 208 attrs = { 209 "expected_copts": attr.string_list(mandatory = True), 210 }, 211) 212 213def _tidy_flags_test_impl(ctx): 214 env = analysistest.begin(ctx) 215 actions = analysistest.target_actions(env) 216 217 args = actions[0].argv 218 tidy_flags = [] 219 for i, a in enumerate(args): 220 if a == "--" and len(args) > i + 1: 221 tidy_flags = args[:i] 222 asserts.true( 223 env, 224 len(tidy_flags) > 0, 225 "no tidy flags passed to clang-tidy; all arguments: %s" % args, 226 ) 227 228 for expected_arg in ctx.attr.expected_tidy_flags: 229 asserts.true( 230 env, 231 expected_arg in tidy_flags, 232 "expected `%s` not present in flags to clang-tidy" % expected_arg, 233 ) 234 235 header_filter = _get_single_arg(actions, "-header-filter=") 236 asserts.true( 237 env, 238 header_filter == ctx.attr.expected_header_filter, 239 ( 240 "expected header-filter to have value `%s`; got `%s`" % 241 (ctx.attr.expected_header_filter, header_filter) 242 ), 243 ) 244 245 extra_arg_before = _get_all_arg(env, actions, "-extra-arg-before=") 246 for expected_arg in ctx.attr.expected_extra_arg_before: 247 asserts.true( 248 env, 249 expected_arg in extra_arg_before, 250 "did not find expected flag `%s` in args to clang-tidy" % expected_arg, 251 ) 252 253 return analysistest.end(env) 254 255_tidy_flags_test = analysistest.make( 256 _tidy_flags_test_impl, 257 attrs = { 258 "expected_tidy_flags": attr.string_list(), 259 "expected_header_filter": attr.string(mandatory = True), 260 "expected_extra_arg_before": attr.string_list(), 261 }, 262) 263 264def _test_clang_tidy(): 265 name = "checks" 266 test_name = name + "_test" 267 checks_test_name = test_name + "_checks" 268 copts_test_name = test_name + "_copts" 269 tidy_flags_test_name = test_name + "_tidy_flags" 270 271 _clang_tidy( 272 name = name, 273 # clang-tidy operates differently on generated and non-generated files 274 # use test_srcs so that the tidy rule doesn't think these are genearted 275 # files 276 srcs = ["//build/bazel/rules/cc/testing:test_srcs"], 277 copts = ["-asdf1", "-asdf2"], 278 tidy_flags = ["-tidy-flag1", "-tidy-flag2"], 279 tags = ["manual"], 280 ) 281 282 _checks_test( 283 name = checks_test_name, 284 target_under_test = name, 285 expected_checks = _DEFAULT_CHECKS + _DEFAULT_GLOBAL_CHECKS, 286 expected_checks_as_errors = _DEFAULT_CHECKS_AS_ERRORS, 287 ) 288 289 _copts_test( 290 name = copts_test_name, 291 target_under_test = name, 292 expected_copts = ["-asdf1", "-asdf2"], 293 ) 294 295 _tidy_flags_test( 296 name = tidy_flags_test_name, 297 target_under_test = name, 298 expected_tidy_flags = ["-tidy-flag1", "-tidy-flag2"], 299 expected_header_filter = _PACKAGE_HEADER_FILTER, 300 expected_extra_arg_before = _EXTRA_ARGS_BEFORE, 301 ) 302 303 return [ 304 checks_test_name, 305 copts_test_name, 306 tidy_flags_test_name, 307 ] 308 309def _test_custom_header_dir(): 310 name = "custom_header_dir" 311 test_name = name + "_test" 312 313 _clang_tidy( 314 name = name, 315 srcs = ["a.cpp"], 316 tidy_flags = ["-header-filter=dir1/"], 317 tags = ["manual"], 318 ) 319 320 _tidy_flags_test( 321 name = test_name, 322 target_under_test = name, 323 expected_header_filter = "dir1/", 324 ) 325 326 return [ 327 test_name, 328 ] 329 330def _test_disabled_checks_are_removed(): 331 name = "disabled_checks_are_removed" 332 test_name = name + "_test" 333 334 _clang_tidy( 335 name = name, 336 # clang-tidy operates differently on generated and non-generated files. 337 # use test_srcs so that the tidy rule doesn't think these are genearted 338 # files 339 srcs = ["//build/bazel/rules/cc/testing:test_srcs"], 340 tidy_checks = ["misc-no-recursion", "readability-function-cognitive-complexity"], 341 tags = ["manual"], 342 ) 343 344 _checks_test( 345 name = test_name, 346 target_under_test = name, 347 expected_checks = _DEFAULT_CHECKS + _DEFAULT_GLOBAL_CHECKS, 348 expected_checks_as_errors = _DEFAULT_CHECKS_AS_ERRORS, 349 unexpected_checks = ["misc-no-recursion", "readability-function-cognitive-complexity"], 350 ) 351 352 return [ 353 test_name, 354 ] 355 356def _create_bad_tidy_checks_test(name, tidy_checks, failure_message): 357 name = "bad_tidy_checks_fail_" + name 358 test_name = name + "_test" 359 360 _clang_tidy( 361 name = name, 362 srcs = ["a.cpp"], 363 tidy_checks = tidy_checks, 364 tags = ["manual"], 365 ) 366 367 expect_failure_test( 368 name = test_name, 369 target_under_test = name, 370 failure_message = failure_message, 371 ) 372 373 return [ 374 test_name, 375 ] 376 377def _test_bad_tidy_checks_fail(): 378 return ( 379 _create_bad_tidy_checks_test( 380 name = "with_spaces", 381 tidy_checks = ["check with spaces"], 382 failure_message = "Check `check with spaces` invalid, cannot contain spaces", 383 ) + 384 _create_bad_tidy_checks_test( 385 name = "with_commas", 386 tidy_checks = ["check,with,commas"], 387 failure_message = "Check `check,with,commas` invalid, cannot contain commas. Split each entry into its own string instead", 388 ) 389 ) 390 391def _create_bad_tidy_flags_test(name, tidy_flags, failure_message): 392 name = "bad_tidy_flags_fail_" + name 393 test_name = name + "_test" 394 395 _clang_tidy( 396 name = name, 397 srcs = ["a.cpp"], 398 tidy_flags = tidy_flags, 399 tags = ["manual"], 400 ) 401 402 expect_failure_test( 403 name = test_name, 404 target_under_test = name, 405 failure_message = failure_message, 406 ) 407 408 return [ 409 test_name, 410 ] 411 412def _test_bad_tidy_flags_fail(): 413 return ( 414 _create_bad_tidy_flags_test( 415 name = "without_leading_dash", 416 tidy_flags = ["flag1"], 417 failure_message = "Flag `flag1` must start with `-`", 418 ) + 419 _create_bad_tidy_flags_test( 420 name = "fix_flags", 421 tidy_flags = ["-fix"], 422 failure_message = "Flag `%s` is not allowed, since it could cause multiple writes to the same source file", 423 ) + 424 _create_bad_tidy_flags_test( 425 name = "checks_in_flags", 426 tidy_flags = ["-checks=asdf"], 427 failure_message = "Flag `-checks=asdf` is not allowed, use `tidy_checks` property instead", 428 ) + 429 _create_bad_tidy_flags_test( 430 name = "warnings_as_errors_in_flags", 431 tidy_flags = ["-warnings-as-errors=asdf"], 432 failure_message = "Flag `-warnings-as-errors=asdf` is not allowed, use `tidy_checks_as_errors` property instead", 433 ) + 434 _create_bad_tidy_flags_test( 435 name = "space_in_flags", 436 tidy_flags = ["-flag with spaces"], 437 failure_message = "Bad flag: `-flag with spaces` is not an allowed multi-word flag. Should it be split into multiple flags", 438 ) 439 ) 440 441def _test_disable_global_checks(): 442 name = "disable_global_checks" 443 test_name = name + "_test" 444 445 _clang_tidy( 446 name = name, 447 srcs = ["a.cpp"], 448 tidy_checks = ["-*"], 449 tags = ["manual"], 450 ) 451 452 _checks_test( 453 name = test_name, 454 target_under_test = name, 455 expected_checks = ["-*"] + _DEFAULT_CHECKS, 456 expected_checks_as_errors = _DEFAULT_CHECKS_AS_ERRORS, 457 ) 458 459 return [ 460 test_name, 461 ] 462 463def _cc_library_static_generates_clang_tidy_actions_for_srcs_test_impl(ctx): 464 env = analysistest.begin(ctx) 465 actions = analysistest.target_actions(env) 466 467 clang_tidy_actions = [a for a in actions if a.mnemonic == "ClangTidy"] 468 asserts.equals( 469 env, 470 ctx.attr.expected_num_actions, 471 len(clang_tidy_actions), 472 "expected to have %s clang-tidy actions, but got %s; actions: %s" % ( 473 ctx.attr.expected_num_actions, 474 len(clang_tidy_actions), 475 clang_tidy_actions, 476 ), 477 ) 478 479 for a in clang_tidy_actions: 480 for input in a.inputs.to_list(): 481 input_is_expected_header = input.short_path in [f.short_path for f in ctx.files.expected_headers] 482 if input in ctx.files._clang_tidy_tools or input_is_expected_header: 483 continue 484 asserts.true( 485 env, 486 input in ctx.files.srcs, 487 "clang-tidy operated on a file not in srcs: %s; all inputs: %s" % (input, a.inputs.to_list()), 488 ) 489 asserts.true( 490 env, 491 input not in ctx.files.disabled_srcs, 492 "clang-tidy operated on a file in disabled_srcs: %s; all inputs: %s" % (input, a.inputs.to_list()), 493 ) 494 495 return analysistest.end(env) 496 497_cc_library_static_generates_clang_tidy_actions_for_srcs_test = analysistest.make( 498 impl = _cc_library_static_generates_clang_tidy_actions_for_srcs_test_impl, 499 attrs = { 500 "expected_num_actions": attr.int(mandatory = True), 501 "srcs": attr.label_list(allow_files = True), 502 "disabled_srcs": attr.label_list(allow_files = True), 503 "expected_headers": attr.label_list(allow_files = True), 504 "_clang_tidy_tools": attr.label_list( 505 default = [ 506 "@//prebuilts/clang/host/linux-x86:clang-tidy", 507 "@//prebuilts/clang/host/linux-x86:clang-tidy.real", 508 "@//prebuilts/clang/host/linux-x86:clang-tidy.sh", 509 ], 510 allow_files = True, 511 ), 512 }, 513 config_settings = { 514 "@//build/bazel/flags/cc/tidy:allow_local_tidy_true": True, 515 }, 516) 517 518def _create_cc_library_static_generates_clang_tidy_actions_for_srcs( 519 name, 520 srcs, 521 expected_num_actions, 522 disabled_srcs = None, 523 expected_headers = []): 524 name = "cc_library_static_generates_clang_tidy_actions_for_srcs_" + name 525 test_name = name + "_test" 526 527 cc_library_static( 528 name = name, 529 srcs = srcs, 530 tidy_disabled_srcs = disabled_srcs, 531 tidy = "local", 532 tags = ["manual"], 533 ) 534 535 _cc_library_static_generates_clang_tidy_actions_for_srcs_test( 536 name = test_name, 537 target_under_test = name, 538 expected_num_actions = expected_num_actions, 539 srcs = srcs, 540 disabled_srcs = disabled_srcs, 541 expected_headers = expected_headers + select({ 542 "//build/bazel/platforms/os:android": ["@//bionic/libc:generated_android_ids"], 543 "//conditions:default": [], 544 }), 545 ) 546 547 return test_name 548 549def _test_cc_library_static_generates_clang_tidy_actions_for_srcs(): 550 return [ 551 _create_cc_library_static_generates_clang_tidy_actions_for_srcs( 552 name = "with_srcs", 553 srcs = ["a.cpp", "b.cpp"], 554 expected_num_actions = 2, 555 ), 556 _create_cc_library_static_generates_clang_tidy_actions_for_srcs( 557 name = "with_disabled_srcs", 558 srcs = ["a.cpp", "b.cpp"], 559 disabled_srcs = ["b.cpp", "c.cpp"], 560 expected_num_actions = 1, 561 ), 562 ] 563 564def _no_clang_analyzer_on_generated_files_test_impl(ctx): 565 env = analysistest.begin(ctx) 566 actions = analysistest.target_actions(env) 567 568 clang_tidy_actions = [a for a in actions if a.mnemonic == "ClangTidy"] 569 for a in clang_tidy_actions: 570 found_clang_analyzer = False 571 for arg in a.argv: 572 if "-clang-analyzer-*" in arg: 573 found_clang_analyzer = True 574 asserts.true(env, found_clang_analyzer) 575 576 return analysistest.end(env) 577 578_no_clang_analyzer_on_generated_files_test = analysistest.make( 579 impl = _no_clang_analyzer_on_generated_files_test_impl, 580 config_settings = { 581 "@//build/bazel/flags/cc/tidy:allow_local_tidy_true": True, 582 }, 583) 584 585def _test_no_clang_analyzer_on_generated_files(): 586 name = "no_clang_analyzer_on_generated_files" 587 gen_name = name + "_generated_files" 588 test_name = name + "_test" 589 590 native.genrule( 591 name = gen_name, 592 outs = ["aout.cpp", "bout.cpp"], 593 cmd = "touch $(OUTS)", 594 tags = ["manual"], 595 ) 596 597 cc_library_static( 598 name = name, 599 srcs = [":" + gen_name], 600 tidy = "local", 601 tags = ["manual"], 602 ) 603 604 _no_clang_analyzer_on_generated_files_test( 605 name = test_name, 606 target_under_test = name, 607 ) 608 609 return [ 610 test_name, 611 ] 612 613def _clang_tidy_actions_count_no_tidy_env_test_impl(ctx): 614 env = analysistest.begin(ctx) 615 actions = analysistest.target_actions(env) 616 617 clang_tidy_actions = [a for a in actions if a.mnemonic == "ClangTidy"] 618 asserts.equals( 619 env, 620 ctx.attr.expected_num_tidy_actions, 621 len(clang_tidy_actions), 622 "expected to find %d tidy actions, but found %d" % ( 623 ctx.attr.expected_num_tidy_actions, 624 len(clang_tidy_actions), 625 ), 626 ) 627 628 return analysistest.end(env) 629 630_clang_tidy_actions_count_no_tidy_env_test = analysistest.make( 631 impl = _clang_tidy_actions_count_no_tidy_env_test_impl, 632 attrs = { 633 "expected_num_tidy_actions": attr.int(), 634 }, 635) 636 637_clang_tidy_actions_count_with_tidy_true_test = analysistest.make( 638 impl = _clang_tidy_actions_count_no_tidy_env_test_impl, 639 attrs = { 640 "expected_num_tidy_actions": attr.int(), 641 }, 642 config_settings = { 643 "@//build/bazel/flags/cc/tidy:with_tidy": True, 644 }, 645) 646 647_clang_tidy_actions_count_with_allow_local_tidy_true_test = analysistest.make( 648 impl = _clang_tidy_actions_count_no_tidy_env_test_impl, 649 attrs = { 650 "expected_num_tidy_actions": attr.int(), 651 }, 652 config_settings = { 653 "@//build/bazel/flags/cc/tidy:allow_local_tidy_true": True, 654 }, 655) 656 657def _test_clang_tidy_runs_if_tidy_true(): 658 name = "clang_tidy_runs_if_tidy_true" 659 test_name = name + "_test" 660 with_tidy_test_name = test_name + "_with_tidy_true" 661 allow_local_tidy_true_test_name = test_name + "_allow_local_tidy_true" 662 663 cc_library_static( 664 name = name, 665 srcs = ["a.cpp"], 666 tidy = "local", 667 tags = ["manual"], 668 ) 669 _clang_tidy_actions_count_no_tidy_env_test( 670 name = test_name, 671 target_under_test = name, 672 expected_num_tidy_actions = 0, 673 ) 674 _clang_tidy_actions_count_with_tidy_true_test( 675 name = with_tidy_test_name, 676 target_under_test = name, 677 expected_num_tidy_actions = 1, 678 ) 679 _clang_tidy_actions_count_with_allow_local_tidy_true_test( 680 name = allow_local_tidy_true_test_name, 681 target_under_test = name, 682 expected_num_tidy_actions = 1, 683 ) 684 return [ 685 test_name, 686 with_tidy_test_name, 687 allow_local_tidy_true_test_name, 688 ] 689 690def _test_clang_tidy_runs_if_attribute_unset(): 691 name = "clang_tidy_runs_if_attribute_unset" 692 test_name = name + "_test" 693 with_tidy_test_name = test_name + "_with_tidy_true" 694 allow_local_tidy_true_test_name = test_name + "_allow_local_tidy_true" 695 696 cc_library_static( 697 name = name, 698 srcs = ["a.cpp"], 699 tags = ["manual"], 700 ) 701 _clang_tidy_actions_count_no_tidy_env_test( 702 name = test_name, 703 target_under_test = name, 704 expected_num_tidy_actions = 0, 705 ) 706 _clang_tidy_actions_count_with_tidy_true_test( 707 name = with_tidy_test_name, 708 target_under_test = name, 709 expected_num_tidy_actions = 1, 710 ) 711 _clang_tidy_actions_count_with_allow_local_tidy_true_test( 712 name = allow_local_tidy_true_test_name, 713 target_under_test = name, 714 expected_num_tidy_actions = 0, 715 ) 716 return [ 717 test_name, 718 with_tidy_test_name, 719 allow_local_tidy_true_test_name, 720 ] 721 722def _test_no_clang_tidy_if_tidy_false(): 723 name = "no_clang_tidy_if_tidy_false" 724 test_name = name + "_test" 725 with_tidy_test_name = test_name + "_with_tidy_true" 726 allow_local_tidy_true_test_name = test_name + "_allow_local_tidy_true" 727 728 cc_library_static( 729 name = name, 730 srcs = ["a.cpp"], 731 tidy = "never", 732 tags = ["manual"], 733 ) 734 _clang_tidy_actions_count_no_tidy_env_test( 735 name = test_name, 736 target_under_test = name, 737 expected_num_tidy_actions = 0, 738 ) 739 _clang_tidy_actions_count_with_tidy_true_test( 740 name = with_tidy_test_name, 741 target_under_test = name, 742 expected_num_tidy_actions = 0, 743 ) 744 _clang_tidy_actions_count_with_allow_local_tidy_true_test( 745 name = allow_local_tidy_true_test_name, 746 target_under_test = name, 747 expected_num_tidy_actions = 0, 748 ) 749 return [ 750 test_name, 751 with_tidy_test_name, 752 allow_local_tidy_true_test_name, 753 ] 754 755def clang_tidy_test_suite(name): 756 native.test_suite( 757 name = name, 758 tests = 759 _test_clang_tidy() + 760 _test_custom_header_dir() + 761 _test_disabled_checks_are_removed() + 762 _test_bad_tidy_checks_fail() + 763 _test_bad_tidy_flags_fail() + 764 _test_disable_global_checks() + 765 _test_cc_library_static_generates_clang_tidy_actions_for_srcs() + 766 _test_no_clang_analyzer_on_generated_files() + 767 _test_no_clang_tidy_if_tidy_false() + 768 _test_clang_tidy_runs_if_tidy_true() + 769 _test_clang_tidy_runs_if_attribute_unset(), 770 ) 771