()
| 2155 | |
| 2156 | #[tokio::test] |
| 2157 | async fn task_child_run_step_budget_enforced() { |
| 2158 | let workspace = tempfile::tempdir().unwrap(); |
| 2159 | let mock = Arc::new(MockLlmClient::new(vec![ |
| 2160 | MockLlmClient::tool_call_response( |
| 2161 | "t1", |
| 2162 | "read", |
| 2163 | serde_json::json!({"file_path": "/tmp/a.txt"}), |
| 2164 | ), |
| 2165 | MockLlmClient::tool_call_response( |
| 2166 | "t2", |
| 2167 | "read", |
| 2168 | serde_json::json!({"file_path": "/tmp/b.txt"}), |
| 2169 | ), |
| 2170 | MockLlmClient::tool_call_response( |
| 2171 | "t3", |
| 2172 | "read", |
| 2173 | serde_json::json!({"file_path": "/tmp/c.txt"}), |
| 2174 | ), |
| 2175 | MockLlmClient::text_response("Should not reach here."), |
| 2176 | ])); |
| 2177 | |
| 2178 | let executor = TaskExecutor::new( |
| 2179 | test_registry_with_writer(), |
| 2180 | mock, |
| 2181 | workspace.path().to_string_lossy().to_string(), |
| 2182 | ); |
| 2183 | |
| 2184 | let result = executor |
| 2185 | .execute( |
| 2186 | TaskParams { |
| 2187 | agent: "writer".to_string(), |
| 2188 | description: "Exceed budget".to_string(), |
| 2189 | prompt: "Read many files".to_string(), |
| 2190 | background: false, |
| 2191 | max_steps: Some(2), |
| 2192 | }, |
| 2193 | None, |
| 2194 | None, |
| 2195 | ) |
| 2196 | .await |
| 2197 | .unwrap(); |
| 2198 | |
| 2199 | // The agent should fail after exceeding 2 tool rounds |
| 2200 | assert!( |
| 2201 | !result.success, |
| 2202 | "should fail when exceeding step budget: {}", |
| 2203 | result.output |
| 2204 | ); |
| 2205 | assert!( |
| 2206 | result.output.contains("Max tool rounds") || result.output.contains("max tool rounds"), |
| 2207 | "error should mention tool rounds: {}", |
| 2208 | result.output |
| 2209 | ); |
| 2210 | } |
| 2211 | |
| 2212 | #[tokio::test] |
| 2213 | async fn parallel_task_executor_runs_children_concurrently_and_preserves_input_order() { |
nothing calls this directly
no test coverage detected