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