#![allow(clippy::all, dead_code)]
#[cfg(test)]
mod tests {
use serde_json::{json, Value};
fn minimal_xes_log() -> String {
r#"<?xml version="1.0" encoding="UTF-8"?>
<log xes.version="1.0" xes.features="nested-attributes" openlog.version="1.0">
<trace>
<string key="concept:name" value="case-1"/>
<event>
<string key="concept:name" value="A"/>
<date key="time:timestamp" value="2026-04-01T10:00:00Z"/>
</event>
<event>
<string key="concept:name" value="B"/>
<date key="time:timestamp" value="2026-04-01T10:01:00Z"/>
</event>
</trace>
<trace>
<string key="concept:name" value="case-2"/>
<event>
<string key="concept:name" value="A"/>
<date key="time:timestamp" value="2026-04-01T11:00:00Z"/>
</event>
<event>
<string key="concept:name" value="B"/>
<date key="time:timestamp" value="2026-04-01T11:01:00Z"/>
</event>
<event>
<string key="concept:name" value="C"/>
<date key="time:timestamp" value="2026-04-01T11:02:00Z"/>
</event>
</trace>
</log>"#
.to_string()
}
#[test]
fn test_validate_output_format_valid_dfg() {
let output = json!({
"nodes": ["A", "B", "C"],
"edges": [["A", "B"], ["B", "C"]]
});
let nodes = output["nodes"].as_array().expect("Should have nodes");
let edges = output["edges"].as_array().expect("Should have edges");
assert!(!nodes.is_empty(), "DFG should have nodes");
assert!(!edges.is_empty(), "DFG should have edges");
}
#[test]
fn test_validate_output_format_missing_fields() {
let output = json!({
"nodes": ["A", "B"]
});
let has_nodes = output.get("nodes").is_some();
let has_edges = output.get("edges").is_some();
assert!(has_nodes, "Should detect nodes present");
assert!(!has_edges, "Should detect edges missing");
}
#[test]
fn test_validate_output_format_invalid_json() {
let invalid_json = "{invalid";
let parsed = serde_json::from_str::<Value>(invalid_json);
assert!(parsed.is_err(), "Should fail to parse invalid JSON");
}
#[test]
fn test_get_algorithm_metadata_dfg() {
let metadata = json!({
"name": "dfg",
"display_name": "Directly-Follows Graph",
"category": "discovery",
"time_complexity": "O(n log n)",
"space_complexity": "O(m)",
"speed_score": 5,
"quality_score": 30,
"supports_ocel": false,
"supports_streaming": false,
"required_inputs": ["log_handle", "activity_key"],
"output_type": "dfg"
});
assert_eq!(
metadata["name"], "dfg",
"Should have correct algorithm name"
);
assert_eq!(
metadata["category"], "discovery",
"Should have correct category"
);
assert_eq!(metadata["speed_score"], 5, "DFG should have speed score 5");
assert_eq!(
metadata["quality_score"], 30,
"DFG should have quality score 30"
);
assert_eq!(metadata["output_type"], "dfg", "Should output DFG");
}
#[test]
fn test_get_algorithm_metadata_genetic() {
let metadata = json!({
"name": "genetic_algorithm",
"display_name": "Genetic Algorithm",
"category": "discovery",
"time_complexity": "O(n * population * generations)",
"space_complexity": "O(m * population)",
"speed_score": 75,
"quality_score": 80,
"supports_ocel": false,
"supports_streaming": false,
"required_inputs": ["log_handle", "activity_key"],
"output_type": "petrinet"
});
assert_eq!(metadata["speed_score"], 75, "Genetic should be slower");
assert_eq!(
metadata["quality_score"], 80,
"Genetic should have high quality"
);
assert_eq!(
metadata["output_type"], "petrinet",
"Genetic outputs Petri nets"
);
}
#[test]
fn test_algorithm_metadata_complexity() {
let dfg = json!({
"name": "dfg",
"time_complexity": "O(n log n)"
});
let genetic = json!({
"name": "genetic_algorithm",
"time_complexity": "O(n * population * generations)"
});
assert!(dfg["time_complexity"].is_string());
assert!(genetic["time_complexity"].is_string());
let dfg_complexity = dfg["time_complexity"].as_str().unwrap();
let genetic_complexity = genetic["time_complexity"].as_str().unwrap();
assert!(
dfg_complexity.contains("n"),
"DFG should have linear/log complexity"
);
assert!(
genetic_complexity.contains("population"),
"Genetic should include population"
);
}
#[test]
fn test_determinism_output_structure() {
let determinism_result = json!({
"algorithm": "dfg",
"log_size": 1500,
"run_count": 3,
"hashes": ["abc123", "abc123", "abc123"],
"stable": true,
"all_identical": true
});
assert_eq!(determinism_result["algorithm"], "dfg");
assert_eq!(determinism_result["run_count"], 3);
assert_eq!(determinism_result["stable"], true);
let hashes = determinism_result["hashes"]
.as_array()
.expect("Should have hashes array");
assert_eq!(hashes.len(), 3, "Should have 3 runs");
let first = hashes[0].as_str().unwrap();
for hash in hashes {
assert_eq!(hash.as_str().unwrap(), first, "All hashes should match");
}
}
#[test]
fn test_quality_baseline_structure() {
let baseline = json!({
"algorithm": "genetic",
"log_size": 2000,
"fitness": 0.87,
"precision": 0.92,
"quality_score": 0.895,
"model_size": { "places": 12, "transitions": 18 }
});
assert_eq!(baseline["algorithm"], "genetic");
assert!(baseline["fitness"].is_f64());
assert!(baseline["precision"].is_f64());
assert!(baseline["quality_score"].is_f64());
let fitness = baseline["fitness"].as_f64().unwrap();
let precision = baseline["precision"].as_f64().unwrap();
let quality = baseline["quality_score"].as_f64().unwrap();
let expected_quality = (fitness + precision) / 2.0;
assert!(
(quality - expected_quality).abs() < 0.001,
"Quality score should be average of fitness and precision"
);
assert!(
fitness >= 0.0 && fitness <= 1.0,
"Fitness should be in [0, 1]"
);
assert!(
precision >= 0.0 && precision <= 1.0,
"Precision should be in [0, 1]"
);
assert!(
quality >= 0.0 && quality <= 1.0,
"Quality should be in [0, 1]"
);
}
#[test]
fn test_benchmark_latency_percentiles() {
let benchmark = json!({
"algorithm": "dfg",
"iterations": 10,
"log_size": 5000,
"p50_ms": 1.2,
"p95_ms": 2.1,
"p99_ms": 3.8,
"mean_ms": 1.5,
"min_ms": 1.1,
"max_ms": 4.2
});
assert_eq!(benchmark["iterations"], 10);
assert!(benchmark["p50_ms"].is_f64());
assert!(benchmark["p95_ms"].is_f64());
assert!(benchmark["p99_ms"].is_f64());
let p50 = benchmark["p50_ms"].as_f64().unwrap();
let p95 = benchmark["p95_ms"].as_f64().unwrap();
let p99 = benchmark["p99_ms"].as_f64().unwrap();
let min = benchmark["min_ms"].as_f64().unwrap();
let max = benchmark["max_ms"].as_f64().unwrap();
assert!(min <= p50, "min should be <= p50");
assert!(p50 <= p95, "p50 should be <= p95");
assert!(p95 <= p99, "p95 should be <= p99");
assert!(p99 <= max, "p99 should be <= max");
assert!(min > 0.0, "min latency should be positive");
assert!(max > 0.0, "max latency should be positive");
}
#[test]
fn test_algorithm_metadata_registry() {
let algorithms = vec!["dfg", "heuristic_miner", "genetic_algorithm", "ilp"];
for algo in algorithms {
let metadata = json!({
"name": algo,
"display_name": algo,
"category": "discovery",
"time_complexity": "O(n)",
"space_complexity": "O(m)",
});
assert!(
metadata["name"].is_string(),
"Should have name for {}",
algo
);
assert!(
metadata["category"].as_str().unwrap() == "discovery",
"Discovery algorithms should have category 'discovery'"
);
}
}
#[test]
fn test_validate_schema_fields_dfg() {
let required = vec!["nodes", "edges"];
let optional = vec!["total_events"];
let valid_dfg = json!({
"nodes": [1, 2, 3],
"edges": [[0, 1], [1, 2]]
});
for field in &required {
assert!(
valid_dfg.get(field).is_some(),
"DFG must have {} field",
field
);
}
}
#[test]
fn test_validate_schema_fields_petrinet() {
let required = vec!["places", "transitions"];
let valid_petrinet = json!({
"places": ["p1", "p2"],
"transitions": ["t1", "t2"],
"arcs": []
});
for field in &required {
assert!(
valid_petrinet.get(field).is_some(),
"Petri net must have {} field",
field
);
}
}
#[test]
fn test_determinism_hash_stability() {
let hash1 = "abc123def456ghi789jkl";
let hash2 = "abc123def456ghi789jkl";
let hash3 = "abc123def456ghi789jkl";
let hashes = vec![hash1, hash2, hash3];
let all_identical = hashes.iter().all(|h| h == &hashes[0]);
assert!(
all_identical,
"All hashes should be identical for deterministic run"
);
}
#[test]
fn test_determinism_hash_instability() {
let hash1 = "abc123def456ghi789jkl";
let hash2 = "different_hash_xyz";
let hash3 = "abc123def456ghi789jkl";
let hashes = vec![hash1, hash2, hash3];
let all_identical = hashes.iter().all(|h| h == &hashes[0]);
assert!(
!all_identical,
"Non-identical hashes should indicate non-determinism"
);
}
#[test]
fn test_output_validation_extra_fields() {
let extra_field_dfg = json!({
"nodes": [1, 2],
"edges": [[0, 1]],
"extra_metadata": "ignored"
});
assert!(extra_field_dfg.get("nodes").is_some());
assert!(extra_field_dfg.get("edges").is_some());
}
#[test]
fn test_quality_metrics_bounds() {
let metrics = vec![0.0, 0.25, 0.5, 0.75, 1.0];
for metric in metrics {
assert!(
metric >= 0.0 && metric <= 1.0,
"Metric {} out of bounds",
metric
);
}
}
#[test]
fn test_speed_quality_tradeoff() {
let dfg = (5, 30); let genetic = (75, 80);
assert!(genetic.0 > dfg.0, "Genetic should be slower");
assert!(genetic.1 > dfg.1, "Genetic should have better quality");
}
}