1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/// Check if a value is the same as an expected value
///
/// By default [`filters`][crate::filter] are applied, including:
/// - `...` is a line-wildcard when on a line by itself
/// - `[..]` is a character-wildcard when inside a line
/// - `[EXE]` matches `.exe` on Windows
/// - `"{...}"` is a JSON value wildcard
/// - `"...": "{...}"` is a JSON key-value wildcard
/// - `\` to `/`
/// - Newlines
///
/// To limit this to newline normalization for text, call [`Data::raw`][crate::Data] on `expected`.
///
/// # Effective signature
///
/// ```rust
/// # use snapbox::IntoData;
/// fn assert_data_eq(actual: impl IntoData, expected: impl IntoData) {
/// // ...
/// }
/// ```
///
/// # Examples
///
/// ```rust
/// # use snapbox::assert_data_eq;
/// let output = "something";
/// let expected = "so[..]g";
/// assert_data_eq!(output, expected);
/// ```
///
/// Can combine this with [`file!`]
/// ```rust,no_run
/// # use snapbox::assert_data_eq;
/// # use snapbox::file;
/// let actual = "something";
/// assert_data_eq!(actual, file!["output.txt"]);
/// ```
#[macro_export]
macro_rules! assert_data_eq {
($actual: expr, $expected: expr $(,)?) => {{
let actual = $crate::IntoData::into_data($actual);
let expected = $crate::IntoData::into_data($expected);
$crate::Assert::new()
.action_env($crate::assert::DEFAULT_ACTION_ENV)
.eq(actual, expected);
}};
}
/// Find the directory for your source file
#[doc(hidden)] // forced to be visible in intended location
#[macro_export]
macro_rules! current_dir {
() => {{
let root = $crate::utils::cargo_rustc_current_dir!();
let file = ::std::file!();
let rel_path = ::std::path::Path::new(file).parent().unwrap();
root.join(rel_path)
}};
}
/// Find the directory for your source file
#[doc(hidden)] // forced to be visible in intended location
#[macro_export]
macro_rules! current_rs {
() => {{
let root = $crate::utils::cargo_rustc_current_dir!();
let file = ::std::file!();
let rel_path = ::std::path::Path::new(file);
root.join(rel_path)
}};
}
/// Find the base directory for [`std::file!`]
#[doc(hidden)] // forced to be visible in intended location
#[macro_export]
macro_rules! cargo_rustc_current_dir {
() => {{
if let Some(rustc_root) = ::std::option_env!("CARGO_RUSTC_CURRENT_DIR") {
::std::path::Path::new(rustc_root)
} else {
let manifest_dir = ::std::path::Path::new(::std::env!("CARGO_MANIFEST_DIR"));
manifest_dir
.ancestors()
.filter(|it| it.join("Cargo.toml").exists())
.last()
.unwrap()
}
}};
}
/// Path to the current function
///
/// Closures are ignored
#[doc(hidden)]
#[macro_export]
macro_rules! fn_path {
() => {{
fn f() {}
fn type_name_of_val<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
let mut name = type_name_of_val(f).strip_suffix("::f").unwrap_or("");
while let Some(rest) = name.strip_suffix("::{{closure}}") {
name = rest;
}
name
}};
}
#[cfg(test)]
mod test {
#[test]
fn direct_fn_path() {
assert_eq!(fn_path!(), "snapbox::macros::test::direct_fn_path");
}
#[test]
#[allow(clippy::redundant_closure_call)]
fn closure_fn_path() {
(|| {
assert_eq!(fn_path!(), "snapbox::macros::test::closure_fn_path");
})()
}
#[test]
fn nested_fn_path() {
fn nested() {
assert_eq!(fn_path!(), "snapbox::macros::test::nested_fn_path::nested");
}
nested()
}
}