#![no_main] use libfuzzer_sys::fuzz_target; use dagx::{task, DagRunner}; fuzz_target!(|data: &[u8]| { // Only test with reasonable sizes if data.is_empty() || data.len() > 100 { return; } // Test various dependency patterns based on input data let pattern = data[0] % 4; struct SimpleTask { val: i32 } #[task] impl SimpleTask { async fn run(&self) -> i32 { self.val } } struct DependentTask; #[task] impl DependentTask { async fn run(input: &i32) -> i32 { input.wrapping_add(1) } } let rt = tokio::runtime::Runtime::new().unwrap(); match pattern { 0 => { // Linear dependency chain let dag = DagRunner::new(); let t1 = dag.add_task(SimpleTask { val: data[0] as i32 }); let t2 = dag.add_task(DependentTask).depends_on(&t1); let t3 = dag.add_task(DependentTask).depends_on(&t2); if rt.block_on(async { dag.run(|fut| { tokio::spawn(fut); }).await }).is_ok() { if let Ok(result) = dag.get(t3) { assert_eq!(result, (data[0] as i32).wrapping_add(2)); } } } 1 => { // Diamond pattern let dag = DagRunner::new(); let source = dag.add_task(SimpleTask { val: data[0] as i32 }); let left = dag.add_task(DependentTask).depends_on(&source); let right = dag.add_task(DependentTask).depends_on(&source); struct MergeTask; #[task] impl MergeTask { async fn run(a: &i32, b: &i32) -> i32 { a.wrapping_add(*b) } } let merge = dag.add_task(MergeTask).depends_on((&left, &right)); if rt.block_on(async { dag.run(|fut| { tokio::spawn(fut); }).await }).is_ok() { if let Ok(result) = dag.get(merge) { let expected = (data[0] as i32).wrapping_add(1); assert_eq!(result, expected.wrapping_add(expected)); } } } 2 => { // Multiple independent sources let dag = DagRunner::new(); let t1 = dag.add_task(SimpleTask { val: data[0] as i32 }); let t2 = dag.add_task(SimpleTask { val: data.get(1).copied().unwrap_or(0) as i32 }); let t3 = dag.add_task(SimpleTask { val: data.get(2).copied().unwrap_or(0) as i32 }); if rt.block_on(async { dag.run(|fut| { tokio::spawn(fut); }).await }).is_ok() { if let (Ok(r1), Ok(r2), Ok(r3)) = (dag.get(t1), dag.get(t2), dag.get(t3)) { assert_eq!(r1, data[0] as i32); assert_eq!(r2, data.get(1).copied().unwrap_or(0) as i32); assert_eq!(r3, data.get(2).copied().unwrap_or(0) as i32); } } } _ => { // Complex dependency graph let dag = DagRunner::new(); let s1 = dag.add_task(SimpleTask { val: data[0] as i32 }); let s2 = dag.add_task(SimpleTask { val: data.get(1).copied().unwrap_or(0) as i32 }); let d1 = dag.add_task(DependentTask).depends_on(&s1); let d2 = dag.add_task(DependentTask).depends_on(&s2); let d3 = dag.add_task(DependentTask).depends_on(&d1); if rt.block_on(async { dag.run(|fut| { tokio::spawn(fut); }).await }).is_ok() { let _ = dag.get(d1); let _ = dag.get(d2); let _ = dag.get(d3); } } } });