use std::path::{Path, PathBuf};
use std::time::Duration;
use shep_core::paths::ShepPaths;
use super::*;
use crate::cli::AdoptArgs;
use crate::commands::dogs::adopt;
use crate::commands::dogs::test_support::streams;
const BUDGET: Duration = Duration::from_secs(30);
fn manifest_dog(dir: &Path, name: &str, manifest: &str) -> PathBuf {
use std::os::unix::fs::PermissionsExt;
let path = dir.join(name);
std::fs::write(
&path,
format!(
"#!/bin/sh\ncase \"$1\" in\n{flag})\necho '{manifest}'\n;;\nesac\n",
flag = shep_core::dogs::MANIFEST_FLAG
),
)
.unwrap();
let mut perms = std::fs::metadata(&path).unwrap().permissions();
perms.set_mode(0o755);
std::fs::set_permissions(&path, perms).unwrap();
path
}
fn declared(channel: bool, validate: bool) -> String {
serde_json::json!({
"manifest": 1,
"name": "kelpie",
"version": "0.2.0",
"protocol": shep_core::protocol::PROTOCOL_VERSION,
"channel": channel,
"validate": validate,
})
.to_string()
}
#[test]
fn a_dog_that_asks_to_be_consulted_without_a_channel_is_refused() {
let dir = tempfile::tempdir().unwrap();
let bin = manifest_dog(dir.path(), "shep-kelpie", &declared(false, true));
assert_eq!(
vet_binary_within(&bin, dir.path(), "kelpie", BUDGET),
Err(AdoptRefusal::ValidateWithoutChannel)
);
}
#[tokio::test]
async fn adopt_refuses_that_manifest_and_writes_nothing() {
let dir = tempfile::tempdir().unwrap();
let paths = ShepPaths::resolve(&|_| None, dir.path());
let bin = manifest_dog(dir.path(), "shep-kelpie", &declared(false, true));
let args = AdoptArgs {
yes: true,
name: Some("kelpie".to_string()),
path: bin,
};
let mut out = Vec::new();
let mut err = Vec::new();
let code = adopt(&mut streams(&mut out, &mut err), &paths, &args).await;
let text = String::from_utf8(err).unwrap();
assert_eq!(code, ExitCode::InvalidConfig, "{text}");
assert!(
text.contains("consulted") && text.contains("`channel`") && text.contains("`validate`"),
"the refusal names both fields it needs: {text}"
);
assert!(
!paths.daemon_config.exists(),
"a refused adopt writes no `shep.toml`"
);
}
#[tokio::test]
async fn the_same_manifest_with_a_channel_is_adopted() {
let dir = tempfile::tempdir().unwrap();
let paths = ShepPaths::resolve(&|_| None, dir.path());
let bin = manifest_dog(dir.path(), "shep-kelpie", &declared(true, true));
let args = AdoptArgs {
yes: true,
name: Some("kelpie".to_string()),
path: bin.clone(),
};
let mut out = Vec::new();
let mut err = Vec::new();
let code = adopt(&mut streams(&mut out, &mut err), &paths, &args).await;
assert_eq!(
code,
ExitCode::Success,
"{}",
String::from_utf8(err).unwrap()
);
assert!(
vet_binary_within(&bin, dir.path(), "kelpie", BUDGET)
.expect("adopted")
.manifest
.expect("a manifest")
.validate,
"the declaration survives to the cache `shep set` reads"
);
}