#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use std::collections::VecDeque;
use std::sync::Mutex;
use super::port::{PasAuthPort, PasFailure};
use crate::oauth::TokenResponse;
#[derive(Debug)]
struct RefreshExpect {
rt_in: String,
returns: Result<TokenResponse, PasFailure>,
}
#[derive(Debug, Default)]
pub struct MemoryPasAuth {
refresh_script: Mutex<VecDeque<RefreshExpect>>,
}
impl MemoryPasAuth {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn expect_refresh(
self,
rt: impl Into<String>,
returns: Result<TokenResponse, PasFailure>,
) -> Self {
self.refresh_script
.lock()
.unwrap()
.push_back(RefreshExpect { rt_in: rt.into(), returns });
self
}
}
impl PasAuthPort for MemoryPasAuth {
async fn refresh(&self, rt: &str) -> Result<TokenResponse, PasFailure> {
let exp = self
.refresh_script
.lock()
.unwrap()
.pop_front()
.expect("MemoryPasAuth: refresh called with no expect_refresh queued");
assert_eq!(
exp.rt_in, rt,
"MemoryPasAuth: refresh token mismatch (expected={:?}, actual={:?})",
exp.rt_in, rt
);
exp.returns
}
}
impl Drop for MemoryPasAuth {
fn drop(&mut self) {
if std::thread::panicking() {
return;
}
let r = self.refresh_script.get_mut().unwrap();
if !r.is_empty() {
panic!(
"MemoryPasAuth dropped with {} unconsumed refresh expectation(s)",
r.len()
);
}
}
}