cli.rs
2.9 kB · rust · 110 lines
1#[path = "common/sha256.rs"]2mod sha256;34use serde_json::Value;5use std::path::Path;6use std::process::{Command, Output};78fn stored(module: &str, path: &str) -> Value {9 let file = Path::new(env!("CARGO_MANIFEST_DIR"))10 .join("fixtures")11 .join(format!("{module}.json"));12 let text = std::fs::read_to_string(&file)13 .unwrap_or_else(|_| panic!("{} is missing; run the fixtures example", file.display()));14 let rows: Vec<Value> = serde_json::from_str(&text).unwrap();15 rows.into_iter()16 .find(|row| row["fn"] == path)17 .unwrap_or_else(|| panic!("{module}.json holds no {path} row"))["out"]18 .clone()19}2021fn mrly(words: &[&str]) -> Output {22 Command::new(env!("CARGO_BIN_EXE_mrly"))23 .args(words)24 .output()25 .expect("the mrly binary runs")26}2728fn printed(door: &str, args: &str) -> Value {29 let out = mrly(&[door, args]);30 assert!(31 out.status.success(),32 "{door} {args}: {}",33 String::from_utf8_lossy(&out.stderr)34 );35 serde_json::from_slice(&out.stdout).expect("the door prints one json value")36}3738fn hashed(value: &Value) -> Value {39 let bytes: Vec<u8> = serde_json::from_value(value.clone()).expect("a list of bytes");40 Value::String(sha256::hex(&bytes))41}4243#[test]44fn core_replays_its_png() {45 let colors = "[[[255,0,0,255],[0,255,0,255],[0,0,255,255],[255,255,255,255]],2,2,3]";46 assert_eq!(47 hashed(&printed("core.codec.png", colors)),48 stored("core", "core::png")49 );50}5152#[test]53fn num_replays_its_factorial() {54 assert_eq!(55 printed("num.factor.factorial", "[25]"),56 stored("num", "num::factor::factorial")57 );58}5960#[test]61fn math_replays_its_fill() {62 assert_eq!(63 printed("math.counts.fill", r#"["23",3,3,2,2]"#),64 stored("math", "math::counts::fill")65 );66}6768#[test]69fn gen_replays_its_background() {70 assert_eq!(71 hashed(&printed("gen.background", "[1,2,2]")),72 stored("gen", "gen::background")73 );74}7576#[test]77fn life_replays_its_counts() {78 assert_eq!(79 printed("life.counts", r#"["Primes",8,false,false]"#),80 stored("life", "life::counts")81 );82}8384#[test]85fn font_replays_its_path() {86 assert_eq!(printed("font.path", r#"["M"]"#), stored("font", "font::path"));87}8889#[test]90fn a_rust_error_exits_one_on_stderr() {91 let out = mrly(&["num.factor.factorial", "[40]"]);92 assert_eq!(out.status.code(), Some(1));93 assert!(out.stdout.is_empty());94 assert_eq!(95 String::from_utf8_lossy(&out.stderr).trim(),96 "a factorial of 40 passes u128"97 );98}99100#[test]101fn list_names_every_door_with_its_types() {102 let out = mrly(&["list"]);103 assert!(out.status.success());104 let text = String::from_utf8(out.stdout).unwrap();105 assert!(106 text.lines()107 .any(|line| line == "num.factor.gcd(a: u128, b: u128) -> u128"),108 "list does not name num.factor.gcd"109 );110}