diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs deleted file mode 100644 index e84a3cf633f97..0000000000000 --- a/src/tools/run-make-support/src/assertion_helpers.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Collection of assertions and assertion-related helpers. - -use std::panic; -use std::path::Path; - -use crate::{fs, regex}; - -fn print<'a, 'e, A: AsRef, E: AsRef>( - assertion_kind: &str, - haystack: &'a A, - needle: &'e E, -) -> (&'a str, &'e str) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); - eprintln!("{assertion_kind}:"); - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); - (haystack, needle) -} - -/// Assert that `actual` is equal to `expected`. -#[track_caller] -pub fn assert_equals, E: AsRef>(actual: A, expected: E) { - let actual = actual.as_ref(); - let expected = expected.as_ref(); - eprintln!("=== ACTUAL TEXT ==="); - eprintln!("{}", actual); - eprintln!("=== EXPECTED ==="); - eprintln!("{}", expected); - if actual != expected { - panic!("expected text was not found in actual text"); - } -} - -/// Assert that `haystack` contains `needle`. -#[track_caller] -pub fn assert_contains, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_contains", &haystack, &needle); - if !haystack.contains(needle) { - panic!("needle was not found in haystack"); - } -} - -/// Assert that `haystack` does not contain `needle`. -#[track_caller] -pub fn assert_not_contains, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_not_contains", &haystack, &needle); - if haystack.contains(needle) { - panic!("needle was unexpectedly found in haystack"); - } -} - -/// Assert that `haystack` contains the regex pattern `needle`. -#[track_caller] -pub fn assert_contains_regex, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_contains_regex", &haystack, &needle); - let re = regex::Regex::new(needle).unwrap(); - if !re.is_match(haystack) { - panic!("needle was not found in haystack"); - } -} - -/// Assert that `haystack` does not contain the regex pattern `needle`. -#[track_caller] -pub fn assert_not_contains_regex, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_not_contains_regex", &haystack, &needle); - let re = regex::Regex::new(needle).unwrap(); - if re.is_match(haystack) { - panic!("needle was unexpectedly found in haystack"); - } -} - -/// Assert that `haystack` contains `needle` a `count` number of times. -#[track_caller] -pub fn assert_count_is, N: AsRef>(count: usize, haystack: H, needle: N) { - let (haystack, needle) = print("assert_count_is", &haystack, &needle); - if count != haystack.matches(needle).count() { - panic!("needle did not appear {count} times in haystack"); - } -} - -/// Assert that all files in `dir1` exist and have the same content in `dir2` -pub fn assert_dirs_are_equal(dir1: impl AsRef, dir2: impl AsRef) { - 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`, 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(), - ); - } - }); -} diff --git a/src/tools/run-make-support/src/assertion_helpers/mod.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs new file mode 100644 index 0000000000000..9b666473b5b37 --- /dev/null +++ b/src/tools/run-make-support/src/assertion_helpers/mod.rs @@ -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, E: AsRef>(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, N: AsRef>(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, N: AsRef>(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, N: AsRef>(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, N: AsRef>(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, N: AsRef>( + 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, dir2: impl AsRef) { + 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`, 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(), + ); + } + }); +} diff --git a/src/tools/run-make-support/src/assertion_helpers/tests.rs b/src/tools/run-make-support/src/assertion_helpers/tests.rs new file mode 100644 index 0000000000000..8bf7740d2e69e --- /dev/null +++ b/src/tools/run-make-support/src/assertion_helpers/tests.rs @@ -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"); + } +}