mod common;
use std::path::{Path, PathBuf};
use std::process::Command;
fn fixture_dir() -> PathBuf {
let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
p.push("tests/fixtures/flakes/minimal");
p
}
fn nix_flake_eval(fixture: &Path, selector: &str) -> serde_json::Value {
let ref_str = format!("path:{}#{selector}", fixture.display());
let out = Command::new("nix")
.args([
"eval",
"--json",
"--no-write-lock-file",
"--extra-experimental-features",
"nix-command flakes",
&ref_str,
])
.output();
let out = match out {
Ok(o) => o,
Err(e) => return wrap_error(format!("spawn nix: {e}")),
};
if !out.status.success() {
return wrap_error(String::from_utf8_lossy(&out.stderr).into_owned());
}
let stdout = String::from_utf8_lossy(&out.stdout);
match serde_json::from_str(stdout.trim()) {
Ok(v) => v,
Err(e) => wrap_error(format!("nix stdout not json: {e}: {stdout}")),
}
}
fn sui_flake_eval(fixture: &Path, selector: &str) -> serde_json::Value {
let expr = format!(
r#"(builtins.getFlake "{}").{selector}"#,
fixture.display()
);
common::sui_eval_json(&expr)
}
fn wrap_error(msg: String) -> serde_json::Value {
let mut m = serde_json::Map::new();
m.insert("__error".to_string(), serde_json::Value::String(msg));
serde_json::Value::Object(m)
}
fn assert_flake_parity(fixture: &Path, selector: &str) {
if common::skip_if_offline("flake_parity") {
return;
}
let oracle = nix_flake_eval(fixture, selector);
let ours = sui_flake_eval(fixture, selector);
if oracle != ours {
panic!(
"flake parity mismatch on {} # {selector}\n nix: {}\n sui: {}",
fixture.display(),
serde_json::to_string(&oracle).unwrap_or_default(),
serde_json::to_string(&ours).unwrap_or_default(),
);
}
}
#[test]
fn minimal_flake_answer() {
assert_flake_parity(&fixture_dir(), "answer");
}
#[test]
fn minimal_flake_greeting() {
assert_flake_parity(&fixture_dir(), "greeting");
}
#[test]
fn minimal_flake_numbers() {
assert_flake_parity(&fixture_dir(), "numbers");
}
#[test]
fn minimal_flake_nested() {
assert_flake_parity(&fixture_dir(), "nested");
}
#[test]
fn minimal_flake_nested_deeper() {
assert_flake_parity(&fixture_dir(), "nested.b.c");
}
#[test]
fn minimal_flake_description_matches() {
if common::skip_if_offline("minimal_flake_description_matches") {
return;
}
let dir = fixture_dir();
let ref_str = format!("path:{}", dir.display());
let out = Command::new("nix")
.args([
"flake",
"metadata",
"--json",
"--no-write-lock-file",
"--extra-experimental-features",
"nix-command flakes",
&ref_str,
])
.output()
.expect("spawn nix flake metadata");
assert!(
out.status.success(),
"nix flake metadata failed: {}",
String::from_utf8_lossy(&out.stderr)
);
let meta: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
let nix_desc = meta.get("description").and_then(|v| v.as_str()).unwrap();
let sui_desc = sui_flake_eval(&dir, "description");
assert_eq!(
sui_desc,
serde_json::Value::String(nix_desc.to_string()),
"description mismatch: nix={:?}, sui={sui_desc}",
nix_desc
);
}