//! Unit tests for task module use crate::task::{task_fn, Task, TaskInput}; use std::any::Any; use std::future::Future; use std::pin::Pin; use std::sync::Arc; // Test the task_fn function and TaskFn struct #[tokio::test] async fn test_task_fn_creation_and_execution() { // Test line 111 in task.rs - Task implementation for TaskFn // Create a simple task function let task = task_fn::(|input: &i32| input * 2); // Test the Task trait implementation let result = task .run(TaskInput::new( [Arc::new(42) as Arc].iter(), )) .await; assert_eq!(result, 84); } #[tokio::test] async fn test_task_fn_with_unit_input() { // Test task_fn with unit input let task = task_fn::<(), _, _>(|_: ()| 100); let result = task .run(TaskInput::new( [Arc::new(()) as Arc].iter(), )) .await; assert_eq!(result, 100); } #[tokio::test] async fn test_task_fn_with_tuple_input() { // Test task_fn with tuple input let task = task_fn::<(i32, i32), _, _>(|(a, b): (&i32, &i32)| a + b); let result = task .run(TaskInput::new( [ Arc::new(10) as Arc, Arc::new(20) as Arc, ] .iter(), )) .await; assert_eq!(result, 30); } #[tokio::test] async fn test_task_fn_with_string_input() { // Test task_fn with String input let task = task_fn::(|input: &String| input.len()); let test_string = String::from("hello"); let result = task .run(TaskInput::new( [Arc::new(test_string) as Arc].iter(), )) .await; assert_eq!(result, 5); } #[tokio::test] async fn test_task_fn_with_complex_output() { // Test task_fn with complex output type let task = task_fn::(|&input: &i32| vec![input, input * 2, input * 3]); let result = task .run(TaskInput::new( [Arc::new(5) as Arc].iter(), )) .await; assert_eq!(result, vec![5, 10, 15]); } #[tokio::test] async fn test_task_fn_stateful_closure() { // Test that task_fn can capture state let multiplier = 3; let task = task_fn::(move |input: &i32| input * multiplier); let result = task .run(TaskInput::new( [Arc::new(7) as Arc].iter(), )) .await; assert_eq!(result, 21); } // Test custom Task implementation struct CustomTask { state: i32, } impl Task for CustomTask { type Input = (i32,); type Output = i32; #[allow(refining_impl_trait)] fn run( mut self, input: TaskInput<'_, Self::Input>, ) -> Pin + Send + '_>> { Box::pin(async move { self.state += input.next().0; self.state }) } } #[tokio::test] async fn test_custom_task_implementation() { let task = CustomTask { state: 10 }; let result1 = task .run(TaskInput::new( [Arc::new(5) as Arc].iter(), )) .await; assert_eq!(result1, 15); // Can't call run again since task was consumed // This demonstrates the ownership model } // Test that Task trait bounds are correct fn assert_task_bounds() { // This function just checks that T implements Task with the right bounds fn assert_send() {} // These should compile if bounds are correct assert_send::(); assert_send::(); assert_send::(); } #[test] fn test_task_trait_bounds() { // Verify that our test tasks meet the Task trait bounds assert_task_bounds::(); // We can't directly test TaskFn because it's a private type and needs a concrete closure type, // but the fact that task_fn works in the tests above proves it's correct } #[tokio::test] async fn test_task_fn_single_call() { // Test that task_fn works (can only call once due to ownership) let task = task_fn::(|x: &i32| x + 1); assert_eq!( task.run(TaskInput::new( [Arc::new(1) as Arc].iter() )) .await, 2 ); } #[tokio::test] async fn test_task_fn_with_result_type() { // Test task_fn returning Result let task = task_fn::(|&x: &i32| { if x > 0 { Ok(x * 2) } else { Err("negative input") } }); assert_eq!( task.run(TaskInput::new( [Arc::new(5) as Arc].iter() )) .await, Ok(10) ); } #[tokio::test] async fn test_task_fn_with_option_type() { // Test task_fn returning Option let task = task_fn::(|&x: &i32| if x > 0 { Some(x * 2) } else { None }); assert_eq!( task.run(TaskInput::new( [Arc::new(5) as Arc].iter() )) .await, Some(10) ); } #[tokio::test] async fn test_task_fn_explicit_trait_call() { // Test explicit Task trait method call to cover line 121 let task = task_fn::(|x: &i32| x * 3); // Explicitly call the Task trait's run method let result = Task::run( task, TaskInput::new([Arc::new(10) as Arc].iter()), ) .await; assert_eq!(result, 30); }