fix: change where TaskHandle is borrowed to prevent repeat output fetches
This commit is contained in:
1 parent
c8efb00175
commit
9fbe4c2fd8
47 files changed
+323
-513
No files matched your search
@@ -20,7 +20,7 @@ async fn test_multiple_parallel_deep_chains() -> DagResult<()> {
|
||||
for _ in 0..500 {
|
||||
current = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&prev: &i32| prev + 1))
|
||||
.depends_on(current);
|
||||
.depends_on(¤t);
|
||||
}
|
||||
|
||||
chain_ends.push(current);
|
||||
@@ -41,14 +41,14 @@ async fn test_multiple_parallel_deep_chains() -> DagResult<()> {
|
||||
},
|
||||
))
|
||||
.depends_on((
|
||||
chain_ends[0],
|
||||
chain_ends[1],
|
||||
chain_ends[2],
|
||||
chain_ends[3],
|
||||
chain_ends[4],
|
||||
chain_ends[5],
|
||||
chain_ends[6],
|
||||
chain_ends[7],
|
||||
&chain_ends[0],
|
||||
&chain_ends[1],
|
||||
&chain_ends[2],
|
||||
&chain_ends[3],
|
||||
&chain_ends[4],
|
||||
&chain_ends[5],
|
||||
&chain_ends[6],
|
||||
&chain_ends[7],
|
||||
));
|
||||
|
||||
let mut output = dag
|
||||
@@ -60,7 +60,7 @@ async fn test_multiple_parallel_deep_chains() -> DagResult<()> {
|
||||
// Chain 1: 1000 + 500 = 1500
|
||||
// ...
|
||||
// Sum = 500*8 + (0+1000+2000+...+7000) = 4000 + 28000 = 32000
|
||||
assert_eq!(output.get(final_task)?, 32000);
|
||||
assert_eq!(output.get(final_task), 32000);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -91,7 +91,7 @@ async fn test_deep_chain_execution_order() -> DagResult<()> {
|
||||
prev + 1
|
||||
}
|
||||
}))
|
||||
.depends_on(current);
|
||||
.depends_on(¤t);
|
||||
}
|
||||
|
||||
let mut output = dag
|
||||
@@ -99,7 +99,7 @@ async fn test_deep_chain_execution_order() -> DagResult<()> {
|
||||
.await?;
|
||||
|
||||
assert_eq!(order.load(Ordering::SeqCst), 100);
|
||||
assert_eq!(output.get(current)?, 99);
|
||||
assert_eq!(output.get(current), 99);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -120,7 +120,7 @@ async fn test_deep_binary_tree() -> DagResult<()> {
|
||||
dag.add_task(task_fn::<(i32, i32), _, _>(move |(l, r): (&i32, &i32)| {
|
||||
l + r
|
||||
}))
|
||||
.depends_on((left, right))
|
||||
.depends_on((&left, &right))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ async fn test_deep_binary_tree() -> DagResult<()> {
|
||||
|
||||
// Sum of all values in a complete binary tree with values 1024..2047
|
||||
// This is sum from 2^10 to 2^11-1 = 1024 * 1023 / 2 + 1024 * 512 = 1047552
|
||||
let result = output.get(root)?;
|
||||
let result = output.get(root);
|
||||
assert!(result > 0);
|
||||
|
||||
Ok(())
|
||||
@@ -152,7 +152,7 @@ async fn test_fibonacci_chain() -> DagResult<()> {
|
||||
for _ in 2..50 {
|
||||
let next = dag
|
||||
.add_task(task_fn::<(i64, i64), _, _>(|(a, b): (&i64, &i64)| a + b))
|
||||
.depends_on((prev2, prev1));
|
||||
.depends_on((&prev2, &prev1));
|
||||
|
||||
prev2 = prev1;
|
||||
prev1 = next;
|
||||
@@ -163,7 +163,7 @@ async fn test_fibonacci_chain() -> DagResult<()> {
|
||||
.await?;
|
||||
|
||||
// 50th Fibonacci number (0-indexed) = 7778742049
|
||||
assert_eq!(output.get(prev1)?, 7778742049);
|
||||
assert_eq!(output.get(prev1), 7778742049);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -184,25 +184,25 @@ async fn test_zigzag_dependencies() -> DagResult<()> {
|
||||
// A depends on B
|
||||
chain_a = dag
|
||||
.add_task(task_fn::<i32, _, _>(move |b_val: &i32| b_val + 1))
|
||||
.depends_on(chain_b);
|
||||
.depends_on(&chain_b);
|
||||
} else {
|
||||
// B depends on A
|
||||
chain_b = dag
|
||||
.add_task(task_fn::<i32, _, _>(move |a_val: &i32| a_val + 2))
|
||||
.depends_on(chain_a);
|
||||
.depends_on(&chain_a);
|
||||
}
|
||||
}
|
||||
|
||||
// Final task depends on both chains
|
||||
let final_task = dag
|
||||
.add_task(task_fn::<(i32, i32), _, _>(|(a, b): (&i32, &i32)| a + b))
|
||||
.depends_on((chain_a, chain_b));
|
||||
.depends_on((&chain_a, &chain_b));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
let result = output.get(final_task)?;
|
||||
let result = output.get(final_task);
|
||||
assert!(result > 100);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -35,15 +35,15 @@ async fn test_zero_sized_types_throughout() -> DagResult<()> {
|
||||
assert_eq!(val, 42);
|
||||
"success"
|
||||
}))
|
||||
.depends_on(t2);
|
||||
.depends_on(&t2);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(t1)?, Empty);
|
||||
assert_eq!(output.get(t2)?, 42);
|
||||
assert_eq!(output.get(t4)?, "success");
|
||||
assert_eq!(output.get(t1), Empty);
|
||||
assert_eq!(output.get(t2), 42);
|
||||
assert_eq!(output.get(t4), "success");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -72,13 +72,13 @@ async fn test_large_value_types() -> DagResult<()> {
|
||||
.add_task(task_fn::<usize, _, _>(|&val: &usize| {
|
||||
val // Just pass through to verify
|
||||
}))
|
||||
.depends_on(t1);
|
||||
.depends_on(&t1);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(t2)?, 1042);
|
||||
assert_eq!(output.get(t2), 1042);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -99,13 +99,13 @@ async fn test_reference_wrapper_types() -> DagResult<()> {
|
||||
|
||||
let t2 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&val: &i32| val * 2))
|
||||
.depends_on(t1);
|
||||
.depends_on(&t1);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(t2)?, 200);
|
||||
assert_eq!(output.get(t2), 200);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -19,7 +19,7 @@ async fn test_dag_with_only_source_tasks() -> DagResult<()> {
|
||||
.await?;
|
||||
|
||||
for (i, task) in tasks.into_iter().enumerate() {
|
||||
assert_eq!(output.get(task)?, i);
|
||||
assert_eq!(output.get(task), i);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -46,7 +46,7 @@ async fn test_single_self_contained_stateful_task() -> DagResult<()> {
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(task)?, 42);
|
||||
assert_eq!(output.get(task), 42);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -71,6 +71,6 @@ async fn test_minimal_task_with_minimal_async_work() -> DagResult<()> {
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(task)?, 1337);
|
||||
assert_eq!(output.get(task), 1337);
|
||||
Ok(())
|
||||
}
|
||||
+12
-12
@@ -54,14 +54,14 @@ async fn test_custom_type_single_dependency() {
|
||||
let mut dag = DagRunner::new();
|
||||
|
||||
let fetch = dag.add_task(FetchPerson);
|
||||
let process = dag.add_task(ProcessPerson).depends_on(fetch);
|
||||
let process = dag.add_task(ProcessPerson).depends_on(&fetch);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result = output.get(process).unwrap();
|
||||
let result = output.get(process);
|
||||
assert_eq!(result, "Alice is 30 years old");
|
||||
}
|
||||
|
||||
@@ -70,16 +70,16 @@ async fn test_custom_type_passthrough() {
|
||||
let mut dag = DagRunner::new();
|
||||
|
||||
let fetch = dag.add_task(FetchPerson);
|
||||
let transform = dag.add_task(PersonToCompany).depends_on(fetch);
|
||||
let process = dag.add_task(ProcessPerson).depends_on(fetch);
|
||||
let transform = dag.add_task(PersonToCompany).depends_on(&fetch);
|
||||
let process = dag.add_task(ProcessPerson).depends_on(&fetch);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let person_result = output.get(process).unwrap();
|
||||
let company_result = output.get(transform).unwrap();
|
||||
let person_result = output.get(process);
|
||||
let company_result = output.get(transform);
|
||||
|
||||
assert_eq!(person_result.as_str(), "Alice is 30 years old");
|
||||
assert_eq!(company_result.name, "Alice's Company");
|
||||
@@ -91,18 +91,18 @@ async fn test_custom_type_fan_out() {
|
||||
let mut dag = DagRunner::new();
|
||||
|
||||
let fetch = dag.add_task(FetchPerson);
|
||||
let process1 = dag.add_task(ProcessPerson).depends_on(fetch);
|
||||
let process2 = dag.add_task(ProcessPerson).depends_on(fetch);
|
||||
let process3 = dag.add_task(ProcessPerson).depends_on(fetch);
|
||||
let process1 = dag.add_task(ProcessPerson).depends_on(&fetch);
|
||||
let process2 = dag.add_task(ProcessPerson).depends_on(&fetch);
|
||||
let process3 = dag.add_task(ProcessPerson).depends_on(&fetch);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result1 = output.get(process1).unwrap();
|
||||
let result2 = output.get(process2).unwrap();
|
||||
let result3 = output.get(process3).unwrap();
|
||||
let result1 = output.get(process1);
|
||||
let result2 = output.get(process2);
|
||||
let result3 = output.get(process3);
|
||||
|
||||
assert_eq!(result1, "Alice is 30 years old");
|
||||
assert_eq!(result2, "Alice is 30 years old");
|
||||
|
||||
+13
-42
@@ -30,40 +30,11 @@ fn test_builder_consumed_by_depends_on() {
|
||||
let consumer_builder = dag.add_task(Consumer);
|
||||
|
||||
// This consumes consumer_builder and returns a TaskHandle
|
||||
let _consumer_handle = consumer_builder.depends_on(source);
|
||||
let _consumer_handle = consumer_builder.depends_on(&source);
|
||||
|
||||
// We CANNOT use consumer_builder again because it was moved
|
||||
// This would fail to compile:
|
||||
// let _consumer2 = consumer_builder.depends_on(source); // ERROR: use of moved value
|
||||
}
|
||||
|
||||
/// Demonstrates that you can only get a TaskHandle by finalizing a builder,
|
||||
/// and handles are immutable references with no methods to add dependencies
|
||||
#[test]
|
||||
fn test_handle_is_immutable_reference() {
|
||||
struct NoInput;
|
||||
#[task]
|
||||
impl NoInput {
|
||||
async fn run(&self) -> i32 {
|
||||
100
|
||||
}
|
||||
}
|
||||
|
||||
let mut dag = DagRunner::new();
|
||||
let builder = dag.add_task(NoInput);
|
||||
|
||||
// Convert to handle (only works because Input = ())
|
||||
let handle = builder;
|
||||
|
||||
// TaskHandle is Copy/Clone - just an ID wrapper
|
||||
let _copy1 = handle;
|
||||
let _copy2 = handle;
|
||||
let _copy3 = handle;
|
||||
|
||||
// But TaskHandle has NO methods to modify the DAG
|
||||
// There's no way to add dependencies to it
|
||||
// This would fail to compile:
|
||||
// handle.depends_on(something); // ERROR: no method named `depends_on`
|
||||
// let _consumer2 = consumer_builder.depends_on(&source); // ERROR: use of moved value
|
||||
}
|
||||
|
||||
/// Documents the ordering constraint that prevents cycles
|
||||
@@ -108,8 +79,8 @@ fn test_ordering_prevents_cycles() {
|
||||
|
||||
// Let's create a valid DAG instead: A→B (B depends on A)
|
||||
let a_handle = a_builder; // A has no deps (unit input)
|
||||
let _b_handle = b_builder.depends_on(a_handle);
|
||||
// Now we could try: a_handle.depends_on(b_handle)?
|
||||
let _b_handle = b_builder.depends_on(&a_handle);
|
||||
// Now we could try: a_handle.depends_on(&b_handle)?
|
||||
// But TaskHandle has no such method!
|
||||
}
|
||||
|
||||
@@ -182,9 +153,9 @@ fn test_three_way_cycle_impossible() {
|
||||
let _c_builder = dag.add_task(C);
|
||||
|
||||
// To create A→C→B→A:
|
||||
// 1. a_builder.depends_on(c_handle) // Need c_handle
|
||||
// 2. c_builder.depends_on(b_handle) // Need b_handle
|
||||
// 3. b_builder.depends_on(a_handle) // Need a_handle (from step 1!)
|
||||
// 1. a_builder.depends_on(&c_handle) // Need c_handle
|
||||
// 2. c_builder.depends_on(&b_handle) // Need b_handle
|
||||
// 3. b_builder.depends_on(&a_handle) // Need a_handle (from step 1!)
|
||||
//
|
||||
// But step 3 needs a_handle which doesn't exist until step 1 completes.
|
||||
// And step 1 needs c_handle which doesn't exist until step 2 completes.
|
||||
@@ -209,7 +180,7 @@ fn test_self_loop_prevented() {
|
||||
let _builder = dag.add_task(SelfReferential);
|
||||
|
||||
// To create A→A (self-loop):
|
||||
// builder.depends_on(builder)
|
||||
// builder.depends_on(&builder)
|
||||
//
|
||||
// But this would fail because:
|
||||
// 1. depends_on() takes `self` by value (moves builder)
|
||||
@@ -217,7 +188,7 @@ fn test_self_loop_prevented() {
|
||||
// 3. We can't also use &builder as an argument because it's being moved
|
||||
//
|
||||
// This would fail to compile:
|
||||
// let _handle = builder.depends_on(builder); // ERROR: use of moved value
|
||||
// let _handle = builder.depends_on(&builder); // ERROR: use of moved value
|
||||
}
|
||||
|
||||
/// Comprehensive test showing all the guardrails
|
||||
@@ -263,11 +234,11 @@ async fn test_type_safety_prevents_invalid_graphs() {
|
||||
let s2 = dag.add_task(Source);
|
||||
|
||||
// Transform depends on sources
|
||||
let t1 = dag.add_task(Transform).depends_on(s1);
|
||||
let t2 = dag.add_task(Transform).depends_on(s2);
|
||||
let t1 = dag.add_task(Transform).depends_on(&s1);
|
||||
let t2 = dag.add_task(Transform).depends_on(&s2);
|
||||
|
||||
// Aggregate depends on transforms
|
||||
let result = dag.add_task(Aggregate).depends_on((t1, t2));
|
||||
let result = dag.add_task(Aggregate).depends_on((&t1, &t2));
|
||||
|
||||
// Execute and verify
|
||||
let mut output = dag
|
||||
@@ -275,7 +246,7 @@ async fn test_type_safety_prevents_invalid_graphs() {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output.get(result).unwrap(), 40); // (10*2) + (10*2)
|
||||
assert_eq!(output.get(result), 40); // (10*2) + (10*2)
|
||||
|
||||
// Now if we wanted to add a cycle, we'd need to:
|
||||
// - Make one of the Source tasks depend on the Aggregate result
|
||||
|
||||
@@ -40,7 +40,7 @@ async fn test_dependency_resolution_order() -> DagResult<()> {
|
||||
log.lock().unwrap().push(("B_end", x + 1));
|
||||
x + 1
|
||||
}))
|
||||
.depends_on(a)
|
||||
.depends_on(&a)
|
||||
};
|
||||
|
||||
let c = {
|
||||
@@ -52,7 +52,7 @@ async fn test_dependency_resolution_order() -> DagResult<()> {
|
||||
log.lock().unwrap().push(("C_end", x + 1));
|
||||
x + 1
|
||||
}))
|
||||
.depends_on(b)
|
||||
.depends_on(&b)
|
||||
};
|
||||
|
||||
let d = {
|
||||
@@ -64,7 +64,7 @@ async fn test_dependency_resolution_order() -> DagResult<()> {
|
||||
log.lock().unwrap().push(("D_end", x + 1));
|
||||
x + 1
|
||||
}))
|
||||
.depends_on(c)
|
||||
.depends_on(&c)
|
||||
};
|
||||
|
||||
let e = {
|
||||
@@ -76,14 +76,14 @@ async fn test_dependency_resolution_order() -> DagResult<()> {
|
||||
log.lock().unwrap().push(("E_end", x + 1));
|
||||
x + 1
|
||||
}))
|
||||
.depends_on(d)
|
||||
.depends_on(&d)
|
||||
};
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(e)?, 5);
|
||||
assert_eq!(output.get(e), 5);
|
||||
|
||||
// Verify execution order
|
||||
let log = execution_log.lock().unwrap();
|
||||
|
||||
@@ -11,13 +11,13 @@ async fn test_two_dependencies() -> DagResult<()> {
|
||||
let b = dag.add_task(task_fn::<(), _, _>(|_: ()| 20));
|
||||
let sum = dag
|
||||
.add_task(task_fn::<(i32, i32), _, _>(|(x, y): (&i32, &i32)| x + y))
|
||||
.depends_on((a, b));
|
||||
.depends_on((&a, &b));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 30);
|
||||
assert_eq!(output.get(sum), 30);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ async fn test_three_dependencies() -> DagResult<()> {
|
||||
.add_task(task_fn::<(i32, i32, i32), _, _>(
|
||||
|(x, y, z): (&i32, &i32, &i32)| x + y + z,
|
||||
))
|
||||
.depends_on((a, b, c));
|
||||
.depends_on((&a, &b, &c));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 6);
|
||||
assert_eq!(output.get(sum), 6);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -54,13 +54,13 @@ async fn test_four_dependencies() -> DagResult<()> {
|
||||
.add_task(task_fn::<(i32, i32, i32, i32), _, _>(
|
||||
|(a, b, c, d): (&i32, &i32, &i32, &i32)| a + b + c + d,
|
||||
))
|
||||
.depends_on((deps[0], deps[1], deps[2], deps[3]));
|
||||
.depends_on((&deps[0], &deps[1], &deps[2], &deps[3]));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 10); // 1+2+3+4
|
||||
assert_eq!(output.get(sum), 10); // 1+2+3+4
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -76,13 +76,13 @@ async fn test_five_dependencies() -> DagResult<()> {
|
||||
.add_task(task_fn::<(i32, i32, i32, i32, i32), _, _>(
|
||||
|(a, b, c, d, e): (&i32, &i32, &i32, &i32, &i32)| a + b + c + d + e,
|
||||
))
|
||||
.depends_on((deps[0], deps[1], deps[2], deps[3], deps[4]));
|
||||
.depends_on((&deps[0], &deps[1], &deps[2], &deps[3], &deps[4]));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 15); // 1+2+3+4+5
|
||||
assert_eq!(output.get(sum), 15); // 1+2+3+4+5
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -98,13 +98,13 @@ async fn test_six_dependencies() -> DagResult<()> {
|
||||
.add_task(task_fn::<(i32, i32, i32, i32, i32, i32), _, _>(
|
||||
|(a, b, c, d, e, f): (&i32, &i32, &i32, &i32, &i32, &i32)| a + b + c + d + e + f,
|
||||
))
|
||||
.depends_on((deps[0], deps[1], deps[2], deps[3], deps[4], deps[5]));
|
||||
.depends_on((&deps[0], &deps[1], &deps[2], &deps[3], &deps[4], &deps[5]));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 21); // 1+2+3+4+5+6
|
||||
assert_eq!(output.get(sum), 21); // 1+2+3+4+5+6
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -123,14 +123,14 @@ async fn test_seven_dependencies() -> DagResult<()> {
|
||||
},
|
||||
))
|
||||
.depends_on((
|
||||
deps[0], deps[1], deps[2], deps[3], deps[4], deps[5], deps[6],
|
||||
&deps[0], &deps[1], &deps[2], &deps[3], &deps[4], &deps[5], &deps[6],
|
||||
));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 28); // 1+2+3+4+5+6+7
|
||||
assert_eq!(output.get(sum), 28); // 1+2+3+4+5+6+7
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -149,13 +149,13 @@ async fn test_eight_dependencies() -> DagResult<()> {
|
||||
},
|
||||
))
|
||||
.depends_on((
|
||||
deps[0], deps[1], deps[2], deps[3], deps[4], deps[5], deps[6], deps[7],
|
||||
&deps[0], &deps[1], &deps[2], &deps[3], &deps[4], &deps[5], &deps[6], &deps[7],
|
||||
));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(sum)?, 36); // Sum of 1..=8
|
||||
assert_eq!(output.get(sum), 36); // Sum of 1..=8
|
||||
Ok(())
|
||||
}
|
||||
+14
-14
@@ -16,12 +16,12 @@ async fn test_linear_error_propagation() {
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| -> i32 {
|
||||
panic!("Error at t2 with input {}", x);
|
||||
}))
|
||||
.depends_on(t1);
|
||||
.depends_on(&t1);
|
||||
let t3 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 1))
|
||||
.depends_on(t2);
|
||||
.depends_on(&t2);
|
||||
dag.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(t3);
|
||||
.depends_on(&t3);
|
||||
|
||||
assert!(matches!(
|
||||
dag.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
@@ -44,16 +44,16 @@ async fn test_diamond_error_propagation() {
|
||||
|
||||
let left = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x / 2))
|
||||
.depends_on(source);
|
||||
.depends_on(&source);
|
||||
|
||||
let right = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| {
|
||||
panic!("Right path fails with {}", x);
|
||||
}))
|
||||
.depends_on(source);
|
||||
.depends_on(&source);
|
||||
|
||||
dag.add_task(task_fn::<(i32, i32), _, _>(|(l, r): (&i32, &i32)| l + r))
|
||||
.depends_on((left, right));
|
||||
.depends_on((&left, &right));
|
||||
|
||||
assert!(matches!(
|
||||
dag.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
@@ -73,7 +73,7 @@ async fn test_error_in_wide_fanout() {
|
||||
// Create wide fanout from failing source
|
||||
for i in 0..20 {
|
||||
dag.add_task(task_fn::<i32, _, _>(move |&x: &i32| x + i))
|
||||
.depends_on(source);
|
||||
.depends_on(&source);
|
||||
}
|
||||
|
||||
assert!(matches!(
|
||||
@@ -102,7 +102,7 @@ async fn test_selective_error_propagation() {
|
||||
}
|
||||
},
|
||||
))
|
||||
.depends_on(source);
|
||||
.depends_on(&source);
|
||||
|
||||
// Further processing
|
||||
let final_task = dag
|
||||
@@ -113,7 +113,7 @@ async fn test_selective_error_propagation() {
|
||||
format!("Success: {}", val)
|
||||
}
|
||||
}))
|
||||
.depends_on(handler);
|
||||
.depends_on(&handler);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
@@ -121,13 +121,13 @@ async fn test_selective_error_propagation() {
|
||||
.unwrap();
|
||||
|
||||
// Source returns an Err variant (not a panic)
|
||||
assert_eq!(output.get(source).unwrap(), Err("Source error".to_string()));
|
||||
assert_eq!(output.get(source), Err("Source error".to_string()));
|
||||
|
||||
// Handler processes it
|
||||
assert_eq!(output.get(handler).unwrap(), -1);
|
||||
assert_eq!(output.get(handler), -1);
|
||||
|
||||
// Final task handles the error case
|
||||
assert_eq!(output.get(final_task).unwrap(), "Handled error case");
|
||||
assert_eq!(output.get(final_task), "Handled error case");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -169,7 +169,7 @@ async fn test_error_propagation_timing() {
|
||||
.add_task(T2Task {
|
||||
order: propagation_order.clone(),
|
||||
})
|
||||
.depends_on(t1);
|
||||
.depends_on(&t1);
|
||||
|
||||
let _t3 = dag
|
||||
.add_task(task_fn::<i32, _, _>({
|
||||
@@ -180,7 +180,7 @@ async fn test_error_propagation_timing() {
|
||||
x + 1
|
||||
}
|
||||
}))
|
||||
.depends_on(t2);
|
||||
.depends_on(&t2);
|
||||
|
||||
let _ = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
|
||||
+10
-10
@@ -34,7 +34,7 @@ async fn test_retry_pattern_simulation() -> DagResult<()> {
|
||||
.await?;
|
||||
|
||||
// Task completes with error on first "attempt"
|
||||
assert_eq!(output.get(task)?, Err("Simulated failure"));
|
||||
assert_eq!(output.get(task), Err("Simulated failure"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -78,7 +78,7 @@ async fn test_circuit_breaker_pattern() -> DagResult<()> {
|
||||
|
||||
// First few tasks fail and open circuit
|
||||
for task in tasks.into_iter().take(4) {
|
||||
assert!(output.get(task)?.is_err());
|
||||
assert!(output.get(task).is_err());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -120,8 +120,8 @@ async fn test_error_accumulation_pattern() -> DagResult<()> {
|
||||
let [first, second] = <[_; 2]>::try_from(tasks).map_err(|_e| ()).unwrap();
|
||||
|
||||
// Verify specific results
|
||||
assert!(output.get(first)?.is_err());
|
||||
assert_eq!(output.get(second)?, Ok(1));
|
||||
assert!(output.get(first).is_err());
|
||||
assert_eq!(output.get(second), Ok(1));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -136,29 +136,29 @@ async fn test_error_boundary_isolation() -> DagResult<()> {
|
||||
.add_task(task_fn::<i32, _, _>(|_x: &i32| {
|
||||
Err::<i32, &str>("Group A error")
|
||||
}))
|
||||
.depends_on(a1);
|
||||
.depends_on(&a1);
|
||||
|
||||
// Group B: should be isolated from Group A's error
|
||||
let b1 = dag.add_task(task_fn::<(), _, _>(|_: ()| 20));
|
||||
let b2 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(b1);
|
||||
.depends_on(&b1);
|
||||
|
||||
// Group C: depends on B but not A
|
||||
let c1 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 5))
|
||||
.depends_on(b2);
|
||||
.depends_on(&b2);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
// Group A fails (returns Err)
|
||||
assert_eq!(output.get(a2)?, Err("Group A error"));
|
||||
assert_eq!(output.get(a2), Err("Group A error"));
|
||||
|
||||
// Groups B and C succeed
|
||||
assert_eq!(output.get(b2)?, 40);
|
||||
assert_eq!(output.get(c1)?, 45);
|
||||
assert_eq!(output.get(b2), 40);
|
||||
assert_eq!(output.get(c1), 45);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+24
-24
@@ -20,7 +20,7 @@ async fn test_single_task() {
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(output.get(task).unwrap(), 42);
|
||||
assert_eq!(output.get(task), 42);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -37,7 +37,7 @@ async fn test_wide_parallel() {
|
||||
.unwrap();
|
||||
|
||||
for (i, task) in tasks.into_iter().enumerate() {
|
||||
assert_eq!(output.get(task).unwrap(), i * 2);
|
||||
assert_eq!(output.get(task), i * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,13 +48,13 @@ async fn test_diamond_dependency() {
|
||||
let a = dag.add_task(task_fn::<(), _, _>(|_: ()| 10));
|
||||
let b = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 5))
|
||||
.depends_on(a);
|
||||
.depends_on(&a);
|
||||
let c = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(a);
|
||||
.depends_on(&a);
|
||||
let d = dag
|
||||
.add_task(task_fn::<(i32, i32), _, _>(|(x, y): (&i32, &i32)| x + y))
|
||||
.depends_on((b, c));
|
||||
.depends_on((&b, &c));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
@@ -63,7 +63,7 @@ async fn test_diamond_dependency() {
|
||||
|
||||
// Note: a, b, and c are not sinks (they have dependents)
|
||||
// Only d is a sink and can be retrieved
|
||||
assert_eq!(output.get(d).unwrap(), 35); // 15 + 20
|
||||
assert_eq!(output.get(d), 35); // 15 + 20
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -88,9 +88,9 @@ async fn test_different_output_types() {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(&output.get(string_task).unwrap(), "hello");
|
||||
assert_eq!(output.get(vec_task).unwrap(), vec![1, 2, 3]);
|
||||
let user = output.get(struct_task).unwrap();
|
||||
assert_eq!(&output.get(string_task), "hello");
|
||||
assert_eq!(output.get(vec_task), vec![1, 2, 3]);
|
||||
let user = output.get(struct_task);
|
||||
assert_eq!(user.name, "Alice");
|
||||
assert_eq!(user.age, 30);
|
||||
}
|
||||
@@ -104,26 +104,26 @@ async fn test_multiple_sinks() {
|
||||
// Branch 1
|
||||
let branch1 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(source);
|
||||
.depends_on(&source);
|
||||
let sink1 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 1))
|
||||
.depends_on(branch1);
|
||||
.depends_on(&branch1);
|
||||
|
||||
// Branch 2
|
||||
let branch2 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 5))
|
||||
.depends_on(source);
|
||||
.depends_on(&source);
|
||||
let sink2 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 3))
|
||||
.depends_on(branch2);
|
||||
.depends_on(&branch2);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap(); // Should wait for both sinks
|
||||
|
||||
assert_eq!(output.get(sink1).unwrap(), 21); // (10 * 2) + 1
|
||||
assert_eq!(output.get(sink2).unwrap(), 45); // (10 + 5) * 3
|
||||
assert_eq!(output.get(sink1), 21); // (10 * 2) + 1
|
||||
assert_eq!(output.get(sink2), 45); // (10 + 5) * 3
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -135,17 +135,17 @@ async fn test_single_task_inline_path() {
|
||||
let t1 = dag.add_task(task_fn::<(), _, _>(|_: ()| 10));
|
||||
let t2 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(t1);
|
||||
.depends_on(&t1);
|
||||
let t3 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 5))
|
||||
.depends_on(t2);
|
||||
.depends_on(&t2);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output.get(t3).unwrap(), 25); // (10 * 2) + 5
|
||||
assert_eq!(output.get(t3), 25); // (10 * 2) + 5
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -158,20 +158,20 @@ async fn test_multi_consumer_fanout() {
|
||||
// Multiple consumers
|
||||
let c1 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(producer);
|
||||
.depends_on(&producer);
|
||||
let c2 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x + 10))
|
||||
.depends_on(producer);
|
||||
.depends_on(&producer);
|
||||
let c3 = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x - 5))
|
||||
.depends_on(producer);
|
||||
.depends_on(&producer);
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output.get(c1).unwrap(), 84);
|
||||
assert_eq!(output.get(c2).unwrap(), 52);
|
||||
assert_eq!(output.get(c3).unwrap(), 37);
|
||||
assert_eq!(output.get(c1), 84);
|
||||
assert_eq!(output.get(c2), 52);
|
||||
assert_eq!(output.get(c3), 37);
|
||||
}
|
||||
@@ -62,13 +62,13 @@ async fn test_forced_interleaving_with_barriers() -> DagResult<()> {
|
||||
.add_task(task_fn::<(i32, i32, i32), _, _>(
|
||||
|(a, b, c): (&i32, &i32, &i32)| a + b + c,
|
||||
))
|
||||
.depends_on((t1, t2, t3));
|
||||
.depends_on((&t1, &t2, &t3));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(collector)?, 6);
|
||||
assert_eq!(output.get(collector), 6);
|
||||
|
||||
// Check interleaving pattern
|
||||
let events = order.lock().unwrap().clone();
|
||||
@@ -178,7 +178,7 @@ async fn test_alternating_execution_pattern() -> DagResult<()> {
|
||||
turn: turn.clone(),
|
||||
idx: i,
|
||||
})
|
||||
.depends_on(chain_a);
|
||||
.depends_on(&chain_a);
|
||||
|
||||
chain_b = dag
|
||||
.add_task(ChainB {
|
||||
@@ -186,7 +186,7 @@ async fn test_alternating_execution_pattern() -> DagResult<()> {
|
||||
events: events.clone(),
|
||||
idx: i,
|
||||
})
|
||||
.depends_on(chain_b);
|
||||
.depends_on(&chain_b);
|
||||
}
|
||||
|
||||
let _output = dag
|
||||
@@ -255,7 +255,7 @@ async fn test_layered_interleaving() -> DagResult<()> {
|
||||
dag.add_task(Layer23Task {
|
||||
active: layer_active.clone(),
|
||||
})
|
||||
.depends_on((layer1[idx], layer1[idx + 1]))
|
||||
.depends_on((&layer1[idx], &layer1[idx + 1]))
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -264,14 +264,14 @@ async fn test_layered_interleaving() -> DagResult<()> {
|
||||
.add_task(Layer23Task {
|
||||
active: layer_active.clone(),
|
||||
})
|
||||
.depends_on((layer2[0], layer2[1]));
|
||||
.depends_on((&layer2[0], &layer2[1]));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
// Sum of 0+1+2+3 = 6
|
||||
assert_eq!(output.get(layer3)?, 6);
|
||||
assert_eq!(output.get(layer3), 6);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -33,7 +33,7 @@ async fn test_spawner_actually_spawns_tasks() -> DagResult<()> {
|
||||
|
||||
// Verify all tasks were spawned
|
||||
for (i, task) in tasks.into_iter().enumerate() {
|
||||
assert_eq!(output.get(task)?, i as i32);
|
||||
assert_eq!(output.get(task), i as i32);
|
||||
}
|
||||
|
||||
// The spawner should have been called once for each task
|
||||
|
||||
@@ -68,7 +68,7 @@ async fn test_concurrent_execution_with_atomic_counter() -> DagResult<()> {
|
||||
|
||||
// Verify all tasks completed
|
||||
for (i, task) in tasks.into_iter().enumerate() {
|
||||
assert_eq!(output.get(task)?, i);
|
||||
assert_eq!(output.get(task), i);
|
||||
}
|
||||
|
||||
// Check that we achieved real parallelism
|
||||
@@ -135,7 +135,7 @@ async fn test_massive_parallel_fanout() -> DagResult<()> {
|
||||
}
|
||||
|
||||
// Create 1000 tasks all depending on the same source
|
||||
let tasks: Vec<_> = (0..1000)
|
||||
let mut tasks: Vec<_> = (0..1000)
|
||||
.map(|i| {
|
||||
dag.add_task(FanoutTask {
|
||||
comp: completed.clone(),
|
||||
@@ -143,7 +143,7 @@ async fn test_massive_parallel_fanout() -> DagResult<()> {
|
||||
curr: current.clone(),
|
||||
idx: i,
|
||||
})
|
||||
.depends_on(source)
|
||||
.depends_on(&source)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -157,9 +157,9 @@ async fn test_massive_parallel_fanout() -> DagResult<()> {
|
||||
assert_eq!(completed.load(Ordering::SeqCst), 1000);
|
||||
|
||||
// Check some results
|
||||
assert_eq!(output.get(tasks[0])?, 1);
|
||||
assert_eq!(output.get(tasks[500])?, 501);
|
||||
assert_eq!(output.get(tasks[999])?, 1000);
|
||||
assert_eq!(output.get(tasks.remove(999)), 1000);
|
||||
assert_eq!(output.get(tasks.remove(500)), 501);
|
||||
assert_eq!(output.get(tasks.remove(0)), 1);
|
||||
|
||||
let max_seen = max_concurrent.load(Ordering::SeqCst);
|
||||
println!(
|
||||
|
||||
@@ -40,7 +40,7 @@ async fn test_parallel_execution_speedup() -> DagResult<()> {
|
||||
|
||||
// Verify all tasks completed
|
||||
for (i, task) in tasks.into_iter().enumerate() {
|
||||
assert_eq!(output.get(task)?, i);
|
||||
assert_eq!(output.get(task), i);
|
||||
}
|
||||
|
||||
// If tasks ran sequentially: 10 * 50ms = 500ms
|
||||
@@ -125,7 +125,7 @@ async fn test_layers_execute_in_parallel() -> DagResult<()> {
|
||||
idx: i,
|
||||
timing: layer_timing.clone(),
|
||||
})
|
||||
.depends_on(source)
|
||||
.depends_on(&source)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -140,14 +140,14 @@ async fn test_layers_execute_in_parallel() -> DagResult<()> {
|
||||
a + b + c
|
||||
},
|
||||
))
|
||||
.depends_on((layer1[0], layer1[1], layer1[2]))
|
||||
.depends_on((&layer1[0], &layer1[1], &layer1[2]))
|
||||
};
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await?;
|
||||
|
||||
assert_eq!(output.get(final_task)?, 33); // (0+1) + (10+1) + (20+1)
|
||||
assert_eq!(output.get(final_task), 33); // (0+1) + (10+1) + (20+1)
|
||||
|
||||
// Analyze timing
|
||||
let timing = layer_timing.lock().unwrap();
|
||||
|
||||
@@ -99,11 +99,11 @@ fn test_basic_dag(runner: impl RuntimeTest) {
|
||||
|
||||
let x = dag.add_task(Value(2));
|
||||
let y = dag.add_task(Value(3));
|
||||
let sum = dag.add_task(Add).depends_on((x, y));
|
||||
let sum = dag.add_task(Add).depends_on((&x, &y));
|
||||
|
||||
let mut output = dag.run(spawner).await.unwrap();
|
||||
|
||||
assert_eq!(output.get(sum).unwrap(), 5);
|
||||
assert_eq!(output.get(sum), 5);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ fn test_parallel_execution(runner: impl RuntimeTest) {
|
||||
let mut output = dag.run(spawner).await.unwrap();
|
||||
|
||||
for (i, task) in tasks.into_iter().enumerate() {
|
||||
assert_eq!(output.get(task).unwrap(), i * 2);
|
||||
assert_eq!(output.get(task), i * 2);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -137,13 +137,13 @@ fn test_complex_dependencies(runner: impl RuntimeTest) {
|
||||
|
||||
let a = dag.add_task(Value(10));
|
||||
let b = dag.add_task(Value(20));
|
||||
let sum = dag.add_task(Add).depends_on((a, b));
|
||||
let sum = dag.add_task(Add).depends_on((&a, &b));
|
||||
let double = dag
|
||||
.add_task(task_fn::<i32, _, _>(|&x: &i32| x * 2))
|
||||
.depends_on(sum);
|
||||
.depends_on(&sum);
|
||||
|
||||
let mut output = dag.run(spawner).await.unwrap();
|
||||
|
||||
assert_eq!(output.get(double).unwrap().clone(), 60);
|
||||
assert_eq!(output.get(double).clone(), 60);
|
||||
});
|
||||
}
|
||||
@@ -43,14 +43,14 @@ async fn test_tracing_with_subscriber() {
|
||||
|
||||
let a = dag.add_task(Value(2));
|
||||
let b = dag.add_task(Value(3));
|
||||
let sum = dag.add_task(Add).depends_on((a, b));
|
||||
let sum = dag.add_task(Add).depends_on((&a, &b));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(output.get(sum).unwrap(), 5);
|
||||
assert_eq!(output.get(sum), 5);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
@@ -65,8 +65,8 @@ async fn test_tracing_inline_execution() {
|
||||
|
||||
// Create a linear chain (should trigger inline execution)
|
||||
let a = dag.add_task(Value(1));
|
||||
let b = dag.add_task(Add).depends_on((a, a));
|
||||
let c = dag.add_task(Multiply).depends_on((b, b));
|
||||
let b = dag.add_task(Add).depends_on((&a, &a));
|
||||
let c = dag.add_task(Multiply).depends_on((&b, &b));
|
||||
|
||||
let mut output = dag
|
||||
.run(|fut| async move { tokio::spawn(fut).await.unwrap() })
|
||||
@@ -76,5 +76,5 @@ async fn test_tracing_inline_execution() {
|
||||
// a = 1
|
||||
// b = 1 + 1 = 2
|
||||
// c = 2 * 2 = 4
|
||||
assert_eq!(output.get(c).unwrap(), 4);
|
||||
assert_eq!(output.get(c), 4);
|
||||
}
|
||||
Reference in new issue
Block a user