diff options
Diffstat (limited to 'third_party/rust/litrs/src/test_util.rs')
-rw-r--r-- | third_party/rust/litrs/src/test_util.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/third_party/rust/litrs/src/test_util.rs b/third_party/rust/litrs/src/test_util.rs new file mode 100644 index 0000000000..fd284e984e --- /dev/null +++ b/third_party/rust/litrs/src/test_util.rs @@ -0,0 +1,128 @@ +use crate::*; +use std::fmt::{Debug, Display}; + + +#[track_caller] +pub(crate) fn assert_parse_ok_eq<T: PartialEq + Debug + Display>( + input: &str, + result: Result<T, ParseError>, + expected: T, + parse_method: &str, +) { + match result { + Ok(actual) if actual == expected => { + if actual.to_string() != input { + panic!( + "formatting does not yield original input `{}`: {:?}", + input, + actual, + ); + } + } + Ok(actual) => { + panic!( + "unexpected parsing result (with `{}`) for `{}`:\nactual: {:?}\nexpected: {:?}", + parse_method, + input, + actual, + expected, + ); + } + Err(e) => { + panic!( + "expected `{}` to be parsed (with `{}`) successfully, but it failed: {:?}", + input, + parse_method, + e, + ); + } + } +} + +// This is not ideal, but to perform this check we need `proc-macro2`. So we +// just don't do anything if that feature is not enabled. +#[cfg(not(feature = "proc-macro2"))] +pub(crate) fn assert_roundtrip<T>(_: T, _: &str) {} + +#[cfg(feature = "proc-macro2")] +#[track_caller] +pub(crate) fn assert_roundtrip<T>(ours: T, input: &str) +where + T: std::convert::TryFrom<proc_macro2::Literal> + fmt::Debug + PartialEq + Clone, + proc_macro2::Literal: From<T>, + <T as std::convert::TryFrom<proc_macro2::Literal>>::Error: std::fmt::Display, +{ + let pm_lit = input.parse::<proc_macro2::Literal>() + .expect("failed to parse input as proc_macro2::Literal"); + let t_name = std::any::type_name::<T>(); + + // Unfortunately, `proc_macro2::Literal` does not implement `PartialEq`, so + // this is the next best thing. + if proc_macro2::Literal::from(ours.clone()).to_string() != pm_lit.to_string() { + panic!( + "Converting {} to proc_macro2::Literal has unexpected result:\ + \nconverted: {:?}\nexpected: {:?}", + t_name, + proc_macro2::Literal::from(ours), + pm_lit, + ); + } + + match T::try_from(pm_lit) { + Err(e) => { + panic!("Trying to convert proc_macro2::Literal to {} results in error: {}", t_name, e); + } + Ok(res) => { + if res != ours { + panic!( + "Converting proc_macro2::Literal to {} has unexpected result:\ + \nactual: {:?}\nexpected: {:?}", + t_name, + res, + ours, + ); + } + } + } +} + +macro_rules! assert_err { + ($ty:ident, $input:literal, $kind:ident, $( $span:tt )+ ) => { + assert_err_single!($ty::parse($input), $kind, $($span)+); + assert_err_single!($crate::Literal::parse($input), $kind, $($span)+); + }; +} + +macro_rules! assert_err_single { + ($expr:expr, $kind:ident, $( $span:tt )+ ) => { + let res = $expr; + let err = match res { + Err(e) => e, + Ok(v) => panic!( + "Expected `{}` to return an error, but it returned Ok({:?})", + stringify!($expr), + v, + ), + }; + if err.kind != $crate::err::ParseErrorKind::$kind { + panic!( + "Expected error kind {} for `{}` but got {:?}", + stringify!($kind), + stringify!($expr), + err.kind, + ) + } + let expected_span = assert_err_single!(@span $($span)+); + if err.span != expected_span { + panic!( + "Expected error span {:?} for `{}` but got {:?}", + expected_span, + stringify!($expr), + err.span, + ) + } + }; + (@span $start:literal .. $end:literal) => { Some($start .. $end) }; + (@span $at:literal) => { Some($at.. $at + 1) }; + (@span None) => { None }; +} |