//! Compile-time-backed audit of every pinned upstream program and `TestClient` command. use crate::commands::TEST_CLIENT_COMMANDS; use crate::test_client::{IMPLEMENTED_TEST_CLIENT_COMMANDS, registered_test_client_command_count}; use serde::Deserialize; use std::collections::{BTreeMap, BTreeSet}; const CARGO_MANIFEST: &str = include_str!("../Cargo.toml"); const SOURCE_MANIFEST: &str = include_str!("../upstream-programs.json"); #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct ProgramTarget { pub project: &'static str, pub binary: &'static str, binary_source: &'static str, offline_test_source: &'static str, } pub const ORIGINAL_PROGRAMS: &[ProgramTarget] = &[ ProgramTarget { project: "OSDInspector", binary: "osd-inspector", binary_source: include_str!("bin/osd_inspector.rs"), offline_test_source: include_str!("../tests/osd_inspector_cli.rs"), }, ProgramTarget { project: "SimpleBot", binary: "simple-bot", binary_source: include_str!("bin/simple_bot.rs"), offline_test_source: include_str!("../tests/simple_bot_cli.rs"), }, ProgramTarget { project: "PacketDump", binary: "packet-dump", binary_source: include_str!("bin/packet_dump.rs"), offline_test_source: include_str!("../tests/packet_dump_cli.rs"), }, ProgramTarget { project: "PrimInspector", binary: "prim-inspector", binary_source: include_str!("bin/prim_inspector.rs"), offline_test_source: include_str!("../tests/prim_inspector_cli.rs"), }, ProgramTarget { project: "InventoryExplorer", binary: "inventory-explorer", binary_source: include_str!("bin/inventory_explorer.rs"), offline_test_source: include_str!("../tests/inventory_explorer_cli.rs"), }, ProgramTarget { project: "IRCGateway", binary: "irc-gateway", binary_source: include_str!("bin/irc_gateway.rs"), offline_test_source: include_str!("../tests/irc_gateway_cli.rs"), }, ProgramTarget { project: "TestClient", binary: "test-client", binary_source: include_str!("bin/test_client.rs"), offline_test_source: include_str!("../tests/test_client_services_cli.rs"), }, ProgramTarget { project: "VivoxTest", binary: "vivox-test", binary_source: include_str!("bin/vivox_test.rs"), offline_test_source: include_str!("../tests/vivox_test_cli.rs"), }, ProgramTarget { project: "WebRtcTest", binary: "webrtc-test", binary_source: include_str!("bin/webrtc_test.rs"), offline_test_source: include_str!("../tests/webrtc_test_cli.rs"), }, ]; #[derive(Clone, Debug, Eq, PartialEq)] pub struct CompletenessReport { pub programs: usize, pub source_files: usize, pub test_client_commands: usize, pub pending_programs: usize, pub pending_commands: usize, } #[derive(Deserialize)] struct SourceManifest { upstream_commit: String, projects: Vec, } #[derive(Deserialize)] struct SourceProject { project: String, files: Vec, } #[derive(Deserialize)] struct SourceFile { path: String, sha256: String, } /// Audits the pinned source manifest, all original Rust program targets, their /// offline test entry points, and every generated `TestClient` command. /// /// # Errors /// /// Returns an error when the pinned source manifest is malformed or differs /// from the native target, test, implementation, or runtime registries. pub fn audit_program_completeness() -> Result { let manifest: SourceManifest = serde_json::from_str(SOURCE_MANIFEST) .map_err(|_| "program source manifest is not valid JSON".to_owned())?; if manifest.upstream_commit.len() != 40 || !manifest .upstream_commit .bytes() .all(|byte| byte.is_ascii_hexdigit()) { return Err("program source manifest has an invalid upstream commit".into()); } let mut projects = BTreeMap::new(); let mut source_paths = BTreeSet::new(); let mut source_files = 0_usize; for project in &manifest.projects { if project.files.is_empty() || projects.insert(project.project.as_str(), project).is_some() { return Err("program source manifest has an empty or duplicate project".into()); } for file in &project.files { if !source_paths.insert(file.path.as_str()) || file.sha256.len() != 64 || !file.sha256.bytes().all(|byte| byte.is_ascii_hexdigit()) { return Err("program source manifest has an invalid file record".into()); } source_files += 1; } } let expected_projects: BTreeSet<_> = ORIGINAL_PROGRAMS .iter() .map(|target| target.project) .collect(); if projects.keys().copied().collect::>() != expected_projects { return Err("Rust program targets do not exactly match the source manifest".into()); } for target in ORIGINAL_PROGRAMS { let cargo_marker = format!("name = \"{}\"", target.binary); if !CARGO_MANIFEST.contains(&cargo_marker) || target.binary_source.contains("pending_program") || !target.binary_source.contains("main_entry") || !target.offline_test_source.contains("#[test]") { return Err(format!( "program {} lacks a native target or offline test", target.project )); } } let source_commands: BTreeSet<_> = projects["TestClient"] .files .iter() .filter_map(|file| { file.path .contains("/Commands/") .then(|| file.path.rsplit('/').next()) .flatten() .and_then(|name| name.strip_suffix(".cs")) }) .collect(); let generated_commands: BTreeSet<_> = TEST_CLIENT_COMMANDS.iter().copied().collect(); let implemented_commands: BTreeSet<_> = IMPLEMENTED_TEST_CLIENT_COMMANDS.iter().copied().collect(); if source_commands != generated_commands || implemented_commands != generated_commands || registered_test_client_command_count() != generated_commands.len() { return Err("TestClient source, implementation, and runtime registries differ".into()); } Ok(CompletenessReport { programs: ORIGINAL_PROGRAMS.len(), source_files, test_client_commands: generated_commands.len(), pending_programs: 0, pending_commands: 0, }) } #[cfg(test)] mod tests { use super::*; #[test] fn every_source_program_and_command_has_a_native_tested_target() { let report = audit_program_completeness().unwrap(); assert_eq!(report.programs, 9); assert!(report.source_files > report.programs); assert_eq!(report.test_client_commands, TEST_CLIENT_COMMANDS.len()); assert_eq!(report.pending_programs, 0); assert_eq!(report.pending_commands, 0); } }