use super::*;
#[test]
fn test_validation_level_default() {
let level = ValidationLevel::default();
assert_eq!(level, ValidationLevel::Minimal);
}
#[test]
fn test_validation_level_ordering() {
assert!(ValidationLevel::None < ValidationLevel::Minimal);
assert!(ValidationLevel::Minimal < ValidationLevel::Strict);
assert!(ValidationLevel::Strict < ValidationLevel::Paranoid);
}
#[test]
fn test_validation_level_equality() {
assert_eq!(ValidationLevel::None, ValidationLevel::None);
assert_eq!(ValidationLevel::Minimal, ValidationLevel::Minimal);
assert_eq!(ValidationLevel::Strict, ValidationLevel::Strict);
assert_eq!(ValidationLevel::Paranoid, ValidationLevel::Paranoid);
assert_ne!(ValidationLevel::None, ValidationLevel::Minimal);
assert_ne!(ValidationLevel::Strict, ValidationLevel::Paranoid);
}
#[test]
fn test_validation_level_serialization() {
let level = ValidationLevel::Strict;
let json = serde_json::to_string(&level).expect("Failed to serialize");
let deserialized: ValidationLevel = serde_json::from_str(&json).expect("Failed to deserialize");
assert_eq!(level, deserialized);
}
#[test]
fn test_validation_level_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(ValidationLevel::None);
set.insert(ValidationLevel::Minimal);
set.insert(ValidationLevel::Strict);
set.insert(ValidationLevel::Paranoid);
assert_eq!(set.len(), 4);
assert!(set.contains(&ValidationLevel::Strict));
}
#[test]
fn test_severity_variants() {
let error = Severity::Error;
let warning = Severity::Warning;
let style = Severity::Style;
assert_eq!(error.as_str(), "error");
assert_eq!(warning.as_str(), "warning");
assert_eq!(style.as_str(), "style");
}
#[test]
fn test_severity_equality() {
assert_eq!(Severity::Error, Severity::Error);
assert_eq!(Severity::Warning, Severity::Warning);
assert_eq!(Severity::Style, Severity::Style);
assert_ne!(Severity::Error, Severity::Warning);
assert_ne!(Severity::Warning, Severity::Style);
}
#[test]
fn test_severity_style_variant() {
let style = Severity::Style;
assert_eq!(style.as_str(), "style");
}
#[test]
fn test_validation_error_display_minimal() {
let error = ValidationError {
rule: "TEST001",
severity: Severity::Warning,
message: "Test message".to_string(),
suggestion: None,
auto_fix: None,
line: None,
column: None,
};
let display = format!("{error}");
assert!(display.contains("TEST001"));
assert!(display.contains("warning"));
assert!(display.contains("Test message"));
assert!(!display.contains("Suggestion:"));
}
#[test]
fn test_validation_error_display_with_suggestion() {
let error = ValidationError {
rule: "TEST002",
severity: Severity::Error,
message: "Error occurred".to_string(),
suggestion: Some("Try this instead".to_string()),
auto_fix: None,
line: Some(42),
column: Some(10),
};
let display = format!("{error}");
assert!(display.contains("Suggestion: Try this instead"));
}
#[test]
fn test_validation_error_as_error_trait() {
let error = ValidationError {
rule: "TEST003",
severity: Severity::Error,
message: "Test error".to_string(),
suggestion: None,
auto_fix: None,
line: None,
column: None,
};
let _: &dyn std::error::Error = &error;
}
#[test]
fn test_validation_error_with_all_fields() {
let error = ValidationError {
rule: "SC2086",
severity: Severity::Error,
message: "Unquoted variable expansion".to_string(),
suggestion: Some("Quote the variable".to_string()),
auto_fix: Some(Fix {
description: "Add quotes".to_string(),
replacement: "\"$VAR\"".to_string(),
}),
line: Some(15),
column: Some(8),
};
assert_eq!(error.rule, "SC2086");
assert_eq!(error.severity, Severity::Error);
assert_eq!(error.line, Some(15));
assert_eq!(error.column, Some(8));
assert!(error.suggestion.is_some());
assert!(error.auto_fix.is_some());
}
#[test]
fn test_fix_creation() {
let fix = Fix {
description: "Replace with safer alternative".to_string(),
replacement: "safe_code".to_string(),
};
assert_eq!(fix.description, "Replace with safer alternative");
assert_eq!(fix.replacement, "safe_code");
}
#[test]
fn test_fix_clone() {
let fix = Fix {
description: "Test fix".to_string(),
replacement: "fixed".to_string(),
};
let cloned = fix.clone();
assert_eq!(fix.description, cloned.description);
assert_eq!(fix.replacement, cloned.replacement);
}
#[test]
fn test_validated_node_size() {
assert_eq!(std::mem::size_of::<ValidatedNode>(), 8);
}
#[test]
fn test_implemented_rules_access() {
assert!(!IMPLEMENTED_RULES.is_empty());
assert!(IMPLEMENTED_RULES.contains(&"SC2086"));
assert!(IMPLEMENTED_RULES.contains(&"SC2046"));
assert!(IMPLEMENTED_RULES.contains(&"SC2006"));
}
#[test]
fn test_implemented_rules_content() {
let rules: Vec<&str> = IMPLEMENTED_RULES.to_vec();
assert!(
rules.contains(&"SC2086"),
"Missing SC2086 (unquoted variables)"
);
assert!(
rules.contains(&"SC2046"),
"Missing SC2046 (unquoted command substitution)"
);
assert!(
rules.contains(&"SC2164"),
"Missing SC2164 (cd without error check)"
);
assert!(
rules.contains(&"SC2162"),
"Missing SC2162 (read without -r)"
);
}
#[test]
fn test_validate_shell_snippet_valid() {
let result = validate_shell_snippet("echo \"hello world\"");
assert!(result.is_ok());
}
#[test]
fn test_validate_shell_snippet_invalid_backticks() {
let result = validate_shell_snippet("echo `date`");
assert!(result.is_err());
}
#[test]
fn test_validate_shell_snippet_invalid_cd() {
let result = validate_shell_snippet("cd /tmp");
assert!(result.is_err());
}
#[test]
fn test_validate_shell_snippet_empty() {
let result = validate_shell_snippet("");
assert!(result.is_ok());
}
#[test]
fn test_validate_shell_snippet_multiline() {
let snippet = r#"
echo "Starting"
cd /tmp || exit 1
read -r var
echo "Done"
"#;
let result = validate_shell_snippet(snippet);
assert!(result.is_ok());
}
#[test]
fn test_validation_error_clone() {
let error = ValidationError {
rule: "TEST004",
severity: Severity::Warning,
message: "Clone test".to_string(),
suggestion: Some("Fix it".to_string()),
auto_fix: Some(Fix {
description: "Auto fix".to_string(),
replacement: "fixed".to_string(),
}),
line: Some(10),
column: Some(5),
};
let cloned = error.clone();
assert_eq!(error.rule, cloned.rule);
assert_eq!(error.severity, cloned.severity);
assert_eq!(error.message, cloned.message);
assert_eq!(error.line, cloned.line);
assert_eq!(error.column, cloned.column);
}
#[test]
fn test_validation_level_copy() {
let level = ValidationLevel::Strict;
let copied = level;
assert_eq!(level, copied);
}
#[test]
fn test_validation_level_clone() {
let level = ValidationLevel::Paranoid;
let cloned = level;
assert_eq!(level, cloned);
}
#[test]
fn test_severity_copy() {
let sev = Severity::Error;
let copied = sev;
assert_eq!(sev, copied);
}
#[test]
fn test_severity_clone() {
let sev = Severity::Warning;
let cloned = sev;
assert_eq!(sev, cloned);
}