blob: 330048548033f25a5771f3e0fc4d4ff142081282 [file] [log] [blame]
use bstr::{BString, ByteVec};
use gix_credentials::{helper, protocol::Context, Program};
use gix_testtools::fixture_path;
#[test]
fn get() {
let mut outcome = gix_credentials::helper::invoke(
&mut script_helper("last-pass"),
&helper::Action::get_for_url("https://github.com/byron/gitoxide"),
)
.unwrap()
.expect("mock provides credentials");
assert_eq!(
outcome.consume_identity().expect("complete"),
gix_sec::identity::Account {
username: "user".into(),
password: "pass".into()
}
);
assert_eq!(
outcome.next.store().payload().unwrap(),
"username=user\npassword=pass\nquit=1\n"
);
}
#[test]
fn store_and_reject() {
let ctx = Context {
url: Some("https://github.com/byron/gitoxide".into()),
..Default::default()
};
let ctxbuf = || -> BString {
let mut buf = Vec::<u8>::new();
ctx.write_to(&mut buf).expect("cannot fail");
buf.into()
};
for action in [helper::Action::Store(ctxbuf()), helper::Action::Erase(ctxbuf())] {
let outcome = gix_credentials::helper::invoke(&mut script_helper("last-pass"), &action).unwrap();
assert!(
outcome.is_none(),
"store and erase have no outcome, they just shouldn't fail"
);
}
}
mod program {
use gix_credentials::{helper, program::Kind, Program};
use crate::helper::invoke::script_helper;
#[test]
fn builtin() {
assert!(
matches!(
gix_credentials::helper::invoke(
&mut Program::from_kind(Kind::Builtin).suppress_stderr(),
&helper::Action::get_for_url("/path/without/scheme/fails/with/error"),
)
.unwrap_err(),
helper::Error::CredentialsHelperFailed { .. }
),
"this failure indicates we could launch the helper, even though it wasn't happy which is fine. It doesn't like the URL"
);
}
#[test]
fn script() {
assert_eq!(
gix_credentials::helper::invoke(
&mut Program::from_custom_definition(
"!f() { test \"$1\" = get && echo \"password=pass\" && echo \"username=user\"; }; f"
),
&helper::Action::get_for_url("/does/not/matter"),
)
.unwrap()
.expect("present")
.consume_identity()
.expect("complete"),
gix_sec::identity::Account {
username: "user".into(),
password: "pass".into()
}
);
}
#[cfg(unix)] // needs executable bits to work
#[test]
fn path_to_helper_script() -> crate::Result {
assert_eq!(
gix_credentials::helper::invoke(
&mut Program::from_custom_definition(
gix_path::into_bstr(gix_path::realpath(gix_testtools::fixture_path("custom-helper.sh"))?)
.into_owned()
),
&helper::Action::get_for_url("/does/not/matter"),
)?
.expect("present")
.consume_identity()
.expect("complete"),
gix_sec::identity::Account {
username: "user-script".into(),
password: "pass-script".into()
}
);
Ok(())
}
#[test]
fn path_to_helper_as_script_to_workaround_executable_bits() -> crate::Result {
assert_eq!(
gix_credentials::helper::invoke(
&mut script_helper("custom-helper"),
&helper::Action::get_for_url("/does/not/matter")
)?
.expect("present")
.consume_identity()
.expect("complete"),
gix_sec::identity::Account {
username: "user-script".into(),
password: "pass-script".into()
}
);
Ok(())
}
}
pub fn script_helper(name: &str) -> Program {
let mut script = gix_path::to_unix_separators_on_windows(gix_path::into_bstr(
gix_path::realpath(fixture_path(format!("{name}.sh"))).unwrap(),
))
.into_owned();
script.insert_str(0, "sh ");
Program::from_kind(gix_credentials::program::Kind::ExternalShellScript(script))
}