oci-zero 0.3.0

A no-std, allocation-free streaming core for OCI registries
Documentation
use std::{ffi::OsString, string::ToString};

use super::{
    config::{EnvironmentAuths, TEST_DOCKER_HUB_AUTH_KEY},
    helper::parse_response,
    DockerCredentialError, DockerCredentialProvider, OwnedCredentials,
};

fn config(json: &str) -> DockerCredentialProvider {
    DockerCredentialProvider::from_config_bytes(json.as_bytes()).unwrap()
}

#[test]
fn registry_helper_precedes_global_store_and_inline_auth() {
    let provider = config(
        r#"{
            "auths": {"ghcr.io": {"auth": "d3Jvbmc6d3Jvbmc="}},
            "credsStore": "osxkeychain",
            "credHelpers": {"ghcr.io": "ghcr"}
        }"#,
    );
    let credentials = provider
        .resolve_with("GHCR.IO", |helper, server| {
            assert_eq!(helper, "ghcr");
            assert_eq!(server, "ghcr.io");
            Ok(Some(OwnedCredentials {
                username: "helper-user".to_string(),
                secret: "helper-secret".to_string(),
            }))
        })
        .unwrap()
        .unwrap();
    assert_eq!(credentials.username, "helper-user");
    assert_eq!(credentials.secret, "helper-secret");
}

#[test]
fn global_store_precedes_inline_auth() {
    let provider = config(
        r#"{
            "auths": {"ghcr.io": {"auth": "d3Jvbmc6d3Jvbmc="}},
            "credsStore": "ddtool"
        }"#,
    );
    let credentials = provider
        .resolve_with("ghcr.io", |helper, server| {
            assert_eq!((helper, server), ("ddtool", "ghcr.io"));
            Ok(Some(OwnedCredentials {
                username: "store-user".to_string(),
                secret: "store-secret".to_string(),
            }))
        })
        .unwrap()
        .unwrap();
    assert_eq!(credentials.username, "store-user");
}

#[test]
fn environment_auth_precedes_helpers() {
    let mut provider = config(r#"{"credsStore":"desktop"}"#);
    provider.environment_auths = EnvironmentAuths::parse(
        br#"{"auths":{"ghcr.io":{"auth":"ZW52LXVzZXI6ZW52LXNlY3JldA=="}}}"#,
    )
    .unwrap();
    let credentials = provider
        .resolve_with("ghcr.io", |_, _| panic!("helper must not run"))
        .unwrap()
        .unwrap();
    assert_eq!(credentials.username, "env-user");
    assert_eq!(credentials.secret, "env-secret");
}

#[test]
fn environment_auth_falls_back_for_unmatched_registry() {
    let mut provider = config(r#"{"credsStore":"desktop"}"#);
    provider.environment_auths = EnvironmentAuths::parse(
        br#"{"auths":{"registry.example":{"auth":"ZW52LXVzZXI6ZW52LXNlY3JldA=="}}}"#,
    )
    .unwrap();
    provider
        .resolve_with("ghcr.io", |helper, server| {
            assert_eq!((helper, server), ("desktop", "ghcr.io"));
            Ok(None)
        })
        .unwrap();
}

#[test]
fn decodes_inline_auth_and_preserves_colons_in_secret() {
    let provider = config(r#"{"auths":{"registry.example":{"auth":"dXNlcjpwYXNzOndvcmQ="}}}"#);
    let credentials = provider
        .resolve_with("registry.example", |_, _| panic!("helper must not run"))
        .unwrap()
        .unwrap();
    assert_eq!(credentials.username, "user");
    assert_eq!(credentials.secret, "pass:word");
}

#[test]
fn canonicalizes_docker_hub_for_helper_lookup() {
    let provider = config(r#"{"credHelpers":{"https://index.docker.io/v1/":"osxkeychain"}}"#);
    for authority in ["docker.io", "index.docker.io", "registry-1.docker.io"] {
        provider
            .resolve_with(authority, |helper, server| {
                assert_eq!(helper, "osxkeychain");
                assert_eq!(server, TEST_DOCKER_HUB_AUTH_KEY);
                Ok(None)
            })
            .unwrap();
    }
}

#[test]
fn helper_not_found_does_not_fall_back_to_inline_auth() {
    let provider = config(
        r#"{
            "auths": {"ghcr.io": {"auth": "dXNlcjpwYXNz"}},
            "credHelpers": {"ghcr.io": "ghcr"}
        }"#,
    );
    assert!(provider
        .resolve_with("ghcr.io", |_, _| Ok(None))
        .unwrap()
        .is_none());
}

#[test]
fn empty_registry_helper_disables_the_global_store() {
    let provider = config(
        r#"{
            "auths": {"ghcr.io": {"auth": "dXNlcjpwYXNz"}},
            "credsStore": "desktop",
            "credHelpers": {"ghcr.io": ""}
        }"#,
    );
    let credentials = provider
        .resolve_with("ghcr.io", |_, _| panic!("helper must not run"))
        .unwrap()
        .unwrap();
    assert_eq!(credentials.username, "user");
    assert_eq!(credentials.secret, "pass");
}

#[test]
fn rejects_helper_paths() {
    let provider = config(r#"{"credsStore":"../../helper"}"#);
    assert!(matches!(
        provider.resolve_with("ghcr.io", |_, _| Ok(None)),
        Err(DockerCredentialError::InvalidHelperName { .. })
    ));
}

#[test]
fn parses_standard_helper_response_without_exposing_secret() {
    let credentials = parse_response(
        OsString::from("docker-credential-test"),
        br#"{"Username":"alice","Secret":"top-secret"}"#,
    )
    .unwrap();
    assert_eq!(credentials.username, "alice");
    assert_eq!(credentials.secret, "top-secret");
}

#[test]
fn rejects_helper_response_without_username() {
    assert!(matches!(
        parse_response(
            OsString::from("docker-credential-test"),
            br#"{"Username":"","Secret":"top-secret"}"#,
        ),
        Err(DockerCredentialError::MissingHelperUsername { .. })
    ));
}

#[test]
fn empty_config_is_valid() {
    let provider = DockerCredentialProvider::from_config_bytes(b" \n\t").unwrap();
    assert!(provider
        .resolve_with("ghcr.io", |_, _| Ok(None))
        .unwrap()
        .is_none());
}

#[test]
fn environment_config_rejects_unknown_fields() {
    assert!(EnvironmentAuths::parse(
        br#"{"auths":{"ghcr.io":{"auth":"dXNlcjpwYXNz","email":"x"}}}"#
    )
    .is_err());
}