tree-sitter/cli/src/tests/corpuses.rs

182 lines
5.5 KiB
Rust
Raw Normal View History

2019-01-17 17:16:04 -08:00
use super::fixtures::{fixtures_dir, get_language, get_test_language};
use crate::generate;
use crate::test::{parse_tests, print_diff, print_diff_key, 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",
"python",
];
lazy_static! {
static ref LANGUAGE_FILTER: Option<String> =
std::env::var("TREE_SITTER_TEST_LANGUAGE_FILTER").ok();
static ref EXAMPLE_FILTER: Option<String> =
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());
}
let mut did_fail = false;
for language_name in LANGUAGES.iter().cloned() {
if let Some(filter) = LANGUAGE_FILTER.as_ref() {
if language_name != 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();
did_fail |= run_mutation_tests(&mut parser, test);
}
drop(parser);
drop(log_session);
if did_fail {
panic!("Corpus tests failed");
}
}
#[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());
}
let mut did_fail = false;
for entry in fs::read_dir(&test_grammars_dir).unwrap() {
let entry = entry.unwrap();
2019-01-11 17:26:45 -08:00
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 != filter.as_str() {
2019-01-11 17:26:45 -08:00
continue;
}
}
eprintln!("test language: {:?}", language_name);
2019-01-11 17:26:45 -08:00
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);
2019-01-11 17:26:45 -08:00
if error_message_path.exists() {
2019-01-11 17:26:45 -08:00
let expected_message = fs::read_to_string(&error_message_path).unwrap();
if let Err(e) = generate_result {
2019-01-11 17:26:45 -08:00
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 {
2019-01-11 17:26:45 -08:00
let corpus_path = test_path.join("corpus.txt");
let c_code = generate_result.unwrap().1;
let language = get_test_language(language_name, c_code, &test_path);
2019-01-11 17:26:45 -08:00
let test = parse_tests(&corpus_path).unwrap();
parser.set_language(language).unwrap();
did_fail |= run_mutation_tests(&mut parser, test);
}
}
drop(parser);
drop(log_session);
if did_fail {
panic!("Corpus tests failed");
}
}
fn run_mutation_tests(parser: &mut Parser, test: TestEntry) -> bool {
match test {
TestEntry::Example {
name,
input,
output,
} => {
if let Some(filter) = EXAMPLE_FILTER.as_ref() {
if !name.contains(filter.as_str()) {
return false;
}
}
eprintln!(" example: {:?}", name);
let tree = parser
.parse_utf8(&mut |byte_offset, _| &input[byte_offset..], None)
.unwrap();
let actual = tree.root_node().to_sexp();
if actual != output {
print_diff_key();
print_diff(&actual, &output);
println!("");
true
} else {
false
}
}
TestEntry::Group { children, .. } => {
let mut result = false;
for child in children {
result |= run_mutation_tests(parser, child);
}
result
}
}
}