liminal-cli 0.3.0

The liminal command: serve the network, maintain its stores, or serve its discovery MCP over stdio
Documentation
//! A worker's refusal crosses the wire and the MCP result in both eras with
//! its words verbatim (ACCESS-008), on the binary this crate builds.

use super::super::*;

const WORDS: &str = " busy\nworker-private-words é ";

/// The fixture worker on its own thread: refuses `n` pushes with `WORDS`.
fn refusing_worker(
    address: SocketAddr,
    pushes: usize,
) -> Result<(PushClient, std::thread::JoinHandle<usize>), Box<dyn Error>> {
    let worker = PushClient::connect_with_registration_and_auth(
        &address.to_string(),
        registration(),
        BEARER.as_bytes(),
    )?;
    let receiver = worker.receiver_handle()?;
    let writer = worker.writer_handle();
    let serving = std::thread::spawn(move || {
        let mut refused = 0;
        for _ in 0..pushes {
            let Ok(PushReceiveOutcome::Frame(push)) = receiver.recv() else {
                break;
            };
            if writer.refuse(push.correlation_id(), "busy", WORDS).is_err() {
                break;
            }
            refused += 1;
        }
        refused
    });
    Ok((worker, serving))
}

fn refused_call(host: &mut Host) -> Result<(), Box<dyn Error>> {
    let answer = host.tool(
        "call",
        &json!({ "subject": SUBJECT, "input": { "private": "request" } }),
    )?;
    assert_eq!(answer["isError"], true, "{answer}");
    if host.modern {
        assert_eq!(answer["resultType"], "complete", "{answer}");
    }
    assert_eq!(answer["structuredContent"]["error"], WORDS, "{answer}");
    assert_eq!(answer["content"][0]["text"], WORDS, "{answer}");
    Ok(())
}

#[test]
fn worker_refusal_ticket_call_is_error_with_verbatim_words_in_both_eras()
-> Result<(), Box<dyn Error>> {
    let persistence = test_persistence::directory()?;
    let server = RunningServer::start(persistence.path())?;
    let (worker, serving) = refusing_worker(server.address, 2)?;
    for modern in [false, true] {
        let dir = tempfile::tempdir()?;
        let ticket = Ticket::start(dir.path(), server.address, 5_000)?;
        let mut host = Host::open(ticket, modern)?;
        refused_call(&mut host)?;
        let (stderr, code) = host.ticket.close()?;
        assert_eq!(code, 0, "{stderr}");
        assert!(stderr.is_empty(), "{stderr}");
    }
    drop(worker);
    assert_eq!(serving.join().map_err(|_| "fixture worker panicked")?, 2);
    Ok(())
}