swactor/crates/data-plane/tests/bootstrap_guarantees.rs
Zachery Aaron Shores-Chmielewski 77f3cdc660 feat(data-plane): add exec bootstrap ABI for job processes
Define the spawn-time handoff a job process consumes before any
application code runs: two inherited descriptors named by
SWACTOR_ARENA_FD and SWACTOR_WAKE_FD, and a fixed 48-byte little-endian
header at arena offset 0 naming one control-ring region.

- Canonical header layout, shared parser, and a host writer that leases
  the header region and control ring disjointly under the arena's own
  placement law, zeroes the ring, stamps its generation, and returns the
  handoff (env map, inheritable arena and wake descriptors, host wake
  eventfd) only after every write completes.
- Python binding gains swactor.run(main): map the arena read-only, take
  ground truth from fstat, validate through the shared parser, arm
  FD_CLOEXEC on the wake descriptor, close the arena descriptor after
  mapping, and drive main on asyncio with Context.data carrying the
  resolved state. Fail-fast BootstrapError before main on any defect.
- Rewrite jobs/tiny_linear_inference.py against the approved path API and
  record the slice, invariants, and remaining bridge work in the handoff
  doc.

Verified with 12 new data-plane bootstrap guarantee tests (parser defect
table, fuzzed pages, writer round-trip), 29 binding tests across
in-process and exec boundaries, and full data-plane and iroh-driver
suites with no regressions.
2026-08-20 20:43:44 +04:00

352 lines
11 KiB
Rust

