use super::*;
#[test]
fn test9952_an_identity_is_generated_once_and_reused() {
let dir = tempfile::tempdir().expect("tempdir");
let first = MachineIdentity::load_or_create(dir.path(), "desktop").expect("created");
let second = MachineIdentity::load_or_create(dir.path(), "ignored").expect("loaded");
assert_eq!(first.id(), second.id());
assert_eq!(first.public_key(), second.public_key());
assert_eq!(
second.name(),
"desktop",
"the name comes from the file, not from the caller's default"
);
let other = tempfile::tempdir().expect("tempdir");
let laptop = MachineIdentity::load_or_create(other.path(), "laptop").expect("created");
assert_ne!(first.id(), laptop.id());
}
#[test]
fn test9953_the_secret_half_stays_private() {
let dir = tempfile::tempdir().expect("tempdir");
let identity = MachineIdentity::load_or_create(dir.path(), "desktop").expect("created");
let path = MachineIdentity::path_in(dir.path());
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = std::fs::metadata(&path).expect("metadata").permissions().mode();
assert_eq!(mode & 0o077, 0, "the identity file is readable by others: {mode:o}");
}
let rendered = format!("{identity:?}");
let stored = std::fs::read_to_string(&path).expect("read");
let secret: serde_json::Value = serde_json::from_str(&stored).expect("json");
let secret = secret["secret_key"].as_str().expect("a key");
assert!(!rendered.contains(secret), "the secret key reached Debug: {rendered}");
assert!(rendered.contains(identity.id().as_str()));
}
#[test]
fn test9954_a_damaged_identity_is_refused_not_replaced() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(MachineIdentity::path_in(dir.path()), b"not an identity").expect("write");
let error = MachineIdentity::load_or_create(dir.path(), "desktop")
.expect_err("a damaged identity must be refused");
assert!(error.contains("not a machine identity"), "{error}");
std::fs::write(
MachineIdentity::path_in(dir.path()),
br#"{"secret_key":"c2hvcnQ=","name":"desktop"}"#,
)
.expect("write");
let error = MachineIdentity::load_or_create(dir.path(), "desktop").expect_err("refused");
assert!(error.contains("32-byte"), "{error}");
}
#[test]
fn test9955_identity_is_derived_from_the_key_alone() {
let dir = tempfile::tempdir().expect("tempdir");
let mut identity = MachineIdentity::load_or_create(dir.path(), "desktop").expect("created");
let id = identity.id().clone();
let fingerprint = identity.fingerprint().clone();
identity.rename(dir.path(), "workshop").expect("renamed");
assert_eq!(identity.name(), "workshop");
assert_eq!(identity.id(), &id, "a rename must not change the identity");
assert_eq!(identity.fingerprint(), &fingerprint);
let reloaded = MachineIdentity::load_or_create(dir.path(), "ignored").expect("loaded");
assert_eq!(reloaded.id(), &id);
assert_eq!(reloaded.name(), "workshop");
assert_eq!(peer_id_of(&reloaded.public_key()), id);
assert!(super::super::model::PeerId::parse(id.as_str()).is_ok());
}
#[test]
fn test9956_pairing_codes_forgive_typing_and_nothing_else() {
let code = PairingCode::mint();
let text = code.to_string();
assert_eq!(text.split('-').count(), 3, "{text} is not three groups");
for spelling in [
text.clone(),
text.to_lowercase(),
format!(" {text} "),
text.replace('-', " - "),
] {
assert_eq!(
PairingCode::parse(&spelling).expect("a code"),
code,
"{spelling:?} did not parse back to the same code"
);
}
for hostile in ["", "FERN", "FERN-74", "FERN-74-MOON-EXTRA"] {
assert!(
PairingCode::parse(hostile).is_err(),
"{hostile:?} was accepted as a code"
);
}
let same = PairingCode::parse(&text).expect("a code");
assert_eq!(code.secret(), same.secret());
assert_ne!(code.secret(), PairingCode::mint().secret());
}