use crate::parse::traits::LanguageConfig;
#[cfg(test)]
mod language_detection_tests {
use super::*;
#[test]
fn test_python_extension_detection() {
let config = LanguageConfig::from_extension("py");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "Python");
}
#[test]
fn test_javascript_extension_detection() {
let config = LanguageConfig::from_extension("js");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "JavaScript");
let config = LanguageConfig::from_extension("jsx");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "JavaScript");
}
#[test]
fn test_typescript_extension_detection() {
let config = LanguageConfig::from_extension("ts");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "TypeScript");
let config = LanguageConfig::from_extension("tsx");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "TypeScript");
}
#[test]
fn test_c_extension_detection() {
let config = LanguageConfig::from_extension("c");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "C");
let config = LanguageConfig::from_extension("h");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "C");
}
#[test]
fn test_bash_extension_detection() {
let config = LanguageConfig::from_extension("sh");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "Bash");
let config = LanguageConfig::from_extension("bash");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "Bash");
}
#[test]
fn test_json_extension_detection() {
let config = LanguageConfig::from_extension("json");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "JSON");
}
#[test]
fn test_go_extension_detection() {
let config = LanguageConfig::from_extension("go");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "Go");
}
#[test]
fn test_rust_extension_detection() {
let config = LanguageConfig::from_extension("rs");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "Rust");
}
#[test]
fn test_case_insensitive_extension_detection() {
let config = LanguageConfig::from_extension("PY");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "Python");
let config = LanguageConfig::from_extension("Js");
assert!(config.is_some());
assert_eq!(config.unwrap().name, "JavaScript");
}
#[test]
fn test_unknown_extension_returns_none() {
let config = LanguageConfig::from_extension("unknown");
assert!(config.is_none());
let config = LanguageConfig::from_extension("");
assert!(config.is_none());
}
#[test]
fn test_language_config_extensions() {
let py_config = LanguageConfig::from_extension("py").unwrap();
assert!(py_config.extensions.contains(&"py".to_string()));
assert_eq!(py_config.extensions.len(), 1);
let js_config = LanguageConfig::from_extension("js").unwrap();
assert!(js_config.extensions.contains(&"js".to_string()));
assert!(js_config.extensions.contains(&"jsx".to_string()));
}
}
#[cfg(all(test, feature = "cli"))]
mod stack_overflow_regression_tests {
use crate::cli::LeIndex;
use std::env;
use std::fs;
use std::process::Command;
use tempfile::TempDir;
const HELPER_TEST_NAME: &str = "helper_index_deep_nested_project";
const HELPER_ENV: &str = "LEINDEX_STACK_HELPER";
const PROJECT_ENV: &str = "LEINDEX_STACK_PROJECT";
fn write_deep_rust_file(temp_dir: &TempDir, depth: usize) {
let mut source = String::from("fn main() {\n");
let mut indent = String::from(" ");
for _ in 0..depth {
source.push_str(&format!("{indent}if true {{\n"));
indent.push_str(" ");
}
source.push_str(&format!("{indent}let _x = 1;\n"));
for _ in 0..depth {
indent.truncate(indent.len() - 4);
source.push_str(&format!("{indent}}}\n"));
}
source.push_str("}\n");
fs::write(temp_dir.path().join("deep.rs"), source).unwrap();
}
fn write_deep_cpp_file(temp_dir: &TempDir, depth: usize) {
let mut source = String::from("int main() {\n");
let mut indent = String::from(" ");
for _ in 0..depth {
source.push_str(&format!("{indent}if (true) {{\n"));
indent.push_str(" ");
}
source.push_str(&format!("{indent}return 0;\n"));
for _ in 0..depth {
indent.truncate(indent.len() - 4);
source.push_str(&format!("{indent}}}\n"));
}
source.push_str("}\n");
fs::write(temp_dir.path().join("deep.cpp"), source).unwrap();
}
#[test]
fn helper_index_deep_nested_project() {
if env::var_os(HELPER_ENV).is_none() {
return;
}
let project_path = env::var(PROJECT_ENV).unwrap();
let mut index = LeIndex::new(&project_path).unwrap();
let stats = index.index_project(true).unwrap();
assert_eq!(stats.failed_parses, 0);
assert_eq!(stats.successful_parses, 1);
}
#[test]
fn test_index_deep_nested_rust_project_does_not_overflow_stack() {
let temp_dir = TempDir::new().unwrap();
write_deep_rust_file(&temp_dir, 6000);
let output = Command::new(env::current_exe().unwrap())
.env(HELPER_ENV, "1")
.env(PROJECT_ENV, temp_dir.path())
.arg("--exact")
.arg(HELPER_TEST_NAME)
.arg("--nocapture")
.output()
.unwrap();
assert!(
output.status.success(),
"child process failed\nstatus: {:?}\nstdout:\n{}\nstderr:\n{}",
output.status.code(),
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn test_index_deep_nested_cpp_project_does_not_overflow_stack() {
let temp_dir = TempDir::new().unwrap();
write_deep_cpp_file(&temp_dir, 6000);
let output = Command::new(env::current_exe().unwrap())
.env(HELPER_ENV, "1")
.env(PROJECT_ENV, temp_dir.path())
.arg("--exact")
.arg(HELPER_TEST_NAME)
.arg("--nocapture")
.output()
.unwrap();
assert!(
output.status.success(),
"child process failed\nstatus: {:?}\nstdout:\n{}\nstderr:\n{}",
output.status.code(),
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
}
}