use crate::ie::IeType;
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct ComparisonOptions {
pub ignore_sequence: bool,
pub ignore_seid: bool,
pub ignore_priority: bool,
pub ignore_timestamps: bool,
pub timestamp_tolerance_secs: Option<u32>,
pub ignored_ie_types: HashSet<IeType>,
pub focus_ie_types: Option<HashSet<IeType>>,
pub strict_ie_order: bool,
pub ie_multiplicity_mode: IeMultiplicityMode,
pub optional_ie_mode: OptionalIeMode,
pub deep_compare_grouped: bool,
pub use_semantic_comparison: bool,
pub semantic_ie_types: HashSet<IeType>,
pub generate_diff: bool,
pub max_reported_differences: Option<usize>,
pub include_payload_in_diff: bool,
}
impl Default for ComparisonOptions {
fn default() -> Self {
Self {
ignore_sequence: false,
ignore_seid: false,
ignore_priority: false,
ignore_timestamps: false,
timestamp_tolerance_secs: None,
ignored_ie_types: HashSet::new(),
focus_ie_types: None,
strict_ie_order: false,
ie_multiplicity_mode: IeMultiplicityMode::ExactMatch,
optional_ie_mode: OptionalIeMode::Strict,
deep_compare_grouped: true,
use_semantic_comparison: false,
semantic_ie_types: HashSet::new(),
generate_diff: false,
max_reported_differences: None,
include_payload_in_diff: false,
}
}
}
impl ComparisonOptions {
pub fn should_compare_ie(&self, ie_type: IeType) -> bool {
if self.ignored_ie_types.contains(&ie_type) {
return false;
}
if self.ignore_timestamps && is_timestamp_ie(ie_type) {
return false;
}
if let Some(ref focus) = self.focus_ie_types {
return focus.contains(&ie_type);
}
true
}
pub fn use_semantic_for_ie(&self, ie_type: IeType) -> bool {
self.use_semantic_comparison || self.semantic_ie_types.contains(&ie_type)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IeMultiplicityMode {
ExactMatch,
SetEquality,
Lenient,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OptionalIeMode {
Strict,
IgnoreMissing,
RequireLeft,
RequireRight,
}
fn is_timestamp_ie(ie_type: IeType) -> bool {
matches!(
ie_type,
IeType::RecoveryTimeStamp
| IeType::StartTime
| IeType::EndTime
| IeType::TimeOfFirstPacket
| IeType::TimeOfLastPacket
| IeType::ActivationTime
| IeType::DeactivationTime
| IeType::MonitoringTime
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_options() {
let options = ComparisonOptions::default();
assert!(!options.ignore_sequence);
assert!(!options.ignore_timestamps);
assert!(options.deep_compare_grouped);
assert_eq!(options.ie_multiplicity_mode, IeMultiplicityMode::ExactMatch);
assert_eq!(options.optional_ie_mode, OptionalIeMode::Strict);
}
#[test]
fn test_should_compare_ie_default() {
let options = ComparisonOptions::default();
assert!(options.should_compare_ie(IeType::Cause));
assert!(options.should_compare_ie(IeType::CreatePdr));
}
#[test]
fn test_should_compare_ie_ignored() {
let mut options = ComparisonOptions::default();
options.ignored_ie_types.insert(IeType::RecoveryTimeStamp);
assert!(!options.should_compare_ie(IeType::RecoveryTimeStamp));
assert!(options.should_compare_ie(IeType::Cause));
}
#[test]
fn test_should_compare_ie_ignore_timestamps() {
let options = ComparisonOptions {
ignore_timestamps: true,
..Default::default()
};
assert!(!options.should_compare_ie(IeType::RecoveryTimeStamp));
assert!(!options.should_compare_ie(IeType::StartTime));
assert!(!options.should_compare_ie(IeType::EndTime));
assert!(options.should_compare_ie(IeType::Cause));
}
#[test]
fn test_should_compare_ie_focus() {
let mut options = ComparisonOptions::default();
let mut focus = HashSet::new();
focus.insert(IeType::CreatePdr);
focus.insert(IeType::CreateFar);
options.focus_ie_types = Some(focus);
assert!(options.should_compare_ie(IeType::CreatePdr));
assert!(options.should_compare_ie(IeType::CreateFar));
assert!(!options.should_compare_ie(IeType::Cause));
assert!(!options.should_compare_ie(IeType::NodeId));
}
#[test]
fn test_use_semantic_for_ie() {
let mut options = ComparisonOptions::default();
assert!(!options.use_semantic_for_ie(IeType::Fteid));
options.use_semantic_comparison = true;
assert!(options.use_semantic_for_ie(IeType::Fteid));
assert!(options.use_semantic_for_ie(IeType::Cause));
options.use_semantic_comparison = false;
options.semantic_ie_types.insert(IeType::Fteid);
assert!(options.use_semantic_for_ie(IeType::Fteid));
assert!(!options.use_semantic_for_ie(IeType::Cause));
}
#[test]
fn test_is_timestamp_ie() {
assert!(is_timestamp_ie(IeType::RecoveryTimeStamp));
assert!(is_timestamp_ie(IeType::StartTime));
assert!(is_timestamp_ie(IeType::EndTime));
assert!(is_timestamp_ie(IeType::TimeOfFirstPacket));
assert!(is_timestamp_ie(IeType::TimeOfLastPacket));
assert!(is_timestamp_ie(IeType::ActivationTime));
assert!(is_timestamp_ie(IeType::DeactivationTime));
assert!(is_timestamp_ie(IeType::MonitoringTime));
assert!(!is_timestamp_ie(IeType::Cause));
assert!(!is_timestamp_ie(IeType::NodeId));
assert!(!is_timestamp_ie(IeType::CreatePdr));
}
}