lease v2: byte goldens, hold-loop and lease-helper tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-31 05:27:38 +01:00
commit 9f10887169
3 changed files with 207 additions and 0 deletions

View file

@ -0,0 +1,16 @@
# lease_v2 fixtures
The exact bytes of the claude lease protocol v2: each file is one whole frame (a u32
big-endian length, then the named-MessagePack map `{kind, value}`).
- `request.bin`: `claude_lease_request`.
- `refusal_unknown_caller.bin`, `refusal_expired.bin`, `refusal_busy.bin`,
`refusal_provider_rejected.bin`: `claude_lease_refusal`; `kind` is the variant name as a
PascalCase string.
- `grant.bin`: `claude_lease_grant` with `lease_id` and `plan_quota` carrying `five_hour` and
`seven_day` windows (utilization_permille, resets_at_unix_ms, status, observed_at_unix_ms).
On the wire the grant travels with one SCM_RIGHTS fd; the file holds the frame only.
Huginn's lease client vendors these files from this repository and tests against the same
bytes. Generator: `tests/lease_wire_golden.rs`; run it with `LEASE_V2_REGENERATE=1`, then
review the diff: a changed byte is a wire change.

View file

@ -543,3 +543,99 @@ fn connections_past_the_limit_are_dropped_and_finished_ones_free_their_place() {
drop(first);
assert!(granted_ok(&ask_until_granted(&harness, 2)));
}
#[test]
fn a_lease_survives_many_polls_while_its_holder_and_invocation_stay() {
let harness = start(setup());
let mut first = ask(&harness, 60_000);
assert!(granted_ok(&first));
// Three polls later the lease still holds: a second invocation is Busy.
std::thread::sleep(Duration::from_millis(1_700));
harness.enter(2);
let second = ask(&harness, 60_000);
assert_eq!(refusal_of(&second), Some(LeaseRefusalKind::Busy));
// The holder talking does not end it either.
first._stream.write_all(b"x").unwrap();
std::thread::sleep(Duration::from_millis(1_200));
harness.enter(3);
assert_eq!(
refusal_of(&ask(&harness, 60_000)),
Some(LeaseRefusalKind::Busy)
);
}
#[test]
fn a_lease_ends_when_the_unit_runs_a_different_invocation() {
let harness = start(setup());
let first = ask(&harness, 60_000);
assert!(granted_ok(&first));
// The same unit, a new invocation: the one that leased is over.
harness.enter(2);
std::thread::sleep(Duration::from_millis(1_200));
assert!(granted_ok(&ask(&harness, 60_000)));
drop(first);
}
#[test]
fn a_lease_asks_the_system_about_its_holders_process_for_its_own_unit() {
let harness = start(setup());
let first = ask(&harness, 60_000);
assert!(granted_ok(&first));
std::thread::sleep(Duration::from_millis(1_200));
let asked = harness.units.as_ref().unwrap().asked_about.lock().unwrap().clone();
assert!(asked.len() >= 3, "the hold polled: {asked:?}");
assert!(asked.iter().all(|(_, unit)| unit == UNIT));
}
#[test]
fn an_account_resolves_to_its_uid_and_a_missing_one_to_none() {
assert_eq!(claude_connector::user_uid("root"), Some(0));
assert_eq!(claude_connector::user_uid("no-such-account-4c1f9a"), None);
assert_eq!(claude_connector::user_uid("bad\0name"), None);
}
#[test]
fn a_token_up_to_one_atomic_pipe_write_is_lent_and_a_longer_one_is_not() {
let exact: &'static str = Box::leak("a".repeat(4096).into_boxed_str());
let harness = start(Setup {
token: Some(exact),
..setup()
});
let mut answer = ask(&harness, 60_000);
assert!(granted_ok(&answer));
let mut read = Vec::new();
File::from(answer.fds.remove(0))
.read_to_end(&mut read)
.unwrap();
assert_eq!(read.len(), 4096);
let long: &'static str = Box::leak("a".repeat(4097).into_boxed_str());
let harness = start(Setup {
token: Some(long),
..setup()
});
let refused = ask(&harness, 60_000);
assert!(refused.message.is_none() && refused.fds.is_empty());
}
#[test]
fn a_request_trickled_past_the_socket_timeout_is_dropped_without_a_lease() {
let harness = start(setup());
let mut stream = UnixStream::connect(&harness.socket).unwrap();
stream
.set_read_timeout(Some(Duration::from_secs(8)))
.unwrap();
stream.write_all(&[0, 0]).unwrap();
let started = Instant::now();
let mut byte = [0_u8; 1];
let outcome = stream.read(&mut byte);
// The listener gave up at its own two-second bound and closed the
// connection: end of file or a reset, never our own read timing out.
assert!(
matches!(outcome, Ok(0))
|| outcome.as_ref().is_err_and(|e| e.kind() == std::io::ErrorKind::ConnectionReset),
"{outcome:?}"
);
assert!(started.elapsed() < Duration::from_secs(6));
assert_eq!(harness.tokens.reads.load(Ordering::SeqCst), 0);
}

