error.rs
1 use std::io::Write; 2 3 use colored::Colorize; 4 use serde_json::Value; 5 use similar_asserts::serde_impl::Debug as SimilarAssertsDebug; 6 use similar_asserts::SimpleDiff; 7 use tracing::warn; 8 9 const TRUNCATE_THRESHOLD: usize = 1000; 10 const DIFF_TRUNCATE_THRESHOLD: usize = 2000; 11 12 fn truncate(s: &str, threshold: usize, write_tempfile: bool) -> String { 13 if s.chars().count() <= threshold { 14 return s.to_owned(); 15 } 16 17 let mut full_output_hint = "".to_owned(); 18 19 if write_tempfile { 20 match tempfile::Builder::new() 21 .prefix("apibara-test-diff-") 22 .suffix(".patch") 23 .tempfile() 24 .map_err(|err| err.to_string()) 25 .and_then(|keep| keep.keep().map_err(|err| err.to_string())) 26 .and_then(|(mut file, path)| match file.write_all(s.as_bytes()) { 27 Ok(_) => Ok(path), 28 Err(err) => Err(err.to_string()), 29 }) { 30 Ok(path) => full_output_hint = format!(", full output written to `{}`", path.display()), 31 Err(err) => { 32 warn!(err =? err, "Cannot create tempfile to save long diff"); 33 } 34 } 35 } 36 37 let start = &s[..threshold / 2]; 38 let end = &s[s.len() - threshold / 2..]; 39 40 let truncated_prefix = format!("<truncated{}>\n", full_output_hint).yellow(); 41 42 let truncated_msg = format!( 43 "\n ... \n {} chars truncated{}\n ... \n", 44 s.chars().count() - threshold, 45 full_output_hint, 46 ) 47 .yellow(); 48 49 format!("{truncated_prefix} {start} {truncated_msg} {end}") 50 } 51 52 pub fn get_assertion_error(expected_outputs: &[Value], found_outputs: &[Value]) -> String { 53 let left = format!("{:#?}", SimilarAssertsDebug(&expected_outputs)); 54 let right = format!("{:#?}", SimilarAssertsDebug(&found_outputs)); 55 56 let left_label = "expected"; 57 let right_label = "found"; 58 let label_padding = left_label.chars().count().max(right_label.chars().count()); 59 60 let diff = SimpleDiff::from_str(left.as_str(), right.as_str(), left_label, right_label); 61 62 let assert_fail = format!( 63 "assertion failed: `({} == {})`'\n {:<label_padding$}: `{:?}`\n {:<label_padding$}: `{:?}`", 64 left_label, 65 right_label, 66 left_label, 67 truncate(&left, TRUNCATE_THRESHOLD, false), 68 right_label, 69 truncate(&right, TRUNCATE_THRESHOLD, false), 70 label_padding = label_padding, 71 ) 72 .bright_red(); 73 74 let diff_str = truncate(&diff.to_string(), DIFF_TRUNCATE_THRESHOLD, true); 75 76 format!("{}\n\n{}", &assert_fail, &diff_str) 77 }