Rewrite update-all-references bash scripts in Rust

This replaces the `update-all-references` scripts with a single

    cargo dev bless

command.

cc #5394
This commit is contained in:
Philipp Hansch 2020-12-02 18:20:02 +01:00
parent baf5f2da8b
commit 4bd9ed9b88
No known key found for this signature in database
GPG key ID: 188FE733728652B1
11 changed files with 87 additions and 208 deletions

71
clippy_dev/src/bless.rs Normal file
View file

@ -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
}

View file

@ -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;

View file

@ -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")
@ -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"));
},

View file

@ -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.
@ -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
@ -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
@ -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.

View file

@ -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

View file

@ -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."

View file

@ -1,46 +0,0 @@
#!/bin/bash
# A script to update the references for particular 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. This
# script will then copy that output and replace the "expected output"
# files. You can then commit the changes.
#
# If you find yourself manually editing a foo.stderr file, you're
# doing it wrong.
if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
echo ""
echo "For example:"
echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
fi
MYDIR=$(dirname "$0")
BUILD_DIR="$1"
shift
while [[ "$1" != "" ]]; do
STDERR_NAME="${1/%.rs/.stderr}"
STDOUT_NAME="${1/%.rs/.stdout}"
shift
if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then
echo updating "$MYDIR"/"$STDOUT_NAME"
cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"
if [[ ! -s "$MYDIR"/"$STDOUT_NAME" ]]; then
echo removing "$MYDIR"/"$STDOUT_NAME"
rm "$MYDIR"/"$STDOUT_NAME"
fi
fi
if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then
echo updating "$MYDIR"/"$STDERR_NAME"
cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"
if [[ ! -s "$MYDIR"/"$STDERR_NAME" ]]; then
echo removing "$MYDIR"/"$STDERR_NAME"
rm "$MYDIR"/"$STDERR_NAME"
fi
fi
done

View file

@ -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."

View file

@ -1,46 +0,0 @@
#!/bin/bash
# A script to update the references for particular 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. This
# script will then copy that output and replace the "expected output"
# files. You can then commit the changes.
#
# If you find yourself manually editing a foo.stderr file, you're
# doing it wrong.
if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
echo ""
echo "For example:"
echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
fi
MYDIR=$(dirname "$0")
BUILD_DIR="$1"
shift
while [[ "$1" != "" ]]; do
STDERR_NAME="${1/%.rs/.stderr}"
STDOUT_NAME="${1/%.rs/.stdout}"
shift
if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then
echo updating "$MYDIR"/"$STDOUT_NAME"
cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"
if [[ ! -s "$MYDIR"/"$STDOUT_NAME" ]]; then
echo removing "$MYDIR"/"$STDOUT_NAME"
rm "$MYDIR"/"$STDOUT_NAME"
fi
fi
if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then
echo updating "$MYDIR"/"$STDERR_NAME"
cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"
if [[ ! -s "$MYDIR"/"$STDERR_NAME" ]]; then
echo removing "$MYDIR"/"$STDERR_NAME"
rm "$MYDIR"/"$STDERR_NAME"
fi
fi
done

View file

@ -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."

View file

@ -1,56 +0,0 @@
#!/bin/bash
# A script to update the references for particular 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. This
# script will then copy that output and replace the "expected output"
# files. You can then commit the changes.
#
# If you find yourself manually editing a `foo.stderr` file, you're
# doing it wrong.
if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
echo ""
echo "For example:"
echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
fi
MYDIR=$(dirname "$0")
BUILD_DIR="$1"
shift
while [[ "$1" != "" ]]; do
STDERR_NAME="${1/%.rs/.stderr}"
STDOUT_NAME="${1/%.rs/.stdout}"
FIXED_NAME="${1/%.rs/.fixed}"
shift
if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then
echo updating "$MYDIR"/"$STDOUT_NAME"
cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"
if [[ ! -s "$MYDIR"/"$STDOUT_NAME" ]]; then
echo removing "$MYDIR"/"$STDOUT_NAME"
rm "$MYDIR"/"$STDOUT_NAME"
fi
fi
if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then
echo updating "$MYDIR"/"$STDERR_NAME"
cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"
if [[ ! -s "$MYDIR"/"$STDERR_NAME" ]]; then
echo removing "$MYDIR"/"$STDERR_NAME"
rm "$MYDIR"/"$STDERR_NAME"
fi
fi
if [[ -f "$BUILD_DIR"/"$FIXED_NAME" ]] && \
! (cmp -s -- "$BUILD_DIR"/"$FIXED_NAME" "$MYDIR"/"$FIXED_NAME"); then
echo updating "$MYDIR"/"$FIXED_NAME"
cp "$BUILD_DIR"/"$FIXED_NAME" "$MYDIR"/"$FIXED_NAME"
if [[ ! -s "$MYDIR"/"$FIXED_NAME" ]]; then
echo removing "$MYDIR"/"$FIXED_NAME"
rm "$MYDIR"/"$FIXED_NAME"
fi
fi
done