cloud-sdk-reqwest 0.28.0

Optional provider-neutral reqwest transport boundary for cloud-sdk.
Documentation
use std::boxed::Box;
use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
use std::sync::{
    Arc, Barrier,
    atomic::{AtomicUsize, Ordering},
};

use cloud_sdk_sanitization::SecretBuffer;

use super::{BearerToken, CredentialStore, TokenRefreshError, TokenRotationError};

#[test]
fn mutable_and_guarded_sources_clear_on_success_and_failure() {
    let mut valid = *b"replacement";
    let token = BearerToken::from_mut_bytes(&mut valid);
    assert!(token.is_ok());
    assert_eq!(valid, [0; 11]);

    let mut invalid = *b"bad token";
    assert!(BearerToken::from_mut_bytes(&mut invalid).is_err());
    assert_eq!(invalid, [0; 9]);

    let mut guarded = *b"guarded-token";
    let token = BearerToken::from_secret_buffer(SecretBuffer::new(&mut guarded));
    assert!(token.is_ok());
    assert_eq!(guarded, [0; 13]);
}

#[test]
fn rejected_rotation_preserves_active_token_and_clears_input() {
    let Ok(active) = BearerToken::new("active-token") else {
        return;
    };
    let store = CredentialStore::new(active);
    let mut rejected = *b"bad token";
    assert!(matches!(
        store.rotate_from_mut_bytes(&mut rejected),
        Err(TokenRotationError::TokenRejected(_))
    ));
    assert_eq!(rejected, [0; 9]);
    let snapshot = store.snapshot();
    assert!(snapshot.is_ok());
    if let Ok(snapshot) = snapshot {
        assert_eq!(snapshot.owned_bytes(), b"Bearer active-token");
    }
}

#[test]
fn retired_token_waits_for_last_snapshot_and_generations_advance() {
    let drops = Arc::new(AtomicUsize::new(0));
    let active = BearerToken::with_drop_probe("old-token", Arc::clone(&drops));
    let Ok(active) = active else { return };
    let store = CredentialStore::new(active);
    let old_snapshot = store.snapshot();
    let Ok(old_snapshot) = old_snapshot else {
        return;
    };
    let Ok(replacement) = BearerToken::new("new-token") else {
        return;
    };

    let generation = store.rotate(replacement);
    assert_eq!(generation.map(|value| value.get()), Ok(2));
    assert_eq!(drops.load(Ordering::SeqCst), 0);
    assert_eq!(old_snapshot.owned_bytes(), b"Bearer old-token");
    let new_snapshot = store.snapshot();
    assert!(new_snapshot.is_ok());
    if let Ok(new_snapshot) = new_snapshot {
        assert_eq!(new_snapshot.generation().get(), 2);
        assert_eq!(new_snapshot.owned_bytes(), b"Bearer new-token");
    }
    drop(old_snapshot);
    assert_eq!(drops.load(Ordering::SeqCst), 1);
}

#[test]
fn stale_refresh_cannot_overwrite_newer_rotation() {
    let Ok(active) = BearerToken::new("active-token") else {
        return;
    };
    let store = CredentialStore::new(active);
    let Ok(snapshot) = store.snapshot() else {
        return;
    };
    let handoff = snapshot.refresh_handoff();
    let Ok(rotated) = BearerToken::new("rotated-token") else {
        return;
    };
    assert!(store.rotate(rotated).is_ok());
    let Ok(stale) = BearerToken::new("stale-refresh") else {
        return;
    };
    assert_eq!(
        store.refresh(handoff, stale),
        Err(TokenRefreshError::StaleGeneration)
    );
    let current = store.snapshot();
    assert!(current.is_ok());
    if let Ok(current) = current {
        assert_eq!(current.owned_bytes(), b"Bearer rotated-token");
        assert_eq!(current.generation().get(), 2);
    }
}

#[test]
fn refresh_handoff_cannot_cross_credential_store_lineages() {
    let Ok(first_token) = BearerToken::new("first-token") else {
        return;
    };
    let Ok(second_token) = BearerToken::new("second-token") else {
        return;
    };
    let first = CredentialStore::new(first_token);
    let second = CredentialStore::new(second_token);
    let Ok(first_snapshot) = first.snapshot() else {
        return;
    };
    let drops = Arc::new(AtomicUsize::new(0));
    let Ok(replacement) = BearerToken::with_drop_probe("foreign-replacement", Arc::clone(&drops))
    else {
        return;
    };

    assert_eq!(
        second.refresh(first_snapshot.refresh_handoff(), replacement),
        Err(TokenRefreshError::CredentialMismatch)
    );
    assert_eq!(
        second.snapshot().map(|value| value.generation().get()),
        Ok(1)
    );
    assert_eq!(drops.load(Ordering::SeqCst), 1);
    let current = second.snapshot();
    assert!(current.is_ok());
    if let Ok(current) = current {
        assert_eq!(current.owned_bytes(), b"Bearer second-token");
    }
}

