Skip to content

Commit

Permalink
Rewrite update-all-references bash scripts in Rust
Browse files Browse the repository at this point in the history
This replaces the `update-all-references` scripts with a single

    cargo dev bless

command.

cc #5394
  • Loading branch information
phansch committed Dec 12, 2020
1 parent baf5f2d commit 4bd9ed9
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 208 deletions.
71 changes: 71 additions & 0 deletions clippy_dev/src/bless.rs
@@ -0,0 +1,71 @@
//! `bless` updates the 'expected output' files in the repo with changed output files
//! from the last test run.

use std::env;
use std::ffi::OsStr;
use std::fs;
use std::lazy::SyncLazy;
use std::path::PathBuf;
use walkdir::WalkDir;

use crate::clippy_project_root;

// NOTE: this is duplicated with tests/cargo/mod.rs What to do?
pub static CARGO_TARGET_DIR: SyncLazy<PathBuf> = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") {
Some(v) => v.into(),
None => env::current_dir().unwrap().join("target"),
});

pub fn bless() {
let test_dirs = [
clippy_project_root().join("tests").join("ui"),
clippy_project_root().join("tests").join("ui-toml"),
clippy_project_root().join("tests").join("ui-cargo"),
];
for test_dir in &test_dirs {
WalkDir::new(test_dir)
.into_iter()
.filter_map(Result::ok)
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
.for_each(|f| {
update_test_file(f.path().with_extension("stdout"));
update_test_file(f.path().with_extension("stderr"));
update_test_file(f.path().with_extension("fixed"));
});
}
}

fn update_test_file(test_file_path: PathBuf) {
let build_output_path = build_dir().join(PathBuf::from(test_file_path.file_name().unwrap()));
let relative_test_file_path = test_file_path.strip_prefix(clippy_project_root()).unwrap();

// If compiletest did not write any changes during the test run,
// we don't have to update anything
if !build_output_path.exists() {
return;
}

let build_output = fs::read(&build_output_path).expect("Unable to read build output file");
let test_file = fs::read(&test_file_path).expect("Unable to read test file");

if build_output != test_file {
// If a test run caused an output file to change, update the test file
println!("updating {}", &relative_test_file_path.display());
fs::copy(build_output_path, &test_file_path).expect("Could not update test file");

if test_file.is_empty() {
// If we copied over an empty output file, we remove it
println!("removing {}", &relative_test_file_path.display());
fs::remove_file(test_file_path).expect("Could not remove test file");
}
}
}

fn build_dir() -> PathBuf {
let profile = format!("{}", env::var("PROFILE").unwrap_or("debug".to_string()));
let mut path = PathBuf::new();
path.push(CARGO_TARGET_DIR.clone());
path.push(profile);
path.push("test_build_base");
path
}
1 change: 1 addition & 0 deletions clippy_dev/src/lib.rs
Expand Up @@ -10,6 +10,7 @@ use std::lazy::SyncLazy;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub mod bless;
pub mod fmt;
pub mod new_lint;
pub mod ra_setup;
Expand Down
6 changes: 5 additions & 1 deletion clippy_dev/src/main.rs
@@ -1,10 +1,11 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use clap::{App, Arg, SubCommand};
use clippy_dev::{fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};
use clippy_dev::{bless, fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};

