#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::needless_raw_string_hashes,
clippy::duration_suboptimal_units,
clippy::branches_sharing_code,
clippy::used_underscore_binding,
clippy::single_char_pattern,
clippy::ignore_without_reason,
clippy::cloned_ref_to_slice_refs,
clippy::doc_overindented_list_items,
clippy::match_wildcard_for_single_variants,
clippy::ignored_unit_patterns,
clippy::needless_collect,
clippy::unnecessary_map_or,
clippy::manual_flatten,
clippy::manual_strip,
clippy::future_not_send,
clippy::unnested_or_patterns,
clippy::no_effect_underscore_binding,
clippy::literal_string_with_formatting_args
)]
use ggen_core::validation::{detect_language, validate_syntax, LanguageType};
use std::path::Path;
use tempfile::TempDir;
#[test]
fn test_detect_language_rust() {
assert_eq!(detect_language(Path::new("main.rs")), LanguageType::Rust);
assert_eq!(detect_language(Path::new("lib.rs")), LanguageType::Rust);
}
#[test]
fn test_detect_language_toml() {
assert_eq!(detect_language(Path::new("Cargo.toml")), LanguageType::Toml);
assert_eq!(detect_language(Path::new("ggen.toml")), LanguageType::Toml);
}
#[test]
fn test_detect_language_json() {
assert_eq!(
detect_language(Path::new("config.json")),
LanguageType::Json
);
}
#[test]
fn test_detect_language_yaml() {
assert_eq!(
detect_language(Path::new("config.yaml")),
LanguageType::Yaml
);
assert_eq!(detect_language(Path::new("config.yml")), LanguageType::Yaml);
}
#[test]
fn test_detect_language_markdown() {
assert_eq!(
detect_language(Path::new("README.md")),
LanguageType::Markdown
);
}
#[test]
fn test_detect_language_tera() {
assert_eq!(
detect_language(Path::new("template.tera")),
LanguageType::Tera
);
}
#[test]
fn test_validate_syntax_rust_valid_minimal() {
let code = "fn main() {}";
assert!(
validate_syntax(Path::new("main.rs"), code).is_ok(),
"Valid minimal Rust code must pass"
);
}
#[test]
fn test_validate_syntax_rust_valid_struct() {
let code = "struct Point { x: i32, y: i32 }";
assert!(
validate_syntax(Path::new("types.rs"), code).is_ok(),
"Valid Rust struct must pass"
);
}
#[test]
fn test_validate_syntax_rust_valid_impl_block() {
let code = r#"
impl Point {
fn new(x: i32, y: i32) -> Self {
Point { x, y }
}
}
"#;
assert!(
validate_syntax(Path::new("impl.rs"), code).is_ok(),
"Valid Rust impl block must pass"
);
}
#[test]
fn test_validate_syntax_toml_valid() {
let toml = "[package]\nname = \"test\"\nversion = \"0.1.0\"\n";
assert!(
validate_syntax(Path::new("Cargo.toml"), toml).is_ok(),
"Valid TOML must pass"
);
}
#[test]
fn test_validate_syntax_json_valid() {
let json = r#"{"name": "test", "count": 42, "enabled": true}"#;
assert!(
validate_syntax(Path::new("config.json"), json).is_ok(),
"Valid JSON must pass"
);
}
#[test]
fn test_validate_syntax_json_nested() {
let json = r#"{
"database": {
"host": "localhost",
"port": 5432
},
"features": ["auth", "logging"]
}"#;
assert!(
validate_syntax(Path::new("config.json"), json).is_ok(),
"Valid nested JSON must pass"
);
}
#[test]
fn test_validate_syntax_yaml_valid() {
let yaml = "key: value\nlist:\n - item1\n - item2\n";
assert!(
validate_syntax(Path::new("config.yaml"), yaml).is_ok(),
"Valid YAML must pass"
);
}
#[test]
fn test_validate_syntax_markdown_passthrough() {
let md = "# Title\n\nContent with `code`.\n";
assert!(
validate_syntax(Path::new("README.md"), md).is_ok(),
"Markdown files passthrough validation"
);
}
#[test]
fn test_validate_syntax_rust_invalid_missing_semicolon() {
let code = "fn main() { let x = 1 }";
let result = validate_syntax(Path::new("main.rs"), code);
assert!(
result.is_err(),
"Rust code with missing semicolon must fail"
);
let err = result.unwrap_err().to_string();
assert!(err.contains("Rust"), "Error must mention Rust language");
}
#[test]
fn test_validate_syntax_rust_invalid_bad_token() {
let code = "fn main() { @@@ }";
assert!(
validate_syntax(Path::new("main.rs"), code).is_err(),
"Rust code with bad tokens must fail"
);
}
#[test]
fn test_validate_syntax_rust_invalid_incomplete_statement() {
let code = "fn main() { let x }";
assert!(
validate_syntax(Path::new("main.rs"), code).is_err(),
"Incomplete Rust statement must fail"
);
}
#[test]
fn test_validate_syntax_rust_invalid_mismatched_braces() {
let code = "fn main() { let x = vec![1, 2, 3 }";
assert!(
validate_syntax(Path::new("main.rs"), code).is_err(),
"Mismatched braces must fail"
);
}
#[test]
fn test_validate_syntax_toml_invalid_missing_bracket() {
let toml = "[package\nname = \"test\"\n";
assert!(
validate_syntax(Path::new("Cargo.toml"), toml).is_err(),
"TOML with missing ] must fail"
);
}
#[test]
fn test_validate_syntax_toml_invalid_bad_key() {
let toml = "[section invalid key =]\n";
assert!(
validate_syntax(Path::new("test.toml"), toml).is_err(),
"TOML with bad key syntax must fail"
);
}
#[test]
fn test_validate_syntax_json_invalid_trailing_comma() {
let json = r#"{"key": "value",}"#;
assert!(
validate_syntax(Path::new("config.json"), json).is_err(),
"JSON with trailing comma must fail"
);
}
#[test]
fn test_validate_syntax_json_invalid_unclosed_string() {
let json = r#"{"key": "unclosed}"#;
assert!(
validate_syntax(Path::new("config.json"), json).is_err(),
"JSON with unclosed string must fail"
);
}
#[test]
fn test_validate_syntax_json_invalid_missing_quote() {
let json = r#"{key: "value"}"#;
assert!(
validate_syntax(Path::new("config.json"), json).is_err(),
"JSON with unquoted key must fail"
);
}
#[test]
fn test_validate_syntax_yaml_invalid_bad_structure() {
let yaml = "key: value\n bad_indent: wrong\n";
let result = validate_syntax(Path::new("config.yaml"), yaml);
let _ = result;
}
#[test]
fn test_validate_syntax_rust_empty_file() {
let code = "";
assert!(
validate_syntax(Path::new("empty.rs"), code).is_err(),
"Empty Rust file must fail"
);
}
#[test]
fn test_validate_syntax_json_empty_file() {
let json = "";
assert!(
validate_syntax(Path::new("empty.json"), json).is_err(),
"Empty JSON file must fail"
);
}
#[test]
fn test_validate_syntax_markdown_empty_file() {
let md = "";
assert!(
validate_syntax(Path::new("empty.md"), md).is_ok(),
"Empty markdown is valid"
);
}
#[test]
fn test_validate_syntax_rust_whitespace_only() {
let code = " \n \n ";
let result = validate_syntax(Path::new("whitespace.rs"), code);
let _ = result;
}
#[test]
fn test_validate_syntax_multifile_all_valid() {
let dir = TempDir::new().unwrap();
let rust_file = dir.path().join("main.rs");
std::fs::write(&rust_file, "fn main() {}").unwrap();
let json_file = dir.path().join("config.json");
std::fs::write(&json_file, r#"{"enabled": true}"#).unwrap();
let toml_file = dir.path().join("test.toml");
std::fs::write(&toml_file, "key = \"value\"").unwrap();
let rust_content = std::fs::read_to_string(&rust_file).unwrap();
let json_content = std::fs::read_to_string(&json_file).unwrap();
let toml_content = std::fs::read_to_string(&toml_file).unwrap();
assert!(validate_syntax(&rust_file, &rust_content).is_ok());
assert!(validate_syntax(&json_file, &json_content).is_ok());
assert!(validate_syntax(&toml_file, &toml_content).is_ok());
}
#[test]
fn test_validate_syntax_multifile_one_fails() {
let dir = TempDir::new().unwrap();
let rust_file = dir.path().join("main.rs");
std::fs::write(&rust_file, "fn main() { broken").unwrap();
let json_file = dir.path().join("config.json");
std::fs::write(&json_file, r#"{"enabled": true}"#).unwrap();
let rust_content = std::fs::read_to_string(&rust_file).unwrap();
let json_content = std::fs::read_to_string(&json_file).unwrap();
assert!(
validate_syntax(&rust_file, &rust_content).is_err(),
"Rust file with syntax error must fail"
);
assert!(
validate_syntax(&json_file, &json_content).is_ok(),
"Valid JSON must pass"
);
}
#[test]
fn test_validate_syntax_error_message_includes_language() {
let code = "fn main() { broken";
let result = validate_syntax(Path::new("main.rs"), code);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("[Rust]"),
"Error must include language in brackets: {}",
err
);
}
#[test]
fn test_validate_syntax_error_message_format() {
let json = "{invalid}";
let result = validate_syntax(Path::new("config.json"), json);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("JSON"),
"Error format must include language type: {}",
err
);
}