use std::env; use std::fs::read_dir; use std::io; use std::path::PathBuf; use pretty_assertions::assert_str_eq; struct TestFixture { fixture: String, code_file: PathBuf, ast_file: PathBuf, error_file: PathBuf, } struct ExpectedTestResult { ast: String, error: String, } impl TestFixture { fn new(entry: PathBuf) -> Self { Self { fixture: entry.to_string_lossy().to_string(), code_file: entry.join("code.php"), ast_file: entry.join("ast.txt"), error_file: entry.join("error.txt"), } } fn code(&self) -> String { std::fs::read_to_string(&self.code_file).unwrap_or_default() } fn validate(&self) -> io::Result<()> { if !self.code_file.exists() { return Err(io::Error::new( io::ErrorKind::NotFound, format!( "Code file {} does not exist", self.code_file.to_string_lossy() ), )); } if !self.ast_file.exists() && !self.error_file.exists() { return Err(io::Error::new( io::ErrorKind::NotFound, format!( "Test fixture {} must have either an ast.txt or error.txt file", self.fixture ), )); } Ok(()) } fn expected(&self) -> ExpectedTestResult { let ast = std::fs::read_to_string(&self.ast_file).unwrap_or_default(); let error = std::fs::read_to_string(&self.error_file).unwrap_or_default(); ExpectedTestResult { ast, error } } } #[test] fn test_fixtures() -> io::Result<()> { let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let tests = manifest.join("tests/fixtures"); let mut entries = read_dir(tests)? .flatten() .map(|entry| entry.path()) .filter(|entry| entry.is_dir()) .collect::>(); entries.sort(); for entry in entries { let test_fixture = TestFixture::new(entry); test_fixture.validate()?; run_test(&test_fixture)?; } Ok(()) } fn run_test(test_fixture: &TestFixture) -> io::Result<()> { let code = test_fixture.code(); let expected = test_fixture.expected(); if !expected.ast.is_empty() { let ast = php_parser_rs::parse(&code).unwrap(); assert_str_eq!( expected.ast.trim(), format!("{:#?}", ast), "ast mismatch for fixture `{}`", test_fixture.fixture ); } if !expected.error.is_empty() { let error = php_parser_rs::parse(&code).err().unwrap(); assert_str_eq!( expected.error.trim(), (error.report(&code, Some("code.php"), false, true)?) .to_string() .trim(), "error mismatch for fixture `{}`", test_fixture.fixture ); } Ok(()) }