molo_coding/coding/
test_runner.rs1use crate::harness::ExecutionPolicy;
2use crate::{RunContext, RunMetadata};
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5
6use super::command::{CommandExecutor, CommandOutput, CommandRequest, CommandStatus};
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct TestRunRequest {
11 pub command: CommandRequest,
13 pub name: String,
15}
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct VerificationResult {
20 pub name: String,
22 pub passed: bool,
24 pub summary: String,
26 pub output: Option<CommandOutput>,
28 pub metadata: RunMetadata,
30}
31
32#[async_trait]
34pub trait TestRunner: Send + Sync {
35 async fn run(
37 &self,
38 request: TestRunRequest,
39 policy: &ExecutionPolicy,
40 context: &RunContext,
41 ) -> Result<VerificationResult, TestRunError>;
42}
43
44#[derive(Debug, Clone)]
46pub struct CommandTestRunner<C> {
47 commands: C,
48}
49
50impl<C> CommandTestRunner<C> {
51 pub fn new(commands: C) -> Self {
53 Self { commands }
54 }
55}
56
57#[async_trait]
58impl<C> TestRunner for CommandTestRunner<C>
59where
60 C: CommandExecutor,
61{
62 async fn run(
63 &self,
64 request: TestRunRequest,
65 policy: &ExecutionPolicy,
66 context: &RunContext,
67 ) -> Result<VerificationResult, TestRunError> {
68 let output = self
69 .commands
70 .execute(request.command, policy, context)
71 .await
72 .map_err(|error| TestRunError::Command {
73 message: error.to_string(),
74 })?;
75 let passed = matches!(output.status, CommandStatus::Exited { code: 0 });
76 let summary = if passed {
77 format!("{} passed", request.name)
78 } else {
79 format!("{} failed: {:?}", request.name, output.status)
80 };
81 Ok(VerificationResult {
82 name: request.name,
83 passed,
84 summary,
85 output: Some(output),
86 metadata: RunMetadata::new(),
87 })
88 }
89}
90
91#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
93#[non_exhaustive]
94pub enum TestRunError {
95 #[error("test command error: {message}")]
97 Command {
98 message: String,
100 },
101}