--- /dev/null
+//! `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
+}
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
+pub mod bless;
pub mod fmt;
pub mod new_lint;
pub mod ra_setup;
#![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")
.get_matches();
match matches.subcommand() {
+ ("bless", Some(_)) => {
+ bless::bless();
+ },
("fmt", Some(matches)) => {
fmt::run(matches.is_present("check"), matches.is_present("verbose"));
},
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.
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
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
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.
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
#!/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."
+++ /dev/null
-#!/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
#!/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."
+++ /dev/null
-#!/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
#!/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."
+++ /dev/null
-#!/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