Add actor-owned contextual process provisioning, descriptor bootstrap, scoped namespace operations, Python bindings, Myelin orchestration, and adversarial end-to-end coverage. Remove the superseded job runner, pipeline APIs, images, entrypoints, and specifications.
154 lines
5.1 KiB
Rust
Executable file
154 lines
5.1 KiB
Rust
Executable file
#![cfg(target_os = "linux")]
|
|
|
|
use std::ffi::CString;
|
|
use std::io;
|
|
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd};
|
|
|
|
use data_plane::bootstrap::channel::{
|
|
AttachmentResult, BootstrapChannelError, GuestBootstrap, SessionBootstrap, bootstrap_channel,
|
|
};
|
|
use data_plane::protocol::SessionCapability;
|
|
use swactor::actor::ActorAddress;
|
|
|
|
fn arena_fd() -> OwnedFd {
|
|
let name = CString::new("swactor-bootstrap-test").expect("memfd name");
|
|
// SAFETY: name is NUL-terminated and memfd_create returns a fresh descriptor.
|
|
let fd = unsafe { libc::memfd_create(name.as_ptr(), libc::MFD_CLOEXEC) };
|
|
assert!(fd >= 0, "memfd_create: {}", io::Error::last_os_error());
|
|
// SAFETY: fd is fresh and uniquely owned.
|
|
let fd = unsafe { OwnedFd::from_raw_fd(fd) };
|
|
let bytes = b"arena";
|
|
// SAFETY: fd is writable and bytes is a valid input buffer.
|
|
assert_eq!(
|
|
unsafe { libc::pwrite(fd.as_raw_fd(), bytes.as_ptr().cast(), bytes.len(), 0) },
|
|
bytes.len() as isize
|
|
);
|
|
fd
|
|
}
|
|
|
|
fn material() -> SessionBootstrap {
|
|
SessionBootstrap {
|
|
host_session: ActorAddress([0x11; 32]),
|
|
session_capability: SessionCapability::new([0x22; 32]),
|
|
routing: br#"{"endpoint":"host"}"#.to_vec(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn one_use_claim_transfers_arena_and_reports_attachment() {
|
|
let (mut host, child) = bootstrap_channel().expect("bootstrap channel");
|
|
let arena = arena_fd();
|
|
let expected = material();
|
|
let pending = GuestBootstrap::begin_claim(child).expect("begin guest claim");
|
|
let mut attachment = host
|
|
.accept_claim(&expected, arena.as_raw_fd())
|
|
.expect("accept claim");
|
|
let guest = pending.receive().expect("guest claim");
|
|
assert_eq!(guest.material, expected);
|
|
// SAFETY: F_GETFD only reads flags for the received live descriptor.
|
|
let flags = unsafe { libc::fcntl(guest.arena_fd.as_raw_fd(), libc::F_GETFD) };
|
|
assert_ne!(flags & libc::FD_CLOEXEC, 0);
|
|
let mut bytes = [0_u8; 5];
|
|
// SAFETY: descriptor is readable and bytes is writable.
|
|
assert_eq!(
|
|
unsafe {
|
|
libc::pread(
|
|
guest.arena_fd.as_raw_fd(),
|
|
bytes.as_mut_ptr().cast(),
|
|
bytes.len(),
|
|
0,
|
|
)
|
|
},
|
|
bytes.len() as isize
|
|
);
|
|
assert_eq!(&bytes, b"arena");
|
|
guest.attachment_succeeded().expect("notify attachment");
|
|
assert_eq!(
|
|
attachment.receive_result().expect("attachment result"),
|
|
AttachmentResult::Succeeded
|
|
);
|
|
let duplicate = host.accept_claim(&expected, arena.as_raw_fd());
|
|
assert!(matches!(
|
|
duplicate,
|
|
Err(BootstrapChannelError::AlreadyClaimed)
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn rejected_claim_is_reported_without_descriptor() {
|
|
let (mut host, child) = bootstrap_channel().expect("bootstrap channel");
|
|
let pending = GuestBootstrap::begin_claim(child).expect("begin guest claim");
|
|
host.reject_claim("session revoked")
|
|
.expect("host rejection");
|
|
let result = pending.receive();
|
|
assert!(matches!(
|
|
result,
|
|
Err(BootstrapChannelError::Rejected(reason)) if reason == "session revoked"
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn incompatible_and_truncated_claims_are_rejected() {
|
|
for packet in [
|
|
vec![b'S', b'W', b'C', b'L', 99, 0, 0, 0, 0, 0, 0, 0],
|
|
vec![b'S', b'W', b'C'],
|
|
] {
|
|
let (mut host, child) = bootstrap_channel().expect("bootstrap channel");
|
|
// SAFETY: child is connected and packet is a valid readable buffer.
|
|
assert_eq!(
|
|
unsafe {
|
|
libc::send(
|
|
child.as_raw_fd(),
|
|
packet.as_ptr().cast(),
|
|
packet.len(),
|
|
libc::MSG_NOSIGNAL,
|
|
)
|
|
},
|
|
packet.len() as isize
|
|
);
|
|
let result = host.accept_claim(&material(), arena_fd().as_raw_fd());
|
|
if packet.len() == 12 {
|
|
assert!(matches!(
|
|
result,
|
|
Err(BootstrapChannelError::UnsupportedVersion {
|
|
found: 99,
|
|
supported: 1
|
|
})
|
|
));
|
|
} else {
|
|
assert!(matches!(
|
|
result,
|
|
Err(BootstrapChannelError::Malformed("short frame prefix"))
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn peer_closure_resolves_blocked_claim_as_closed() {
|
|
let (mut host, child) = bootstrap_channel().expect("bootstrap channel");
|
|
drop(child);
|
|
assert!(matches!(
|
|
host.accept_claim(&material(), arena_fd().as_raw_fd()),
|
|
Err(BootstrapChannelError::ChannelClosed)
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn guest_failure_reason_reaches_host() {
|
|
let (mut host, child) = bootstrap_channel().expect("bootstrap channel");
|
|
let arena = arena_fd();
|
|
let pending = GuestBootstrap::begin_claim(child).expect("begin guest claim");
|
|
let mut attachment = host
|
|
.accept_claim(&material(), arena.as_raw_fd())
|
|
.expect("accept claim");
|
|
pending
|
|
.receive()
|
|
.expect("guest claim")
|
|
.attachment_failed("route rejected")
|
|
.expect("notify failure");
|
|
assert_eq!(
|
|
attachment.receive_result().expect("attachment result"),
|
|
AttachmentResult::Failed("route rejected".to_owned())
|
|
);
|
|
}
|