cfgd_core/generate/
validate.rs1use crate::config::{CfgdConfig, ModuleDocument, ProfileDocument};
2use crate::generate::{SchemaKind, ValidationResult};
3
4pub fn validate_yaml(content: &str, kind: SchemaKind) -> ValidationResult {
5 let value: serde_yaml::Value = match serde_yaml::from_str(content) {
7 Ok(v) => v,
8 Err(e) => {
9 return ValidationResult {
10 valid: false,
11 errors: vec![format!("YAML syntax error: {}", e)],
12 };
13 }
14 };
15
16 if let Some(doc_kind) = value.get("kind").and_then(|v| v.as_str())
18 && doc_kind != kind.as_str()
19 {
20 return ValidationResult {
21 valid: false,
22 errors: vec![format!(
23 "Expected kind '{}', found '{}'",
24 kind.as_str(),
25 doc_kind
26 )],
27 };
28 }
29
30 let deser_result = match kind {
32 SchemaKind::Module => serde_yaml::from_str::<ModuleDocument>(content).map(|_| ()),
33 SchemaKind::Profile => serde_yaml::from_str::<ProfileDocument>(content).map(|_| ()),
34 SchemaKind::Config => serde_yaml::from_str::<CfgdConfig>(content).map(|_| ()),
35 };
36
37 match deser_result {
38 Ok(()) => ValidationResult {
39 valid: true,
40 errors: vec![],
41 },
42 Err(e) => ValidationResult {
43 valid: false,
44 errors: vec![format!("Deserialization error: {}", e)],
45 },
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn test_validate_valid_module() {
55 let yaml = r#"
56apiVersion: cfgd.io/v1alpha1
57kind: Module
58metadata:
59 name: nvim
60spec:
61 packages:
62 - name: neovim
63"#;
64 let result = validate_yaml(yaml, SchemaKind::Module);
65 assert!(
66 result.valid,
67 "Expected valid, got errors: {:?}",
68 result.errors
69 );
70 }
71
72 #[test]
73 fn test_validate_valid_profile() {
74 let yaml = r#"
75apiVersion: cfgd.io/v1alpha1
76kind: Profile
77metadata:
78 name: base
79spec:
80 modules: [nvim, tmux]
81"#;
82 let result = validate_yaml(yaml, SchemaKind::Profile);
83 assert!(
84 result.valid,
85 "Expected valid, got errors: {:?}",
86 result.errors
87 );
88 }
89
90 #[test]
91 fn test_validate_invalid_yaml_syntax() {
92 let yaml = "not: [valid: yaml: {{";
93 let result = validate_yaml(yaml, SchemaKind::Module);
94 assert!(!result.valid);
95 assert!(!result.errors.is_empty());
96 }
97
98 #[test]
99 fn test_validate_wrong_kind() {
100 let yaml = r#"
101apiVersion: cfgd.io/v1alpha1
102kind: Profile
103metadata:
104 name: test
105spec: {}
106"#;
107 let result = validate_yaml(yaml, SchemaKind::Module);
108 assert!(!result.valid);
109 assert!(result.errors.iter().any(|e| e.contains("kind")));
110 }
111
112 #[test]
113 fn test_validate_missing_api_version() {
114 let yaml = r#"
115kind: Module
116metadata:
117 name: test
118spec: {}
119"#;
120 let result = validate_yaml(yaml, SchemaKind::Module);
121 assert!(!result.valid);
122 assert!(result.errors.iter().any(|e| e.contains("apiVersion")));
123 }
124}