fn main() {
let matches = App::new("Clippy developer tooling")
.subcommand(SubCommand::with_name("bless").about("bless the test output changes"))
.subcommand(
SubCommand::with_name("fmt")
.about("Run rustfmt on all projects and tests")
Expand Down Expand Up @@ -116,6 +117,9 @@ fn main() {
.get_matches();

match matches.subcommand() {
("bless", Some(_)) => {
bless::bless();
},
("fmt", Some(matches)) => {
fmt::run(matches.is_present("check"), matches.is_present("verbose"));
},
Expand Down
13 changes: 6 additions & 7 deletions doc/adding_lints.md
Expand Up @@ -98,12 +98,12 @@ While we are working on implementing our lint, we can keep running the UI
test. That allows us to check if the output is turning into what we want.

Once we are satisfied with the output, we need to run
`tests/ui/update-all-references.sh` to update the `.stderr` file for our lint.
`cargo dev bless` to update the `.stderr` file for our lint.
Please note that, we should run `TESTNAME=foo_functions cargo uitest`
every time before running `tests/ui/update-all-references.sh`.
every time before running `cargo dev bless`.
Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit
our lint, we need to commit the generated `.stderr` files, too. In general, you
should only commit files changed by `tests/ui/update-all-references.sh` for the
should only commit files changed by `cargo dev bless` for the
specific lint you are creating/editing. Note that if the generated files are
empty, they should be removed.

Expand All @@ -122,8 +122,7 @@ we will find by default two new crates, each with its manifest file:
If you need more cases, you can copy one of those crates (under `foo_categories`) and rename it.

The process of generating the `.stderr` file is the same, and prepending the `TESTNAME`
variable to `cargo uitest` works too, but the script to update the references
is in another path: `tests/ui-cargo/update-all-references.sh`.
variable to `cargo uitest` works too.

## Rustfix tests

Expand All @@ -133,7 +132,7 @@ additionally run [rustfix] for that test. Rustfix will apply the suggestions
from the lint to the code of the test file and compare that to the contents of
a `.fixed` file.

Use `tests/ui/update-all-references.sh` to automatically generate the
Use `cargo dev bless` to automatically generate the
`.fixed` file after running the tests.

[rustfix]: https://github.com/rust-lang/rustfix
Expand Down Expand Up @@ -368,7 +367,7 @@ fn is_foo_fn(fn_kind: FnKind<'_>) -> bool {

Now we should also run the full test suite with `cargo test`. At this point
running `cargo test` should produce the expected output. Remember to run
`tests/ui/update-all-references.sh` to update the `.stderr` file.
`cargo dev bless` to update the `.stderr` file.

`cargo test` (as opposed to `cargo uitest`) will also ensure that our lint
implementation is not violating any Clippy lints itself.
Expand Down
2 changes: 1 addition & 1 deletion doc/basics.md
Expand Up @@ -61,7 +61,7 @@ If the output of a [UI test] differs from the expected output, you can update th
reference file with:

```bash
sh tests/ui/update-all-references.sh
cargo dev bless
```

For example, this is necessary, if you fix a typo in an error message of a lint
Expand Down
17 changes: 1 addition & 16 deletions tests/ui-cargo/update-all-references.sh
@@ -1,18 +1,3 @@
#!/bin/bash
#
# A script to update the references for all tests. The idea is that
# you do a run, which will generate files in the build directory
# containing the (normalized) actual output of the compiler. You then
# run this script, which will copy those files over. If you find
# yourself manually editing a foo.stderr file, you're doing it wrong.
#
# See all `update-references.sh`, if you just want to update a single test.

if [[ "$1" == "--help" || "$1" == "-h" ]]; then
echo "usage: $0"
fi

BUILD_DIR=$PWD/target/debug/test_build_base
MY_DIR=$(dirname "$0")
cd "$MY_DIR" || exit
find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} +
echo "Please use 'cargo dev bless' instead."
46 changes: 0 additions & 46 deletions tests/ui-cargo/update-references.sh

This file was deleted.

17 changes: 1 addition & 16 deletions tests/ui-toml/update-all-references.sh
@@ -1,18 +1,3 @@
#!/bin/bash
#
# A script to update the references for all tests. The idea is that
# you do a run, which will generate files in the build directory
# containing the (normalized) actual output of the compiler. You then
# run this script, which will copy those files over. If you find
# yourself manually editing a foo.stderr file, you're doing it wrong.
#
# See all `update-references.sh`, if you just want to update a single test.

if [[ "$1" == "--help" || "$1" == "-h" ]]; then
echo "usage: $0"
fi

BUILD_DIR=$PWD/target/debug/test_build_base
MY_DIR=$(dirname "$0")
cd "$MY_DIR" || exit
find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} +
echo "Please use 'cargo dev bless' instead."
46 changes: 0 additions & 46 deletions tests/ui-toml/update-references.sh

This file was deleted.

20 changes: 1 addition & 19 deletions tests/ui/update-all-references.sh
@@ -1,21 +1,3 @@
#!/bin/bash

# A script to update the references for all tests. The idea is that
# you do a run, which will generate files in the build directory
# containing the (normalized) actual output of the compiler. You then
# run this script, which will copy those files over. If you find
# yourself manually editing a foo.stderr file, you're doing it wrong.
#
# See all `update-references.sh`, if you just want to update a single test.

if [[ "$1" == "--help" || "$1" == "-h" ]]; then
echo "usage: $0"
fi

CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-$PWD/target}
PROFILE=${PROFILE:-debug}
BUILD_DIR=${CARGO_TARGET_DIR}/${PROFILE}/test_build_base

MY_DIR=$(dirname "$0")
cd "$MY_DIR" || exit
find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} +
echo "Please use 'cargo dev bless' instead."
56 changes: 0 additions & 56 deletions tests/ui/update-references.sh

This file was deleted.

0 comments on commit 4bd9ed9

Please sign in to comment.