//! Conformance corpus for QoE aggregation (`live-conformance/aggregate/`,
//! extensions/telemetry-aggregation.md §12).
//!
//!   wai_telemetry_aggregate_vectors gen     <corpus-dir>   write vectors.json, from fixed seeds
//!   wai_telemetry_aggregate_vectors verify  <corpus-dir>   vectors.json regenerates byte for
//!                                                          byte, every receipt, cell and
//!                                                          delivery-only report gets the outcome
//!                                                          it states, and the Prio3 test
//!                                                          vectors under vdaf-22/ pass
//!
//! The generator and this verifier are one implementation. The corpus's second
//! implementation is `live-conformance/telemetry_aggregate_verify.py`, written from the
//! extension's text and the drafts it cites, sharing no code with this binary.

use std::path::Path;
use wai::telemetry_aggregate::{corpus, vdaf_vectors};

fn main() {
    let a: Vec<String> = std::env::args().collect();
    match (a.get(1).map(String::as_str), a.get(2)) {
        (Some("gen"), Some(d)) => {
            let p = Path::new(d).join("vectors.json");
            if let Err(e) = std::fs::create_dir_all(d).and_then(|_| std::fs::write(&p, corpus::generate())) {
                eprintln!("write {}: {e}", p.display());
                std::process::exit(1);
            }
            println!("wrote {}", p.display());
        }
        (Some("verify"), Some(d)) => std::process::exit(verify(Path::new(d))),
        _ => {
            eprintln!("usage: wai_telemetry_aggregate_vectors gen|verify <corpus-dir>");
            std::process::exit(2);
        }
    }
}

fn verify(dir: &Path) -> i32 {
    let p = dir.join("vectors.json");
    let doc = match std::fs::read_to_string(&p) {
        Ok(s) => s,
        Err(e) => {
            eprintln!("read {}: {e}", p.display());
            return 1;
        }
    };
    let mut fail = 0;
    let same = doc == corpus::generate();
    println!("{} vectors.json regenerates byte for byte from its seeds", if same { "PASS" } else { "FAIL" });
    fail += (!same) as i32;
    let fails = corpus::verify(&doc);
    for f in &fails {
        println!("FAIL {f}");
    }
    println!("{} every receipt, cell and delivery-only report gets the outcome the corpus states", if fails.is_empty() { "PASS" } else { "FAIL" });
    fail += (!fails.is_empty()) as i32;
    let (names, vfails) = vdaf_vectors::run_dir(&dir.join("vdaf-22"));
    for f in &vfails {
        println!("FAIL {f}");
    }
    println!("{} the draft's Prio3 test vectors pass ({} files)", if vfails.is_empty() && !names.is_empty() { "PASS" } else { "FAIL" }, names.len());
    fail += (!vfails.is_empty() || names.is_empty()) as i32;
    (fail != 0) as i32
}
