hara-native 0.1.21

HAL-free native host runtime and package launcher for Hara
Documentation
use super::super::source::SourceModule;
use super::super::unit;
use super::super::{analyze_modules, report, BuildPlan};
use crate::kernel::parse;
use std::collections::BTreeSet;

fn plan(entrypoint: &str) -> BuildPlan {
    BuildPlan {
        project_id: "demo-app".into(),
        project_version: "0.1.0".into(),
        profile: "production".into(),
        language: "hara".into(),
        main: "app.main".into(),
        entrypoints: vec![entrypoint.into()],
        default_entrypoint: entrypoint.into(),
        keep_vars: Vec::new(),
        keep_namespaces: Vec::new(),
        output_bundle: "target/demo-app-production.hbx".into(),
        output_report: "target/demo-app-production.shake.edn".into(),
    }
}

#[test]
fn records_struct_protocol_and_multimethod_providers() {
    let forms = crate::kernel::parse_forms(
        "(defstruct Point [x y]) (defprotocol Shape (area [value])) (defmulti render type)",
    )
    .unwrap();
    let provided = forms
        .iter()
        .flat_map(|form| unit::raw_provided_vars(form, "app.model"))
        .collect::<BTreeSet<_>>();
    let expected = [
        "app.model/->Point",
        "app.model/Point",
        "app.model/Shape",
        "app.model/area",
        "app.model/map->Point",
        "app.model/render",
    ]
    .into_iter()
    .map(str::to_owned)
    .collect::<BTreeSet<_>>();
    assert_eq!(provided, expected);
}

#[test]
fn emits_byte_identical_analysis_reports() {
    let modules = vec![SourceModule::synthetic(
        "app.main",
        "(ns app.main)\n(defn start [] 42)\n(defn unused [] 0)\n",
    )];
    let build = plan("app.main/start");
    let first = analyze_modules(&build, modules.clone()).unwrap();
    let second = analyze_modules(&build, modules).unwrap();
    let first = report::report_source(&build, &first, None);
    let second = report::report_source(&build, &second, None);
    assert_eq!(first, second);
    let parsed = parse(&first).unwrap();
    assert!(parsed
        .to_string()
        .contains("hara.production-analysis/0-alpha"));
}

#[test]
fn missing_entrypoints_are_deterministic_analysis_diagnostics() {
    let modules = vec![SourceModule::synthetic(
        "app.main",
        "(ns app.main)\n(defn other [] 42)\n",
    )];
    let analysis = analyze_modules(&plan("app.main/start"), modules).unwrap();
    assert_eq!(
        analysis
            .diagnostics
            .iter()
            .filter(|diagnostic| diagnostic.code == "production/missing-entrypoint")
            .count(),
        1
    );
}