kshana 0.32.0

Open, reproducible PNT-resilience simulator with quantum-sensor performance models
Documentation
//! The code fences on the registry front pages are copied verbatim into strangers' editors,
//! and until this file no test read a single one of them. An ES import of an export that
//! did not exist and a Rust example that did not compile both shipped to their registries
//! that way. Two checks, each over the fence as it is actually published:
//!
//! 1. Every name imported from `"kshana"` in a JavaScript fence is a `#[wasm_bindgen]`
//!    function in `src/wasm.rs`, or one of the loaders wasm-bindgen generates beside them
//!    (the `default` export `init`, and `initSync`, which the Node.js recipe uses).
//! 2. The Rust fence in `README.crates.md` is byte-identical to the `readme_crates_example`
//!    module below, which this test binary compiles. A README edit that stops compiling
//!    therefore fails here as a mismatch, and an API change that breaks the example fails
//!    the build. The fence is a complete program and carries its scenario inline, so it
//!    runs as written in a fresh project with no scenario file on disk.
//!    The example is compiled, never called: running it would write a result file into the
//!    working directory on every `cargo test`.

fn fences<'a>(doc: &'a str, lang: &str) -> Vec<Vec<&'a str>> {
    let open = format!("```{lang}");
    let mut out = Vec::new();
    let mut cur: Option<Vec<&str>> = None;
    for line in doc.lines() {
        match cur.as_mut() {
            None if line.trim_end() == open => cur = Some(Vec::new()),
            Some(body) if line.trim_end() == "```" => {
                out.push(std::mem::take(body));
                cur = None;
            }
            Some(body) => body.push(line),
            None => {}
        }
    }
    out
}

/// The named loader wasm-bindgen writes into every `--target web` package beside the
/// crate's own exports. `init` itself is the `default` export and is never imported by name.
const GENERATED_LOADERS: &[&str] = &["initSync"];

fn wasm_exports() -> std::collections::BTreeSet<String> {
    let src = include_str!("../src/wasm.rs");
    let lines: Vec<&str> = src.lines().collect();
    let mut names: std::collections::BTreeSet<String> =
        GENERATED_LOADERS.iter().map(|s| s.to_string()).collect();
    for (i, l) in lines.iter().enumerate() {
        if !l.trim_start().starts_with("#[wasm_bindgen") {
            continue;
        }
        // The attribute may be followed by doc comments or further attributes.
        if let Some(sig) = lines[i + 1..]
            .iter()
            .map(|s| s.trim_start())
            .find(|s| s.starts_with("pub fn "))
        {
            let name = sig["pub fn ".len()..]
                .split(['(', '<'])
                .next()
                .unwrap()
                .to_string();
            names.insert(name);
        }
    }
    names
}

#[test]
fn every_js_import_from_kshana_is_a_real_wasm_export() {
    let exports = wasm_exports();
    assert!(
        exports.contains("run") && exports.len() >= 6,
        "found only {exports:?} in src/wasm.rs — the export scan is broken, not the README"
    );
    let surfaces = [
        ("README.npm.md", include_str!("../README.npm.md")),
        ("README.md", include_str!("../README.md")),
    ];
    let mut checked = 0;
    let mut bad = Vec::new();
    for (name, doc) in surfaces {
        for fence in fences(doc, "js")
            .into_iter()
            .chain(fences(doc, "javascript"))
        {
            for line in fence {
                let l = line.trim();
                if !(l.starts_with("import ")
                    && (l.contains("from \"kshana\"") || l.contains("from 'kshana'")))
                {
                    continue;
                }
                let (Some(a), Some(b)) = (l.find('{'), l.find('}')) else {
                    continue;
                };
                if b < a {
                    continue;
                }
                for imp in l[a + 1..b].split(',') {
                    // `x as y` imports the export `x`.
                    let imp = imp.split(" as ").next().unwrap().trim();
                    if imp.is_empty() {
                        continue;
                    }
                    checked += 1;
                    if !exports.contains(imp) {
                        bad.push(format!(
                            "{name}: imports `{imp}`, which src/wasm.rs does not export"
                        ));
                    }
                }
            }
        }
    }
    assert!(
        checked > 0,
        "no `import {{ … }} from \"kshana\"` line found in any JS fence — the gate is grading nothing"
    );
    assert!(bad.is_empty(), "{}", bad.join("\n"));
}

