Address soundness hole in cycle prevention
This commit is contained in:
1 parent
4ad88bcd68
commit
f82205baf4
80 files changed
+730
-717
No files matched your search
@@ -1,7 +1,7 @@
|
||||
//! Butterfly pattern DAG tests
|
||||
|
||||
use crate::common::task_fn;
|
||||
use dagx::{DagResult, DagRunner};
|
||||
use dagx::{DagResult, DagRunner, TaskHandle};
|
||||
use futures::FutureExt;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
@@ -13,7 +13,10 @@ async fn test_butterfly_network() -> DagResult<()> {
|
||||
// Simplified butterfly network - avoid tuples entirely
|
||||
// Layer 0: inputs
|
||||
let inputs: Vec<_> = (0..8)
|
||||
.map(|i| dag.add_task(task_fn(move |_: ()| async move { i as f64 })))
|
||||
.map(|i| {
|
||||
dag.add_task(task_fn(move |_: ()| async move { i as f64 }))
|
||||
.into()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Layer 1: butterfly operations (compute pairs separately)
|
||||
@@ -92,7 +95,7 @@ async fn test_recursive_butterfly() -> DagResult<()> {
|
||||
.into_iter()
|
||||
.map(|val| {
|
||||
let task = dag.add_task(task_fn(move |_: ()| async move { val }));
|
||||
(&task).into()
|
||||
task.into()
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -115,7 +118,10 @@ async fn test_benes_network() -> DagResult<()> {
|
||||
|
||||
// 4 inputs
|
||||
let inputs: Vec<_> = (0..4)
|
||||
.map(|i| dag.add_task(task_fn(move |_: ()| async move { 1 << i }))) // Powers of 2
|
||||
.map(|i| {
|
||||
dag.add_task(task_fn(move |_: ()| async move { 1 << i }))
|
||||
.into()
|
||||
}) // Powers of 2
|
||||
.collect();
|
||||
|
||||
// First stage: sort pairs
|
||||
@@ -153,7 +159,7 @@ async fn test_shuffle_exchange_network() -> DagResult<()> {
|
||||
let counter = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
// Create 8 inputs
|
||||
let inputs: Vec<_> = (0..8)
|
||||
let inputs: Vec<TaskHandle<_>> = (0..8)
|
||||
.map(|i| {
|
||||
let counter = counter.clone();
|
||||
dag.add_task(task_fn(move |_: ()| {
|
||||
@@ -163,6 +169,7 @@ async fn test_shuffle_exchange_network() -> DagResult<()> {
|
||||
i
|
||||
}
|
||||
}))
|
||||
.into()
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -172,7 +179,7 @@ async fn test_shuffle_exchange_network() -> DagResult<()> {
|
||||
// Shuffle pattern: rotate bits
|
||||
let source = ((i << 1) | (i >> 2)) & 0x7;
|
||||
dag.add_task(task_fn(move |x: i32| async move { x }))
|
||||
.depends_on(&inputs[source])
|
||||
.depends_on(inputs[source])
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
||||
+12
-10
@@ -1,7 +1,7 @@
|
||||
//! Complex DAG pattern tests
|
||||
|
||||
use crate::common::task_fn;
|
||||
use dagx::{DagResult, DagRunner};
|
||||
use dagx::{DagResult, DagRunner, TaskHandle};
|
||||
use futures::FutureExt;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
@@ -21,7 +21,7 @@ async fn test_workflow_with_conditional_paths() -> DagResult<()> {
|
||||
Err("Invalid input")
|
||||
}
|
||||
}))
|
||||
.depends_on(&input);
|
||||
.depends_on(input);
|
||||
|
||||
// Process valid input
|
||||
let process = dag
|
||||
@@ -31,7 +31,7 @@ async fn test_workflow_with_conditional_paths() -> DagResult<()> {
|
||||
Err(_) => -1,
|
||||
}
|
||||
}))
|
||||
.depends_on(&validate);
|
||||
.depends_on(validate);
|
||||
|
||||
// Parallel enhancement steps
|
||||
let enhance1 = dag
|
||||
@@ -80,7 +80,7 @@ async fn test_map_reduce_pattern() -> DagResult<()> {
|
||||
// Simulate word count
|
||||
vec![("word1", i % 3), ("word2", i % 5), ("word3", i % 7)]
|
||||
}));
|
||||
(&task).into()
|
||||
task.into()
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -166,7 +166,7 @@ async fn test_pipeline_with_feedback() -> DagResult<()> {
|
||||
}
|
||||
}
|
||||
}))
|
||||
.depends_on(&init);
|
||||
.depends_on(init);
|
||||
|
||||
// Stage 2: Filter
|
||||
let stage2 = dag
|
||||
@@ -209,9 +209,11 @@ async fn test_scatter_gather_pattern() -> DagResult<()> {
|
||||
let dag = DagRunner::new();
|
||||
|
||||
// Scatter: distribute work to multiple workers
|
||||
let source = dag.add_task(task_fn(|_: ()| async {
|
||||
vec![10, 20, 30, 40, 50, 60, 70, 80]
|
||||
}));
|
||||
let source: TaskHandle<_> = dag
|
||||
.add_task(task_fn(|_: ()| async {
|
||||
vec![10, 20, 30, 40, 50, 60, 70, 80]
|
||||
}))
|
||||
.into();
|
||||
|
||||
// Workers process chunks
|
||||
let workers: Vec<_> = (0..4)
|
||||
@@ -228,7 +230,7 @@ async fn test_scatter_gather_pattern() -> DagResult<()> {
|
||||
|
||||
data[start..end].iter().sum::<i32>()
|
||||
}))
|
||||
.depends_on(&source)
|
||||
.depends_on(source)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -266,7 +268,7 @@ async fn test_fork_join_with_barriers() -> DagResult<()> {
|
||||
|
||||
// Multiple parallel paths
|
||||
let mut path1 = Vec::new();
|
||||
let parent_handle: dagx::TaskHandle<i32> = (&parent).into();
|
||||
let parent_handle: dagx::TaskHandle<i32> = parent.into();
|
||||
let mut prev1 = parent_handle;
|
||||
for i in 0..3 {
|
||||
let counter = phase_counter.clone();
|
||||
|
||||
@@ -15,10 +15,10 @@ async fn test_2d_grid_pattern() -> DagResult<()> {
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 0..4 {
|
||||
let task = dag.add_task(task_fn(move |_: ()| async move { i as i32 }));
|
||||
grid[0][i] = Some((&task).into());
|
||||
grid[0][i] = Some(task.into());
|
||||
if i > 0 {
|
||||
let task = dag.add_task(task_fn(move |_: ()| async move { i as i32 * 10 }));
|
||||
grid[i][0] = Some((&task).into());
|
||||
grid[i][0] = Some(task.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ async fn test_3d_grid_pattern() -> DagResult<()> {
|
||||
|
||||
// Initialize origin
|
||||
let origin = dag.add_task(task_fn(|_: ()| async { 1 }));
|
||||
grid[0][0][0] = Some((&origin).into());
|
||||
grid[0][0][0] = Some(origin.into());
|
||||
|
||||
// Fill the 3D grid
|
||||
for x in 0..size {
|
||||
@@ -77,7 +77,7 @@ async fn test_3d_grid_pattern() -> DagResult<()> {
|
||||
let task_handle: dagx::TaskHandle<usize> = match deps.len() {
|
||||
0 => {
|
||||
let t = dag.add_task(task_fn(move |_: ()| async move { x + y + z }));
|
||||
(&t).into()
|
||||
t.into()
|
||||
}
|
||||
1 => dag
|
||||
.add_task(task_fn(move |prev: usize| async move { prev + 1 }))
|
||||
@@ -121,7 +121,7 @@ async fn test_hexagonal_grid() -> DagResult<()> {
|
||||
|
||||
// Center hex
|
||||
let center_builder = dag.add_task(task_fn(|_: ()| async { 100 }));
|
||||
let center: dagx::TaskHandle<i32> = (¢er_builder).into();
|
||||
let center: dagx::TaskHandle<i32> = center_builder.into();
|
||||
hex_grid.insert((0, 0), center);
|
||||
|
||||
// Ring 1 (6 hexes around center)
|
||||
@@ -168,7 +168,7 @@ async fn test_hexagonal_grid() -> DagResult<()> {
|
||||
.depends_on(neighbors[0])
|
||||
} else {
|
||||
let t = dag.add_task(task_fn(move |_: ()| async move { q + r }));
|
||||
(&t).into()
|
||||
t.into()
|
||||
};
|
||||
|
||||
hex_grid.insert((q, r), task);
|
||||
@@ -194,7 +194,7 @@ async fn test_toroidal_grid() -> DagResult<()> {
|
||||
for i in 0..SIZE {
|
||||
for j in 0..SIZE {
|
||||
let task = dag.add_task(task_fn(move |_: ()| async move { (i * SIZE + j) as i32 }));
|
||||
grid[i][j] = Some((&task).into());
|
||||
grid[i][j] = Some(task.into());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-14
@@ -1,7 +1,7 @@
|
||||
//! Tree pattern DAG tests
|
||||
|
||||
use crate::common::task_fn;
|
||||
use dagx::{DagResult, DagRunner};
|
||||
use dagx::{DagResult, DagRunner, TaskHandle};
|
||||
use futures::FutureExt;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -15,7 +15,7 @@ async fn test_binary_tree_reduction() -> DagResult<()> {
|
||||
|
||||
// Build binary tree reduction
|
||||
let mut current_level: Vec<dagx::TaskHandle<i32>> =
|
||||
leaves.into_iter().map(|t| (&t).into()).collect();
|
||||
leaves.into_iter().map(|t| t.into()).collect();
|
||||
|
||||
while current_level.len() > 1 {
|
||||
let mut next_level = Vec::new();
|
||||
@@ -52,7 +52,7 @@ async fn test_n_ary_tree() -> DagResult<()> {
|
||||
fn build_tree(dag: &DagRunner, depth: usize, value: i32) -> dagx::TaskHandle<i32> {
|
||||
if depth == 0 {
|
||||
let task = dag.add_task(task_fn(move |_: ()| async move { value }));
|
||||
return (&task).into();
|
||||
return task.into();
|
||||
}
|
||||
|
||||
let children: Vec<_> = (0..3)
|
||||
@@ -88,19 +88,19 @@ async fn test_unbalanced_tree() -> DagResult<()> {
|
||||
// / \
|
||||
// f g
|
||||
|
||||
let f = dag.add_task(task_fn(|_: ()| async { 1 }));
|
||||
let f: TaskHandle<_> = dag.add_task(task_fn(|_: ()| async { 1 })).into();
|
||||
let g = dag.add_task(task_fn(|_: ()| async { 2 }));
|
||||
|
||||
let c = dag
|
||||
.add_task(task_fn(|x: i32| async move { x * 2 }))
|
||||
.depends_on(&f);
|
||||
.depends_on(f);
|
||||
|
||||
let d_builder = dag.add_task(task_fn(|_: ()| async { 3 }));
|
||||
let d: dagx::TaskHandle<i32> = (&d_builder).into();
|
||||
let d: dagx::TaskHandle<i32> = d_builder.into();
|
||||
|
||||
let e = dag
|
||||
.add_task(task_fn(|x: i32| async move { x * 3 }))
|
||||
.depends_on(&g);
|
||||
.depends_on(g);
|
||||
|
||||
let a = dag
|
||||
.add_task(task_fn(|(c, d): (i32, i32)| async move { c + d }))
|
||||
@@ -116,7 +116,7 @@ async fn test_unbalanced_tree() -> DagResult<()> {
|
||||
|
||||
dag.run(|fut| tokio::spawn(fut).map(Result::unwrap)).await?;
|
||||
|
||||
assert_eq!(dag.get(&f)?, 1);
|
||||
assert_eq!(dag.get(f)?, 1);
|
||||
assert_eq!(dag.get(c)?, 2);
|
||||
assert_eq!(dag.get(a)?, 5); // 2 + 3
|
||||
assert_eq!(dag.get(b)?, 16); // 6 + 10
|
||||
@@ -130,20 +130,22 @@ async fn test_trie_like_structure() -> DagResult<()> {
|
||||
let dag = DagRunner::new();
|
||||
|
||||
// Build a trie-like structure for paths
|
||||
let root = dag.add_task(task_fn(|_: ()| async { "root".to_string() }));
|
||||
let root: TaskHandle<_> = dag
|
||||
.add_task(task_fn(|_: ()| async { "root".to_string() }))
|
||||
.into();
|
||||
|
||||
// First level
|
||||
let usr = dag
|
||||
.add_task(task_fn(|r: String| async move { format!("{}/usr", r) }))
|
||||
.depends_on(&root);
|
||||
.depends_on(root);
|
||||
|
||||
let etc = dag
|
||||
.add_task(task_fn(|r: String| async move { format!("{}/etc", r) }))
|
||||
.depends_on(&root);
|
||||
.depends_on(root);
|
||||
|
||||
let var = dag
|
||||
.add_task(task_fn(|r: String| async move { format!("{}/var", r) }))
|
||||
.depends_on(&root);
|
||||
.depends_on(root);
|
||||
|
||||
// Second level
|
||||
let usr_bin = dag
|
||||
@@ -188,7 +190,7 @@ async fn test_balanced_k_ary_tree() -> DagResult<()> {
|
||||
) -> dagx::TaskHandle<usize> {
|
||||
if depth == 0 {
|
||||
let task = dag.add_task(task_fn(move |_: ()| async move { node_id }));
|
||||
return (&task).into();
|
||||
return task.into();
|
||||
}
|
||||
|
||||
let children: Vec<_> = (0..k)
|
||||
@@ -243,7 +245,7 @@ async fn test_merkle_tree_pattern() -> DagResult<()> {
|
||||
|
||||
// Convert to TaskHandles
|
||||
let mut current_level: Vec<dagx::TaskHandle<String>> =
|
||||
data_blocks.into_iter().map(|t| (&t).into()).collect();
|
||||
data_blocks.into_iter().map(|t| t.into()).collect();
|
||||
|
||||
while current_level.len() > 1 {
|
||||
let mut next_level = Vec::new();
|
||||
|
||||
Reference in new issue
Block a user