use crate::{EvaluationError, EvaluationResult};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::Duration;
use voirs_sdk::AudioBuffer;
pub struct ValidationFramework {
pub config: ValidationConfig,
pub reference_implementations: HashMap<String, Box<dyn ReferenceImplementation>>,
pub platform_tests: HashMap<String, PlatformTestSuite>,
pub precision_validators: Vec<Box<dyn PrecisionValidator>>,
pub edge_case_generators: Vec<Box<dyn EdgeCaseGenerator>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationConfig {
pub enable_reference_validation: bool,
pub enable_cross_platform_testing: bool,
pub enable_precision_verification: bool,
pub enable_edge_case_testing: bool,
pub numerical_tolerance: f64,
pub max_execution_time: Duration,
pub test_iterations: usize,
pub confidence_level: f64,
pub generate_detailed_reports: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationResult {
pub overall_status: ValidationStatus,
pub reference_validation: Option<ReferenceValidationResult>,
pub platform_validation: Option<PlatformValidationResult>,
pub precision_validation: Option<PrecisionValidationResult>,
pub edge_case_validation: Option<EdgeCaseValidationResult>,
pub summary: ValidationSummary,
pub detailed_results: Vec<DetailedTestResult>,
pub timestamp: std::time::SystemTime,
pub duration: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ValidationStatus {
Passed,
PassedWithWarnings,
Failed,
Incomplete,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReferenceValidationResult {
pub tests_passed: usize,
pub tests_failed: usize,
pub average_correlation: f64,
pub max_deviation: f64,
pub metric_results: HashMap<String, MetricValidationResult>,
pub reference_details: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformValidationResult {
pub tested_platforms: Vec<String>,
pub consistency_score: f64,
pub platform_results: HashMap<String, PlatformSpecificResult>,
pub compatibility_matrix: Vec<Vec<f64>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrecisionValidationResult {
pub stability_score: f64,
pub precision_tests: Vec<PrecisionTestResult>,
pub fp_consistency: FpConsistencyResult,
pub determinism: DeterminismResult,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EdgeCaseValidationResult {
pub edge_cases_tested: usize,
pub edge_cases_passed: usize,
pub robustness_score: f64,
pub categories_tested: Vec<String>,
pub failed_cases: Vec<FailedEdgeCaseResult>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationSummary {
pub total_tests: usize,
pub tests_passed: usize,
pub tests_failed: usize,
pub success_rate: f64,
pub avg_execution_time: Duration,
pub memory_usage: MemoryUsageStats,
pub performance_metrics: ValidationPerformanceMetrics,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DetailedTestResult {
pub test_name: String,
pub category: TestCategory,
pub status: TestStatus,
pub expected: Option<serde_json::Value>,
pub actual: Option<serde_json::Value>,
pub deviation: Option<f64>,
pub execution_time: Duration,
pub memory_usage: u64,
pub error_message: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TestCategory {
ReferenceImplementation,
CrossPlatform,
NumericalPrecision,
EdgeCase,
PerformanceRegression,
MemoryUsage,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum TestStatus {
Passed,
Failed,
Skipped,
Timeout,
Crashed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricValidationResult {
pub metric_name: String,
pub correlation: f64,
pub mean_absolute_error: f64,
pub root_mean_square_error: f64,
pub test_cases: usize,
pub validation_passed: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformSpecificResult {
pub platform: String,
pub os_version: String,
pub architecture: String,
pub test_results: Vec<DetailedTestResult>,
pub performance: PlatformPerformanceMetrics,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrecisionTestResult {
pub test_name: String,
pub input_precision: u32,
pub output_precision: u32,
pub precision_loss: f64,
pub numerical_stability: f64,
pub passed: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FpConsistencyResult {
pub range_consistency: f64,
pub type_consistency: f64,
pub rounding_consistency: f64,
pub overall_consistency: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeterminismResult {
pub determinism_score: f64,
pub determinism_tests: usize,
pub seed_reproducibility: bool,
pub cross_run_consistency: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FailedEdgeCaseResult {
pub case_name: String,
pub category: String,
pub input_description: String,
pub expected_behavior: String,
pub actual_behavior: String,
pub severity: EdgeCaseSeverity,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum EdgeCaseSeverity {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryUsageStats {
pub peak_memory: u64,
pub average_memory: u64,
pub efficiency_score: f64,
pub memory_leaks_detected: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationPerformanceMetrics {
pub total_time: Duration,
pub tests_per_second: f64,
pub cpu_usage: f64,
pub memory_usage: u64,
pub throughput: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformPerformanceMetrics {
pub throughput: f64,
pub latency: Duration,
pub resource_utilization: HashMap<String, f64>,
}
#[async_trait]
pub trait ReferenceImplementation: Send + Sync {
fn name(&self) -> &str;
fn version(&self) -> &str;
async fn validate_against_reference(
&self,
test_input: &AudioBuffer,
actual_result: &serde_json::Value,
) -> EvaluationResult<MetricValidationResult>;
async fn get_expected_result(
&self,
test_input: &AudioBuffer,
) -> EvaluationResult<serde_json::Value>;
fn supports_test(&self, test_name: &str) -> bool;
}
pub trait PrecisionValidator: Send + Sync {
fn validate_precision(
&self,
input: &[f64],
output: &[f64],
tolerance: f64,
) -> Result<PrecisionTestResult, voirs_sdk::VoirsError>;
fn name(&self) -> &str;
}
pub trait EdgeCaseGenerator: Send + Sync {
fn generate_edge_cases(&self) -> Result<Vec<EdgeCaseTest>, voirs_sdk::VoirsError>;
fn name(&self) -> &str;
fn supported_categories(&self) -> Vec<String>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EdgeCaseTest {
pub name: String,
pub category: String,
pub input: AudioBuffer,
pub expected_behavior: String,
pub acceptance_criteria: AcceptanceCriteria,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AcceptanceCriteria {
pub should_not_crash: bool,
pub should_return_valid_result: bool,
pub max_processing_time: Option<Duration>,
pub min_quality_threshold: Option<f64>,
pub custom_validator: Option<String>,
}
#[derive(Debug, Clone)]
pub struct PlatformTestSuite {
pub platform: String,
pub test_cases: Vec<PlatformTestCase>,
pub config: PlatformTestConfig,
}
#[derive(Debug, Clone)]
pub struct PlatformTestCase {
pub name: String,
pub input: AudioBuffer,
pub expected_characteristics: HashMap<String, f64>,
pub platform_params: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformTestConfig {
pub tolerances: HashMap<String, f64>,
pub timeouts: HashMap<String, Duration>,
pub capabilities: Vec<String>,
}
impl ValidationFramework {
pub fn new(config: ValidationConfig) -> Self {
Self {
config,
reference_implementations: HashMap::new(),
platform_tests: HashMap::new(),
precision_validators: Vec::new(),
edge_case_generators: Vec::new(),
}
}
pub fn add_reference_implementation(
&mut self,
name: String,
implementation: Box<dyn ReferenceImplementation>,
) {
self.reference_implementations.insert(name, implementation);
}
pub fn add_platform_test_suite(&mut self, platform: String, test_suite: PlatformTestSuite) {
self.platform_tests.insert(platform, test_suite);
}
pub fn add_precision_validator(&mut self, validator: Box<dyn PrecisionValidator>) {
self.precision_validators.push(validator);
}
pub fn add_edge_case_generator(&mut self, generator: Box<dyn EdgeCaseGenerator>) {
self.edge_case_generators.push(generator);
}
pub async fn run_comprehensive_validation(
&self,
target_evaluator: &dyn ValidationTarget,
) -> EvaluationResult<ValidationResult> {
let start_time = std::time::Instant::now();
let mut detailed_results = Vec::new();
let mut tests_passed = 0;
let mut tests_failed = 0;
let reference_validation = if self.config.enable_reference_validation {
match self.run_reference_validation(target_evaluator).await {
Ok(result) => {
tests_passed += result.tests_passed;
tests_failed += result.tests_failed;
Some(result)
}
Err(_) => None,
}
} else {
None
};
let platform_validation = if self.config.enable_cross_platform_testing {
match self.run_platform_validation(target_evaluator).await {
Ok(result) => Some(result),
Err(_) => None,
}
} else {
None
};
let precision_validation = if self.config.enable_precision_verification {
match self.run_precision_validation(target_evaluator).await {
Ok(result) => Some(result),
Err(_) => None,
}
} else {
None
};
let edge_case_validation = if self.config.enable_edge_case_testing {
match self.run_edge_case_validation(target_evaluator).await {
Ok(result) => {
tests_passed += result.edge_cases_passed;
tests_failed += result.edge_cases_tested - result.edge_cases_passed;
Some(result)
}
Err(_) => None,
}
} else {
None
};
let duration = start_time.elapsed();
let total_tests = tests_passed + tests_failed;
let success_rate = if total_tests > 0 {
tests_passed as f64 / total_tests as f64
} else {
0.0
};
let overall_status = if success_rate >= 0.95 {
ValidationStatus::Passed
} else if success_rate >= 0.8 {
ValidationStatus::PassedWithWarnings
} else if total_tests > 0 {
ValidationStatus::Failed
} else {
ValidationStatus::Incomplete
};
let summary = ValidationSummary {
total_tests,
tests_passed,
tests_failed,
success_rate,
avg_execution_time: if total_tests > 0 {
duration / total_tests as u32
} else {
Duration::ZERO
},
memory_usage: MemoryUsageStats {
peak_memory: 0, average_memory: 0,
efficiency_score: 0.9,
memory_leaks_detected: false,
},
performance_metrics: ValidationPerformanceMetrics {
total_time: duration,
tests_per_second: if duration.as_secs_f64() > 0.0 {
total_tests as f64 / duration.as_secs_f64()
} else {
0.0
},
cpu_usage: 0.0, memory_usage: 0,
throughput: HashMap::new(),
},
};
Ok(ValidationResult {
overall_status,
reference_validation,
platform_validation,
precision_validation,
edge_case_validation,
summary,
detailed_results,
timestamp: std::time::SystemTime::now(),
duration,
})
}
async fn run_reference_validation(
&self,
target_evaluator: &dyn ValidationTarget,
) -> EvaluationResult<ReferenceValidationResult> {
let mut tests_passed = 0;
let mut tests_failed = 0;
let mut correlations = Vec::new();
let mut deviations = Vec::new();
let mut metric_results = HashMap::new();
for (name, reference) in &self.reference_implementations {
let test_inputs = self.generate_test_inputs()?;
for (i, test_input) in test_inputs.iter().enumerate() {
let test_name = format!("{}_{}", name, i);
let expected = reference.get_expected_result(test_input).await?;
let actual = target_evaluator.evaluate_for_validation(test_input).await?;
let validation_result = reference
.validate_against_reference(test_input, &actual)
.await?;
if validation_result.validation_passed {
tests_passed += 1;
} else {
tests_failed += 1;
}
correlations.push(validation_result.correlation);
deviations.push(validation_result.mean_absolute_error);
metric_results.insert(test_name, validation_result);
}
}
let average_correlation = correlations.iter().sum::<f64>() / correlations.len() as f64;
let max_deviation = deviations
.iter()
.fold(0.0, |acc, &x| if x > acc { x } else { acc });
Ok(ReferenceValidationResult {
tests_passed,
tests_failed,
average_correlation,
max_deviation,
metric_results,
reference_details: self
.reference_implementations
.iter()
.map(|(name, reference)| {
(
name.clone(),
format!("{} v{}", reference.name(), reference.version()),
)
})
.collect(),
})
}
async fn run_platform_validation(
&self,
_target_evaluator: &dyn ValidationTarget,
) -> EvaluationResult<PlatformValidationResult> {
Ok(PlatformValidationResult {
tested_platforms: vec!["current".to_string()],
consistency_score: 0.95,
platform_results: HashMap::new(),
compatibility_matrix: vec![vec![1.0]],
})
}
async fn run_precision_validation(
&self,
_target_evaluator: &dyn ValidationTarget,
) -> EvaluationResult<PrecisionValidationResult> {
let mut precision_tests = Vec::new();
for validator in &self.precision_validators {
let input = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let output = vec![1.0001, 2.0001, 3.0001, 4.0001, 5.0001];
let result =
validator.validate_precision(&input, &output, self.config.numerical_tolerance)?;
precision_tests.push(result);
}
let stability_score = precision_tests
.iter()
.map(|t| t.numerical_stability)
.sum::<f64>()
/ precision_tests.len() as f64;
Ok(PrecisionValidationResult {
stability_score,
precision_tests,
fp_consistency: FpConsistencyResult {
range_consistency: 0.95,
type_consistency: 0.98,
rounding_consistency: 0.92,
overall_consistency: 0.95,
},
determinism: DeterminismResult {
determinism_score: 0.99,
determinism_tests: 10,
seed_reproducibility: true,
cross_run_consistency: 0.99,
},
})
}
async fn run_edge_case_validation(
&self,
target_evaluator: &dyn ValidationTarget,
) -> EvaluationResult<EdgeCaseValidationResult> {
let mut edge_cases_tested = 0;
let mut edge_cases_passed = 0;
let mut categories_tested = Vec::new();
let mut failed_cases = Vec::new();
for generator in &self.edge_case_generators {
let edge_cases = generator.generate_edge_cases()?;
categories_tested.extend(generator.supported_categories());
for edge_case in edge_cases {
edge_cases_tested += 1;
match target_evaluator
.evaluate_for_validation(&edge_case.input)
.await
{
Ok(_result) => {
if self.check_acceptance_criteria(&edge_case.acceptance_criteria) {
edge_cases_passed += 1;
} else {
failed_cases.push(FailedEdgeCaseResult {
case_name: edge_case.name.clone(),
category: edge_case.category.clone(),
input_description: format!(
"Audio buffer with {} samples",
edge_case.input.len()
),
expected_behavior: edge_case.expected_behavior.clone(),
actual_behavior: "Did not meet acceptance criteria".to_string(),
severity: EdgeCaseSeverity::Medium,
});
}
}
Err(_error) => {
if edge_case.acceptance_criteria.should_not_crash {
failed_cases.push(FailedEdgeCaseResult {
case_name: edge_case.name.clone(),
category: edge_case.category.clone(),
input_description: format!(
"Audio buffer with {} samples",
edge_case.input.len()
),
expected_behavior: edge_case.expected_behavior.clone(),
actual_behavior: "System crashed or returned error".to_string(),
severity: EdgeCaseSeverity::High,
});
} else {
edge_cases_passed += 1; }
}
}
}
}
let robustness_score = if edge_cases_tested > 0 {
edge_cases_passed as f64 / edge_cases_tested as f64
} else {
0.0
};
Ok(EdgeCaseValidationResult {
edge_cases_tested,
edge_cases_passed,
robustness_score,
categories_tested: categories_tested.into_iter().collect(),
failed_cases,
})
}
fn generate_test_inputs(&self) -> EvaluationResult<Vec<AudioBuffer>> {
let mut inputs = Vec::new();
for i in 0..self.config.test_iterations {
let samples = match i % 4 {
0 => vec![0.1; 16000], 1 => vec![0.5; 16000], 2 => (0..16000).map(|x| (x as f32 * 0.001).sin()).collect(), _ => (0..16000).map(|x| (x as f32 * 0.01) % 1.0 - 0.5).collect(), };
inputs.push(AudioBuffer::new(samples, 16000, 1));
}
Ok(inputs)
}
fn check_acceptance_criteria(&self, _criteria: &AcceptanceCriteria) -> bool {
true
}
}
#[async_trait]
pub trait ValidationTarget: Send + Sync {
async fn evaluate_for_validation(
&self,
input: &AudioBuffer,
) -> EvaluationResult<serde_json::Value>;
fn get_metadata(&self) -> HashMap<String, String>;
fn supports_validation_test(&self, test_name: &str) -> bool;
}
impl Default for ValidationConfig {
fn default() -> Self {
Self {
enable_reference_validation: true,
enable_cross_platform_testing: true,
enable_precision_verification: true,
enable_edge_case_testing: true,
numerical_tolerance: 1e-6,
max_execution_time: Duration::from_secs(300),
test_iterations: 10,
confidence_level: 0.95,
generate_detailed_reports: true,
}
}
}
pub struct DefaultPrecisionValidator {
name: String,
}
impl DefaultPrecisionValidator {
pub fn new() -> Self {
Self {
name: "Default Precision Validator".to_string(),
}
}
}
impl PrecisionValidator for DefaultPrecisionValidator {
fn validate_precision(
&self,
input: &[f64],
output: &[f64],
tolerance: f64,
) -> Result<PrecisionTestResult, voirs_sdk::VoirsError> {
if input.len() != output.len() {
return Err(voirs_sdk::VoirsError::ConfigError {
field: "precision_validation".to_string(),
message: "Input and output lengths must match".to_string(),
});
}
let mut max_error: f64 = 0.0;
let mut total_error: f64 = 0.0;
for (i, o) in input.iter().zip(output.iter()) {
let error = (i - o).abs();
max_error = max_error.max(error);
total_error += error;
}
let mean_error = total_error / input.len() as f64;
let precision_loss = max_error;
let numerical_stability = if max_error < tolerance {
1.0
} else {
tolerance / max_error
};
let passed = max_error < tolerance;
Ok(PrecisionTestResult {
test_name: self.name.clone(),
input_precision: 64, output_precision: 64,
precision_loss,
numerical_stability,
passed,
})
}
fn name(&self) -> &str {
&self.name
}
}
pub struct DefaultEdgeCaseGenerator {
name: String,
}
impl DefaultEdgeCaseGenerator {
pub fn new() -> Self {
Self {
name: "Default Edge Case Generator".to_string(),
}
}
}
impl EdgeCaseGenerator for DefaultEdgeCaseGenerator {
fn generate_edge_cases(&self) -> Result<Vec<EdgeCaseTest>, voirs_sdk::VoirsError> {
let mut edge_cases = Vec::new();
edge_cases.push(EdgeCaseTest {
name: "empty_audio".to_string(),
category: "boundary".to_string(),
input: AudioBuffer::new(vec![], 16000, 1),
expected_behavior: "Should handle empty audio gracefully".to_string(),
acceptance_criteria: AcceptanceCriteria {
should_not_crash: true,
should_return_valid_result: true,
max_processing_time: Some(Duration::from_millis(100)),
min_quality_threshold: None,
custom_validator: None,
},
});
edge_cases.push(EdgeCaseTest {
name: "very_short_audio".to_string(),
category: "boundary".to_string(),
input: AudioBuffer::new(vec![0.1], 16000, 1),
expected_behavior: "Should handle very short audio".to_string(),
acceptance_criteria: AcceptanceCriteria {
should_not_crash: true,
should_return_valid_result: true,
max_processing_time: Some(Duration::from_millis(100)),
min_quality_threshold: None,
custom_validator: None,
},
});
edge_cases.push(EdgeCaseTest {
name: "clipped_audio".to_string(),
category: "distortion".to_string(),
input: AudioBuffer::new(vec![1.0; 8000], 16000, 1),
expected_behavior: "Should detect clipping and handle appropriately".to_string(),
acceptance_criteria: AcceptanceCriteria {
should_not_crash: true,
should_return_valid_result: true,
max_processing_time: Some(Duration::from_millis(500)),
min_quality_threshold: Some(0.0), custom_validator: None,
},
});
edge_cases.push(EdgeCaseTest {
name: "silent_audio".to_string(),
category: "boundary".to_string(),
input: AudioBuffer::new(vec![0.0; 16000], 16000, 1),
expected_behavior: "Should handle silent audio appropriately".to_string(),
acceptance_criteria: AcceptanceCriteria {
should_not_crash: true,
should_return_valid_result: true,
max_processing_time: Some(Duration::from_millis(200)),
min_quality_threshold: None,
custom_validator: None,
},
});
edge_cases.push(EdgeCaseTest {
name: "nan_audio".to_string(),
category: "invalid_data".to_string(),
input: AudioBuffer::new(vec![f32::NAN; 1000], 16000, 1),
expected_behavior: "Should handle NaN values gracefully".to_string(),
acceptance_criteria: AcceptanceCriteria {
should_not_crash: true,
should_return_valid_result: false, max_processing_time: Some(Duration::from_millis(100)),
min_quality_threshold: None,
custom_validator: None,
},
});
Ok(edge_cases)
}
fn name(&self) -> &str {
&self.name
}
fn supported_categories(&self) -> Vec<String> {
vec![
"boundary".to_string(),
"distortion".to_string(),
"invalid_data".to_string(),
]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validation_config_default() {
let config = ValidationConfig::default();
assert!(config.enable_reference_validation);
assert!(config.enable_cross_platform_testing);
assert!(config.enable_precision_verification);
assert!(config.enable_edge_case_testing);
assert!((config.numerical_tolerance - 1e-6).abs() < 1e-9);
assert_eq!(config.test_iterations, 10);
assert!((config.confidence_level - 0.95).abs() < 0.001);
}
#[test]
fn test_validation_framework_creation() {
let config = ValidationConfig::default();
let framework = ValidationFramework::new(config);
assert!(framework.reference_implementations.is_empty());
assert!(framework.platform_tests.is_empty());
assert!(framework.precision_validators.is_empty());
assert!(framework.edge_case_generators.is_empty());
}
#[test]
fn test_default_precision_validator() {
let validator = DefaultPrecisionValidator::new();
let input = vec![1.0, 2.0, 3.0];
let output = vec![1.0001, 2.0001, 3.0001];
let result = validator.validate_precision(&input, &output, 1e-3);
assert!(result.is_ok());
let result = result.unwrap();
assert!(result.passed);
assert!(result.precision_loss < 1e-3);
}
#[test]
fn test_default_edge_case_generator() {
let generator = DefaultEdgeCaseGenerator::new();
let edge_cases = generator.generate_edge_cases().unwrap();
assert!(!edge_cases.is_empty());
assert!(edge_cases.iter().any(|case| case.name == "empty_audio"));
assert!(edge_cases.iter().any(|case| case.name == "silent_audio"));
assert!(edge_cases.iter().any(|case| case.name == "clipped_audio"));
}
#[test]
fn test_validation_status() {
assert_eq!(ValidationStatus::Passed, ValidationStatus::Passed);
assert_ne!(ValidationStatus::Passed, ValidationStatus::Failed);
}
#[test]
fn test_test_status() {
assert_eq!(TestStatus::Passed, TestStatus::Passed);
assert_ne!(TestStatus::Passed, TestStatus::Failed);
}
#[test]
fn test_edge_case_severity() {
let severity = EdgeCaseSeverity::High;
assert!(matches!(severity, EdgeCaseSeverity::High));
}
}