edifact-mapper 0.8.0

EDIFACT to BO4E bidirectional conversion for the German energy market
Documentation
//! A data bundle from a different release than the crate is refused.
//!
//! `bundle_version` guards the *serialisation format*, and it has been `2` for
//! a long time — so a bundle five months old passed that check and loaded
//! cleanly while its mappings and schemas were from another era. What came out
//! was not an error but a smaller message: one such bundle rendered 12% of a
//! 59-segment message, returned `Ok`, and the caller found out only when
//! `detect_pid` failed on bytes the library had just written (issue #158).
//!
//! Nothing could have caught that, because nothing recorded which release
//! produced the bundle. `built_by` does, and the pairing a consumer put best
//! after losing an afternoon to it is the rule enforced here: a crate and a
//! bundle from different releases is the combination that goes wrong.
//!
//! A bundle without the stamp predates it, and so is by definition older than
//! the release that started stamping — refused for the same reason.

use edifact_mapper::{DataDir, Mapper};
use std::path::PathBuf;

fn write_bundle(dir: &std::path::Path, fv: &str, built_by: Option<&str>) {
    std::fs::create_dir_all(dir).unwrap();
    let mut bundle = serde_json::json!({
        "format_version": fv,
        "bundle_version": 2,
        "variants": {},
        "bo4e_catalog": { "types": {} },
    });
    if let Some(v) = built_by {
        bundle["built_by"] = serde_json::Value::String(v.to_string());
    }
    std::fs::write(
        dir.join(format!("edifact-data-{fv}.bin")),
        serde_json::to_vec(&bundle).unwrap(),
    )
    .unwrap();
}

fn tmp(name: &str) -> PathBuf {
    let dir =
        std::env::temp_dir().join(format!("edifact-provenance-{name}-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&dir);
    dir
}

/// The case from #158: format-compatible, content from another release.
#[test]
fn a_bundle_from_another_release_is_refused_by_name() {
    let dir = tmp("mismatch");
    write_bundle(&dir, "FV2604", Some("0.0.1-from-another-era"));

    let text = match Mapper::from_data_dir(DataDir::path(&dir).eager(&["FV2604"])) {
        Err(e) => e.to_string(),
        Ok(_) => panic!("a bundle from another release must not load silently"),
    };

    assert!(
        text.contains("0.0.1-from-another-era"),
        "the error does not say which release produced the bundle: {text}"
    );
    assert!(
        text.contains(env!("CARGO_PKG_VERSION")),
        "the error does not say which release the crate expects: {text}"
    );
}

/// A bundle predating the stamp is older than the release that added it.
#[test]
fn a_bundle_without_provenance_is_refused() {
    let dir = tmp("unstamped");
    write_bundle(&dir, "FV2604", None);

    let text = match Mapper::from_data_dir(DataDir::path(&dir).eager(&["FV2604"])) {
        Err(e) => e.to_string(),
        Ok(_) => panic!("an unstamped bundle must not load silently"),
    };
    assert!(
        text.to_lowercase().contains("bundle"),
        "the error does not mention the bundle: {text}"
    );
}

/// A caller that pins deliberately can still say so — the check is a default,
/// not a wall.
#[test]
fn a_mismatched_bundle_loads_when_the_caller_opts_in() {
    let dir = tmp("optin");
    write_bundle(&dir, "FV2604", Some("0.0.1-from-another-era"));

    assert!(
        Mapper::from_data_dir(
            DataDir::path(&dir)
                .allow_bundle_from_other_release(true)
                .eager(&["FV2604"]),
        )
        .is_ok(),
        "an explicit opt-in should load the bundle"
    );
}

/// The bundles this repository ships match the crate that reads them.
#[test]
fn the_committed_bundles_match_this_crate() {
    let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .and_then(|p| p.parent())
        .unwrap()
        .to_path_buf();
    if !root.join("dist/edifact-data-FV2604.bin").exists() {
        eprintln!("skipping: build the bundles first");
        return;
    }
    assert!(
        Mapper::from_data_dir(DataDir::path(root.join("dist")).eager(&["FV2604"])).is_ok(),
        "the committed bundle should be from this release"
    );
}