use std::path::{Path, PathBuf};
use std::process::{Command, Output};
use std::sync::atomic::{AtomicU64, Ordering};
fn bin() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_rustyfi"))
}
fn repo_lib_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../lib-rustyfi")
}
fn minimal_fixture() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/minimal.saty")
}
fn tmpdir(tag: &str) -> PathBuf {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
let p = std::env::temp_dir().join(format!(
"rustyfi-format-html-{tag}-{}-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos(),
n
));
std::fs::create_dir_all(&p).unwrap();
p
}
fn assert_ok(out: &Output, ctx: &str) {
assert!(
out.status.success(),
"{ctx}: compile failed (code {:?})\nstdout:\n{}\nstderr:\n{}",
out.status.code(),
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr),
);
}
#[test]
fn format_html_fixed_writes_a_page_div_and_a_word_span() {
let work = tmpdir("basic");
let out = work.join("out.html");
let result = Command::new(bin())
.arg(minimal_fixture())
.args(["-o".as_ref(), out.as_os_str()])
.args(["--lib-root".as_ref(), repo_lib_root().as_os_str()])
.args(["--cache-dir".as_ref(), work.join("cache").as_os_str()])
.args(["--format", "html-fixed"])
.output()
.expect("spawn rustyfi");
assert_ok(&result, "compile --format html-fixed");
let html =
std::fs::read_to_string(&out).expect("--format html-fixed must write the output file");
assert!(
html.starts_with("<!doctype html>"),
"missing doctype:\n{html}"
);
assert!(
html.contains("<div class=\"page\""),
"missing page div:\n{html}"
);
assert!(
html.contains("<span"),
"missing at least one run span:\n{html}"
);
let text: String = {
let mut out = String::new();
let mut depth = 0usize;
for ch in html.chars() {
match ch {
'<' => depth += 1,
'>' => depth = depth.saturating_sub(1),
c if depth == 0 => out.push(c),
_ => {}
}
}
out.chars().filter(|c| !c.is_whitespace()).collect()
};
assert!(
text.contains("Hello,"),
"missing expected fixture word:\n{html}"
);
assert!(
text.contains("world!"),
"missing expected fixture word:\n{html}"
);
std::fs::remove_dir_all(&work).ok();
}
#[test]
fn default_format_is_still_pdf() {
let work = tmpdir("default");
let out = work.join("out.pdf");
let result = Command::new(bin())
.arg(minimal_fixture())
.args(["-o".as_ref(), out.as_os_str()])
.args(["--lib-root".as_ref(), repo_lib_root().as_os_str()])
.args(["--cache-dir".as_ref(), work.join("cache").as_os_str()])
.output()
.expect("spawn rustyfi");
assert_ok(&result, "compile with no --format");
let bytes = std::fs::read(&out).expect("default format must write the output file");
assert!(
bytes.starts_with(b"%PDF-"),
"default --format must still produce a PDF"
);
std::fs::remove_dir_all(&work).ok();
}