From f7d0842198df9c47a75c397cff62bd56a3c023f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 3 Jan 2025 19:56:30 +0800 Subject: [PATCH 1/3] run-make-support: convert `assertion_helpers` to module --- .../src/{assertion_helpers.rs => assertion_helpers/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/tools/run-make-support/src/{assertion_helpers.rs => assertion_helpers/mod.rs} (100%) diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs similarity index 100% rename from src/tools/run-make-support/src/assertion_helpers.rs rename to src/tools/run-make-support/src/assertion_helpers/mod.rs From 7b763031e12c6f8455ea1b4b7c39adcb00391c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 3 Jan 2025 19:57:30 +0800 Subject: [PATCH 2/3] run-make-support: add basic sanity tests for assertion helpers --- .../src/assertion_helpers/mod.rs | 3 + .../src/assertion_helpers/tests.rs | 100 ++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/tools/run-make-support/src/assertion_helpers/tests.rs diff --git a/src/tools/run-make-support/src/assertion_helpers/mod.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs index e84a3cf633f97..ae926f0c2079c 100644 --- a/src/tools/run-make-support/src/assertion_helpers/mod.rs +++ b/src/tools/run-make-support/src/assertion_helpers/mod.rs @@ -1,5 +1,8 @@ //! Collection of assertions and assertion-related helpers. +#[cfg(test)] +mod tests; + use std::panic; use std::path::Path; 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"); + } +} From 6175d738625d07a1e3d3c7db06b6d6a69f59a04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:06:46 +0800 Subject: [PATCH 3/3] run-make-support: tidy up assertion failure dumping Avoid double-dumping or dumping even when assertion is successful. --- .../src/assertion_helpers/mod.rs | 91 ++++++++++++------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/src/tools/run-make-support/src/assertion_helpers/mod.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs index ae926f0c2079c..9b666473b5b37 100644 --- a/src/tools/run-make-support/src/assertion_helpers/mod.rs +++ b/src/tools/run-make-support/src/assertion_helpers/mod.rs @@ -8,40 +8,44 @@ 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"); + 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, needle) = print("assert_contains", &haystack, &needle); + 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"); } } @@ -49,42 +53,63 @@ pub fn assert_contains, N: AsRef>(haystack: H, needle: N) { /// 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); + 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 pattern `needle`. +/// Assert that `haystack` contains the regex `needle`. #[track_caller] pub fn assert_contains_regex, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_contains_regex", &haystack, &needle); + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); let re = regex::Regex::new(needle).unwrap(); if !re.is_match(haystack) { - panic!("needle was not found in 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 pattern `needle`. +/// 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, needle) = print("assert_not_contains_regex", &haystack, &needle); + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); let re = regex::Regex::new(needle).unwrap(); if re.is_match(haystack) { - panic!("needle was unexpectedly found in haystack"); + SearchDetails { assertion_name: "assert_not_contains_regex", haystack, needle }.dump(); + panic!("regex was unexpectedly found in haystack"); } } -/// Assert that `haystack` contains `needle` a `count` number of times. +/// Assert that `haystack` contains regex `needle` an `expected_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"); +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| {