mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 02:33:24 -03:00
Merge bitcoin/bitcoin#30219: Lint: Support running individual lint checks
0fcbfdb7ad
Support running individual lint checks (David Gumberg) Pull request description: This PR was split out from #29965: Adds support for running individual tests in the rust lint suite by passing `--lint=LINT_TO_RUN` to the lint runner. This PR also adds a corresponding help message. When running with `cargo run`, arguments after a double dash (`--`) are passed to the binary instead of the cargo command. For example, in order to run the linter check that tabs are not used as whitespace: ```console cd test/lint/test_runner && cargo run -- --lint=tabs_whitespace ``` ACKs for top commit: maflcko: ACK0fcbfdb7ad
achow101: ACK0fcbfdb7ad
marcofleon: Tested ACK0fcbfdb7ad
. Ran `cargo run` with various of the individual tests and with bad input. Also ran it with no arguments. Everything works as expected and help message looks good. Tree-SHA512: 48fe4aa9fbb2acef5f8e3c17382ae22e0e350ae6ad9aeeb1a3c0a9192de98809f98728e32b8db24a36906ace999e35626ebd6cb2ca05f74146d21e9b6fb14615
This commit is contained in:
commit
ff21eb2def
2 changed files with 138 additions and 15 deletions
|
@ -26,6 +26,21 @@ Then you can use:
|
|||
( cd ./test/lint/test_runner/ && cargo fmt && cargo clippy && RUST_BACKTRACE=1 cargo run )
|
||||
```
|
||||
|
||||
If you wish to run individual lint checks, run the test_runner with
|
||||
`--lint=TEST_TO_RUN` arguments. If running with `cargo run`, arguments after
|
||||
`--` are passed to the binary you are running e.g.:
|
||||
|
||||
```sh
|
||||
( cd ./test/lint/test_runner/ && RUST_BACKTRACE=1 cargo run -- --lint=doc --lint=trailing_whitespace )
|
||||
```
|
||||
|
||||
To see a list of all individual lint checks available in test_runner, use `-h`
|
||||
or `--help`:
|
||||
|
||||
```sh
|
||||
( cd ./test/lint/test_runner/ && RUST_BACKTRACE=1 cargo run -- --help )
|
||||
```
|
||||
|
||||
#### Dependencies
|
||||
|
||||
| Lint test | Dependency |
|
||||
|
|
|
@ -12,6 +12,113 @@ type LintError = String;
|
|||
type LintResult = Result<(), LintError>;
|
||||
type LintFn = fn() -> LintResult;
|
||||
|
||||
struct Linter {
|
||||
pub description: &'static str,
|
||||
pub name: &'static str,
|
||||
pub lint_fn: LintFn,
|
||||
}
|
||||
|
||||
fn get_linter_list() -> Vec<&'static Linter> {
|
||||
vec![
|
||||
&Linter {
|
||||
description: "Check that all command line arguments are documented.",
|
||||
name: "doc",
|
||||
lint_fn: lint_doc
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that no symbol from bitcoin-config.h is used without the header being included",
|
||||
name: "includes_build_config",
|
||||
lint_fn: lint_includes_build_config
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that markdown links resolve",
|
||||
name: "markdown",
|
||||
lint_fn: lint_markdown
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that std::filesystem is not used directly",
|
||||
name: "std_filesystem",
|
||||
lint_fn: lint_std_filesystem
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that subtrees are pure subtrees",
|
||||
name: "subtree",
|
||||
lint_fn: lint_subtree
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that tabs are not used as whitespace",
|
||||
name: "tabs_whitespace",
|
||||
lint_fn: lint_tabs_whitespace
|
||||
},
|
||||
&Linter {
|
||||
description: "Check for trailing whitespace",
|
||||
name: "trailing_whitespace",
|
||||
lint_fn: lint_trailing_whitespace
|
||||
},
|
||||
&Linter {
|
||||
description: "Run all linters of the form: test/lint/lint-*.py",
|
||||
name: "all_python_linters",
|
||||
lint_fn: run_all_python_linters
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn print_help_and_exit() {
|
||||
print!(
|
||||
r#"
|
||||
Usage: test_runner [--lint=LINTER_TO_RUN]
|
||||
Runs all linters in the lint test suite, printing any errors
|
||||
they detect.
|
||||
|
||||
If you wish to only run some particular lint tests, pass
|
||||
'--lint=' with the name of the lint test you wish to run.
|
||||
You can set as many '--lint=' values as you wish, e.g.:
|
||||
test_runner --lint=doc --lint=subtree
|
||||
|
||||
The individual linters available to run are:
|
||||
"#
|
||||
);
|
||||
for linter in get_linter_list() {
|
||||
println!("{}: \"{}\"", linter.name, linter.description)
|
||||
}
|
||||
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
fn parse_lint_args(args: &[String]) -> Vec<&'static Linter> {
|
||||
let linter_list = get_linter_list();
|
||||
let mut lint_values = Vec::new();
|
||||
|
||||
for arg in args {
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
if arg.starts_with("--lint=") {
|
||||
let lint_arg_value = arg
|
||||
.trim_start_matches("--lint=")
|
||||
.trim_matches('"')
|
||||
.trim_matches('\'');
|
||||
|
||||
let try_find_linter = linter_list
|
||||
.iter()
|
||||
.find(|linter| linter.name == lint_arg_value);
|
||||
match try_find_linter {
|
||||
Some(linter) => {
|
||||
lint_values.push(*linter);
|
||||
}
|
||||
None => {
|
||||
println!("No linter {lint_arg_value} found!");
|
||||
print_help_and_exit();
|
||||
}
|
||||
}
|
||||
} else if arg.eq("--help") || arg.eq("-h") {
|
||||
print_help_and_exit();
|
||||
} else {
|
||||
print_help_and_exit();
|
||||
}
|
||||
}
|
||||
|
||||
lint_values
|
||||
}
|
||||
|
||||
/// Return the git command
|
||||
fn git() -> Command {
|
||||
let mut git = Command::new("git");
|
||||
|
@ -337,7 +444,7 @@ Markdown link errors found:
|
|||
}
|
||||
}
|
||||
|
||||
fn lint_all() -> LintResult {
|
||||
fn run_all_python_linters() -> LintResult {
|
||||
let mut good = true;
|
||||
let lint_dir = get_git_root().join("test/lint");
|
||||
for entry in fs::read_dir(lint_dir).unwrap() {
|
||||
|
@ -352,7 +459,7 @@ fn lint_all() -> LintResult {
|
|||
.success()
|
||||
{
|
||||
good = false;
|
||||
println!("^---- failure generated from {}", entry_fn);
|
||||
println!("^---- ⚠️ Failure generated from {}", entry_fn);
|
||||
}
|
||||
}
|
||||
if good {
|
||||
|
@ -363,25 +470,26 @@ fn lint_all() -> LintResult {
|
|||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let test_list: Vec<(&str, LintFn)> = vec![
|
||||
("subtree check", lint_subtree),
|
||||
("std::filesystem check", lint_std_filesystem),
|
||||
("trailing whitespace check", lint_trailing_whitespace),
|
||||
("no-tabs check", lint_tabs_whitespace),
|
||||
("build config includes check", lint_includes_build_config),
|
||||
("-help=1 documentation check", lint_doc),
|
||||
("markdown hyperlink check", lint_markdown),
|
||||
("lint-*.py scripts", lint_all),
|
||||
];
|
||||
let linters_to_run: Vec<&Linter> = if env::args().count() > 1 {
|
||||
let args: Vec<String> = env::args().skip(1).collect();
|
||||
parse_lint_args(&args)
|
||||
} else {
|
||||
// If no arguments are passed, run all linters.
|
||||
get_linter_list()
|
||||
};
|
||||
|
||||
let git_root = get_git_root();
|
||||
|
||||
let mut test_failed = false;
|
||||
for (lint_name, lint_fn) in test_list {
|
||||
for linter in linters_to_run {
|
||||
// chdir to root before each lint test
|
||||
env::set_current_dir(&git_root).unwrap();
|
||||
if let Err(err) = lint_fn() {
|
||||
println!("{err}\n^---- ⚠️ Failure generated from {lint_name}!");
|
||||
if let Err(err) = (linter.lint_fn)() {
|
||||
println!(
|
||||
"{err}\n^---- ⚠️ Failure generated from lint check '{}'!",
|
||||
linter.name
|
||||
);
|
||||
println!("{}", linter.description);
|
||||
test_failed = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue