213 lines
6.1 KiB
Rust
213 lines
6.1 KiB
Rust
//! Comprehensive tests for DAG (Directed Acyclic Graph) functionality in RTX-ETL
|
|
|
|
use rtx_etl::{
|
|
EtlError,
|
|
dag::{Task, TaskGraph, TaskType},
|
|
};
|
|
use std::collections::HashMap;
|
|
|
|
#[cfg(test)]
|
|
mod dag_tests {
|
|
use super::*;
|
|
|
|
fn create_sample_task(id: &str, _name: &str) -> Task {
|
|
Task::new(id.to_string(), TaskType::Transform)
|
|
}
|
|
|
|
#[test]
|
|
fn test_dag_creation() {
|
|
let dag = TaskGraph::new();
|
|
assert_eq!(dag.tasks.len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_add_single_task() {
|
|
let mut dag = TaskGraph::new();
|
|
let task = create_sample_task("task1", "task1");
|
|
|
|
dag.add_task(task);
|
|
assert_eq!(dag.tasks.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_add_multiple_tasks() {
|
|
let mut dag = TaskGraph::new();
|
|
|
|
for i in 1..=5 {
|
|
let task = create_sample_task(&format!("task{}", i), &format!("task{}", i));
|
|
dag.add_task(task);
|
|
}
|
|
|
|
assert_eq!(dag.tasks.len(), 5);
|
|
}
|
|
|
|
#[test]
|
|
fn test_add_dependency() {
|
|
let mut dag = TaskGraph::new();
|
|
|
|
let task1 = create_sample_task("task1", "task1");
|
|
let mut task2 = create_sample_task("task2", "task2");
|
|
|
|
// Task2 depends on task1
|
|
task2.dependencies.push("task1".to_string());
|
|
|
|
dag.add_task(task1);
|
|
dag.add_task(task2);
|
|
|
|
assert!(
|
|
dag.dependencies
|
|
.get("task2")
|
|
.unwrap()
|
|
.contains(&"task1".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_multiple_dependencies() {
|
|
let mut dag = TaskGraph::new();
|
|
|
|
// Create tasks
|
|
for i in 1..=4 {
|
|
let task = create_sample_task(&format!("task{}", i), &format!("task{}", i));
|
|
dag.add_task(task);
|
|
}
|
|
|
|
// Task 4 depends on tasks 1, 2, and 3
|
|
let mut task4 = dag.tasks.remove("task4").unwrap();
|
|
task4.dependencies = vec![
|
|
"task1".to_string(),
|
|
"task2".to_string(),
|
|
"task3".to_string(),
|
|
];
|
|
dag.add_task(task4);
|
|
|
|
let deps = dag.dependencies.get("task4").unwrap();
|
|
assert_eq!(deps.len(), 3);
|
|
assert!(deps.contains(&"task1".to_string()));
|
|
assert!(deps.contains(&"task2".to_string()));
|
|
assert!(deps.contains(&"task3".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn test_validation_with_missing_dependency() {
|
|
let mut dag = TaskGraph::new();
|
|
|
|
let task1 = create_sample_task("task1", "task1");
|
|
let mut task2 = create_sample_task("task2", "task2");
|
|
|
|
// Task2 depends on non-existent task
|
|
task2.dependencies.push("task999".to_string());
|
|
|
|
dag.add_task(task1);
|
|
dag.add_task(task2);
|
|
|
|
let result = dag.validate();
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_remove_task() {
|
|
let mut dag = TaskGraph::new();
|
|
|
|
let task1 = create_sample_task("task1", "task1");
|
|
dag.add_task(task1);
|
|
|
|
assert_eq!(dag.tasks.len(), 1);
|
|
|
|
let removed = dag.remove_task("task1");
|
|
assert!(removed.is_some());
|
|
assert_eq!(dag.tasks.len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_complex_dag() {
|
|
let mut dag = TaskGraph::new();
|
|
|
|
// Create tasks with dependencies
|
|
let task1 = create_sample_task("task1", "task1");
|
|
let task2 = create_sample_task("task2", "task2");
|
|
let mut task3 = create_sample_task("task3", "task3");
|
|
task3.dependencies = vec!["task1".to_string(), "task2".to_string()];
|
|
|
|
let mut task4 = create_sample_task("task4", "task4");
|
|
task4.dependencies = vec!["task2".to_string()];
|
|
|
|
let mut task5 = create_sample_task("task5", "task5");
|
|
task5.dependencies = vec!["task3".to_string(), "task4".to_string()];
|
|
|
|
dag.add_task(task1);
|
|
dag.add_task(task2);
|
|
dag.add_task(task3);
|
|
dag.add_task(task4);
|
|
dag.add_task(task5);
|
|
|
|
// Validate the graph
|
|
let result = dag.validate();
|
|
assert!(result.is_ok());
|
|
assert_eq!(dag.tasks.len(), 5);
|
|
}
|
|
|
|
#[test]
|
|
fn test_task_types() {
|
|
let extract_task = Task::new("extract1".to_string(), TaskType::Extract);
|
|
let transform_task = Task::new("transform1".to_string(), TaskType::Transform);
|
|
let load_task = Task::new("load1".to_string(), TaskType::Load);
|
|
let quality_task = Task::new("quality1".to_string(), TaskType::QualityCheck);
|
|
|
|
assert_eq!(extract_task.task_type.as_str(), "extract");
|
|
assert_eq!(transform_task.task_type.as_str(), "transform");
|
|
assert_eq!(load_task.task_type.as_str(), "load");
|
|
assert_eq!(quality_task.task_type.as_str(), "quality_check");
|
|
}
|
|
|
|
#[test]
|
|
fn test_task_metadata() {
|
|
let mut task = Task::new("task1".to_string(), TaskType::Transform);
|
|
task.metadata
|
|
.insert("key1".to_string(), "value1".to_string());
|
|
task.metadata
|
|
.insert("key2".to_string(), "value2".to_string());
|
|
|
|
assert_eq!(task.metadata.get("key1").unwrap(), "value1");
|
|
assert_eq!(task.metadata.get("key2").unwrap(), "value2");
|
|
}
|
|
|
|
#[test]
|
|
fn test_task_config() {
|
|
let mut task = Task::new("task1".to_string(), TaskType::Transform);
|
|
task.config
|
|
.insert("batch_size".to_string(), serde_json::json!(100));
|
|
task.config
|
|
.insert("timeout".to_string(), serde_json::json!(5000));
|
|
|
|
assert_eq!(
|
|
task.config.get("batch_size").unwrap(),
|
|
&serde_json::json!(100)
|
|
);
|
|
assert_eq!(
|
|
task.config.get("timeout").unwrap(),
|
|
&serde_json::json!(5000)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_graph_metadata() {
|
|
let dag = TaskGraph::new();
|
|
|
|
assert!(!dag.metadata.graph_id.is_empty());
|
|
assert_eq!(dag.metadata.name, "unnamed_graph");
|
|
assert_eq!(dag.metadata.version, "1.0.0");
|
|
}
|
|
|
|
#[test]
|
|
fn test_task_priority() {
|
|
let mut high_priority = Task::new("task1".to_string(), TaskType::Extract);
|
|
high_priority.priority = 100;
|
|
|
|
let mut low_priority = Task::new("task2".to_string(), TaskType::Load);
|
|
low_priority.priority = 1;
|
|
|
|
assert!(high_priority.priority > low_priority.priority);
|
|
}
|
|
}
|