use super::fixtures::{get_language, get_test_language, fixtures_dir}; use crate::generate; use crate::test::{parse_tests, TestEntry}; use crate::util; use std::fs; use tree_sitter::{LogType, Parser}; const LANGUAGES: &'static [&'static str] = &[ "bash", "c", "cpp", "embedded-template", "go", "html", "javascript", ]; lazy_static! { static ref LANGUAGE_FILTER: Option = std::env::var("TREE_SITTER_TEST_LANGUAGE_FILTER").ok(); static ref EXAMPLE_FILTER: Option = std::env::var("TREE_SITTER_TEST_EXAMPLE_FILTER").ok(); static ref LOG_ENABLED: bool = std::env::var("TREE_SITTER_ENABLE_LOG").is_ok(); static ref LOG_GRAPH_ENABLED: bool = std::env::var("TREE_SITTER_ENABLE_LOG_GRAPHS").is_ok(); } #[test] fn test_real_language_corpus_files() { let mut log_session = None; let mut parser = Parser::new(); let grammars_dir = fixtures_dir().join("grammars"); if *LOG_ENABLED { parser.set_logger(Some(Box::new(|log_type, msg| { if log_type == LogType::Lex { eprintln!(" {}", msg); } else { eprintln!("{}", msg); } }))); } else if *LOG_GRAPH_ENABLED { log_session = Some(util::log_graphs(&mut parser, "log.html").unwrap()); } for language_name in LANGUAGES.iter().cloned() { if let Some(filter) = LANGUAGE_FILTER.as_ref() { if !language_name.contains(filter.as_str()) { continue; } } eprintln!("language: {:?}", language_name); let language = get_language(language_name); let corpus_dir = grammars_dir.join(language_name).join("corpus"); let test = parse_tests(&corpus_dir).unwrap(); parser.set_language(language).unwrap(); run_mutation_tests(&mut parser, test); } drop(parser); drop(log_session); } #[test] fn test_feature_corpus_files() { let mut log_session = None; let mut parser = Parser::new(); let test_grammars_dir = fixtures_dir().join("test_grammars"); if *LOG_ENABLED { parser.set_logger(Some(Box::new(|log_type, msg| { if log_type == LogType::Lex { eprintln!(" {}", msg); } else { eprintln!("{}", msg); } }))); } else if *LOG_GRAPH_ENABLED { log_session = Some(util::log_graphs(&mut parser, "log.html").unwrap()); } for entry in fs::read_dir(&test_grammars_dir).unwrap() { let entry = entry.unwrap(); if !entry.metadata().unwrap().is_dir() { continue; } let language_name = entry.file_name(); let language_name = language_name.to_str().unwrap(); if let Some(filter) = LANGUAGE_FILTER.as_ref() { if !language_name.contains(filter.as_str()) { continue; } } eprintln!("test language: {:?}", language_name); let test_path = entry.path(); let grammar_path = test_path.join("grammar.json"); let error_message_path = test_path.join("expected_error.txt"); let grammar_json = fs::read_to_string(grammar_path).unwrap(); let generate_result = generate::generate_parser_for_grammar(&grammar_json); if error_message_path.exists() { let expected_message = fs::read_to_string(&error_message_path).unwrap(); if let Err(e) = generate_result { if e.0 != expected_message { panic!( "Unexpected error message.\n\nExpected:\n\n{}\nActual:\n\n{}\n", expected_message, e.0 ); } } else { panic!( "Expected error message but got none for test grammar '{}'", language_name ); } } else { let corpus_path = test_path.join("corpus.txt"); let c_code = generate_result.unwrap(); let language = get_test_language(language_name, c_code, &test_path); let test = parse_tests(&corpus_path).unwrap(); parser.set_language(language).unwrap(); run_mutation_tests(&mut parser, test); } } drop(parser); drop(log_session); } fn run_mutation_tests(parser: &mut Parser, test: TestEntry) { match test { TestEntry::Example { name, input, output, } => { if let Some(filter) = EXAMPLE_FILTER.as_ref() { if !name.contains(filter.as_str()) { return; } } eprintln!(" example: {:?}", name); let tree = parser .parse_utf8(&mut |byte_offset, _| &input[byte_offset..], None) .unwrap(); let actual = tree.root_node().to_sexp(); assert_eq!(actual, output); } TestEntry::Group { children, .. } => { for child in children { run_mutation_tests(parser, child); } } } }