Skip to content

Commit

Permalink
Rollup merge of rust-lang#135036 - jieyouxu:rmake-be-quiet, r=compile…
Browse files Browse the repository at this point in the history
…r-errors

run-make-support: adjust assertion printing, add some basic sanity checks

cc `@Noratrieb`

I think we may have unintentionally regressed this recently and double-printed (or printed even when the assertions didn't fail). This PR should condition the detail dumps only when the assertions fail.

Added some basic sanity checks for the assertions helpers except for the directory comparisons. That particular helper is not robust against symlinks, and I intend to address it in a follow-up (issue is rust-lang#135037).

r? bootstrap (or compiler)
  • Loading branch information
matthiaskrgr authored Jan 3, 2025
2 parents 8425bc5 + 6175d73 commit ded6292
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 107 deletions.
107 changes: 0 additions & 107 deletions src/tools/run-make-support/src/assertion_helpers.rs

This file was deleted.

135 changes: 135 additions & 0 deletions src/tools/run-make-support/src/assertion_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//! Collection of assertions and assertion-related helpers.
#[cfg(test)]
mod tests;

use std::panic;
use std::path::Path;

use crate::{fs, regex};

/// Assert that `actual` is equal to `expected`.
#[track_caller]
pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
let actual = actual.as_ref();
let expected = expected.as_ref();

if actual != expected {
eprintln!("=== ACTUAL TEXT ===");
eprintln!("{}", actual);
eprintln!("=== EXPECTED ===");
eprintln!("{}", expected);
panic!("expected text does not match actual text");
}
}

struct SearchDetails<'assertion_name, 'haystack, 'needle> {
assertion_name: &'assertion_name str,
haystack: &'haystack str,
needle: &'needle str,
}

impl<'assertion_name, 'haystack, 'needle> SearchDetails<'assertion_name, 'haystack, 'needle> {
fn dump(&self) {
eprintln!("{}:", self.assertion_name);
eprintln!("=== HAYSTACK ===");
eprintln!("{}", self.haystack);
eprintln!("=== NEEDLE ===");
eprintln!("{}", self.needle);
}
}

/// Assert that `haystack` contains `needle`.
#[track_caller]
pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
let haystack = haystack.as_ref();
let needle = needle.as_ref();
if !haystack.contains(needle) {
SearchDetails { assertion_name: "assert_contains", haystack, needle }.dump();
panic!("needle was not found in haystack");
}
}

/// Assert that `haystack` does not contain `needle`.
#[track_caller]
pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
let haystack = haystack.as_ref();
let needle = needle.as_ref();
if haystack.contains(needle) {
SearchDetails { assertion_name: "assert_not_contains", haystack, needle }.dump();
panic!("needle was unexpectedly found in haystack");
}
}

/// Assert that `haystack` contains the regex `needle`.
#[track_caller]
pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
let haystack = haystack.as_ref();
let needle = needle.as_ref();
let re = regex::Regex::new(needle).unwrap();
if !re.is_match(haystack) {
SearchDetails { assertion_name: "assert_contains_regex", haystack, needle }.dump();
panic!("regex was not found in haystack");
}
}

/// Assert that `haystack` does not contain the regex `needle`.
#[track_caller]
pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
let haystack = haystack.as_ref();
let needle = needle.as_ref();
let re = regex::Regex::new(needle).unwrap();
if re.is_match(haystack) {
SearchDetails { assertion_name: "assert_not_contains_regex", haystack, needle }.dump();
panic!("regex was unexpectedly found in haystack");
}
}

/// Assert that `haystack` contains regex `needle` an `expected_count` number of times.
#[track_caller]
pub fn assert_count_is<H: AsRef<str>, N: AsRef<str>>(
expected_count: usize,
haystack: H,
needle: N,
) {
let haystack = haystack.as_ref();
let needle = needle.as_ref();

let actual_count = haystack.matches(needle).count();
if expected_count != actual_count {
let count_fmt = format!(
"assert_count_is (expected_count = {expected_count}, actual_count = {actual_count})"
);
SearchDetails { assertion_name: &count_fmt, haystack, needle }.dump();
panic!(
"regex did not appear {expected_count} times in haystack (expected_count = \
{expected_count}, actual_count = {actual_count})"
);
}
}

/// Assert that all files in `dir1` exist and have the same content in `dir2`
// FIXME(#135037): not robust against symlinks, lacks sanity test coverage.
pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
let dir2 = dir2.as_ref();
fs::read_dir_entries(dir1, |entry_path| {
let entry_name = entry_path.file_name().unwrap();
if entry_path.is_dir() {
assert_dirs_are_equal(&entry_path, &dir2.join(entry_name));
} else {
let path2 = dir2.join(entry_name);
let file1 = fs::read(&entry_path);
let file2 = fs::read(&path2);

// We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
// Why not using String? Because there might be minified files or even potentially
// binary ones, so that would display useless output.
assert!(
file1 == file2,
"`{}` and `{}` have different content",
entry_path.display(),
path2.display(),
);
}
});
}
100 changes: 100 additions & 0 deletions src/tools/run-make-support/src/assertion_helpers/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//! Basic sanity checks for assertion helpers.
use super::*;

mod test_assert_equals {
use super::*;

#[test]
fn assert_equals_same() {
assert_equals("foo", "foo");
assert_equals("", "");
}

#[test]
#[should_panic]
fn assert_equals_different() {
assert_equals("foo", "bar");
}
}

mod test_assert_contains {
use super::*;

#[test]
fn assert_contains_yes() {
assert_contains("", "");
assert_contains(" ", "");
assert_contains("a", "a");
assert_contains("ab", "a");
}

#[test]
#[should_panic]
fn assert_contains_no() {
assert_contains("a", "b");
}
}

mod test_assert_not_contains {
use super::*;

#[test]
fn assert_not_contains_yes() {
assert_not_contains("a", "b");
}

#[test]
#[should_panic]
fn assert_not_contains_no() {
assert_not_contains(" ", "");
}
}

mod assert_contains_regex {
use super::*;

#[test]
fn assert_contains_regex_yes() {
assert_contains_regex("", "");
assert_contains_regex("", ".*");
assert_contains_regex("abcde", ".*");
assert_contains_regex("abcde", ".+");
}

#[test]
#[should_panic]
fn assert_contains_regex_no() {
assert_contains_regex("", ".+");
}
}

mod assert_not_contains_regex_regex {
use super::*;

#[test]
fn assert_not_contains_regex_yes() {
assert_not_contains_regex("abc", "d");
}

#[test]
#[should_panic]
fn assert_not_contains_regex_no() {
assert_not_contains_regex("abc", ".*");
}
}

mod test_assert_count_is {
use super::*;

#[test]
fn assert_count_is_yes() {
assert_count_is(0, "", "b");
assert_count_is(3, "abcbdb", "b");
}

#[test]
#[should_panic]
fn assert_count_is_no() {
assert_count_is(2, "abcbdb", "b");
}
}

0 comments on commit ded6292

Please sign in to comment.