Specify and plan M3b: the runner and the tools
A draft spec for the owner's review and 13 offline tasks with their given tests: shared tool arguments and host rules in proto, the sealed fetch target (M3a finding 14), the toolkit tools and SOCKS5 egress proxy, and brokerd's [runner], podman argument lists, runtime and proxy lifecycle. Each task's tests were run against a reference at that task's end state (560 to 638 tests, clippy clean); the reference is not in the repository. Adds the runner-unavailable runbook entry and tip T23 (ETXTBSY in script tests). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
//! Running the `toolkit` binary as `brokerd` does: arguments on standard input. Do not edit.
|
||||
|
||||
#![allow(dead_code)] // each test file uses its own part
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
static NEXT: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
/// A temporary directory, removed when dropped.
|
||||
pub struct TempDir(pub PathBuf);
|
||||
|
||||
impl TempDir {
|
||||
pub fn new(tag: &str) -> TempDir {
|
||||
let n = NEXT.fetch_add(1, Ordering::SeqCst);
|
||||
let path = std::env::temp_dir().join(format!("tk-{tag}-{}-{n}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&path);
|
||||
std::fs::create_dir_all(&path).unwrap();
|
||||
TempDir(path)
|
||||
}
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.0
|
||||
}
|
||||
/// The path of `name` inside, as a string (the tools take strings).
|
||||
pub fn at(&self, name: &str) -> String {
|
||||
self.0.join(name).to_str().unwrap().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempDir {
|
||||
fn drop(&mut self) {
|
||||
let _ = std::fs::remove_dir_all(&self.0);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Ran {
|
||||
pub code: i32,
|
||||
pub stdout: String,
|
||||
pub stderr: String,
|
||||
}
|
||||
|
||||
/// Run `toolkit <args…>` with `input` on standard input.
|
||||
pub fn toolkit(args: &[&str], input: &[u8]) -> Ran {
|
||||
let mut child = Command::new(env!("CARGO_BIN_EXE_toolkit"))
|
||||
.args(args)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
// A broken pipe here only means toolkit stopped reading, which some tests expect.
|
||||
let _ = stdin.write_all(input);
|
||||
drop(stdin);
|
||||
let out = child.wait_with_output().unwrap();
|
||||
Ran {
|
||||
code: out.status.code().unwrap_or(-1),
|
||||
stdout: String::from_utf8(out.stdout).unwrap(),
|
||||
stderr: String::from_utf8_lossy(&out.stderr).into_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The JSON for one argument struct.
|
||||
pub fn json<T: serde::Serialize>(value: &T) -> Vec<u8> {
|
||||
serde_json::to_vec(value).unwrap()
|
||||
}
|
||||
Reference in New Issue
Block a user