warriors/joy/cli/tests/artifact_files.rs

#![cfg(unix)]
use joy_rs::{
    state_execution::load_certificate, ExecutionArtifact, ProofArtifact, StateExecutionArtifact,
    ZkExecutionArtifact,
};
use std::{
    fs,
    path::PathBuf,
    process::{Command, Output, Stdio},
    time::{Duration, Instant},
};

struct Fixture(PathBuf);
impl Fixture {
    fn new() -> Self {
        let root = std::env::temp_dir().join(format!("joy-artifact-files-{}", std::process::id()));
        fs::create_dir(&root).unwrap();
        fs::write(
            root.join("main.tri"),
            "program file_check\nfn main()->Field {7}\n",
        )
        .unwrap();
        Self(root)
    }
    fn run(&self, args: &[&str]) -> Output {
        let mut child = Command::new(env!("CARGO_BIN_EXE_joy"))
            .args(args)
            .current_dir(&self.0)
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .unwrap();
        let start = Instant::now();
        while child.try_wait().unwrap().is_none() {
            if start.elapsed() > Duration::from_secs(3) {
                child.kill().unwrap();
                child.wait().unwrap();
                panic!("verification blocked on file input: {args:?}");
            }
            std::thread::sleep(Duration::from_millis(10));
        }
        child.wait_with_output().unwrap()
    }
}
impl Drop for Fixture {
    fn drop(&mut self) {
        let _ = fs::remove_dir_all(&self.0);
    }
}

#[test]
fn verification_rejects_streams_links_and_oversize_files_but_keeps_real_proof_roundtrip() {
    let f = Fixture::new();
    let fifo = f.0.join("pipe.nox");
    assert!(Command::new("mkfifo")
        .arg(&fifo)
        .status()
        .unwrap()
        .success());
    std::os::unix::fs::symlink(&fifo, f.0.join("pipe-link.zheng")).unwrap();
    for name in ["pipe.nox", "pipe-link.zheng"] {
        for args in [
            vec!["verify", name],
            vec!["verify", "main.tri", "--proof", name],
        ] {
            let result = f.run(&args);
            assert_eq!(result.status.code(), Some(1));
            assert!(String::from_utf8_lossy(&result.stderr).contains("regular file"));
        }
    }
    let oversized = f.0.join("oversized.zheng");
    fs::File::create(&oversized)
        .unwrap()
        .set_len(64 * 1024 * 1024 + 1)
        .unwrap();
    for name in ["oversized.json", "oversized.nox"] {
        fs::hard_link(&oversized, f.0.join(name)).unwrap();
        let result = f.run(&["verify", name, "--claim", "7"]);
        assert_eq!(result.status.code(), Some(1));
        assert!(String::from_utf8_lossy(&result.stderr).contains("size limit"));
    }
    for path in [&fifo, &f.0, &f.0.join("pipe-link.zheng"), &oversized] {
        assert!(!ExecutionArtifact::has_header(path));
        assert!(!ZkExecutionArtifact::has_header(path));
        assert!(!StateExecutionArtifact::has_header(path));
        assert!(ExecutionArtifact::load(path).is_err());
        assert!(ZkExecutionArtifact::load(path).is_err());
        assert!(StateExecutionArtifact::load(path).is_err());
        assert!(ProofArtifact::load(path).is_err());
        assert!(load_certificate(path).is_err());
    }
    let proved = f.run(&["prove", "main.tri", "--output", "proof.zheng"]);
    assert!(
        proved.status.success(),
        "{}",
        String::from_utf8_lossy(&proved.stderr)
    );
    assert!(ExecutionArtifact::has_header(&f.0.join("proof.zheng")));
    for args in [
        vec!["verify", "proof.zheng", "--claim", "7"],
        vec![
            "verify",
            "main.tri",
            "--proof",
            "proof.zheng",
            "--claim",
            "7",
        ],
    ] {
        let verified = f.run(&args);
        assert!(
            verified.status.success(),
            "{}",
            String::from_utf8_lossy(&verified.stderr)
        );
    }
    assert_eq!(
        f.run(&["verify", "proof.zheng", "--claim", "8"])
            .status
            .code(),
        Some(1)
    );
    std::os::unix::fs::symlink(f.0.join("proof.zheng"), f.0.join("proof-link.zheng")).unwrap();
    assert_eq!(
        f.run(&["verify", "proof-link.zheng"]).status.code(),
        Some(1)
    );
}

Graph