thrall 0.0.24

thrall: the foot — a tool-execution client for a yog server
Documentation
//! The act against a fake commons and a loopback punch port: every way it
//! refuses, the call it writes, and the cache the third rung re-calls from.

use super::write::{listed, nonce, unix_now};
use super::*;
use crate::dht::tests::fake::Mood;
use crate::rendezvous::item::Call;
use crate::test_support::roving::{commons, commons_as, engine, pairing, presence, tuned};
use std::net::IpAddr;

pub(super) fn roving(tuning: Tuning) -> Roving {
    Roving::new(pairing(), tuning)
}

/// A port nothing listens on.
pub(super) fn dead_port() -> u16 {
    let gone = std::net::TcpListener::bind("127.0.0.1:0").expect("bind");
    let port = gone.local_addr().expect("addr").port();
    drop(gone);
    port
}

#[test]
fn the_defaults_are_the_stated_ones() {
    let t = Tuning::default();
    assert_eq!(t.window, Duration::from_secs(35));
    assert_eq!(t.bootstrap, crate::rendezvous::mainline());
    assert_eq!(t.config.k, 8);
}

#[test]
fn no_bootstrap_resolving_refuses_before_any_datagram() {
    for bootstrap in [vec![], vec!["nowhere.invalid:6881".to_owned()]] {
        let mut r = roving(tuned(bootstrap));
        assert_eq!(
            r.rendezvous().expect_err("refused"),
            "no DHT bootstrap node resolved"
        );
    }
}

#[test]
fn no_presence_on_the_commons_refuses() {
    let (_node, tuning) = commons(vec![]);
    let mut r = roving(tuning);
    assert_eq!(
        r.rendezvous().expect_err("refused"),
        "no presence is published under the engine's rendezvous key"
    );
}

#[test]
fn a_presence_sealed_under_another_pairing_refuses() {
    let p = pairing();
    let sealed = crate::rendezvous::item::Presence {
        endpoints: vec!["127.0.0.1:1".parse().expect("addr")],
    }
    .seal(&[7u8; 32])
    .expect("seal");
    let item = engine().sign(p.presence_salt(), 1, sealed).expect("signed");
    let (_node, tuning) = commons(vec![item]);
    let mut r = roving(tuning);
    assert_eq!(
        r.rendezvous().expect_err("refused"),
        "the presence item does not open under this pairing"
    );
}

#[test]
fn a_presence_naming_no_endpoint_refuses() {
    let p = pairing();
    let sealed = crate::rendezvous::item::Presence { endpoints: vec![] }
        .seal(&p.seal_key())
        .expect("seal");
    let item = engine().sign(p.presence_salt(), 1, sealed).expect("signed");
    let (_node, tuning) = commons(vec![item]);
    let mut r = roving(tuning);
    assert_eq!(
        r.rendezvous().expect_err("refused"),
        "the engine's presence names no endpoint"
    );
}

/// The call is written before the punch, sealed so the commons cannot read
/// it, under a sequence that rises on every call — and a punch nobody
/// answers is the window waited out.
#[test]
fn a_call_is_filed_sealed_and_a_punch_nobody_answers_is_refused() {
    let port = dead_port();
    let (node, tuning) = commons(vec![presence(port, 1)]);
    let mut r = roving(tuning);
    let refusal = r.rendezvous().expect_err("nobody there");
    assert_eq!(
        refusal,
        "no SYN crossed toward 1 engine endpoint(s) inside the window"
    );
    let p = pairing();
    let inbox = p.inbox_keypair().expect("keypair").public();
    let held = node.held();
    let call = held
        .iter()
        .find(|i| i.key == inbox && i.salt == p.inbox_salt())
        .expect("the call was filed");
    assert!(call.verify());
    let opened = Call::open(&p.seal_key(), &call.value).expect("opens under the pairing");
    let punch = r.punch.as_ref().expect("bound").port();
    assert!(
        opened
            .endpoints
            .iter()
            .all(|e| e.port() == punch && !e.ip().is_loopback()),
        "{opened:?} names this box at its punch port"
    );
    let first = call.seq;
    r.rendezvous().expect_err("still nobody");
    let again = node
        .held()
        .into_iter()
        .find(|i| i.key == inbox)
        .expect("the call was filed again");
    assert!(again.seq > first, "the sequence rises");
    assert!(again.seq >= r.last_seq);
}

/// A commons that holds a newer call than this box can write refuses the
/// put, and the refusal is the act's.
#[test]
fn a_put_the_commons_refuses_is_the_acts_refusal() {
    let p = pairing();
    let future = p
        .inbox_keypair()
        .expect("keypair")
        .sign(p.inbox_salt(), i64::MAX, vec![])
        .expect("signed");
    let (_node, tuning) = commons(vec![presence(dead_port(), 1), future]);
    let mut r = roving(tuning);
    let refusal = r.rendezvous().expect_err("refused");
    assert!(
        refusal.ends_with("302 sequence number less than current"),
        "{refusal}"
    );
}

#[test]
fn a_nonce_is_fresh_and_the_clock_rises() {
    assert_ne!(nonce().expect("a"), nonce().expect("b"));
    assert!(unix_now() > 1_700_000_000);
}

/// The observed address joins the route-local ones at the punch port, never
/// twice, and never at the port the commons saw.
#[test]
fn an_observed_address_is_listed_once_at_the_punch_port() {
    let local: IpAddr = "192.0.2.5".parse().expect("ip");
    let seen = |s: &str| s.parse::<SocketAddr>().expect("addr");
    let far = seen("203.0.113.7:6881");
    assert_eq!(
        listed(vec![local], &[far, seen("[2001:db8::7]:1")], 9),
        vec![
            SocketAddr::new(local, 9),
            seen("203.0.113.7:9"),
            seen("[2001:db8::7]:9")
        ]
    );
    assert_eq!(
        listed(vec![local], &[seen("192.0.2.5:6881")], 9),
        vec![SocketAddr::new(local, 9)],
        "an observed address that is already local is not a second entry"
    );
    assert_eq!(listed(vec![], &[far], 9), vec![seen("203.0.113.7:9")]);
    assert_eq!(listed(vec![local], &[], 9), vec![SocketAddr::new(local, 9)]);
}

/// The call a foot behind a NAT files carries where the commons saw it,
/// through the seal and back; a walk that heard no claim adds nothing.
#[test]
fn the_filed_call_carries_the_observed_address_when_the_commons_named_one() {
    let us: SocketAddr = "203.0.113.7:6881".parse().expect("addr");
    for (mood, expect) in [(Mood::Claim(us), true), (Mood::Answer, false)] {
        let (node, tuning) = commons_as(mood, vec![presence(dead_port(), 1)]);
        let mut r = roving(tuning);
        r.rendezvous().expect_err("nobody there");
        let p = pairing();
        let inbox = p.inbox_keypair().expect("keypair").public();
        let filed = node
            .held()
            .into_iter()
            .find(|i| i.key == inbox)
            .expect("the call was filed");
        let opened = Call::open(&p.seal_key(), &filed.value).expect("opens");
        let punch = r.punch.as_ref().expect("bound").port();
        let at = SocketAddr::new(us.ip(), punch);
        assert_eq!(opened.endpoints.contains(&at), expect, "{opened:?}");
        assert!(opened.endpoints.iter().all(|e| e.port() == punch));
    }
}

/// The third rung: the re-call, and the cache it reads and clears.
mod recall;
/// What the act says, arm by arm, into a captured sink.
mod said;