use std::path::{Path, PathBuf}; use erg_common::config::ErgConfig; use erg_common::io::Input; use erg_common::spawn::exec_new_thread; use erg_compiler::artifact::{CompleteArtifact, IncompleteArtifact}; use pylyzer_core::PythonAnalyzer; #[allow(clippy::result_large_err)] pub fn exec_analyzer(file_path: &'static str) -> Result { let cfg = ErgConfig { input: Input::file(PathBuf::from(file_path)), effect_check: false, ownership_check: false, ..Default::default() }; let mut analyzer = PythonAnalyzer::new(cfg); let py_code = analyzer.cfg.input.read(); analyzer.analyze(py_code, "exec") } fn _expect(file_path: &'static str, warns: usize, errors: usize) -> Result<(), String> { println!("Testing {file_path} ..."); match exec_analyzer(file_path) { Ok(artifact) => { if artifact.warns.len() != warns { eprintln!("warns: {}", artifact.warns); return Err(format!( "Expected {warns} warnings, found {}", artifact.warns.len() )); } if errors != 0 { return Err(format!("Expected {errors} errors, found 0")); } Ok(()) } Err(artifact) => { if artifact.warns.len() != warns { eprintln!("warns: {}", artifact.warns); return Err(format!( "Expected {warns} warnings, found {}", artifact.warns.len() )); } if artifact.errors.len() != errors { eprintln!("errors: {}", artifact.errors); return Err(format!( "Expected {errors} errors, found {}", artifact.errors.len() )); } Ok(()) } } } pub fn expect(file_path: &'static str, warns: usize, errors: usize) -> Result<(), String> { exec_new_thread(move || _expect(file_path, warns, errors), file_path) } #[test] fn exec_test() -> Result<(), String> { expect("tests/test.py", 0, 11) } #[test] fn exec_import() -> Result<(), String> { if Path::new("tests/__pycache__").exists() { std::fs::remove_dir_all("tests/__pycache__").unwrap(); } if Path::new("tests/foo/__pycache__").exists() { std::fs::remove_dir_all("tests/foo/__pycache__").unwrap(); } if Path::new("tests/bar/__pycache__").exists() { std::fs::remove_dir_all("tests/bar/__pycache__").unwrap(); } expect("tests/import.py", 1, 2) } #[test] fn exec_dict() -> Result<(), String> { expect("tests/dict.py", 0, 2) } #[test] fn exec_export() -> Result<(), String> { expect("tests/export.py", 0, 0) } #[test] fn exec_func() -> Result<(), String> { expect("tests/func.py", 0, 1) } #[test] fn exec_class() -> Result<(), String> { expect("tests/class.py", 0, 6) } #[test] fn exec_errors() -> Result<(), String> { expect("tests/errors.py", 0, 3) } #[test] fn exec_warns() -> Result<(), String> { expect("tests/warns.py", 2, 0) } #[test] fn exec_typespec() -> Result<(), String> { expect("tests/typespec.py", 0, 16) } #[test] fn exec_projection() -> Result<(), String> { expect("tests/projection.py", 0, 5) } #[test] fn exec_pyi() -> Result<(), String> { expect("tests/pyi.py", 0, 5) } #[test] fn exec_list() -> Result<(), String> { expect("tests/list.py", 0, 2) } #[test] fn exec_literal() -> Result<(), String> { expect("tests/literal.py", 0, 2) } #[test] fn exec_narrowing() -> Result<(), String> { expect("tests/narrowing.py", 0, 1) } #[test] fn exec_casting() -> Result<(), String> { expect("tests/casting.py", 4, 1) } #[test] fn exec_collection() -> Result<(), String> { expect("tests/collection.py", 0, 4) } #[test] fn exec_call() -> Result<(), String> { expect("tests/call.py", 0, 6) } #[test] fn exec_decl() -> Result<(), String> { expect("tests/decl.py", 0, 1) } #[test] fn exec_shadowing() -> Result<(), String> { expect("tests/shadowing.py", 0, 4) } #[test] fn exec_typevar() -> Result<(), String> { expect("tests/typevar.py", 0, 3) } #[test] fn exec_union() -> Result<(), String> { expect("tests/union.py", 0, 0) } #[test] fn exec_widening() -> Result<(), String> { expect("tests/widening.py", 0, 1) }