View file

@ -0,0 +1,95 @@
//! Pins the bytes of the lease protocol v2: every frame a lease client sends
//! or receives. The fixtures in `fixtures/lease_v2` are the contract's bytes
//! for other implementations (Huginn's lease client vendors them and tests
//! against the same bytes); the types in `claude_connector::lease` own the
//! shape. Regenerate with `LEASE_V2_REGENERATE=1`, then review the diff.
#![cfg(target_os = "linux")]
use std::path::{Path, PathBuf};
use claude_connector::{
LeaseGranted, LeaseMessage, LeaseRefusalKind, LeaseRefused, LeaseRequest, decode_frame,
encode_frame,
};
use model_connector::PlanQuota;
const REGENERATE: &str = "LEASE_V2_REGENERATE";
fn fixtures() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/lease_v2")
}
fn assert_frame(name: &str, message: &LeaseMessage) {
let path = fixtures().join(name);
let bytes = encode_frame(message);
if std::env::var_os(REGENERATE).is_some() {
std::fs::create_dir_all(fixtures()).unwrap();
std::fs::write(&path, &bytes).unwrap();
}
let committed = std::fs::read(&path).unwrap_or_else(|_| panic!("{name} is missing"));
assert_eq!(committed, bytes, "{name} is not what the types encode");
assert_eq!(decode_frame(&committed).as_ref(), Some(message), "{name}");
}
#[test]
fn the_request_frame_is_pinned() {
assert_frame(
"request.bin",
&LeaseMessage::ClaudeLeaseRequest(LeaseRequest {
expires_at_unix_ms: 1_793_307_000_000,
}),
);
}
#[test]
fn every_refusal_frame_is_pinned_with_its_kind_as_a_pascal_case_string() {
let kinds = [
("refusal_unknown_caller.bin", LeaseRefusalKind::UnknownCaller, "UnknownCaller"),
("refusal_expired.bin", LeaseRefusalKind::Expired, "Expired"),
("refusal_busy.bin", LeaseRefusalKind::Busy, "Busy"),
(
"refusal_provider_rejected.bin",
LeaseRefusalKind::ProviderRejected,
"ProviderRejected",
),
];
for (name, kind, spelled) in kinds {
let message = LeaseMessage::ClaudeLeaseRefusal(LeaseRefused {
kind,
detail: "the reason".to_string(),
});
assert_frame(name, &message);
// The kind travels as the variant's name, which other runtimes read.
let bytes = encode_frame(&message);
let value: rmpv::Value = rmp_serde::from_slice(&bytes[4..]).unwrap();
let rmpv::Value::Map(outer) = value else {
panic!("a frame is a map")
};
let rmpv::Value::Map(inner) = &outer[1].1 else {
panic!("the value is a map")
};
assert_eq!(inner[0].0.as_str(), Some("kind"));
assert_eq!(inner[0].1.as_str(), Some(spelled));
}
}
#[test]
fn a_grant_with_both_usage_windows_is_pinned() {
let window = |name: &str, permille, status: &str, resets| PlanQuota {
window: name.to_string(),
utilization_permille: Some(permille),
resets_at_unix_ms: resets,
status: status.to_string(),
observed_at_unix_ms: 1_793_300_000_000,
};
assert_frame(
"grant.bin",
&LeaseMessage::ClaudeLeaseGrant(LeaseGranted {
lease_id: "lease:0123456789abcdef0123456789abcdef".to_string(),
plan_quota: vec![
window("five_hour", 420, "allowed", 1_793_307_000_000),
window("seven_day", 999, "allowed_warning", 1_793_800_000_000),
],
}),
);
}