cairo_lang_test_utils/
lib.rs1#![cfg(feature = "testing")]
2
3pub mod parse_test_file;
4
5use std::fs;
9use std::path::Path;
10use std::str::FromStr;
11use std::sync::{Mutex, MutexGuard};
12
13pub use cairo_lang_proc_macros::test;
14pub use cairo_lang_utils::logging;
15use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
16use cairo_lang_utils::require;
17pub use parse_test_file::parse_test_file;
18
19fn get_expected_contents(path: &Path) -> String {
21 fs::read_to_string(path).unwrap_or_else(|_| panic!("Could not read file: '{path:?}'"))
22}
23
24fn set_contents(path: &Path, content: String) {
26 fs::write(path, content).unwrap_or_else(|_| panic!("Could not write file: '{path:?}'"));
27}
28
29pub fn compare_contents_or_fix_with_path(path: &Path, content: String) {
32 let is_fix_mode = std::env::var("CAIRO_FIX_TESTS") == Ok("1".into());
33 if is_fix_mode {
34 set_contents(path, content);
35 } else {
36 pretty_assertions::assert_eq!(content, get_expected_contents(path));
37 }
38}
39
40pub fn test_lock<'a, T: ?Sized + 'a>(m: &'a Mutex<T>) -> MutexGuard<'a, T> {
42 match m.lock() {
43 Ok(guard) => guard,
44 Err(poisoned) => poisoned.into_inner(),
46 }
47}
48
49pub fn verify_diagnostics_expectation(
52 args: &OrderedHashMap<String, String>,
53 diagnostics: &str,
54) -> Option<String> {
55 let expect_diagnostics = args.get("expect_diagnostics")?;
56 require(expect_diagnostics != "*")?;
57
58 let expect_diagnostics = expect_diagnostics_input(expect_diagnostics);
59 let has_diagnostics = !diagnostics.trim().is_empty();
60 let has_errors = diagnostics.lines().any(|line| line.starts_with("error: "));
62 match expect_diagnostics {
63 ExpectDiagnostics::Any => {
64 if !has_diagnostics {
65 return Some(
66 "`expect_diagnostics` is true, but no diagnostics were generated.\n"
67 .to_string(),
68 );
69 }
70 }
71 ExpectDiagnostics::Warnings => {
72 if !has_diagnostics {
73 return Some(
74 "`expect_diagnostics` is 'warnings_only', but no diagnostics were generated.\n"
75 .to_string(),
76 );
77 } else if has_errors {
78 return Some(
79 "`expect_diagnostics` is 'warnings_only', but errors were generated.\n"
80 .to_string(),
81 );
82 }
83 }
84 ExpectDiagnostics::None => {
85 if has_diagnostics {
86 return Some(
87 "`expect_diagnostics` is false, but diagnostics were generated:\n".to_string(),
88 );
89 }
90 }
91 };
92 None
93}
94
95enum ExpectDiagnostics {
97 Any,
99 Warnings,
101 None,
103}
104
105fn expect_diagnostics_input(input: &str) -> ExpectDiagnostics {
108 let input = input.to_lowercase();
109 match input.as_str() {
110 "false" => ExpectDiagnostics::None,
111 "true" => ExpectDiagnostics::Any,
112 "warnings_only" => ExpectDiagnostics::Warnings,
113 _ => panic!("Expected `true`, `false` or `warnings_only`, actual: `{input}`"),
114 }
115}
116
117pub fn bool_input(input: &str) -> bool {
120 let input = input.to_lowercase();
121 bool::from_str(&input).unwrap_or_else(|_| panic!("Expected 'true' or 'false', actual: {input}"))
122}
123
124pub fn get_direct_or_file_content(input: &str) -> (String, String) {
128 if let Some(path) = input.strip_prefix(">>> file: ") {
129 (
130 path.to_string(),
131 fs::read_to_string(path).unwrap_or_else(|_| panic!("Could not read file: '{path}'")),
132 )
133 } else {
134 ("dummy_file.cairo".to_string(), input.to_string())
135 }
136}