Files
honey-biscuit-workshop/workshop-baker/tests/finalize_hook_integration.rs
T
Catty Steve 36112c671d
CI / Check & Lint (push) Failing after 23m46s
style: apply rustfmt and clippy fixes across codebase
2026-04-23 18:34:26 +08:00

186 lines
5.7 KiB
Rust

//! Integration tests for finalize hook execution
//!
//! These tests verify that shell hooks and plugin hooks execute correctly
//! through the finalize stage hook executor.
use std::collections::HashMap;
use std::time::Duration;
use workshop_baker::engine::{ExecutionContext, ExecutionEvent};
use workshop_baker::finalize::plugin::PluginMap;
use workshop_baker::finalize::stage::hook::hook;
use workshop_baker::types::command::CustomCommand;
fn create_test_context() -> ExecutionContext {
ExecutionContext {
task_id: "test-hook-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,
}
}
fn create_test_event_channel() -> (
Option<tokio::sync::mpsc::Sender<ExecutionEvent>>,
tokio::sync::mpsc::Receiver<ExecutionEvent>,
) {
let (tx, rx) = tokio::sync::mpsc::channel(64);
(Some(tx), rx)
}
#[tokio::test]
async fn test_shell_hook_success() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let cmd = CustomCommand {
name: "echo-test".to_string(),
command: "echo 'hook-ok'".to_string(),
environment: None,
working_dir: None,
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
};
let result = hook(Some(&vec![cmd]), &ctx, event_tx, &plugins).await;
assert!(result.is_ok(), "Shell hook should succeed: {:?}", result);
}
#[tokio::test]
async fn test_shell_hook_failure_propagates() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let cmd = CustomCommand {
name: "false-cmd".to_string(),
command: "false".to_string(),
environment: None,
working_dir: None,
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
};
let result = hook(Some(&vec![cmd]), &ctx, event_tx, &plugins).await;
assert!(result.is_err(), "Shell hook failure should propagate");
}
#[tokio::test]
async fn test_hook_timeout_kills_long_command() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let cmd = CustomCommand {
name: "sleep-forever".to_string(),
command: "sleep 10".to_string(),
environment: None,
working_dir: None,
timeout_ms: 500, // 0.5 seconds
argument: serde_yaml::Value::Null,
};
let result = hook(Some(&vec![cmd]), &ctx, event_tx, &plugins).await;
assert!(result.is_err(), "Hook should fail due to timeout");
}
#[tokio::test]
async fn test_hook_working_dir_applied() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let cmd = CustomCommand {
name: "pwd-check".to_string(),
command: "pwd".to_string(),
environment: None,
working_dir: Some("/tmp".to_string()),
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
};
// We verify by checking the hook returns Ok — the working_dir is passed to
// Engine::execute_command_with_delta. Full stdout verification would require
// mocking the Engine or using a more intrusive test setup.
let result = hook(Some(&vec![cmd]), &ctx, event_tx, &plugins).await;
assert!(result.is_ok(), "Hook with working_dir should succeed");
}
#[tokio::test]
async fn test_no_hooks_returns_ok() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let result = hook(None, &ctx, event_tx, &plugins).await;
assert!(result.is_ok(), "No hooks should return Ok immediately");
}
#[tokio::test]
async fn test_multiple_hooks_execute_sequentially() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let cmds = vec![
CustomCommand {
name: "hook-1".to_string(),
command: "true".to_string(),
environment: None,
working_dir: None,
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
},
CustomCommand {
name: "hook-2".to_string(),
command: "true".to_string(),
environment: None,
working_dir: None,
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
},
];
let result = hook(Some(&cmds), &ctx, event_tx, &plugins).await;
assert!(
result.is_ok(),
"Multiple hooks should execute sequentially and succeed"
);
}
#[tokio::test]
async fn test_first_failure_stops_remaining_hooks() {
let ctx = create_test_context();
let (event_tx, _event_rx) = create_test_event_channel();
let plugins = PluginMap::new();
let cmds = vec![
CustomCommand {
name: "failing-hook".to_string(),
command: "false".to_string(),
environment: None,
working_dir: None,
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
},
CustomCommand {
name: "never-reached".to_string(),
command: "true".to_string(),
environment: None,
working_dir: None,
timeout_ms: 5000,
argument: serde_yaml::Value::Null,
},
];
let result = hook(Some(&cmds), &ctx, event_tx, &plugins).await;
assert!(result.is_err(), "First failing hook should stop execution");
}