Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-ops/tests/pep503_layout.rs

//! **RED FIRST for row 1b.** The layout inside holger's archive is the contract
//! between what we pack and what `pip install` can find. Get it wrong and the index
//! resolves, returns a link, and 404s — which reads to a user as "the server is
//! broken", not "the wheel is in the wrong folder".
//!
//! The headline case is `normalize_name`. The shell script this replaces did:
//!
//! ```sh
//! normalize() { echo "$1" | tr '[:upper:]' '[:lower:]' | tr '_.' '--'; }
//! ```
//!
//! `tr` maps character-for-character and **cannot collapse a run**, but PEP 503 is
//! `re.sub(r"[-_.]+", "-", name).lower()` — a run of separators becomes ONE dash.
//! For `facet-wrapped-web`, the only name that script was ever run with, the two
//! agree. For anything with a doubled separator they do not, and the wheel lands in
//! a directory `pip` will never ask for.
//!
//! That is the shape worth testing: a function that is correct for the one input
//! someone tried it with.

use std::path::PathBuf;
use facett_ops::holger::{archive_path_for, distribution_of, normalize_name, stage_index};

// ── PEP 503 normalization, including what `tr` could not do ────────────────

#[test]
fn normalization_collapses_runs_which_is_where_the_shell_was_wrong() {
    // THE case. `tr '_.' '--'` gives `facet--wrapped`; PEP 503 gives `facet-wrapped`.
    assert_eq!(normalize_name("facet__wrapped"), "facet-wrapped");
    assert_eq!(normalize_name("a..b"), "a-b");
    assert_eq!(normalize_name("a-_.b"), "a-b");
    assert_eq!(normalize_name("zope.interface"), "zope-interface");
    // ...and a run at the edges is still one dash, not several.
    assert_eq!(normalize_name("__lead"), "-lead");
    assert_eq!(normalize_name("trail..."), "trail-");
}

#[test]
fn normalization_lowercases() {
    assert_eq!(normalize_name("Facet-Wrapped-Web"), "facet-wrapped-web");
    assert_eq!(normalize_name("PyYAML"), "pyyaml");
}

#[test]
fn the_name_we_actually_ship_normalizes_to_what_pip_asks_for() {
    // The wheel's filename carries `facet_wrapped_web`; a user types
    // `pip install facet-wrapped-web`. These must meet.
    assert_eq!(normalize_name("facet_wrapped_web"), "facet-wrapped-web");
    assert_eq!(normalize_name("facet-wrapped-web"), "facet-wrapped-web");
}

#[test]
fn normalization_is_idempotent() {
    // holger normalizes the incoming REQUEST too. If normalizing twice moved the
    // name, our directory and its lookup would disagree on the second hop.
    for n in ["facet_wrapped_web", "A__b.C", "already-normal", "trail..."] {
        let once = normalize_name(n);
        assert_eq!(normalize_name(&once), once, "`{n}` is not idempotent");
    }
}

// ── reading the distribution out of an artifact filename ───────────────────

#[test]
fn a_wheel_and_its_sdist_land_in_the_same_directory() {
    // They MUST: `/simple/facet-wrapped-web/` lists both, and pip picks. Two
    // directories would make the sdist invisible.
    let whl = archive_path_for("facet_wrapped_web-0.1.19-py3-none-any.whl").unwrap();
    let sdist = archive_path_for("facet_wrapped_web-0.1.19.tar.gz").unwrap();
    assert_eq!(whl, "packages/facet-wrapped-web/facet_wrapped_web-0.1.19-py3-none-any.whl");
    assert_eq!(sdist, "packages/facet-wrapped-web/facet_wrapped_web-0.1.19.tar.gz");
    assert_eq!(
        whl.rsplit_once('/').unwrap().0,
        sdist.rsplit_once('/').unwrap().0,
        "the wheel and the sdist must share one directory"
    );
}

#[test]
fn the_filename_itself_is_never_normalized() {
    // Only the DIRECTORY is normalized. The filename is the artifact's own name and
    // pip matches it against the wheel tags — rewriting it would make the download
    // link name a file that does not exist.
    let p = archive_path_for("facet_wrapped_web-0.1.19-py3-none-any.whl").unwrap();
    assert!(p.ends_with("facet_wrapped_web-0.1.19-py3-none-any.whl"), "{p}");
}

