aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAva Chow <github@achow101.com>2024-06-12 17:19:48 -0400
committerAva Chow <github@achow101.com>2024-06-12 17:19:48 -0400
commitff21eb2def701585fb1c286d8aef6dee86be48c3 (patch)
tree77527afd14d7035520399b1a9e4752cf63b6ca4b
parent011a895a82df8971b7fed4fcd090afb638c4c0d7 (diff)
parent0fcbfdb7ad172e518a10dd6e5be4cb6bb1158784 (diff)
downloadbitcoin-ff21eb2def701585fb1c286d8aef6dee86be48c3.tar.xz
Merge bitcoin/bitcoin#30219: Lint: Support running individual lint checks
0fcbfdb7ad172e518a10dd6e5be4cb6bb1158784 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: ACK 0fcbfdb7ad172e518a10dd6e5be4cb6bb1158784 achow101: ACK 0fcbfdb7ad172e518a10dd6e5be4cb6bb1158784 marcofleon: Tested ACK 0fcbfdb7ad172e518a10dd6e5be4cb6bb1158784. 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
-rw-r--r--test/lint/README.md15
-rw-r--r--test/lint/test_runner/src/main.rs138
2 files changed, 138 insertions, 15 deletions
diff --git a/test/lint/README.md b/test/lint/README.md
index 49ed8356c3..04a836c4d2 100644
--- a/test/lint/README.md
+++ b/test/lint/README.md
@@ -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 |
diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs
index 5f980eb398..9c35898c1f 100644
--- a/test/lint/test_runner/src/main.rs
+++ b/test/lint/test_runner/src/main.rs
@@ -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;
}
}