#[test]
fn competing_refreshes_allow_exactly_one_generation_transition() {
    let Ok(active) = BearerToken::new("active-token") else {
        return;
    };
    let store = CredentialStore::new(active);
    let Ok(snapshot) = store.snapshot() else {
        return;
    };
    let handoff = snapshot.refresh_handoff();
    let first = BearerToken::new("first-refresh");
    let second = BearerToken::new("second-refresh");
    let (Ok(first), Ok(second)) = (first, second) else {
        return;
    };
    assert_eq!(
        store
            .refresh(handoff.clone(), first)
            .map(|value| value.get()),
        Ok(2)
    );
    assert_eq!(
        store.refresh(handoff, second),
        Err(TokenRefreshError::StaleGeneration)
    );
}

#[test]
fn concurrent_refresh_race_allows_exactly_one_winner() {
    let Ok(active) = BearerToken::new("active-token") else {
        return;
    };
    let store = Arc::new(CredentialStore::new(active));
    let Ok(snapshot) = store.snapshot() else {
        return;
    };
    let handoff = snapshot.refresh_handoff();
    let barrier = Arc::new(Barrier::new(3));
    let mut successes = 0_usize;
    let mut stale = 0_usize;
    std::thread::scope(|scope| {
        let first_store = Arc::clone(&store);
        let first_barrier = Arc::clone(&barrier);
        let first_handoff = handoff.clone();
        let first = scope.spawn(move || {
            first_barrier.wait();
            match BearerToken::new("first-refresh") {
                Ok(token) => first_store.refresh(first_handoff, token),
                Err(error) => Err(TokenRefreshError::TokenRejected(error)),
            }
        });
        let second_store = Arc::clone(&store);
        let second_barrier = Arc::clone(&barrier);
        let second = scope.spawn(move || {
            second_barrier.wait();
            let token = BearerToken::new("second-refresh");
            match token {
                Ok(token) => second_store.refresh(handoff, token),
                Err(error) => Err(TokenRefreshError::TokenRejected(error)),
            }
        });
        barrier.wait();
        for result in [first.join(), second.join()] {
            match result {
                Ok(Ok(_)) => successes = successes.saturating_add(1),
                Ok(Err(_)) => stale = stale.saturating_add(1),
                Err(_) => {}
            }
        }
    });
    assert_eq!(successes, 1);
    assert_eq!(stale, 1);
    assert_eq!(
        store.snapshot().map(|value| value.generation().get()),
        Ok(2)
    );
}

#[test]
fn rejected_refresh_clears_input_without_changing_generation() {
    let Ok(active) = BearerToken::new("active-token") else {
        return;
    };
    let store = CredentialStore::new(active);
    let Ok(snapshot) = store.snapshot() else {
        return;
    };
    let mut rejected = *b"bad token";
    assert!(matches!(
        store.refresh_from_mut_bytes(snapshot.refresh_handoff(), &mut rejected),
        Err(TokenRefreshError::TokenRejected(_))
    ));
    assert_eq!(rejected, [0; 9]);
    assert_eq!(
        store.snapshot().map(|value| value.generation().get()),
        Ok(1)
    );
}

#[test]
fn poisoned_state_recovers_for_snapshots_rotations_and_refreshes() {
    let Ok(active) = BearerToken::new("active-token") else {
        return;
    };
    let store = CredentialStore::new(active);

    poison_state(&store);
    let snapshot = store.snapshot();
    assert!(snapshot.is_ok());
    assert!(!store.current.is_poisoned());
    let Ok(snapshot) = snapshot else { return };

    poison_state(&store);
    let Ok(replacement) = BearerToken::new("replacement-token") else {
        return;
    };
    assert!(
        store
            .refresh(snapshot.refresh_handoff(), replacement)
            .is_ok()
    );
    assert!(!store.current.is_poisoned());
    let snapshot = store.snapshot();
    assert!(snapshot.is_ok());
    if let Ok(snapshot) = snapshot {
        assert_eq!(snapshot.owned_bytes(), b"Bearer replacement-token");
    }
}

#[test]
fn header_copy_has_cleanup_owner_and_redacted_snapshot() {
    let drops = Arc::new(AtomicUsize::new(0));
    let token = BearerToken::with_header_drop_probe("active-token", Arc::clone(&drops));
    let Ok(token) = token else { return };
    let store = CredentialStore::new(token);
    let Ok(snapshot) = store.snapshot() else {
        return;
    };
    let header = snapshot.header_value();
    assert!(header.is_ok());
    assert_eq!(drops.load(Ordering::SeqCst), 0);
    drop(header);
    assert_eq!(drops.load(Ordering::SeqCst), 1);
    let debug = std::format!("{snapshot:?}");
    assert!(debug.contains("[redacted]"));
    assert!(!debug.contains("active-token"));
}

fn poison_state(store: &CredentialStore) {
    let result = catch_unwind(AssertUnwindSafe(|| {
        let guard = store.current.write();
        let Ok(_guard) = guard else { return };
        resume_unwind(Box::new(()));
    }));
    assert!(result.is_err());
    assert!(store.current.is_poisoned());
}