SERVER-114770 re-enable clang tidy checks on 8.0 (#44824)
GitOrigin-RevId: 7ef389c4166b3d100799c7f96fd59165319b39a7
This commit is contained in:
committed by
MongoDB Bot
parent
29e14c65c1
commit
ac29497b08
@@ -8,6 +8,7 @@ src/third_party/wiredtiger/dist
|
||||
bazel/auto_header/.auto_header
|
||||
src/mongo/db/modules/atlas/.auto_header
|
||||
src/mongo/db/modules/enterprise/.auto_header
|
||||
.git
|
||||
|
||||
# Ignore node_modules due to the following error
|
||||
# ERROR: in verify_node_modules_ignored:
|
||||
|
||||
5
.bazelrc
5
.bazelrc
@@ -86,8 +86,10 @@ common --strategy=CcGenerateDwp=local
|
||||
common --modify_execution_info=^(TestRunner|CppLink|CppArchive|SolibSymlink|ExtractDebuginfo|StripDebuginfo|CcGenerateIntermediateDwp|CcGenerateDwp)$=+no-remote-cache
|
||||
|
||||
# Global clang tidy flags to avoid invalidating analysis cache between clang-tidy / regular runs
|
||||
common --@bazel_clang_tidy//:clang_tidy_excludes=".pb.cc,icu_init.cpp"
|
||||
common --@bazel_clang_tidy//:clang_tidy_excludes=".pb.cc,icu_init.cpp,parser_gen.cpp"
|
||||
common --@bazel_clang_tidy//:clang_tidy_additional_configs=//:clang_tidy_config_files
|
||||
common --@bazel_clang_tidy//:clang_tidy_config=//:clang_tidy_config_strict
|
||||
common --@bazel_clang_tidy//:clang_tidy_merge_tool=//bazel:merge_tidy_configs
|
||||
common --@bazel_clang_tidy//:clang_tidy_executable=//:clang_tidy
|
||||
common --@bazel_clang_tidy//:clang_tidy_additional_deps=//:toolchain_files
|
||||
common --@bazel_clang_tidy//:clang_tidy_plugin_deps=//src/mongo/tools/mongo_tidy_checks:mongo_tidy_checks
|
||||
@@ -419,6 +421,7 @@ common:clang-tidy --//bazel/config:compiler_type=clang
|
||||
common:clang-tidy --keep_going
|
||||
common:clang-tidy --aspects @bazel_clang_tidy//clang_tidy:clang_tidy.bzl%clang_tidy_aspect
|
||||
common:clang-tidy --output_groups=report
|
||||
common:clang-tidy --//bazel/config:use_diagnostic_latches=True
|
||||
|
||||
--config=mod-scanner
|
||||
common:mod-scanner --config=dbg
|
||||
|
||||
@@ -134,13 +134,12 @@ Checks: '-*,
|
||||
-readability-string-compare,
|
||||
-readability-uniqueptr-delete-release
|
||||
'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*|@MONGO_BUILD_DIR@/.*)'
|
||||
HeaderFilterRegex: 'mongo/[-A-Za-z0-9_/]*\.(h|hpp|ipp|inl|cstruct.h|defs|def.h)'
|
||||
CheckOptions:
|
||||
- key: bugprone-assert-side-effect.AssertMacros
|
||||
value: assert
|
||||
- key: mongo-header-bracket-check.mongoSourceDirs
|
||||
value: 'src/mongo;@MONGO_BUILD_DIR@'
|
||||
value: 'src/mongo;@MONGO_BRACKET_BUILD_DIR@'
|
||||
- key: mongo-collection-sharding-runtime-check.exceptionDirs
|
||||
value: 'src/mongo/db/s'
|
||||
- key: bugprone-assert-side-effect.CheckFunctionCalls
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -290,6 +290,7 @@ buildozer
|
||||
.compiledb
|
||||
.bazelrc.xcode
|
||||
.bazelrc.bazelisk
|
||||
.bazelrc.wrapper_hook
|
||||
*.bazel_info_for_ninja.txt
|
||||
.ninja_last_command_line_targets.txt
|
||||
bazel/coverity/analysis/BUILD.bazel
|
||||
@@ -297,8 +298,8 @@ bazel/coverity/analysis/BUILD.bazel
|
||||
.bazel_header_list_cache
|
||||
.bazel_real
|
||||
.mongo_checks_module_path
|
||||
MODULE.bazel
|
||||
MODULE.bazel.lock
|
||||
**/MODULE.bazel.lock
|
||||
!/MODULE.bazel.lock
|
||||
.auto_header
|
||||
|
||||
# generated configs for external fixture suites
|
||||
|
||||
@@ -448,3 +448,8 @@ sh_binary(
|
||||
"BINARY_PATH": "$(location @scip-src//file)",
|
||||
},
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "clang_tidy_config_files",
|
||||
srcs = [],
|
||||
)
|
||||
|
||||
@@ -15,12 +15,12 @@ http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_
|
||||
|
||||
http_archive(
|
||||
name = "bazel_clang_tidy",
|
||||
integrity = "sha256-A+TGGfuHdS7vWT20eyAEiA3u4YXFtuzsJDcpTEmDMS0=",
|
||||
strip_prefix = "bazel_clang_tidy-10c4bf70a8946789e3932f30e29dfba2dfb78e67",
|
||||
integrity = "sha256-Q5LQ/bAvLIu1kNhnkthNROFxToui376QRiPlYU9uhZU=",
|
||||
strip_prefix = "bazel_clang_tidy-33c9013349b6178897598e67929201356b0ad5ea",
|
||||
urls = [
|
||||
# Implements retry by relisting each url multiple times to be used as a failover.
|
||||
# TODO(SERVER-86719): Re-implement http_archive to allow sleeping between retries
|
||||
"https://github.com/mongodb-forks/bazel_clang_tidy/archive/10c4bf70a8946789e3932f30e29dfba2dfb78e67.tar.gz",
|
||||
"https://github.com/mongodb-forks/bazel_clang_tidy/archive/33c9013349b6178897598e67929201356b0ad5ea.tar.gz",
|
||||
] * 5,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
load("@poetry//:dependencies.bzl", "dependency")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
# Expose script for external usage through bazel.
|
||||
@@ -16,3 +18,18 @@ py_binary(
|
||||
name = "bazelisk",
|
||||
srcs = ["bazelisk.py"],
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "merge_tidy_configs",
|
||||
srcs = [
|
||||
"merge_tidy_configs.py",
|
||||
],
|
||||
main = "merge_tidy_configs.py",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
dependency(
|
||||
"pyyaml",
|
||||
group = "core",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
187
bazel/merge_tidy_configs.py
Normal file
187
bazel/merge_tidy_configs.py
Normal file
@@ -0,0 +1,187 @@
|
||||
"""
|
||||
Merge clang-tidy config files:
|
||||
- Baseline + zero or more additional config files.
|
||||
- Checks: concatenated left→right (later entries can disable earlier via -pattern).
|
||||
- CheckOptions: merged by key (later configs override).
|
||||
- Other keys: deep-merge (dicts) or last-wins (scalars).
|
||||
|
||||
Requires: PyYAML
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
from typing import Any, Dict, List
|
||||
|
||||
import yaml
|
||||
|
||||
# --------------------------- YAML helpers ---------------------------
|
||||
|
||||
|
||||
def load_yaml(file_path: str | pathlib.Path) -> Dict[str, Any]:
|
||||
path = pathlib.Path(file_path)
|
||||
if not path.exists():
|
||||
raise SystemExit(f"Error: Config file '{file_path}' not found.")
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
|
||||
|
||||
def split_checks_to_list(value: Any) -> List[str]:
|
||||
"""Normalize a Checks value (string or list) into a flat list of tokens."""
|
||||
if value is None:
|
||||
return []
|
||||
parts: List[str] = []
|
||||
if isinstance(value, str):
|
||||
parts = [s.strip() for s in value.split(",")]
|
||||
elif isinstance(value, list):
|
||||
for item in value:
|
||||
parts.extend([s.strip() for s in str(item).split(",")])
|
||||
return [s for s in parts if s]
|
||||
|
||||
|
||||
def merge_checks_into_config(
|
||||
target_config: Dict[str, Any], incoming_config: Dict[str, Any]
|
||||
) -> None:
|
||||
"""Append incoming Checks onto target Checks (string-concatenated)."""
|
||||
accumulated = split_checks_to_list(target_config.get("Checks"))
|
||||
additions = split_checks_to_list(incoming_config.get("Checks"))
|
||||
if additions:
|
||||
target_config["Checks"] = ",".join(accumulated + additions)
|
||||
|
||||
|
||||
def check_options_list_to_map(value: Any) -> Dict[str, Any]:
|
||||
"""Transform CheckOptions list[{key,value}] into a dict[key]=value."""
|
||||
out: Dict[str, Any] = {}
|
||||
if isinstance(value, list):
|
||||
for item in value:
|
||||
if isinstance(item, dict) and "key" in item:
|
||||
out[item["key"]] = item.get("value")
|
||||
return out
|
||||
|
||||
|
||||
def merge_check_options_into_config(
|
||||
target_config: Dict[str, Any], incoming_config: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Merge CheckOptions so later configs override earlier by 'key'.
|
||||
Stores back as list[{key,value}] sorted by key for determinism.
|
||||
"""
|
||||
base = check_options_list_to_map(target_config.get("CheckOptions"))
|
||||
override = check_options_list_to_map(incoming_config.get("CheckOptions"))
|
||||
if override:
|
||||
base.update(override) # later wins
|
||||
target_config["CheckOptions"] = [{"key": k, "value": v} for k, v in sorted(base.items())]
|
||||
|
||||
|
||||
def deep_merge_dicts(base: Any, override: Any) -> Any:
|
||||
"""Generic deep merge for everything except Checks/CheckOptions."""
|
||||
if isinstance(base, dict) and isinstance(override, dict):
|
||||
result = dict(base)
|
||||
for key, o_val in override.items():
|
||||
if key in ("Checks", "CheckOptions"):
|
||||
# handled by specialized mergers
|
||||
continue
|
||||
b_val = result.get(key)
|
||||
if isinstance(b_val, dict) and isinstance(o_val, dict):
|
||||
result[key] = deep_merge_dicts(b_val, o_val)
|
||||
else:
|
||||
result[key] = o_val
|
||||
return result
|
||||
return override
|
||||
|
||||
|
||||
# --------------------------- path helpers ---------------------------
|
||||
|
||||
|
||||
def is_ancestor_directory(ancestor: pathlib.Path, descendant: pathlib.Path) -> bool:
|
||||
"""
|
||||
True if 'ancestor' is the same as or a parent of 'descendant'.
|
||||
Resolution ensures symlinks and relative parts are normalized.
|
||||
"""
|
||||
try:
|
||||
ancestor = ancestor.resolve()
|
||||
descendant = descendant.resolve()
|
||||
except FileNotFoundError:
|
||||
# If either path doesn't exist yet, still resolve purely lexicaly
|
||||
ancestor = ancestor.absolute()
|
||||
descendant = descendant.absolute()
|
||||
return ancestor == descendant or ancestor in descendant.parents
|
||||
|
||||
|
||||
def filter_and_sort_config_paths(
|
||||
config_paths: list[str | pathlib.Path], scope_directory: str | None
|
||||
) -> list[pathlib.Path]:
|
||||
"""
|
||||
Keep only config files whose parent directory is an ancestor
|
||||
of the provided scope directory.
|
||||
Sort shallow → deep so deeper configs apply later and override earlier ones.
|
||||
If scope_directory is None, keep paths in the order given.
|
||||
"""
|
||||
config_paths = [pathlib.Path(p) for p in config_paths]
|
||||
|
||||
if not scope_directory:
|
||||
return config_paths
|
||||
|
||||
workspace_root = pathlib.Path.cwd().resolve()
|
||||
scope_abs = (workspace_root / scope_directory).resolve()
|
||||
|
||||
selected: list[tuple[int, pathlib.Path]] = []
|
||||
|
||||
for cfg in config_paths:
|
||||
parent_dir = cfg.parent
|
||||
if is_ancestor_directory(parent_dir, scope_abs):
|
||||
# Depth is number of path components from root
|
||||
selected.append((len(parent_dir.parts), cfg.resolve()))
|
||||
|
||||
# Sort by depth ascending so root-most files merge first
|
||||
selected.sort(key=lambda t: t[0])
|
||||
|
||||
return [cfg for _, cfg in selected]
|
||||
|
||||
|
||||
# --------------------------- main ---------------------------
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--baseline", required=True, help="Baseline clang-tidy YAML.")
|
||||
parser.add_argument(
|
||||
"--config-file",
|
||||
dest="config_files",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Additional clang-tidy config file(s). May be repeated.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--scope-dir",
|
||||
help="Repo-relative directory; only config files in its ancestor dirs are merged.",
|
||||
)
|
||||
parser.add_argument("--out", required=True, help="Output merged YAML path.")
|
||||
args = parser.parse_args()
|
||||
|
||||
merged_config: Dict[str, Any] = load_yaml(args.baseline)
|
||||
|
||||
config_paths: List[pathlib.Path] = filter_and_sort_config_paths(
|
||||
args.config_files, args.scope_dir
|
||||
)
|
||||
|
||||
for config_path in config_paths:
|
||||
incoming_config = load_yaml(config_path)
|
||||
|
||||
# clang-tidy special merges first:
|
||||
merge_checks_into_config(merged_config, incoming_config)
|
||||
merge_check_options_into_config(merged_config, incoming_config)
|
||||
|
||||
# then generic merge:
|
||||
merged_config = deep_merge_dicts(merged_config, incoming_config)
|
||||
|
||||
merged_config["Checks"] = ",".join(split_checks_to_list(merged_config.get("Checks")))
|
||||
output_path = pathlib.Path(args.out)
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(output_path, "w", encoding="utf-8") as f:
|
||||
yaml.safe_dump(merged_config, f, sort_keys=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -69,7 +69,7 @@ commit_queue_aliases:
|
||||
variant_tags: []
|
||||
task_tags: []
|
||||
- variant: "^(amazon-linux2023-arm64-dynamic-compile|linux-x86-dynamic-compile-required)$"
|
||||
task: "clang_tidy.*"
|
||||
task: "^bazel_run_clang_tidy$"
|
||||
variant_tags: []
|
||||
task_tags: []
|
||||
|
||||
@@ -107,6 +107,7 @@ post:
|
||||
- func: "attach task errors"
|
||||
- func: "attach artifacts"
|
||||
- func: "attach multiversion download links"
|
||||
- func: "generate clang-tidy report"
|
||||
- func: "save ec2 task artifacts"
|
||||
- func: "attach wiki page"
|
||||
- func: "upload docker compose"
|
||||
|
||||
@@ -631,16 +631,33 @@ functions:
|
||||
content_type: text/plain
|
||||
display_name: Pip Requirements
|
||||
|
||||
"run clang tidy": &run_clang_tidy
|
||||
- command: subprocess.exec
|
||||
params:
|
||||
binary: bash
|
||||
add_expansions_to_env: true
|
||||
args:
|
||||
"generate clang-tidy report sh": &generate_clang_tidy_report_sh
|
||||
command: subprocess.exec
|
||||
display_name: "generate clang-tidy report"
|
||||
type: test
|
||||
params:
|
||||
binary: bash
|
||||
args:
|
||||
- "src/evergreen/run_python_script.sh"
|
||||
- "buildscripts/clang_tidy.py"
|
||||
- "--split-jobs=4"
|
||||
- "--split=${split}"
|
||||
- "evergreen/generate_clang_tidy_report.py"
|
||||
|
||||
"enable run_for_clang_tidy expansions update":
|
||||
&enable_run_for_clang_tidy_expansions_update
|
||||
command: expansions.update
|
||||
display_name: "enable bazel test report creation"
|
||||
params:
|
||||
updates:
|
||||
- key: run_for_clang_tidy
|
||||
value: "true"
|
||||
|
||||
"enable run_for_clang_tidy expansions":
|
||||
- *f_expansions_write
|
||||
- *enable_run_for_clang_tidy_expansions_update
|
||||
- *f_expansions_write
|
||||
|
||||
"generate clang-tidy report":
|
||||
- *f_expansions_write
|
||||
- *generate_clang_tidy_report_sh
|
||||
|
||||
"upload clang tidy results": &upload_clang_tidy_results
|
||||
- command: s3.put
|
||||
|
||||
@@ -648,6 +648,32 @@ tasks:
|
||||
--keep_going
|
||||
--build_tag_filters=${bazel_filters_for_cache_hydration}
|
||||
|
||||
- name: run_bazel_clang_tidy
|
||||
tags:
|
||||
[
|
||||
"assigned_to_jira_team_devprod_build",
|
||||
"development_critical_single_variant",
|
||||
"requires_large_host",
|
||||
"clang_tidy",
|
||||
]
|
||||
exec_timeout_secs: 3600 # 1 hr timeout for the task overall, commit queue has a more specific timeout
|
||||
depends_on:
|
||||
- name: version_expansions_gen
|
||||
variant: generate-tasks-for-version
|
||||
commands:
|
||||
- func: "do bazel setup"
|
||||
- func: "enable run_for_clang_tidy expansions"
|
||||
- func: "bazel run"
|
||||
vars:
|
||||
target: >-
|
||||
mongo-tidy-test
|
||||
- func: "bazel compile"
|
||||
vars:
|
||||
# Note that we only run clang-tidy on the Mongo-authored targets, not on third-party code.
|
||||
targets: //src/mongo/...
|
||||
bazel_args: --config=clang-tidy --mongo_toolchain_version=${clang_tidy_toolchain|v5} --keep_going
|
||||
- func: "generate clang-tidy report"
|
||||
|
||||
- name: stitch_support_create_lib
|
||||
tags:
|
||||
[
|
||||
|
||||
63
evergreen/generate_clang_tidy_report.py
Normal file
63
evergreen/generate_clang_tidy_report.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from buildscripts.simple_report import make_report, put_report, try_combine_reports
|
||||
from buildscripts.util.read_config import read_config_file
|
||||
|
||||
expansions = read_config_file("../expansions.yml")
|
||||
clang_tidy = expansions.get("run_for_clang_tidy", None)
|
||||
|
||||
if clang_tidy:
|
||||
failures = []
|
||||
for root, _, files in os.walk("bazel-bin"):
|
||||
for name in files:
|
||||
if name.endswith(".clang-tidy.status") and "mongo_tidy_checks/tests/" not in root:
|
||||
with open(os.path.join(root, name)) as f:
|
||||
if f.read().strip() == "1":
|
||||
tokens = name.split(".")
|
||||
log_file = os.path.join(root, ".".join(tokens[:-1]) + ".log")
|
||||
with open(log_file) as log:
|
||||
content = log.read()
|
||||
|
||||
# exmaple
|
||||
# bazel-bin/src/mongo/shell/bazel_clang_tidy_src/mongo/shell/mongo_main.cpp.mongo_main_with_debug.clang-tidy.status
|
||||
# source_file is:
|
||||
# mongo_main.cpp
|
||||
# target is mongo_main_with_debug
|
||||
# target dir is src/mongo/shell
|
||||
filename = os.path.basename(log_file)
|
||||
parts = filename.split(".")
|
||||
if len(parts) < 5:
|
||||
raise ValueError(f"Unexpected status file format: {filename}")
|
||||
source_file = ".".join(parts[:2])
|
||||
target_name = parts[2]
|
||||
target_dir = re.search(
|
||||
r"bazel-bin/(.*)/bazel_clang_tidy_src/", log_file
|
||||
).group(1)
|
||||
target = f"//{target_dir}:{target_name}"
|
||||
content += f"Run 'bazel build --config=clang-tidy --keep_going {target}' to reproduce this error"
|
||||
|
||||
failures.append(
|
||||
[
|
||||
os.path.join(
|
||||
re.sub("^.*/bazel_clang_tidy_src/", "src/", root, 1),
|
||||
source_file,
|
||||
),
|
||||
content,
|
||||
]
|
||||
)
|
||||
|
||||
with open("bazel-invocation.txt", "w") as f:
|
||||
f.write("bazel build --config=clang-tidy //src/mongo/...")
|
||||
|
||||
if failures:
|
||||
for failure in failures:
|
||||
report = make_report(failure[0], failure[1], 1)
|
||||
try_combine_reports(report)
|
||||
put_report(report)
|
||||
sys.exit(1)
|
||||
else:
|
||||
report = make_report("bazel build --config=clang-tidy //src/mongo/...", "", 0)
|
||||
try_combine_reports(report)
|
||||
put_report(report)
|
||||
@@ -83,7 +83,7 @@ StringData CollectionTruncateMarkers::toString(
|
||||
|
||||
boost::optional<CollectionTruncateMarkers::Marker>
|
||||
CollectionTruncateMarkers::peekOldestMarkerIfNeeded(OperationContext* opCtx) const {
|
||||
stdx::lock_guard<std::mutex> lk(_markersMutex);
|
||||
stdx::lock_guard<Latch> lk(_markersMutex);
|
||||
|
||||
if (!_hasExcessMarkers(opCtx)) {
|
||||
return {};
|
||||
@@ -93,7 +93,7 @@ CollectionTruncateMarkers::peekOldestMarkerIfNeeded(OperationContext* opCtx) con
|
||||
}
|
||||
|
||||
void CollectionTruncateMarkers::popOldestMarker() {
|
||||
stdx::lock_guard<std::mutex> lk(_markersMutex);
|
||||
stdx::lock_guard<Latch> lk(_markersMutex);
|
||||
_markers.pop_front();
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void CollectionTruncateMarkers::createNewMarkerIfNeeded(const RecordId& lastReco
|
||||
// Try to lock the mutex, if we fail to lock then someone else is either already creating a new
|
||||
// marker or popping the oldest one. In the latter case, we let the next insert trigger the new
|
||||
// marker's creation.
|
||||
stdx::unique_lock<std::mutex> lk(_markersMutex, stdx::try_to_lock);
|
||||
stdx::unique_lock<Latch> lk(_markersMutex, stdx::try_to_lock);
|
||||
if (!lk) {
|
||||
logFailedLockAcquisition("_markersMutex");
|
||||
return;
|
||||
@@ -187,7 +187,7 @@ void CollectionTruncateMarkers::setMinBytesPerMarker(int64_t size) {
|
||||
}
|
||||
|
||||
void CollectionTruncateMarkers::initialSamplingFinished() {
|
||||
stdx::lock_guard<stdx::mutex> lk(_markersMutex);
|
||||
stdx::lock_guard<Latch> lk(_markersMutex);
|
||||
LOGV2_DEBUG(10167200, 2, "Initial sampling finished marked true.");
|
||||
_initialSamplingFinished = true;
|
||||
}
|
||||
@@ -557,7 +557,7 @@ void CollectionTruncateMarkersWithPartialExpiration::createPartialMarkerIfNecess
|
||||
// creating a new marker or popping the oldest one. In the latter case, we let the next check
|
||||
// trigger the new partial marker's creation.
|
||||
|
||||
stdx::unique_lock<std::mutex> lk(_markersMutex, stdx::try_to_lock);
|
||||
stdx::unique_lock<Latch> lk(_markersMutex, stdx::try_to_lock);
|
||||
if (!lk) {
|
||||
logFailedLockAcquisition("_markersMutex");
|
||||
return;
|
||||
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
static constexpr uint64_t kRandomSamplesPerMarker = 10;
|
||||
|
||||
size_t numMarkers() const {
|
||||
stdx::lock_guard<std::mutex> lk(_markersMutex);
|
||||
stdx::lock_guard<Latch> lk(_markersMutex);
|
||||
return _markers.size();
|
||||
}
|
||||
|
||||
@@ -311,7 +311,8 @@ private:
|
||||
|
||||
// Protects against concurrent access to the deque of collection markers and the
|
||||
// _initialSamplingFinished variable.
|
||||
mutable std::mutex _markersMutex;
|
||||
mutable Mutex _markersMutex = MONGO_MAKE_LATCH("CollectionTruncateMarkers::_markersMutex");
|
||||
|
||||
std::deque<Marker> _markers; // front = oldest, back = newest.
|
||||
|
||||
// Whether or not the initial set of markers has finished being sampled.
|
||||
@@ -349,7 +350,7 @@ protected:
|
||||
* markers will be created.
|
||||
*/
|
||||
bool isEmpty() const {
|
||||
stdx::lock_guard<std::mutex> lk(_markersMutex);
|
||||
stdx::lock_guard<Latch> lk(_markersMutex);
|
||||
return _markers.size() == 0 && _currentBytes.load() == 0 && _currentRecords.load() == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ void OplogCapMaintainerThread::run() {
|
||||
boost::optional<ScopedAdmissionPriority<ExecutionAdmissionContext>> admissionPriority;
|
||||
|
||||
{
|
||||
stdx::lock_guard<stdx::mutex> lk(_opCtxMutex);
|
||||
stdx::lock_guard<Latch> lk(_opCtxMutex);
|
||||
|
||||
// Initialize the thread's opCtx.
|
||||
_uniqueCtx.emplace(tc->makeOperationContext());
|
||||
@@ -251,7 +251,7 @@ void OplogCapMaintainerThread::run() {
|
||||
}
|
||||
|
||||
ON_BLOCK_EXIT([&] {
|
||||
stdx::lock_guard<stdx::mutex> lk(_opCtxMutex);
|
||||
stdx::lock_guard<Latch> lk(_opCtxMutex);
|
||||
admissionPriority.reset();
|
||||
_uniqueCtx.reset();
|
||||
});
|
||||
@@ -260,7 +260,7 @@ void OplogCapMaintainerThread::run() {
|
||||
if (gOplogSamplingAsyncEnabled) {
|
||||
try {
|
||||
{
|
||||
stdx::unique_lock<stdx::mutex> lk(_stateMutex);
|
||||
stdx::unique_lock<Latch> lk(_stateMutex);
|
||||
if (_shuttingDown) {
|
||||
return;
|
||||
}
|
||||
@@ -308,7 +308,7 @@ void OplogCapMaintainerThread::run() {
|
||||
// We need this check since the first check to _shuttingDown is guarded by
|
||||
// gOplogSamplingAsyncEnabled and we will never check this value if async is disabled.
|
||||
{
|
||||
stdx::unique_lock<stdx::mutex> lk(_stateMutex);
|
||||
stdx::unique_lock<Latch> lk(_stateMutex);
|
||||
if (_shuttingDown) {
|
||||
return;
|
||||
}
|
||||
@@ -344,7 +344,7 @@ void OplogCapMaintainerThread::shutdown(const Status& reason) {
|
||||
LOGV2_INFO(7474902, "Shutting down oplog cap maintainer thread", "reason"_attr = reason);
|
||||
|
||||
{
|
||||
stdx::lock_guard<stdx::mutex> lk(_opCtxMutex);
|
||||
stdx::lock_guard<Latch> lk(_opCtxMutex);
|
||||
if (_uniqueCtx) {
|
||||
stdx::lock_guard<Client> lk(*_uniqueCtx->get()->getClient());
|
||||
_uniqueCtx->get()->markKilled(reason.code());
|
||||
@@ -352,7 +352,7 @@ void OplogCapMaintainerThread::shutdown(const Status& reason) {
|
||||
}
|
||||
|
||||
{
|
||||
stdx::lock_guard<stdx::mutex> lk(_stateMutex);
|
||||
stdx::lock_guard<Latch> lk(_stateMutex);
|
||||
_shuttingDown = true;
|
||||
_shutdownReason = reason;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "mongo/db/auth/cluster_auth_mode.h"
|
||||
#include "mongo/db/namespace_string.h"
|
||||
#include "mongo/db/operation_context.h"
|
||||
#include "mongo/platform/mutex.h"
|
||||
#include "mongo/util/background.h"
|
||||
|
||||
namespace mongo {
|
||||
@@ -74,12 +75,12 @@ private:
|
||||
bool _deleteExcessDocuments(OperationContext* opCtx);
|
||||
|
||||
// Serializes setting/resetting _uniqueCtx and marking _uniqueCtx killed.
|
||||
mutable stdx::mutex _opCtxMutex;
|
||||
mutable Mutex _opCtxMutex = MONGO_MAKE_LATCH("OplogCapMaintainerThread::_opCtxMutex");
|
||||
|
||||
// Saves a reference to the cap maintainer thread's operation context.
|
||||
boost::optional<ServiceContext::UniqueOperationContext> _uniqueCtx;
|
||||
|
||||
mutable stdx::mutex _stateMutex;
|
||||
mutable Mutex _stateMutex = MONGO_MAKE_LATCH("OplogCapMaintainerThread::_stateMutex");
|
||||
bool _shuttingDown = false;
|
||||
Status _shutdownReason = Status::OK();
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <third_party/wiredtiger/wiredtiger.h>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <wiredtiger.h>
|
||||
|
||||
#include "mongo/base/data_type_endian.h"
|
||||
#include "mongo/base/data_view.h"
|
||||
|
||||
@@ -84,6 +84,7 @@ cc_library(
|
||||
"-Wno-noexcept-type",
|
||||
"-Wno-redundant-move",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-deprecated-enum-enum-conversion",
|
||||
"-Woverloaded-virtual",
|
||||
"-Wwrite-strings",
|
||||
"-Wsuggest-override",
|
||||
@@ -153,6 +154,7 @@ cc_shared_library(
|
||||
"-Wl,-O3",
|
||||
"-Wl,--gc-sections",
|
||||
"-Wl,-rpath,\\$ORIGIN/../lib", # Ensure that the shared library can find its dependencies.
|
||||
"-Wl,-rpath-link,external/mongo_toolchain_v4/stow/llvm-v4/lib",
|
||||
],
|
||||
deps = [
|
||||
":mongo_tidy_checks_static",
|
||||
|
||||
@@ -30,12 +30,35 @@
|
||||
#include "MongoCollectionShardingRuntimeCheck.h"
|
||||
|
||||
#include <clang-tidy/utils/OptionsUtils.h>
|
||||
#include <filesystem>
|
||||
|
||||
namespace mongo::tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
namespace {
|
||||
|
||||
std::string normalizeToCwdRelative(llvm::StringRef rawPath) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
fs::path p(rawPath.str());
|
||||
p = p.lexically_normal();
|
||||
|
||||
if (p.is_absolute()) {
|
||||
std::error_code ec;
|
||||
auto rel = fs::relative(p, fs::current_path(), ec);
|
||||
if (!ec) {
|
||||
p = std::move(rel);
|
||||
}
|
||||
}
|
||||
|
||||
// Force forward slashes for consistent StringRef::startswith comparisons.
|
||||
return p.generic_string();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MongoCollectionShardingRuntimeCheck::MongoCollectionShardingRuntimeCheck(
|
||||
StringRef Name, clang::tidy::ClangTidyContext* Context)
|
||||
: ClangTidyCheck(Name, Context),
|
||||
@@ -74,16 +97,25 @@ void MongoCollectionShardingRuntimeCheck::check(const MatchFinder::MatchResult&
|
||||
return;
|
||||
}
|
||||
|
||||
std::string suffix = "_test.cpp";
|
||||
// Check if FilePath ends with the suffix "_test.cpp"
|
||||
if (FilePath.size() > suffix.size() &&
|
||||
FilePath.rfind(suffix) == FilePath.size() - suffix.size()) {
|
||||
// Normalize to a path relative to the current working directory (Bazel execroot),
|
||||
// so we don't depend on absolute remote paths.
|
||||
const std::string normPath = normalizeToCwdRelative(FilePath);
|
||||
if (normPath.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string suffix = "_test.cpp";
|
||||
|
||||
// Skip tests.
|
||||
if (normPath.size() > suffix.size() &&
|
||||
normPath.rfind(suffix) == normPath.size() - suffix.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the file path is in an exception directory, skip the check.
|
||||
for (const auto& dir : this->exceptionDirs) {
|
||||
if (FilePath.startswith(dir)) {
|
||||
llvm::StringRef dirRef(dir);
|
||||
if (llvm::StringRef(normPath).startswith(dirRef)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
#include "MongoHeaderBracketCheck.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include <clang-tidy/utils/OptionsUtils.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Lex/PPCallbacks.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
#include <filesystem>
|
||||
#include <llvm/ADT/StringMap.h>
|
||||
#include <llvm/ADT/StringSet.h>
|
||||
|
||||
@@ -42,12 +44,52 @@ namespace mongo::tidy {
|
||||
|
||||
namespace {
|
||||
|
||||
bool startsWithAny(llvm::StringRef fullString, std::vector<std::string> const& startings) {
|
||||
return std::any_of(startings.cbegin(), startings.cend(), [&](llvm::StringRef starting) {
|
||||
return fullString.startswith(starting);
|
||||
static std::optional<std::string> canonicalFromSrc(const std::filesystem::path& full) { // NOLINT
|
||||
std::filesystem::path rel = full.lexically_normal();
|
||||
|
||||
// If absolute, try to make it relative to CWD (best effort; OK if it fails)
|
||||
if (rel.is_absolute()) {
|
||||
std::error_code ec;
|
||||
auto tmp = std::filesystem::relative(rel, std::filesystem::current_path(), ec);
|
||||
if (!ec)
|
||||
rel = std::move(tmp);
|
||||
}
|
||||
|
||||
bool seenSrc = false;
|
||||
std::filesystem::path out;
|
||||
for (const auto& comp : rel) {
|
||||
// Note: on Windows, comp is a path; compare as string ignoring slashes.
|
||||
if (!seenSrc) {
|
||||
if (comp == "src")
|
||||
seenSrc = true;
|
||||
continue;
|
||||
}
|
||||
out /= comp;
|
||||
}
|
||||
if (!seenSrc || out.empty())
|
||||
return std::nullopt;
|
||||
return out.generic_string(); // forward slashes
|
||||
}
|
||||
|
||||
|
||||
bool containsAny(llvm::StringRef fullString, const std::vector<std::string>& patterns) {
|
||||
namespace fs = std::filesystem;
|
||||
const auto cwd = fs::current_path();
|
||||
|
||||
return std::any_of(patterns.begin(), patterns.end(), [&](const std::string& pattern) {
|
||||
fs::path p(pattern);
|
||||
|
||||
// Ensure a trailing separator so we only match directory names.
|
||||
auto patRel = (p / "").generic_string();
|
||||
if (fullString.contains(patRel))
|
||||
return true;
|
||||
|
||||
auto absolute = (cwd / p / "").generic_string();
|
||||
return fullString.contains(absolute);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
class MongoIncludeBracketsPPCallbacks : public clang::PPCallbacks {
|
||||
public:
|
||||
explicit MongoIncludeBracketsPPCallbacks(MongoHeaderBracketCheck& Check,
|
||||
@@ -73,6 +115,10 @@ public:
|
||||
(std::filesystem::path(SearchPath.str()) / std::filesystem::path(RelativePath.str()))
|
||||
.lexically_normal();
|
||||
|
||||
// If the computed path doesn’t actually exist on disk, ignore it as it would not be used.
|
||||
if (!std::filesystem::exists(header_path)) {
|
||||
return;
|
||||
}
|
||||
// This represents the full path from the project root to the
|
||||
// source file that is including the include that is currently being processed.
|
||||
std::filesystem::path origin_source_path(HashLoc.printToString(SM));
|
||||
@@ -83,12 +129,12 @@ public:
|
||||
|
||||
// if this is a mongo source file including a real file
|
||||
if (!llvm::StringRef(origin_source_path).startswith("<built-in>:") &&
|
||||
startsWithAny(llvm::StringRef(origin_source_path.lexically_normal()),
|
||||
Check.mongoSourceDirs)) {
|
||||
containsAny(llvm::StringRef(origin_source_path.lexically_normal()),
|
||||
Check.mongoSourceDirs)) {
|
||||
|
||||
// Check that the a third party header which is included from a mongo source file
|
||||
// is used angle brackets.
|
||||
if (!IsAngled && !startsWithAny(llvm::StringRef(header_path), Check.mongoSourceDirs)) {
|
||||
if (!IsAngled && !containsAny(llvm::StringRef(header_path), Check.mongoSourceDirs)) {
|
||||
|
||||
std::string Replacement = (llvm::Twine("<") + FileName + ">").str();
|
||||
Check.diag(FilenameRange.getBegin(),
|
||||
@@ -99,9 +145,9 @@ public:
|
||||
|
||||
// Check that the a third party header which is in our vendored tree is not including
|
||||
// the third_party in the include path.
|
||||
if (!startsWithAny(llvm::StringRef(header_path), Check.mongoSourceDirs) &&
|
||||
llvm::StringRef(header_path).startswith("src/third_party") &&
|
||||
FileName.startswith("third_party")) {
|
||||
if (!containsAny(llvm::StringRef(header_path), Check.mongoSourceDirs) &&
|
||||
llvm::StringRef(header_path).contains("src/third_party/") &&
|
||||
FileName.contains("third_party/")) {
|
||||
Check.diag(FilenameRange.getBegin(),
|
||||
"third_party include '%0' should not start with 'third_party/'. The "
|
||||
"included file should be useable in either context of system or "
|
||||
@@ -111,12 +157,17 @@ public:
|
||||
|
||||
// Check that the a mongo header which is included from a mongo source file
|
||||
// is used double quotes.
|
||||
else if (IsAngled &&
|
||||
startsWithAny(llvm::StringRef(header_path), Check.mongoSourceDirs)) {
|
||||
std::string Replacement = (llvm::Twine("\"") + FileName + "\"").str();
|
||||
Check.diag(FilenameRange.getBegin(), "mongo include '%0' should use double quotes")
|
||||
<< FileName
|
||||
<< clang::FixItHint::CreateReplacement(FilenameRange.getAsRange(), Replacement);
|
||||
else if (IsAngled && containsAny(llvm::StringRef(header_path), Check.mongoSourceDirs)) {
|
||||
// TODO(SERVER-95253): Explicitly handle third party headers inside of the
|
||||
// enterprise module directory.
|
||||
if (!FileName.contains("bsoncxx/") && !FileName.contains("mongocxx/")) {
|
||||
std::string Replacement = (llvm::Twine("\"") + FileName + "\"").str();
|
||||
Check.diag(FilenameRange.getBegin(),
|
||||
"mongo include '%0' should use double quotes")
|
||||
<< FileName
|
||||
<< clang::FixItHint::CreateReplacement(FilenameRange.getAsRange(),
|
||||
Replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
namespace mongo::tidy {
|
||||
|
||||
/**
|
||||
Overrides the default PPCallback class to primarly override
|
||||
Overrides the default PPCallback class to primarily override
|
||||
the InclusionDirective call which is called for each include included. This
|
||||
allows the chance to evaluate specifically the include and determine whether
|
||||
it is considered a "mongo" include or not and if it is using the appropriate include style.
|
||||
@@ -46,7 +46,12 @@ public:
|
||||
void registerPPCallbacks(const clang::SourceManager& SM,
|
||||
clang::Preprocessor* PP,
|
||||
clang::Preprocessor* ModuleExpanderPP) override;
|
||||
// used to store option `mongoSourceDirs`; supports both absolute and relative paths
|
||||
std::vector<std::string> mongoSourceDirs;
|
||||
|
||||
// The path component that denotes the repo's root source directory (default: "src").
|
||||
// Used to compute canonical include paths "from src/".
|
||||
std::string srcRootComponent;
|
||||
};
|
||||
|
||||
} // namespace mongo::tidy
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
load("//bazel:mongo_src_rules.bzl", "mongo_cc_binary")
|
||||
load("//bazel:mongo_src_rules.bzl", "mongo_cc_binary", "mongo_cc_library")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob([
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"*.inl",
|
||||
"*.hpp",
|
||||
"*.py",
|
||||
"*.in",
|
||||
]))
|
||||
exports_files(
|
||||
glob([
|
||||
"*.h",
|
||||
"*.cpp",
|
||||
"*.tidy_config",
|
||||
]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "tidy_check_headers",
|
||||
srcs = glob(["*.h"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "tests_global_hdrs",
|
||||
@@ -20,61 +24,82 @@ filegroup(
|
||||
]),
|
||||
)
|
||||
|
||||
mongo_cc_binary(
|
||||
name = "MongoTidyCheck_test",
|
||||
srcs = ["MongoTidyCheckTestMain.cpp"] + [
|
||||
# This list represents the test source files, which should contain a single issue which will be flagged
|
||||
# by a clang tidy check. The issue should be isolated in as minimal way as possible.
|
||||
"test_MongoHeaderBracketCheck.cpp",
|
||||
"test_MongoHeaderBracketCheck.h",
|
||||
"test_MongoVolatileCheck.cpp",
|
||||
"test_MongoUninterruptibleLockGuardCheck.cpp",
|
||||
"test_MongoUninterruptibleLockGuardCheckForOpCtxMember.cpp",
|
||||
"test_MongoCctypeCheck.cpp",
|
||||
"test_MongoCctypeCheck.h",
|
||||
"test_MongoConfigHeaderCheck.cpp",
|
||||
"test_MongoCxx20BannedIncludesCheck.cpp",
|
||||
"test_MongoCxx20StdChronoCheck.cpp",
|
||||
"test_MongoStdOptionalCheck.cpp",
|
||||
"test_MongoTraceCheck.cpp",
|
||||
"test_MongoStdAtomicCheck.cpp",
|
||||
"test_MongoAssertCheck.cpp",
|
||||
"test_MongoFCVConstantCheck.cpp",
|
||||
"test_MongoUnstructuredLogCheck.cpp",
|
||||
"test_MongoCollectionShardingRuntimeCheck.cpp",
|
||||
"test_MongoMacroDefinitionLeaksCheck.cpp",
|
||||
"test_MongoMacroDefinitionLeaksCheck.h",
|
||||
"test_MongoRandCheck.cpp",
|
||||
"test_MongoPolyFillCheck.cpp",
|
||||
"test_MongoNoUniqueAddressCheck.cpp",
|
||||
"test_MongoStringDataConstRefCheck1.cpp",
|
||||
"test_MongoStringDataConstRefCheck2.cpp",
|
||||
"test_MongoStringDataConstRefCheck3.cpp",
|
||||
"test_MongoMutexCheck.cpp",
|
||||
],
|
||||
# These test files will purposefully be error prone, so we can disable warnings any warnings we expect
|
||||
# to see.
|
||||
copts = [
|
||||
"-Wno-unused-variable",
|
||||
"-Wno-return-type",
|
||||
"-Wno-deprecated-volatile",
|
||||
],
|
||||
includes = ["."],
|
||||
skip_global_deps = [
|
||||
"allocator",
|
||||
"libunwind",
|
||||
],
|
||||
tags = [
|
||||
"mongo-tidy-tests",
|
||||
],
|
||||
target_compatible_with = select({
|
||||
"@platforms//os:windows": ["@platforms//:incompatible"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
deps = [
|
||||
"//src/third_party/s2",
|
||||
],
|
||||
)
|
||||
tests = [
|
||||
# This list represents the test source files, which should contain a single issue which will be flagged
|
||||
# by a clang tidy check. The issue should be isolated in as minimal way as possible.
|
||||
"test_MongoHeaderBracketCheck",
|
||||
"test_MongoVolatileCheck",
|
||||
"test_MongoUninterruptibleLockGuardCheck",
|
||||
"test_MongoUninterruptibleLockGuardCheckForOpCtxMember",
|
||||
"test_MongoCctypeCheck",
|
||||
"test_MongoConfigHeaderCheck",
|
||||
"test_MongoCxx20BannedIncludesCheck",
|
||||
"test_MongoCxx20StdChronoCheck",
|
||||
"test_MongoStdOptionalCheck",
|
||||
"test_MongoTraceCheck",
|
||||
"test_MongoStdAtomicCheck",
|
||||
"test_MongoAssertCheck",
|
||||
"test_MongoFCVConstantCheck",
|
||||
"test_MongoUnstructuredLogCheck",
|
||||
"test_MongoCollectionShardingRuntimeCheck",
|
||||
"test_MongoMacroDefinitionLeaksCheck",
|
||||
"test_MongoRandCheck",
|
||||
"test_MongoPolyFillCheck",
|
||||
"test_MongoNoUniqueAddressCheck",
|
||||
"test_MongoStringDataConstRefCheck1",
|
||||
"test_MongoStringDataConstRefCheck2",
|
||||
"test_MongoStringDataConstRefCheck3",
|
||||
"test_MongoMutexCheck",
|
||||
]
|
||||
|
||||
[
|
||||
mongo_cc_library(
|
||||
name = test,
|
||||
srcs = [
|
||||
test + ".cpp",
|
||||
"tidy_check_headers",
|
||||
],
|
||||
# These test files will purposefully be error prone, so we can disable warnings any warnings we expect
|
||||
# to see.
|
||||
copts = [
|
||||
"-Wno-unused-but-set-parameter",
|
||||
"-Wno-unused-variable",
|
||||
"-Wno-return-type",
|
||||
"-Isrc/mongo/tools/mongo_tidy_checks/tests",
|
||||
"-Isrc/mongo", # for mongo header path test
|
||||
] + select({
|
||||
"//bazel/config:compiler_type_gcc": ["-Wno-volatile"],
|
||||
"//bazel/config:compiler_type_clang": ["-Wno-deprecated-volatile"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
skip_global_deps = [
|
||||
"allocator",
|
||||
"libunwind",
|
||||
],
|
||||
tags = [
|
||||
"mongo-tidy-tests",
|
||||
],
|
||||
target_compatible_with = select({
|
||||
"@platforms//os:linux": [],
|
||||
"//conditions:default": ["@platforms//:incompatible"],
|
||||
}) + select({
|
||||
"//bazel/config:linkstatic_disabled": ["@platforms//:incompatible"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
deps = [
|
||||
"//src/third_party/s2",
|
||||
],
|
||||
)
|
||||
for test in tests
|
||||
]
|
||||
|
||||
[
|
||||
filegroup(
|
||||
name = test + "_tidy_config",
|
||||
srcs = [test + ".tidy_config"],
|
||||
)
|
||||
for test in tests
|
||||
]
|
||||
|
||||
py_binary(
|
||||
name = "MongoTidyCheck_unittest",
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2023-present MongoDB, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Server Side Public License, version 1,
|
||||
* as published by MongoDB, Inc.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* Server Side Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the Server Side Public License
|
||||
* along with this program. If not, see
|
||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
||||
*
|
||||
* As a special exception, the copyright holders give permission to link the
|
||||
* code of portions of this program with the OpenSSL library under certain
|
||||
* conditions as described in each individual source file and distribute
|
||||
* linked combinations including the program with the OpenSSL library. You
|
||||
* must comply with the Server Side Public License in all respects for
|
||||
* all of the code used other than as permitted herein. If you modify file(s)
|
||||
* with this exception, you may extend this exception to your version of the
|
||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
||||
* delete this exception statement from your version. If you delete this
|
||||
* exception statement from all source files in the program, then also delete
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1,46 +1,45 @@
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
|
||||
class MongoTidyTests(unittest.TestCase):
|
||||
TIDY_BIN = None
|
||||
TIDY_MODULE = None
|
||||
COMPILE_COMMANDS_FILES = []
|
||||
|
||||
def write_config(self, config_str: str):
|
||||
self.config_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
|
||||
self.config_file.write(config_str)
|
||||
self.config_file.close()
|
||||
self.cmd += [f'--clang-tidy-cfg={self.config_file.name}']
|
||||
return self.config_file.name
|
||||
|
||||
def run_clang_tidy(self):
|
||||
p = subprocess.run(self.cmd, capture_output=True, text=True)
|
||||
cmd = [
|
||||
"bazel",
|
||||
"build",
|
||||
"--config=clang-tidy",
|
||||
"--skip_archive=False",
|
||||
"--build_tag_filters=mongo-tidy-tests",
|
||||
"--@bazel_clang_tidy//:clang_tidy_config=//src/mongo/tools/mongo_tidy_checks/tests:"
|
||||
+ self._testMethodName
|
||||
+ "_tidy_config",
|
||||
"//src/mongo/tools/mongo_tidy_checks/tests:" + self._testMethodName + "_with_debug",
|
||||
]
|
||||
p = subprocess.run(
|
||||
cmd, cwd=os.environ.get("BUILD_WORKSPACE_DIRECTORY"), capture_output=True, text=True
|
||||
)
|
||||
|
||||
if isinstance(self.expected_output, list):
|
||||
passed = all([expected_output in p.stdout for expected_output in self.expected_output])
|
||||
print_expected_output = "\n".join(self.expected_output)
|
||||
else:
|
||||
passed = self.expected_output is not None and self.expected_output in p.stdout
|
||||
print_expected_output = self.expected_output
|
||||
|
||||
with open(self.config_file.name) as f:
|
||||
msg = '\n'.join([
|
||||
'>' * 80,
|
||||
msg = "\n".join(
|
||||
[
|
||||
">" * 80,
|
||||
f"Mongo Tidy Unittest {self._testMethodName}: {'PASSED' if passed else 'FAILED'}",
|
||||
"",
|
||||
"Command:",
|
||||
' '.join(self.cmd),
|
||||
"",
|
||||
"With config:",
|
||||
f.read(),
|
||||
" ".join(cmd),
|
||||
"",
|
||||
f"Exit code was: {p.returncode}",
|
||||
"",
|
||||
f"Output expected in stdout: {self.expected_output}",
|
||||
"Output expected in stdout: ",
|
||||
f"{print_expected_output}",
|
||||
"",
|
||||
"stdout was:",
|
||||
p.stdout,
|
||||
@@ -48,49 +47,19 @@ class MongoTidyTests(unittest.TestCase):
|
||||
"stderr was:",
|
||||
p.stderr,
|
||||
"",
|
||||
'<' * 80,
|
||||
])
|
||||
|
||||
if passed:
|
||||
sys.stderr.write(msg)
|
||||
else:
|
||||
print(msg)
|
||||
self.fail()
|
||||
|
||||
with open(f'{os.path.splitext(self.compile_db)[0]}.results', 'w') as results:
|
||||
results.write(msg)
|
||||
|
||||
def setUp(self):
|
||||
self.config_file = None
|
||||
self.expected_output = None
|
||||
for compiledb in self.COMPILE_COMMANDS_FILES:
|
||||
if compiledb.endswith("/" + self._testMethodName + "/compile_commands.json"):
|
||||
self.compile_db = compiledb
|
||||
if self.compile_db:
|
||||
self.cmd = [
|
||||
sys.executable,
|
||||
'buildscripts/clang_tidy.py',
|
||||
'--disable-reporting',
|
||||
f'--check-module={self.TIDY_MODULE}',
|
||||
f'--output-dir={os.path.join(os.path.dirname(self.compile_db), self._testMethodName + "_out")}',
|
||||
f'--compile-commands={self.compile_db}',
|
||||
"<" * 80,
|
||||
]
|
||||
else:
|
||||
raise (f"ERROR: did not findh matching compiledb for {self._testMethodName}")
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
if self.config_file:
|
||||
self.config_file.close()
|
||||
os.unlink(self.config_file.name)
|
||||
if passed:
|
||||
if os.environ.get("CI"):
|
||||
print(msg)
|
||||
else:
|
||||
sys.stderr.write(msg)
|
||||
self.fail()
|
||||
|
||||
def test_MongoHeaderBracketCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-header-bracket-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: non-mongo include 'cctype' should use angle brackets",
|
||||
"error: mongo include 'test_MongoHeaderBracketCheck.h' should use double quotes",
|
||||
@@ -101,12 +70,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoUninterruptibleLockGuardCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-uninterruptible-lock-guard-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = (
|
||||
"Potentially incorrect use of UninterruptibleLockGuard, "
|
||||
"the programming model inside MongoDB requires that all operations be interruptible. "
|
||||
@@ -117,12 +80,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoUninterruptibleLockGuardCheckForOpCtxMember(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-uninterruptible-lock-guard-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = (
|
||||
"Potentially incorrect use of "
|
||||
"OperationContext::uninterruptibleLocksRequested_DO_NOT_USE, this is a legacy "
|
||||
@@ -136,13 +93,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoCctypeCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-cctype-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Use of prohibited \"cctype\" header, use \"mongo/util/ctype.h\"",
|
||||
"Use of prohibited <ctype.h> header, use \"mongo/util/ctype.h\"",
|
||||
@@ -152,13 +102,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoCxx20BannedIncludesCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-cxx20-banned-includes-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Use of prohibited <syncstream> header.",
|
||||
"Use of prohibited <ranges> header.",
|
||||
@@ -170,11 +113,7 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoCxx20StdChronoCheck(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-cxx20-std-chrono-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
prohibited_types = ["day", "day", "month", "year", "month_day", "month", "day", "day"]
|
||||
self.expected_output = [
|
||||
f"Illegal use of prohibited type 'std::chrono::{t}'." for t in prohibited_types
|
||||
@@ -183,12 +122,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoStdOptionalCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-std-optional-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Use of std::optional, use boost::optional instead. [mongo-std-optional-check,-warnings-as-errors]\nvoid f(std::optional<std::string> parameterDeclTest) {",
|
||||
"Use of std::optional, use boost::optional instead. [mongo-std-optional-check,-warnings-as-errors]\n std::optional<std::string> variableDeclTest;",
|
||||
@@ -203,12 +136,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoVolatileCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-volatile-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Illegal use of the volatile storage keyword, use AtomicWord instead from \"mongo/platform/atomic_word.h\" [mongo-volatile-check,-warnings-as-errors]\nvolatile int varVolatileTest;",
|
||||
"Illegal use of the volatile storage keyword, use AtomicWord instead from \"mongo/platform/atomic_word.h\" [mongo-volatile-check,-warnings-as-errors]\n volatile int fieldVolatileTest;",
|
||||
@@ -219,12 +146,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoTraceCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-trace-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Illegal use of prohibited tracing support, this is only for local development use and should not be committed. [mongo-trace-check,-warnings-as-errors]\n TracerProvider::initialize();",
|
||||
"Illegal use of prohibited tracing support, this is only for local development use and should not be committed. [mongo-trace-check,-warnings-as-errors]\n TracerProvider provider = TracerProvider::get();",
|
||||
@@ -234,12 +155,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoStdAtomicCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-std-atomic-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Illegal use of prohibited std::atomic<T>, use AtomicWord<T> or other types from \"mongo/platform/atomic_word.h\" [mongo-std-atomic-check,-warnings-as-errors]\nstd::atomic<int> atomic_var;",
|
||||
"Illegal use of prohibited std::atomic<T>, use AtomicWord<T> or other types from \"mongo/platform/atomic_word.h\" [mongo-std-atomic-check,-warnings-as-errors]\n std::atomic<int> field_decl;",
|
||||
@@ -249,12 +164,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoMutexCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-mutex-check,mongo-std-atomic-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Illegal use of prohibited stdx::mutex, use mongo::Mutex from mongo/platform/mutex.h instead. [mongo-mutex-check,-warnings-as-errors]\nstdx::mutex stdxmutex_vardecl;",
|
||||
"Illegal use of prohibited stdx::mutex, use mongo::Mutex from mongo/platform/mutex.h instead. [mongo-mutex-check,-warnings-as-errors]\nstd::mutex stdmutex_vardecl;",
|
||||
@@ -266,12 +175,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoAssertCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-assert-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of the bare assert function, use a function from assert_util.h instead",
|
||||
]
|
||||
@@ -280,12 +183,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoFCVConstantCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-fcv-constant-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of FCV constant in FCV comparison check functions. FCV gating should be done through feature flags instead.",
|
||||
]
|
||||
@@ -294,12 +191,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoUnstructuredLogCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-unstructured-log-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of unstructured logging, this is only for local development use and should not be committed [mongo-unstructured-log-check,-warnings-as-errors]\n logd();",
|
||||
"error: Illegal use of unstructured logging, this is only for local development use and should not be committed [mongo-unstructured-log-check,-warnings-as-errors]\n doUnstructuredLogImpl();",
|
||||
@@ -309,13 +200,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoConfigHeaderCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-config-header-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: MONGO_CONFIG define used without prior inclusion of config.h [mongo-config-header-check,-warnings-as-errors]\n#define MONGO_CONFIG_TEST1 1",
|
||||
"error: MONGO_CONFIG define used without prior inclusion of config.h [mongo-config-header-check,-warnings-as-errors]\n#ifdef MONGO_CONFIG_TEST1",
|
||||
@@ -327,15 +211,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
def test_MongoCollectionShardingRuntimeCheck(self):
|
||||
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-collection-sharding-runtime-check'
|
||||
WarningsAsErrors: '*'
|
||||
CheckOptions:
|
||||
- key: mongo-collection-sharding-runtime-check.exceptionDirs
|
||||
value: 'src/mongo/db/s'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of CollectionShardingRuntime outside of mongo/db/s/; use CollectionShardingState instead; see src/mongo/db/s/collection_sharding_state.h for details. [mongo-collection-sharding-runtime-check,-warnings-as-errors]\n CollectionShardingRuntime csr(5, \"Test\");",
|
||||
"error: Illegal use of CollectionShardingRuntime outside of mongo/db/s/; use CollectionShardingState instead; see src/mongo/db/s/collection_sharding_state.h for details. [mongo-collection-sharding-runtime-check,-warnings-as-errors]\n int result = CollectionShardingRuntime::functionTest(7, \"Test\");",
|
||||
@@ -344,12 +219,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoMacroDefinitionLeaksCheck(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-macro-definition-leaks-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Missing #undef 'MONGO_LOGV2_DEFAULT_COMPONENT'",
|
||||
@@ -358,12 +227,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoNoUniqueAddressCheck(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-no-unique-address-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Illegal use of [[no_unique_address]]",
|
||||
@@ -372,11 +235,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoPolyFillCheck(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-polyfill-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: Illegal use of banned name from std::/boost:: for std::mutex, use mongo::stdx:: variant instead",
|
||||
@@ -389,11 +247,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoRandCheck(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-rand-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"error: Use of rand or srand, use <random> or PseudoRandom instead. [mongo-rand-check,-warnings-as-errors]\n srand(time(0));",
|
||||
@@ -403,11 +256,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoStringDataConstRefCheck1(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-stringdata-const-ref-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Prefer passing StringData by value.",
|
||||
@@ -416,11 +264,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoStringDataConstRefCheck2(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-stringdata-const-ref-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"Prefer passing StringData by value.",
|
||||
@@ -429,11 +272,6 @@ class MongoTidyTests(unittest.TestCase):
|
||||
self.run_clang_tidy()
|
||||
|
||||
def test_MongoStringDataConstRefCheck3(self):
|
||||
self.write_config(
|
||||
textwrap.dedent("""\
|
||||
Checks: '-*,mongo-stringdata-const-ref-check'
|
||||
WarningsAsErrors: '*'
|
||||
"""))
|
||||
|
||||
self.expected_output = [
|
||||
"",
|
||||
@@ -441,34 +279,5 @@ class MongoTidyTests(unittest.TestCase):
|
||||
|
||||
self.run_clang_tidy()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--clang-tidy-path', default='/opt/mongodbtoolchain/v4/bin/clang-tidy',
|
||||
help="Path to clang-tidy binary.")
|
||||
parser.add_argument('--mongo-tidy-module', default='bazel-bin/install/lib/libmongo_tidy_checks.so',
|
||||
help="Path to mongo tidy check library.")
|
||||
parser.add_argument(
|
||||
'--test-compiledbs', action='append', default=[],
|
||||
help="Used multiple times. Each use adds a test compilation database to use. " +
|
||||
"The compilation database name must match the unittest method name.")
|
||||
parser.add_argument('unittest_args', nargs='*')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
MongoTidyTests.TIDY_BIN = args.clang_tidy_path
|
||||
MongoTidyTests.TIDY_MODULE = args.mongo_tidy_module
|
||||
MongoTidyTests.COMPILE_COMMANDS_FILES = args.test_compiledbs
|
||||
|
||||
# We need to validate the toolchain can support the load operation for our module.
|
||||
cmd = [MongoTidyTests.TIDY_BIN, '-load', MongoTidyTests.TIDY_MODULE, '--list-checks']
|
||||
p = subprocess.run(cmd, capture_output=True)
|
||||
if p.returncode != 0:
|
||||
print(f"Could not validate toolchain was able to load module {cmd}.")
|
||||
sys.exit(1)
|
||||
|
||||
# Workaround to allow use to use argparse on top of unittest module.
|
||||
sys.argv[1:] = args.unittest_args
|
||||
|
||||
unittest.main()
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-assert-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,3 @@
|
||||
Checks: '-*,mongo-cctype-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
@@ -0,0 +1,5 @@
|
||||
Checks: '-*,mongo-collection-sharding-runtime-check'
|
||||
WarningsAsErrors: '*'
|
||||
CheckOptions:
|
||||
- key: mongo-collection-sharding-runtime-check.exceptionDirs
|
||||
value: 'src/mongo/db/s'
|
||||
@@ -0,0 +1,3 @@
|
||||
Checks: '-*,mongo-config-header-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
@@ -0,0 +1,3 @@
|
||||
Checks: '-*,mongo-cxx20-banned-includes-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-cxx20-std-chrono-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-fcv-constant-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-header-bracket-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,3 @@
|
||||
Checks: '-*,mongo-macro-definition-leaks-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-mutex-check,mongo-std-atomic-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,3 @@
|
||||
Checks: '-*,mongo-no-unique-address-check'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '(mongo/.*)'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-polyfill-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-rand-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-std-atomic-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-std-optional-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-stringdata-const-ref-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-stringdata-const-ref-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-stringdata-const-ref-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-trace-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-uninterruptible-lock-guard-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-uninterruptible-lock-guard-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-unstructured-log-check'
|
||||
WarningsAsErrors: '*'
|
||||
@@ -0,0 +1,2 @@
|
||||
Checks: '-*,mongo-volatile-check'
|
||||
WarningsAsErrors: '*'
|
||||
Reference in New Issue
Block a user