#[test]
fn a_file_that_is_not_an_artifact_is_refused_not_mislaid() {
    for bad in ["README.md", "robot_results.json", "facet_wrapped_web-0.1.19.zip", ".whl"] {
        assert!(
            archive_path_for(bad).is_none(),
            "`{bad}` must be refused, not packed somewhere pip will never look"
        );
    }
    assert_eq!(distribution_of("facet_wrapped_web-0.1.19.tar.gz").as_deref(), Some("facet_wrapped_web"));
}

// ── the staged tree on disk ────────────────────────────────────────────────

fn scratch(tag: &str) -> PathBuf {
    let base = std::env::var("CARGO_TARGET_TMPDIR")
        .map(PathBuf::from)
        .unwrap_or_else(|_| std::env::temp_dir());
    let d = base.join(format!("pep503-{tag}"));
    let _ = std::fs::remove_dir_all(&d);
    std::fs::create_dir_all(&d).unwrap();
    d
}

#[test]
fn staging_writes_the_bytes_at_the_served_path() {
    let dir = scratch("stage");
    let src = dir.join("in");
    std::fs::create_dir_all(&src).unwrap();
    let whl = src.join("facet_wrapped_web-0.1.19-py3-none-any.whl");
    let sdist = src.join("facet_wrapped_web-0.1.19.tar.gz");
    std::fs::write(&whl, b"PK\x03\x04wheel-bytes").unwrap();
    std::fs::write(&sdist, b"\x1f\x8bsdist-bytes").unwrap();

    let stage = dir.join("stage");
    let packed = stage_index(&[whl.clone(), sdist.clone()], &stage).unwrap();
    assert_eq!(packed.len(), 2);

    // Assert the APPLIED output — the bytes at the path holger will serve — not
    // that the function returned a list of strings.
    let served = stage.join("packages/facet-wrapped-web/facet_wrapped_web-0.1.19-py3-none-any.whl");
    assert!(served.is_file(), "{} was not written", served.display());
    assert_eq!(std::fs::read(&served).unwrap(), b"PK\x03\x04wheel-bytes");
    assert_eq!(
        std::fs::read(stage.join("packages/facet-wrapped-web/facet_wrapped_web-0.1.19.tar.gz"))
            .unwrap(),
        b"\x1f\x8bsdist-bytes"
    );
}

#[test]
fn staging_refuses_a_stray_file_rather_than_packing_it() {
    let dir = scratch("stray");
    let stray = dir.join("notes.txt");
    std::fs::write(&stray, b"hello").unwrap();
    let err = stage_index(&[stray], &dir.join("stage")).unwrap_err();
    assert!(err.contains("neither a wheel nor an sdist"), "{err}");
    assert!(err.contains("404"), "the refusal must say what would go wrong: {err}");
}

#[test]
fn staging_nothing_is_an_error_not_an_empty_index() {
    // An empty archive would serve a valid, well-formed index of NO packages, and
    // `pip install facet-wrapped-web` against it fails with "no matching
    // distribution" — a message that points at the client, not at the empty publish
    // that caused it.
    let dir = scratch("empty");
    let err = stage_index(&[], &dir.join("stage")).unwrap_err();
    assert!(err.contains("publish-pip"), "the refusal must name the fix: {err}");
}

#[test]
fn staging_is_a_fresh_tree_not_an_accumulating_one() {
    // A previous version's wheel left behind would still be listed and still
    // installable, so `pip install facet-wrapped-web` could resolve to bytes nobody
    // meant to publish. Re-staging must CLEAR.
    let dir = scratch("fresh");
    let src = dir.join("in");
    std::fs::create_dir_all(&src).unwrap();
    let old = src.join("facet_wrapped_web-0.1.15-py3-none-any.whl");
    let new = src.join("facet_wrapped_web-0.1.19-py3-none-any.whl");
    std::fs::write(&old, b"old").unwrap();
    std::fs::write(&new, b"new").unwrap();

    let stage = dir.join("stage");
    stage_index(&[old], &stage).unwrap();
    stage_index(&[new], &stage).unwrap();

    let served = stage.join("packages/facet-wrapped-web");
    let names: Vec<String> = std::fs::read_dir(&served)
        .unwrap()
        .map(|e| e.unwrap().file_name().to_string_lossy().into_owned())
        .collect();
    assert_eq!(names, vec!["facet_wrapped_web-0.1.19-py3-none-any.whl"], "0.1.15 survived: {names:?}");
}