Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m34s
Native code generation / deterministic (push) Has been cancelled
Concurrency and resource soak audit / soak (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
performance evidence / audit (push) Has been cancelled
First release candidate / non-fuzz-release-gate (push) Has been cancelled
Release platform and feature matrix / audit (push) Has been cancelled
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Native release artifact audit / audit (push) Has been cancelled
Imaging and meshing gate / native (push) Failing after 53s
JPEG 2000 feature / linux (push) Successful in 2m49s
Native Rust workspace compile / compile (push) Failing after 59s
Skia feature / linux (push) Has been cancelled
180 lines
5.5 KiB
Rust
180 lines
5.5 KiB
Rust
use serde_json::Value;
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::{Command, Output, Stdio};
|
|
use std::sync::atomic::{AtomicU64, Ordering};
|
|
|
|
const EXIT_USAGE: i32 = 2;
|
|
const EXIT_INPUT: i32 = 3;
|
|
static TEMP_ID: AtomicU64 = AtomicU64::new(0);
|
|
|
|
struct TestDir(PathBuf);
|
|
|
|
impl TestDir {
|
|
fn new() -> Self {
|
|
let id = TEMP_ID.fetch_add(1, Ordering::Relaxed);
|
|
let path = std::env::temp_dir().join(format!(
|
|
"metacrate-live-grid-smoke-{}-{id}",
|
|
std::process::id()
|
|
));
|
|
fs::create_dir(&path).expect("create smoke test directory");
|
|
Self(path)
|
|
}
|
|
|
|
fn path(&self, name: &str) -> PathBuf {
|
|
self.0.join(name)
|
|
}
|
|
}
|
|
|
|
impl Drop for TestDir {
|
|
fn drop(&mut self) {
|
|
let _ = fs::remove_dir_all(&self.0);
|
|
}
|
|
}
|
|
|
|
fn text(path: &Path) -> &str {
|
|
path.to_str().expect("UTF-8 test path")
|
|
}
|
|
|
|
fn run(args: &[&str]) -> Output {
|
|
Command::new(env!("CARGO_BIN_EXE_live-grid-smoke"))
|
|
.args(args)
|
|
.env_remove("GRID_USER")
|
|
.env_remove("GRID_PASSWORD")
|
|
.env_remove("GRID_LOGIN_URL")
|
|
.stdin(Stdio::null())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.output()
|
|
.expect("run live-grid-smoke")
|
|
}
|
|
|
|
#[test]
|
|
fn help_documents_credentials_side_effect_gates_and_unsupported_dangerous_actions() {
|
|
let output = run(&["--help"]);
|
|
assert!(output.status.success());
|
|
let help = String::from_utf8(output.stdout).unwrap();
|
|
for marker in [
|
|
"GRID_USER",
|
|
"workspace .env",
|
|
"OpenSim/compatible-grid LLSD login endpoint",
|
|
"--fake",
|
|
"--audit-only",
|
|
"--evidence",
|
|
"--allow-live-login",
|
|
"--allow-public-chat",
|
|
"--allow-agent-movement",
|
|
"--allow-reversible-inventory",
|
|
"never spends L$",
|
|
"permanently deletes",
|
|
"targets another user",
|
|
] {
|
|
assert!(help.contains(marker), "help omitted {marker}:\n{help}");
|
|
}
|
|
assert_eq!(run(&[]).status.code(), Some(EXIT_USAGE));
|
|
}
|
|
|
|
#[test]
|
|
fn fake_smoke_records_every_sanitized_stage_without_skips_or_credentials() {
|
|
let directory = TestDir::new();
|
|
let evidence = directory.path("evidence.jsonl");
|
|
let output = run(&["--fake", "--evidence", text(&evidence)]);
|
|
let stdout = String::from_utf8(output.stdout).unwrap();
|
|
let stderr = String::from_utf8(output.stderr).unwrap();
|
|
assert!(
|
|
output.status.success(),
|
|
"stdout:\n{stdout}\nstderr:\n{stderr}"
|
|
);
|
|
assert!(stderr.is_empty(), "{stderr}");
|
|
let contents = fs::read_to_string(evidence).unwrap();
|
|
assert!(!contents.contains("://"));
|
|
assert!(!contents.to_ascii_lowercase().contains("password"));
|
|
assert!(!contents.to_ascii_lowercase().contains("token"));
|
|
let records: Vec<Value> = contents
|
|
.lines()
|
|
.map(|line| serde_json::from_str(line).unwrap())
|
|
.collect();
|
|
assert_eq!(records.len(), 9);
|
|
let stages: Vec<_> = records
|
|
.iter()
|
|
.map(|record| record["stage"].as_str().unwrap())
|
|
.collect();
|
|
assert_eq!(
|
|
stages,
|
|
[
|
|
"completeness",
|
|
"login",
|
|
"capabilities-simulator",
|
|
"im-chat",
|
|
"movement-teleport",
|
|
"inventory-folder",
|
|
"object-properties",
|
|
"asset-texture",
|
|
"logout",
|
|
]
|
|
);
|
|
assert!(records.iter().all(|record| record["status"] == "ok"));
|
|
assert!(records.iter().all(|record| record["schema"] == 1));
|
|
assert!(records.iter().all(|record| record["mode"] == "fake"));
|
|
assert!(
|
|
records
|
|
.iter()
|
|
.all(|record| record["recorded_unix_seconds"].as_u64().is_some())
|
|
);
|
|
assert!(
|
|
records
|
|
.iter()
|
|
.all(|record| record["program_version"].as_str().is_some())
|
|
);
|
|
assert!(
|
|
records
|
|
.iter()
|
|
.all(|record| record["rust_commit"].as_str().is_some())
|
|
);
|
|
assert_eq!(records[0]["metrics"]["programs"], 9);
|
|
assert_eq!(records[0]["metrics"]["pending_programs"], 0);
|
|
assert_eq!(records[0]["metrics"]["pending_commands"], 0);
|
|
assert_eq!(records[8]["metrics"]["active_tasks"], 0);
|
|
}
|
|
|
|
#[test]
|
|
fn audit_proves_all_programs_and_commands_without_credentials_or_evidence() {
|
|
let output = run(&["--audit-only"]);
|
|
let stdout = String::from_utf8(output.stdout).unwrap();
|
|
assert!(
|
|
output.status.success(),
|
|
"{}",
|
|
String::from_utf8_lossy(&output.stderr)
|
|
);
|
|
assert!(stdout.contains("programs=9"), "{stdout}");
|
|
assert!(stdout.contains("pending-programs=0"), "{stdout}");
|
|
assert!(stdout.contains("pending-commands=0"), "{stdout}");
|
|
}
|
|
|
|
#[test]
|
|
fn live_mode_requires_every_literal_confirmation_before_loading_credentials() {
|
|
let directory = TestDir::new();
|
|
let evidence = directory.path("evidence.jsonl");
|
|
let output = run(&[
|
|
"--evidence",
|
|
text(&evidence),
|
|
"--allow-live-login",
|
|
"--confirm-live-login",
|
|
"LOGIN",
|
|
]);
|
|
assert_eq!(output.status.code(), Some(EXIT_USAGE));
|
|
let stderr = String::from_utf8(output.stderr).unwrap();
|
|
assert!(stderr.contains("--allow-public-chat"), "{stderr}");
|
|
assert!(!evidence.exists());
|
|
}
|
|
|
|
#[test]
|
|
fn evidence_is_create_new_and_never_overwrites_a_previous_audit() {
|
|
let directory = TestDir::new();
|
|
let evidence = directory.path("evidence.jsonl");
|
|
fs::write(&evidence, "preserve-me\n").unwrap();
|
|
let output = run(&["--fake", "--evidence", text(&evidence)]);
|
|
assert_eq!(output.status.code(), Some(EXIT_INPUT));
|
|
assert_eq!(fs::read_to_string(evidence).unwrap(), "preserve-me\n");
|
|
}
|