mod common;
use base64::prelude::*;
use common::log_capture::LogCapture;
use jmap_base_client::auth::{BasicAuth, BearerAuth};
use jmap_base_client::{AccountName, Username};
#[test]
fn log_capture_captures_traced_output() {
let capture = LogCapture::new();
tracing::info!("sentinel-message-12345 emitted by harness self-test");
capture.assert_contains("sentinel-message-12345");
}
#[test]
fn log_capture_detects_a_leak_when_one_exists() {
#[derive(Debug)]
struct Leaky(#[expect(dead_code, reason = "consumed only via Debug formatting")] &'static str);
const CANARY: &str = "CANARY-NEGATIVE-CONTROL-LEAK-789";
let capture = LogCapture::new();
let leaky = Leaky(CANARY);
tracing::info!(secret = ?leaky, "leaky type formatted via Debug");
let contents = capture.contents();
assert!(
contents.contains(CANARY),
"negative control: expected the canary literal to appear in captured output; \
if this fires, the harness is not capturing Debug-formatted args and the \
positive assertions in other tests pass vacuously. Got:\n{contents}"
);
}
#[test]
fn auth_token_never_appears_in_tracing_capture() {
const CANARY: &str = "CANARY-LOG-TOKEN-DO-NOT-LEAK-456";
let capture = LogCapture::new();
let auth = BearerAuth::new(CANARY).expect("valid ASCII token must construct");
tracing::info!(auth = ?auth, "constructed auth provider");
tracing::debug!("auth provider state: {auth:?}");
tracing::trace!(?auth, "fine-grained auth trace");
tracing::warn!("attempting request with {auth:?}");
tracing::error!("simulated request failure with auth = {auth:?}");
capture.assert_contains("constructed auth provider");
capture.assert_contains("[REDACTED]");
capture.assert_does_not_contain(CANARY);
}
#[test]
fn basic_auth_credentials_never_appear_in_tracing_capture() {
const CANARY_USER: &str = "CANARY-LOG-USER-DO-NOT-LEAK";
const CANARY_PASS: &str = "CANARY-LOG-PASS-DO-NOT-LEAK";
let capture = LogCapture::new();
let auth = BasicAuth::new(CANARY_USER, CANARY_PASS).expect("valid credentials must construct");
tracing::info!(auth = ?auth, "constructed basic auth");
tracing::debug!("basic auth state: {auth:?}");
capture.assert_contains("constructed basic auth");
capture.assert_contains("[REDACTED]");
capture.assert_does_not_contain(CANARY_USER);
capture.assert_does_not_contain(CANARY_PASS);
let base64_pair = BASE64_STANDARD.encode(format!("{CANARY_USER}:{CANARY_PASS}"));
capture.assert_does_not_contain(&base64_pair);
}
#[test]
fn username_never_appears_in_tracing_capture() {
const CANARY: &str = "CANARY-LOG-USERNAME-DO-NOT-LEAK";
let capture = LogCapture::new();
let username = Username::new(CANARY);
tracing::info!(user = %username, "constructed username");
tracing::debug!("username Display path: {username}");
tracing::trace!(?username, "username Debug path");
tracing::warn!("username via mixed Debug: {username:?}");
capture.assert_contains("constructed username");
capture.assert_contains("[REDACTED]");
capture.assert_does_not_contain(CANARY);
}
#[test]
fn account_name_never_appears_in_tracing_capture() {
const CANARY: &str = "CANARY-LOG-ACCOUNT-NAME-DO-NOT-LEAK";
let capture = LogCapture::new();
let account_name = AccountName::new(CANARY);
tracing::info!(name = %account_name, "constructed account name");
tracing::debug!("account name Display path: {account_name}");
tracing::trace!(?account_name, "account name Debug path");
tracing::warn!("account name via mixed Debug: {account_name:?}");
capture.assert_contains("constructed account name");
capture.assert_contains("[REDACTED]");
capture.assert_does_not_contain(CANARY);
}