#[test]
fn every_site_import_from_the_wasm_package_is_a_real_export() {
    // The Studio's engine worker and the smoke test import from the generated package
    // (`./pkg/kshana.js` beside the smoke test, `../pkg/kshana.js` from the Studio's lib/). An
    // ES module that imports a name the package does not export fails to LINK, so one
    // stale name blanks the whole page — not just the feature that used it.
    let exports = wasm_exports();
    let files = [
        ("web/smoke.mjs", include_str!("../web/smoke.mjs")),
        (
            "web/studio/lib/engine-worker.mjs",
            include_str!("../web/studio/lib/engine-worker.mjs"),
        ),
    ];
    let mut checked = 0;
    let mut bad = Vec::new();
    for (name, src) in files {
        // Imports may span lines; join the statement up to its `from`.
        let flat = src.replace('\n', " ");
        let mut rest = flat.as_str();
        while let Some(i) = rest.find("import ") {
            rest = &rest[i + "import ".len()..];
            let Some(from) = rest.find(" from ") else {
                break;
            };
            let (clause, after) = rest.split_at(from);
            let module = after[" from ".len()..].trim_start().get(1..).unwrap_or("");
            if !module.starts_with("./pkg/kshana.js") && !module.starts_with("../pkg/kshana.js") {
                continue;
            }
            let (Some(a), Some(b)) = (clause.find('{'), clause.find('}')) else {
                continue;
            };
            if b < a {
                continue;
            }
            for imp in clause[a + 1..b].split(',') {
                let imp = imp.split(" as ").next().unwrap().trim();
                if imp.is_empty() {
                    continue;
                }
                checked += 1;
                if !exports.contains(imp) {
                    bad.push(format!(
                        "{name}: imports `{imp}`, which src/wasm.rs does not export"
                    ));
                }
            }
        }
    }
    assert!(
        checked >= 3,
        "found only {checked} imported names from the generated package — the scan is broken"
    );

    // The Studio's main script loads the package with a dynamic import and then reads the
    // functions off the module object (`mod.run`, `mod.chart_svg`, …). A name the package
    // does not export is `undefined` there, and the call fails only when a visitor uses
    // that feature. Check those names against the same export list.
    let app = include_str!("../web/studio/app.js");
    let at = app
        .find("import(\"./pkg/kshana.js\")")
        .expect("web/studio/app.js no longer loads ./pkg/kshana.js with a dynamic import");
    let window: String = app[at..].chars().take(1500).collect();
    let mut used = 0;
    let mut rest = window.as_str();
    while let Some(i) = rest.find("mod.") {
        rest = &rest[i + "mod.".len()..];
        let name: String = rest
            .chars()
            .take_while(|c| c.is_ascii_alphanumeric() || *c == '_')
            .collect();
        if name.is_empty() || name == "default" {
            continue;
        }
        used += 1;
        if !exports.contains(name.as_str()) {
            bad.push(format!(
                "web/studio/app.js: uses `mod.{name}`, which src/wasm.rs does not export"
            ));
        }
    }
    assert!(
        used >= 3,
        "found only {used} package functions used by web/studio/app.js — the scan is broken"
    );
    assert!(bad.is_empty(), "{}", bad.join("\n"));
}

// ---- README.crates.md example: the region between the markers is compared to the fence.
// The fence is a whole program, so the compiled copy is a whole program too, inside a
// module of its own: there its `main` is an ordinary function, compiled and never called.
#[allow(dead_code)]
#[rustfmt::skip] // the body must stay byte-identical to the published fence
mod readme_crates_example {
    // README-EXAMPLE-BEGIN
use kshana::api;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // A complete scenario, not a sketch: scenarios/clock-holdover.toml without its
    // comment lines. It runs 2 h, 10 min of GNSS then about 1.8 h with GNSS denied, and
    // asks how long a strontium optical clock and a chip-scale atomic clock (CSAC) each
    // hold time to within 20 ns. sigma_y(1s) is a clock's Allan deviation at an averaging
    // time of one second; q_wf, the white-frequency-noise intensity, is its square.
    let toml = r#"
seed = 42
threshold_ns = 20.0

[time]
step_s = 10.0
duration_s = 7200.0

[gnss]
windows = [
  { t0 = 0.0,    t1 = 600.0,  state = "nominal" },
  { t0 = 600.0,  t1 = 7200.0, state = "denied" },
]

[clock_quantum]
id = "optical-sr-lattice"
provenance = "Strontium optical lattice clock, space-oriented goal sigma_y(1s)=1e-15 (Origlia/Schiller/Bongs et al., arXiv:1503.08457); q_wf=sigma_y(1s)^2; ground-demonstrator maturity, not flown; flicker/aging not modeled"
y0   = 5.0e-17
q_wf = 1.0e-30
q_rw = 0.0

[clock_classical]
id = "csac-sa45s"
provenance = "Microchip SA65 / SA.45s CSAC datasheet sigma_y(1s)=3e-10; q_wf=sigma_y(1s)^2; flicker/aging not modeled"
y0   = 5.0e-10
q_wf = 9.0e-20
q_rw = 0.0
"#;
    let out = api::run_toml(toml)?; // RunOutput { json, svg, summary, csv }
    println!("{}", out.summary); // the one-line result string
    std::fs::write("clock-holdover.result.json", &out.json)?; // the full result document
    Ok(())
}
    // README-EXAMPLE-END
}

#[test]
fn readme_crates_rust_fence_is_the_compiled_example() {
    let me = include_str!("readme_code_fences_doc_sync.rs");
    let begin = me.find("// README-EXAMPLE-BEGIN\n").expect("begin marker")
        + "// README-EXAMPLE-BEGIN\n".len();
    let end = me[begin..]
        .find("    // README-EXAMPLE-END")
        .expect("end marker")
        + begin;
    let compiled: Vec<&str> = me[begin..end].lines().collect();

    let rust = fences(include_str!("../README.crates.md"), "rust");
    assert_eq!(
        rust.len(),
        1,
        "README.crates.md should carry exactly one ```rust fence"
    );
    // No rustdoc-hidden `# ` lines: crates.io renders them, and a reader who pastes the
    // fence gets a syntax error. The fence is a whole program instead, `main` and all.
    let hidden: Vec<&str> = rust[0]
        .iter()
        .copied()
        .filter(|l| l.starts_with("# "))
        .collect();
    assert!(
        hidden.is_empty(),
        "README.crates.md's Rust fence has rustdoc-hidden lines, which crates.io shows and \
         which do not compile when pasted: {hidden:?}"
    );
    let published: Vec<&str> = rust[0].to_vec();
    assert_eq!(
        published, compiled,
        "README.crates.md's Rust example no longer matches the compiled copy in \
         tests/readme_code_fences_doc_sync.rs — edit both together"
    );
}