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 = 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["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"); }