use super::*;
#[test]
fn debug_redacts_value() {
let s = SecretString::new("hunter2");
let dbg = format!("{s:?}");
assert_eq!(dbg, "\"***\"");
assert!(
!dbg.contains("hunter2"),
"raw value must never appear in Debug output"
);
}
#[test]
fn debug_redacts_inside_struct() {
#[derive(Debug)]
struct Wrap {
#[allow(dead_code)] secret: SecretString,
}
let w = Wrap {
secret: SecretString::new("super-secret-token-abc123"),
};
let dbg = format!("{w:?}");
assert!(!dbg.contains("super-secret"), "got: {dbg}");
assert!(dbg.contains("***"), "redaction marker missing: {dbg}");
}
#[test]
fn expose_returns_raw_value() {
let s = SecretString::new("hunter2");
assert_eq!(s.expose(), "hunter2");
}
#[test]
fn is_empty_does_not_leak_value() {
assert!(SecretString::new("").is_empty());
assert!(!SecretString::new("x").is_empty());
}
#[test]
fn deserializes_from_toml_string() {
#[derive(Deserialize)]
struct Wrap {
secret: SecretString,
}
let w: Wrap = toml::from_str("secret = \"hunter2\"").unwrap();
assert_eq!(w.secret.expose(), "hunter2");
}
#[test]
fn serialize_does_not_leak_value() {
let s = SecretString::new("hunter2-this-is-the-secret");
let json = serde_json::to_string(&s).unwrap();
assert!(
!json.contains("hunter2"),
"raw secret leaked through Serialize: {json}"
);
assert!(
json.starts_with("\"hash:") && json.ends_with('"'),
"expected hashed form, got: {json}"
);
}
#[test]
fn serialize_distinguishes_distinct_secrets() {
let a = SecretString::new("old-key");
let b = SecretString::new("new-key");
let ja = serde_json::to_string(&a).unwrap();
let jb = serde_json::to_string(&b).unwrap();
assert_ne!(ja, jb, "distinct secrets must serialize differently");
}
#[test]
fn serialize_is_deterministic_within_process() {
let s = SecretString::new("a-stable-key");
let first = serde_json::to_string(&s).unwrap();
let second = serde_json::to_string(&s).unwrap();
assert_eq!(first, second);
}