use pupoxide::domain::resource::{Ensure, ResourceProvider};
use pupoxide::infrastructure::ExecAdapter;
use std::fs;
use tempfile::tempdir;
#[tokio::test]
async fn test_exec_creates_idempotency() {
let dir = tempdir().unwrap();
let output_file = dir.path().join("exec_output.txt");
let output_path = output_file.to_str().unwrap();
let resource = pupoxide::domain::resource::Resource::Exec(
pupoxide::domain::resource::ExecResource {
id: format!("Exec[echo test > {}]", output_path),
command: format!("echo 'test content' > {}", output_path),
creates: Some(output_file.clone()),
unless: None,
cwd: None,
environment: None,
dependencies: Vec::new(),
},
);
let adapter = ExecAdapter;
let state = adapter
.get_state(&resource, false)
.await
.expect("Failed to get state");
assert_eq!(
state,
pupoxide::domain::resource::ResourceState::Ensure(Ensure::Absent)
);
adapter.apply(&resource).await.expect("Failed to apply");
assert!(output_file.exists());
let content = fs::read_to_string(&output_file).expect("Failed to read");
assert!(content.contains("test content"));
let state2 = adapter
.get_state(&resource, false)
.await
.expect("Failed to get state");
assert_eq!(
state2,
pupoxide::domain::resource::ResourceState::Ensure(Ensure::Present)
);
let original_content = fs::read_to_string(&output_file).expect("Failed to read");
adapter.apply(&resource).await.expect("Failed to apply");
let new_content = fs::read_to_string(&output_file).expect("Failed to read");
assert_eq!(original_content, new_content);
}
#[tokio::test]
async fn test_exec_unless_condition() {
let dir = tempdir().unwrap();
let marker_file = dir.path().join("marker.txt");
let marker_path = marker_file.to_str().unwrap();
fs::write(&marker_file, "marker").expect("Failed to create marker");
let resource = pupoxide::domain::resource::Resource::Exec(
pupoxide::domain::resource::ExecResource {
id: "Exec[test unless]".to_string(),
command: "echo 'should not run'".to_string(),
creates: None,
unless: Some(format!("test -f {}", marker_path)),
cwd: None,
environment: None,
dependencies: Vec::new(),
},
);
let adapter = ExecAdapter;
let state = adapter
.get_state(&resource, false)
.await
.expect("Failed to get state");
assert_eq!(
state,
pupoxide::domain::resource::ResourceState::Ensure(Ensure::Present)
);
}
#[tokio::test]
async fn test_exec_with_environment() {
let dir = tempdir().unwrap();
let output_file = dir.path().join("env_output.txt");
let output_path = output_file.to_str().unwrap();
let mut env = std::collections::HashMap::new();
env.insert("TEST_VAR".to_string(), "test_value".to_string());
let resource = pupoxide::domain::resource::Resource::Exec(
pupoxide::domain::resource::ExecResource {
id: "Exec[test env]".to_string(),
command: format!("echo $TEST_VAR > {}", output_path),
creates: None,
unless: None,
cwd: None,
environment: Some(env),
dependencies: Vec::new(),
},
);
let adapter = ExecAdapter;
adapter.apply(&resource).await.expect("Failed to apply");
assert!(output_file.exists());
let content = fs::read_to_string(&output_file).expect("Failed to read");
assert!(content.contains("test_value"));
}
#[tokio::test]
async fn test_exec_with_cwd() {
let dir = tempdir().unwrap();
let output_file = "cwd_test.txt";
let resource = pupoxide::domain::resource::Resource::Exec(
pupoxide::domain::resource::ExecResource {
id: "Exec[test cwd]".to_string(),
command: format!("echo 'cwd test' > {}", output_file),
creates: None,
unless: None,
cwd: Some(dir.path().to_path_buf()),
environment: None,
dependencies: Vec::new(),
},
);
let adapter = ExecAdapter;
adapter.apply(&resource).await.expect("Failed to apply");
let full_path = dir.path().join(output_file);
assert!(full_path.exists());
let content = fs::read_to_string(&full_path).expect("Failed to read");
assert!(content.contains("cwd test"));
}
#[tokio::test]
async fn test_exec_command_failure() {
let resource = pupoxide::domain::resource::Resource::Exec(
pupoxide::domain::resource::ExecResource {
id: "Exec[failing command]".to_string(),
command: "exit 1".to_string(),
creates: None,
unless: None,
cwd: None,
environment: None,
dependencies: Vec::new(),
},
);
let adapter = ExecAdapter;
let result = adapter.apply(&resource).await;
assert!(result.is_err());
}