Skip to main content

ruda_test_utils/test_mode/
launch.rs

1//! Generic launch-and-capture-outcome plumbing shared by every kernel-test
2//! helper.
3//!
4//! Kernel launches can fail in two windows: synchronously (the launch closure
5//! returns `Err`) or asynchronously when the runtime processes the queued
6//! work. Catching the asynchronous case requires an explicit `flush` both
7//! before and after the launch.
8
9use ruda_kernel::dsl as kernel_dsl;
10use ruda_test_runtime::TestRuntime;
11use ruda_kernel::dsl::prelude::ComputeClient;
12use ruda_kernel::dsl::server::self;
13use ruda_kernel::dsl::server::LaunchError;
14use ruda_kernel::dsl::server::ServerError;
15
16use crate::ExecutionOutcome;
17
18/// Run `launch` against `client`, returning its [`ExecutionOutcome`] after
19/// flushing for any compile/launch errors that surface only asynchronously.
20///
21/// The pre-flush also catches stale errors from a prior launch on the same
22/// client — without it, an earlier failure would be attributed to this one.
23pub fn launch_and_capture_outcome<F>(
24    client: &ComputeClient<TestRuntime>,
25    launch: F,
26) -> ExecutionOutcome
27where
28    F: FnOnce(&ComputeClient<TestRuntime>) -> ExecutionOutcome,
29{
30    let outcome = flush_compile_error(client).unwrap_or_else(|| launch(client));
31    match outcome {
32        ExecutionOutcome::Executed => {
33            flush_compile_error(client).unwrap_or(ExecutionOutcome::Executed)
34        }
35        other => other,
36    }
37}
38
39/// Flush `client` and surface any pending compile/launch failure as a
40/// [`ExecutionOutcome::CompileError`].
41///
42/// Returns `None` when the flush is clean (the kernel ran). Other server
43/// errors are wrapped as `CompileError` so callers see one uniform shape.
44pub fn flush_compile_error(client: &ComputeClient<TestRuntime>) -> Option<ExecutionOutcome> {
45    match client.flush() {
46        Ok(_) => None,
47        Err(ServerError::ServerUnhealthy { errors, .. }) => {
48            for error in errors.iter() {
49                if let server::ServerError::Launch(LaunchError::TooManyResources(_))
50                | server::ServerError::Launch(LaunchError::CompilationError(_)) = error
51                {
52                    return Some(ExecutionOutcome::CompileError(format!("{errors:?}")));
53                }
54            }
55            None
56        }
57        Err(err) => Some(ExecutionOutcome::CompileError(format!("{err:?}"))),
58    }
59}