Files
honey-biscuit-workshop/workshop-baker/tests/engine_integration.rs
T
Catty Steve 7b3b71a4b3 feat(finalize): support multiple manifest extensions and add hook tests
- Remove underscore suffix from FINALIZE_SHELL_ENVPREFIX constant
- Split FINALIZE_PLUGIN_MANIFEST into name + extensions for flexible
  manifest discovery
- Add ManifestNotFound error variant for clearer plugin loading errors
- Add debug logging for plugin download operations
- Add integration tests for finalize hook execution
- Remove obsolete clarification.md
2026-04-21 21:40:19 +08:00

207 lines
5.5 KiB
Rust

//! Integration tests for workshop-executor engine
//!
//! These tests execute real commands and verify results.
//! Run with: cargo test --test engine_integration
//!
//! Note: These are TRUE integration tests - they run in a separate test binary
//! and execute actual commands on the system.
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
use workshop_baker::engine::{Engine, ExecutionContext};
fn create_executor() -> Engine {
Engine::new()
}
fn create_context() -> ExecutionContext {
ExecutionContext {
task_id: "test-integration-1".to_string(),
pipeline_name: "test-pipeline".to_string(),
username: "testuser".to_string(),
working_dir: std::env::temp_dir(),
env_vars: HashMap::new(),
timeout: Some(Duration::from_secs(30)),
cgroup_path: None,
shell: "bash".to_string(),
dry_run: false,
privileged: false,
standalone: false,
}
}
#[tokio::test]
async fn test_execute_echo_outputs_correct_message() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let mut cmd = Command::new("echo");
cmd.arg("hello world");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.success);
assert_eq!(result.exit_code, 0);
assert!(result.stdout.contains("hello world"));
assert!(result.stderr.is_empty());
}
#[tokio::test]
async fn test_execute_true_returns_zero_exit_code() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let cmd = Command::new("true");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.success);
assert_eq!(result.exit_code, 0);
}
#[tokio::test]
async fn test_execute_false_returns_nonzero_exit_code() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let cmd = Command::new("false");
let result = executor.execute(cmd, &ctx, &None).await;
assert!(result.is_err());
// assert!(!result.success);
// assert_ne!(result.exit_code, 0);
}
#[tokio::test]
async fn test_execute_ls_lists_directory() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let mut cmd = Command::new("ls");
cmd.arg("-la");
cmd.arg("/tmp");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.success);
}
#[tokio::test]
async fn test_execute_date_command() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let cmd = Command::new("date");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.success);
assert!(!result.stdout.trim().is_empty());
}
#[tokio::test]
async fn test_execute_invalid_command_returns_error() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let cmd = Command::new("this_command_definitely_does_not_exist_12345");
let result = executor.execute(cmd, &ctx, &None).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_execute_passes_custom_env_var() {
let executor = create_executor();
let mut ctx = create_context();
ctx.env_vars
.insert("MY_CUSTOM_VAR".to_string(), "my_value_123".to_string());
use tokio::process::Command;
let cmd = Command::new("env");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.stdout.contains("MY_CUSTOM_VAR=my_value_123"));
}
#[tokio::test]
async fn test_execute_sets_ws_taskid() {
let executor = create_executor();
let mut ctx = create_context();
ctx.task_id = "task-abc-123".to_string();
ctx.pipeline_name = "pipeline-xyz".to_string();
use tokio::process::Command;
let cmd = Command::new("env");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.stdout.contains("HBW_TASKID=task-abc-123"));
assert!(result.stdout.contains("HBW_PIPELINE=pipeline-xyz"));
}
#[tokio::test]
async fn test_execute_sets_ws_user_info() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let cmd = Command::new("env");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.stdout.contains("HBW_USERNAME=testuser"));
}
#[tokio::test]
async fn test_execute_respects_working_directory() {
let executor = create_executor();
let ctx = ExecutionContext {
task_id: "test-context-1".to_string(),
pipeline_name: "test-pipeline".to_string(),
username: "testuser".to_string(),
working_dir: PathBuf::from("/tmp"),
env_vars: HashMap::new(),
timeout: Some(Duration::from_secs(30)),
cgroup_path: None,
shell: "bash".to_string(),
standalone: false,
..Default::default()
};
use tokio::process::Command;
let cmd = Command::new("pwd");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.success);
let trimmed = result.stdout.trim();
assert!(trimmed == "/tmp" || trimmed.ends_with("tmp"));
}
#[tokio::test]
async fn test_execute_captures_stderr() {
let executor = create_executor();
let ctx = create_context();
use tokio::process::Command;
let mut cmd = Command::new("bash");
cmd.arg("-c");
cmd.arg("echo error >&2");
let result = executor.execute(cmd, &ctx, &None).await.unwrap();
assert!(result.success);
assert!(result.stderr.contains("error"));
}