//! Bootstrap ABI guarantees (behavior invariants, not implementation shape).
//!
//! Defends:
//! - B3/B4: the parser rejects every malformed page with a typed error and
//! never trusts page claims over ground truth.
//! - B8: the writer emits exactly the two environment ABI names.
//! - B10: after `write_bootstrap` returns, the header is readable from the
//! arena and parseable, the ring region is zeroed with its generation
//! stamped, and header/ring leases are disjoint by arena placement law.
#![cfg(target_os = "linux")]
use data_plane::arena::{ArenaConfig, ArenaManager, NodeId};
use data_plane::bootstrap::{
self, parse_bootstrap, BootstrapError, ControlRingLayout, BOOTSTRAP_MAGIC, BOOTSTRAP_VERSION,
ENV_ARENA_FD, ENV_WAKE_FD, HEADER_END_OFFSET, HEADER_LEN,
};
fn arena() -> ArenaManager {
ArenaManager::boot(ArenaConfig {
node_id: NodeId(10),
reservation_ceiling: 1 << 20,
base_alignment: 64,
})
.expect("test arena must boot")
}
fn spec() -> bootstrap::ControlRingSpec {
bootstrap::ControlRingSpec {
data_bytes: 4096,
alignment: 64,
}
}
fn valid_header(arena_size: u64) -> data_plane::bootstrap::BootstrapHeader {
data_plane::bootstrap::BootstrapHeader {
arena_size,
control_ring: ControlRingLayout {
offset: 4096,
capacity: 8192,
generation: 1,
},
}
}
// ─── Parser ──────────────────────────────────────────────────────────────────
#[test]
fn parser_round_trips_encoded_header() {
let page = valid_header(1 << 20).encode();
let resolved = parse_bootstrap(&page, 1 << 20).expect("valid header must parse");
assert_eq!(resolved.arena_size, 1 << 20);
assert_eq!(resolved.control_ring, valid_header(1 << 20).control_ring);
}
#[test]
fn parser_rejects_short_pages() {
let error = parse_bootstrap(&valid_header(1 << 20).encode()[..HEADER_LEN - 1], 1 << 20)
.expect_err("truncated page must fail");
assert_eq!(
error,
BootstrapError::Truncated {
available: HEADER_LEN - 1
}
);
}
#[test]
fn parser_rejects_bad_magic() {
let mut page = valid_header(1 << 20).encode();
page[0] ^= 0xFF;
let error = parse_bootstrap(&page, 1 << 20).expect_err("bad magic must fail");
assert_eq!(
error,
BootstrapError::BadMagic {
found: BOOTSTRAP_MAGIC ^ 0xFF
}
);
}
#[test]
fn parser_rejects_unsupported_versions_without_guessing() {
for version in [0_u16, 2, 3, u16::MAX] {
let mut page = valid_header(1 << 20).encode();
page[4..6].copy_from_slice(&version.to_le_bytes());
let error = parse_bootstrap(&page, 1 << 20)
.expect_err("unsupported version must not parse");
assert_eq!(
error,
BootstrapError::UnsupportedVersion {
found: version,
supported: BOOTSTRAP_VERSION
}
);
}
}
#[test]
fn parser_rejects_nonzero_reserved_bytes() {
for (at, byte) in [(6_usize, 7_u8), (40, 1), (47, 0xFF)] {
let mut page = valid_header(1 << 20).encode();
page[at] = byte;
let error = parse_bootstrap(&page, 1 << 20)
.expect_err("nonzero reserved bytes must not parse");
assert_eq!(
error,
BootstrapError::ReservedBytesNotZero {
at: if at < 8 { 6 } else { 40 }
}
);
}
}
#[test]
fn parser_rejects_lying_arena_size() {
let page = valid_header(1 << 20).encode();
let error =
parse_bootstrap(&page, (1 << 20) + 1).expect_err("size disagreement must fail");
assert_eq!(
error,
BootstrapError::ArenaSizeMismatch {
header: 1 << 20,
backing: (1 << 20) + 1
}
);
}
#[test]
fn parser_rejects_ring_defects() {
let base = valid_header(1 << 20);
let cases: Vec<(ControlRingLayout, BootstrapError)> = vec![
(
ControlRingLayout {
offset: HEADER_END_OFFSET - 8,
..base.control_ring
},
BootstrapError::RingOverlapsHeader {
offset: HEADER_END_OFFSET - 8,
},
),
(
ControlRingLayout {
offset: 1 << 20,
capacity: 1,
..base.control_ring
},
BootstrapError::RingOutOfBounds {
offset: 1 << 20,
capacity: 1,
arena_size: 1 << 20,
},
),
(
ControlRingLayout {
capacity: 0,
..base.control_ring
},
BootstrapError::ZeroRingCapacity,
),
(
ControlRingLayout {
generation: 0,
..base.control_ring
},
BootstrapError::ZeroRingGeneration,
),
];
for (ring, expected) in cases {
let page = data_plane::bootstrap::BootstrapHeader {
control_ring: ring,
..base
}
.encode();
let error = parse_bootstrap(&page, 1 << 20)
.expect_err("defective ring layout must not parse");
assert_eq!(error, expected);
}
}
#[test]
fn parser_survives_offset_capacity_wraparound() {
let page = data_plane::bootstrap::BootstrapHeader {
control_ring: ControlRingLayout {
offset: u64::MAX - 8,
capacity: 16,
generation: 1,
},
arena_size: 1 << 20,
}
.encode();
let error = parse_bootstrap(&page, 1 << 20).expect_err("wrapping ring must fail");
assert_eq!(
error,
BootstrapError::RingOutOfBounds {
offset: u64::MAX - 8,
capacity: 16,
arena_size: 1 << 20
}
);
}
/// Deterministic xorshift fuzz: arbitrary page bytes never panic, and a
/// successful parse implies every invariant (B4).
#[test]
fn parser_never_panics_on_arbitrary_pages() {
let mut state = 0x9E3779B97F4A7C15_u64;
let mut next = move || {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
state
};
for _ in 0..512 {
let mut page = [0_u8; HEADER_LEN];
for chunk in page.chunks_mut(8) {
chunk.copy_from_slice(&next().to_le_bytes()[..chunk.len()]);
}
match parse_bootstrap(&page, 1 << 20) {
Ok(resolved) => {
let ring = resolved.control_ring;
assert!(ring.capacity > 0);
assert!(ring.generation > 0);
assert!(ring.offset >= HEADER_END_OFFSET);
assert!(ring
.offset
.checked_add(ring.capacity)
.is_some_and(|end| end <= resolved.arena_size));
}
Err(_) => {}
}
}
}
// ─── Writer ──────────────────────────────────────────────────────────────────
#[test]
fn writer_produces_parseable_header_and_disjoint_ring() {
let mut arena = arena();
let handoff = bootstrap::write_bootstrap(&mut arena, spec()).expect("bootstrap must write");
let page = arena.read_arena(0, HEADER_LEN).expect("read header");
assert_eq!(&page[0..4], b"SWBS", "magic bytes are frozen ABI");
let resolved =
parse_bootstrap(&page, arena.arena_len()).expect("written header must self-parse");
assert_eq!(resolved.arena_size, arena.arena_len());
assert_eq!(resolved.control_ring, handoff.control_ring);
assert!(
resolved.control_ring.offset >= HEADER_END_OFFSET,
"control ring must not overlap the header region"
);
assert_eq!(
resolved.control_ring.generation,
bootstrap::CONTROL_RING_GENERATION
);
}
#[test]
fn writer_leaves_ring_zeroed_with_generation_stamped() {
let mut arena = arena();
let handoff = bootstrap::write_bootstrap(&mut arena, spec()).expect("bootstrap must write");
let ring = handoff.control_ring;
let bytes = arena
.read_arena(ring.offset, ring.capacity as usize)
.expect("read ring region");
assert_eq!(
&bytes[0..8],
&bootstrap::CONTROL_RING_GENERATION.to_le_bytes(),
"generation is stamped at ring start"
);
assert!(
bytes[8..].iter().all(|&b| b == 0),
"rest of the fresh ring must be zero"
);
}
#[test]
fn writer_emits_exactly_the_environment_abi() {
use std::os::fd::AsRawFd;
let mut arena = arena();
let handoff = bootstrap::write_bootstrap(&mut arena, spec()).expect("bootstrap must write");
let env = handoff.env;
assert_eq!(
env.keys().collect::<Vec<_>>(),
vec![ENV_ARENA_FD, ENV_WAKE_FD],
"B8: the two names are the whole env contract"
);
assert_eq!(
env[ENV_ARENA_FD],
handoff.arena_fd.as_raw_fd().to_string()
);
assert_eq!(env[ENV_WAKE_FD], handoff.wake_fd.as_raw_fd().to_string());
}
#[test]
fn writer_handoff_fds_are_distinct_and_open() {
use std::fs::File;
use std::io::{Read, Write};
use std::os::fd::AsRawFd;
let mut arena = arena();
let handoff = bootstrap::write_bootstrap(&mut arena, spec()).expect("bootstrap must write");
let arena_fd = handoff.arena_fd.as_raw_fd();
let wake_fd = handoff.wake_fd.as_raw_fd();
let host_wake_fd = handoff.host_wake_fd.as_raw_fd();
assert_ne!(arena_fd, wake_fd);
assert_ne!(arena_fd, host_wake_fd);
assert_ne!(wake_fd, host_wake_fd);
// The wake descriptors must behave like eventfds: write 1, read counter.
let mut wake = File::from(handoff.wake_fd);
wake.write_all(&1_u64.to_le_bytes())
.expect("eventfd write");
let mut counter = [0_u8; 8];
wake.read_exact(&mut counter).expect("eventfd read");
assert_eq!(counter, 1_u64.to_le_bytes());
}
#[test]
fn writer_rejects_invalid_specs_and_oversized_rings() {
let mut arena = arena();
for bad in [
bootstrap::ControlRingSpec {
data_bytes: 0,
alignment: 64,
},
bootstrap::ControlRingSpec {
data_bytes: 4096,
alignment: 0,
},
] {
let error = bootstrap::write_bootstrap(&mut arena, bad)
.expect_err("invalid spec must fail before leasing");
assert!(matches!(
error,
bootstrap::BootstrapWriteError::InvalidControlRingSpec
));
}
let oversized = bootstrap::ControlRingSpec {
data_bytes: 1 << 21,
alignment: 64,
};
let error = bootstrap::write_bootstrap(&mut arena, oversized)
.expect_err("ring larger than the arena must fail");
assert!(matches!(
error,
bootstrap::BootstrapWriteError::ControlRingLeaseRejected(_)
));
}