use anyhow::Result;
use regex::Regex;
use fsvalidator::loader::load_root;
use fsvalidator::model::{Node, NodeName};
use fsvalidator::raw::{RawNode, RawNodeType, RawRoot};
use std::collections::HashMap;
#[test]
fn test_load_basic_structure() -> Result<()> {
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Dir,
name: Some("test_dir".to_string()),
pattern: None,
children: Some(vec![RawNode {
r#type: RawNodeType::File,
name: Some("test_file.txt".to_string()),
pattern: None,
children: None,
r#ref: None,
required: Some(true),
allow_defined_only: None,
excluded: None,
}]),
r#ref: None,
required: Some(true),
allow_defined_only: None,
excluded: None,
},
template: HashMap::new(),
config: None,
global: None,
};
let node = load_root(&raw_root)?;
match &node {
Node::Dir(dir_rc) => {
let dir = dir_rc.borrow();
assert_eq!(dir.name, NodeName::Literal("test_dir".to_string()));
assert_eq!(dir.required, true);
assert_eq!(dir.allow_defined_only, false);
assert_eq!(dir.children.len(), 1);
match &dir.children[0] {
Node::File(file_rc) => {
let file = file_rc.borrow();
assert_eq!(file.name, NodeName::Literal("test_file.txt".to_string()));
assert_eq!(file.required, true);
}
_ => panic!("Expected a file node"),
}
}
_ => panic!("Expected a directory node"),
}
Ok(())
}
#[test]
fn test_load_with_pattern() -> Result<()> {
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Dir,
name: None,
pattern: Some("test_dir_\\d+".to_string()),
children: Some(vec![RawNode {
r#type: RawNodeType::File,
name: None,
pattern: Some(".*\\.log".to_string()),
children: None,
r#ref: None,
required: Some(true),
allow_defined_only: None,
excluded: None,
}]),
r#ref: None,
required: Some(true),
allow_defined_only: None,
excluded: None,
},
template: HashMap::new(),
config: None,
global: None,
};
let node = load_root(&raw_root)?;
match &node {
Node::Dir(dir_rc) => {
let dir = dir_rc.borrow();
match &dir.name {
NodeName::Pattern(pattern) => {
assert_eq!(pattern, "test_dir_\\d+");
let re = Regex::new(pattern)?;
assert!(re.is_match("test_dir_123"));
}
_ => panic!("Expected a pattern node name"),
}
match &dir.children[0] {
Node::File(file_rc) => {
let file = file_rc.borrow();
match &file.name {
NodeName::Pattern(pattern) => {
assert_eq!(pattern, ".*\\.log");
let re = Regex::new(pattern)?;
assert!(re.is_match("server.log"));
}
_ => panic!("Expected a pattern node name"),
}
}
_ => panic!("Expected a file node"),
}
}
_ => panic!("Expected a directory node"),
}
Ok(())
}
#[test]
fn test_load_with_templates() -> Result<()> {
let mut templates = HashMap::new();
templates.insert(
"config".to_string(),
RawNode {
r#type: RawNodeType::Dir,
name: Some("config".to_string()),
pattern: None,
children: Some(vec![RawNode {
r#type: RawNodeType::File,
name: Some("settings.json".to_string()),
pattern: None,
children: None,
r#ref: None,
required: Some(true),
allow_defined_only: None,
excluded: None,
}]),
r#ref: None,
required: None,
allow_defined_only: None,
excluded: None,
},
);
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Dir,
name: Some("project".to_string()),
pattern: None,
children: Some(vec![RawNode {
r#type: RawNodeType::Ref,
name: None,
pattern: Some("config.*".to_string()),
children: None,
r#ref: Some("config".to_string()),
required: Some(true),
allow_defined_only: None,
excluded: None,
}]),
r#ref: None,
required: Some(true),
allow_defined_only: None,
excluded: None,
},
template: templates,
config: None,
global: None,
};
let node = load_root(&raw_root)?;
match &node {
Node::Dir(dir_rc) => {
let dir = dir_rc.borrow();
assert_eq!(dir.name, NodeName::Literal("project".to_string()));
match &dir.children[0] {
Node::Dir(template_rc) => {
let template = template_rc.borrow();
match &template.name {
NodeName::Literal(literal) => {
assert_eq!(literal, "config");
}
_ => panic!("Expected a literal node name"),
}
match &template.children[0] {
Node::File(file_rc) => {
let file = file_rc.borrow();
assert_eq!(file.name, NodeName::Literal("settings.json".to_string()));
}
_ => panic!("Expected a file node"),
}
}
_ => panic!("Expected a directory node"),
}
}
_ => panic!("Expected a directory node"),
}
Ok(())
}
#[test]
fn test_load_with_global_settings() -> Result<()> {
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Dir,
name: Some("project".to_string()),
pattern: None,
children: Some(vec![RawNode {
r#type: RawNodeType::File,
name: Some("config.json".to_string()),
pattern: None,
children: None,
r#ref: None,
required: None, allow_defined_only: None,
excluded: None,
}]),
r#ref: None,
required: None, allow_defined_only: None, excluded: None,
},
template: HashMap::new(),
config: None,
global: Some(fsvalidator::raw::RawGlobal {
required: Some(true),
allow_defined_only: Some(true),
excluded: Some(vec![".*\\.bak".to_string()]),
}),
};
let node = load_root(&raw_root)?;
match &node {
Node::Dir(dir_rc) => {
let dir = dir_rc.borrow();
assert_eq!(dir.required, true); assert_eq!(dir.allow_defined_only, true);
match &dir.children[0] {
Node::File(file_rc) => {
let file = file_rc.borrow();
assert_eq!(file.required, true); }
_ => panic!("Expected a file node"),
}
}
_ => panic!("Expected a directory node"),
}
Ok(())
}
#[test]
fn test_load_error_missing_name_and_pattern() {
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Dir,
name: None,
pattern: None, children: None,
r#ref: None,
required: None,
allow_defined_only: None,
excluded: None,
},
template: HashMap::new(),
config: None,
global: None,
};
let result = load_root(&raw_root);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("Node must have either 'name' or 'pattern'")
);
}
#[test]
fn test_load_error_missing_ref() {
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Ref,
name: Some("test".to_string()),
pattern: None,
children: None,
r#ref: None, required: None,
allow_defined_only: None,
excluded: None,
},
template: HashMap::new(),
config: None,
global: None,
};
let result = load_root(&raw_root);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("Ref node missing 'ref' field")
);
}
#[test]
fn test_load_error_unknown_template() {
let raw_root = RawRoot {
root: RawNode {
r#type: RawNodeType::Ref,
name: Some("test".to_string()),
pattern: None,
children: None,
r#ref: Some("non_existent_template".to_string()),
required: None,
allow_defined_only: None,
excluded: None,
},
template: HashMap::new(), config: None,
global: None,
};
let result = load_root(&raw_root);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("Unknown template ref")
);
}