use super::diff;
use crate::colored_writer::ColoredWriter;
use crate::dump::Dump;
use std::process::Command;
#[derive(Clone, Copy)]
enum RefMode {
Ast,
Ir,
Format,
}
fn run_reference_nixfmt(input: &str, mode: RefMode) -> String {
let mut cmd = Command::new("nixfmt");
match mode {
RefMode::Ast => {
cmd.arg("--ast");
}
RefMode::Ir => {
cmd.arg("--ir");
}
RefMode::Format => {}
}
cmd.arg("-");
let nixfmt_output = cmd
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.and_then(|mut child| {
use std::io::Write;
child.stdin.as_mut().unwrap().write_all(input.as_bytes())?;
child.wait_with_output()
})
.expect("Failed to run nixfmt");
match mode {
RefMode::Ast | RefMode::Ir => {
String::from_utf8(nixfmt_output.stderr).expect("nixfmt output is not valid UTF-8")
}
RefMode::Format => {
assert!(
nixfmt_output.status.success(),
"reference nixfmt rejected input:\n{}\n--- stderr ---\n{}",
input,
String::from_utf8_lossy(&nixfmt_output.stderr)
);
String::from_utf8(nixfmt_output.stdout).expect("nixfmt output is not valid UTF-8")
}
}
}
fn fail_with_diff(kind: &str, input: &str, expected: &str, got: &str) -> ! {
eprintln!("TEST FAILED: {kind}");
eprintln!("INPUT:\n{input}");
eprintln!("\n=== EXPECTED (nixfmt) ===");
eprintln!("{expected}");
eprintln!("\n=== GOT (ours) ===");
eprintln!("{got}");
eprintln!("\n=== DIFF ===");
diff::print_colored_diff(expected, got);
panic!("{kind} output mismatch");
}
pub fn test_ast_format(input: &str) {
let ast = crate::parse(input).expect("Failed to parse input");
let mut writer = ColoredWriter::new(input);
ast.dump(&mut writer);
let our_output = writer.finish();
let expected = run_reference_nixfmt(input, RefMode::Ast);
if our_output != expected {
fail_with_diff("AST", input, &expected, &our_output);
}
}
pub fn test_ir_format(input: &str) {
let ast = crate::parse(input).expect("Failed to parse input");
let ir = crate::ast_to_ir(&ast);
let mut writer = ColoredWriter::new(input);
ir.dump(&mut writer);
let our_output = writer.finish();
let expected = run_reference_nixfmt(input, RefMode::Ir);
if our_output != expected {
fail_with_diff("IR", input, &expected, &our_output);
}
}
pub fn test_format(input: &str) {
let our_output = crate::format(input).expect("nixfmt_rs failed to format input");
let expected = run_reference_nixfmt(input, RefMode::Format);
if our_output != expected {
fail_with_diff("format", input, &expected, &our_output);
}
}