uitest/tests/copied_from_gunnar_ui.rs
//! **The drift alarm for the four copied client files.**
//!
//! `src/cdp.rs`, `src/http.rs`, `src/json.rs` and `src/ws.rs` each open with
//!
//! ```text
//! //! Copied from gunnar-ui/uitest/src/<f>.rs (one implementation: the same
//! //! zero-dependency client, not a rewrite). Keep the two in step by copying,
//! //! never by editing one alone.
//! ```
//!
//! Until this file existed that was a PROMISE, and a promise is not a guard.
//! `nornir mimir analyze duplicates` measured what the promise was worth on
//! 2026-09-10: 954 lines across the four files, with `http.rs`, `json.rs` and
//! `ws.rs` differing from gunnar-ui's by **exactly the one header line** and
//! `cdp.rs` by that header plus **one cited flag**. So the copies are in step
//! today — and nothing would have said so tomorrow. The failure mode is not a
//! build error: an edit on one side compiles perfectly on both, and the two
//! consoles then get tested by two different clients that look like one.
//!
//! # Why this is a guard and not a repoint
//!
//! The LAW's answer to a twin is one implementation, and the right home for
//! these four files is a std-only `nornir-cdp` leaf in edda — a CDP/websocket/
//! JSON/HTTP client is domain-free and both consoles want it as-is. That is NOT
//! done here, and the reason is a rule, not an oversight:
//! `gunnar-ui/uitest/Cargo.toml` declares ZERO dependencies **"on purpose"**, so
//! the harness "must build in seconds on an appliance with no crates.io". A
//! shared leaf — even a std-only one — is a dependency, and a path dependency to
//! `../../edda` makes the sibling checkout mandatory for a repository that is
//! the public product. Relaxing that rule is the owner's call, not this test's.
//!
//! Until it is relaxed, the copies stay and this file makes "keep the two in
//! step" a thing that FAILS rather than a thing that is said.
//!
//! # It cannot be satisfied by an absent sibling
//!
//! With no `gunnar-ui` beside this repository the test prints why and passes —
//! a clone of `monetize` alone must still be green. That step-aside is the known
//! hole (gunnar-ui's own `contract.rs` records the day it swallowed a real
//! drift), so it is narrow: `GUNNAR_UI_CHECKOUT` names the tree explicitly, and
//! when it is SET the test refuses instead of stepping aside.
use std::path::{Path, PathBuf};
/// The four files that are copies, not rewrites.
const COPIED: &[&str] = &["cdp.rs", "http.rs", "json.rs", "ws.rs"];
/// The header line each copy carries and its original does not. Compared as a
/// PREFIX, so the sentence may be reworded without breaking the guard, but a
/// copy that carries no attribution at all fails.
const HEADER: &str = "//! Copied from gunnar-ui/uitest/src/";
/// `cdp.rs` alone also carries this, because it is copied whole and the unused
/// half must not warn.
const ALLOW_DEAD: &str = "#![allow(dead_code)]";
/// The ONE sanctioned difference, and the marker that declares it. A divergence
/// that does not say this word is not a divergence; it is drift.
const DIVERGES: &str = "DIVERGES from the gunnar-ui copy";
/// gunnar-ui's `uitest/src`, or `None` when there is no such tree beside us.
fn gunnar_ui_src() -> Option<PathBuf> {
if let Some(explicit) = std::env::var_os("GUNNAR_UI_CHECKOUT") {
let p = Path::new(&explicit).join("uitest/src");
assert!(
p.is_dir(),
"GUNNAR_UI_CHECKOUT is set but {} is not a directory — an explicit \
pointer that misses is a typo, not a reason to skip",
p.display()
);
return Some(p);
}
let sibling = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../gunnar-ui/uitest/src");
sibling.is_dir().then_some(sibling)
}
/// Drop the copy's own header: the attribution line(s) and, for `cdp.rs`, the
/// `allow(dead_code)`. Returns the remaining lines and how many header lines
/// were dropped, because ZERO is itself a failure — a copy with no attribution
/// is the state this whole file exists to make impossible.
fn strip_header(text: &str) -> (Vec<&str>, usize) {
let mut lines = text.lines().peekable();
let mut dropped = 0;
while let Some(l) = lines.peek() {
let t = l.trim_start();
if t.starts_with(HEADER) || t.starts_with(ALLOW_DEAD) {
dropped += 1;
lines.next();
} else {
break;
}
}
(lines.collect(), dropped)
}
/// Remove every sanctioned divergence: a run of `//` comment lines starting at
/// the [`DIVERGES`] marker, plus the ONE code line the run introduces. Returns
/// the remaining lines and the number of divergences removed, so a test can
/// assert the count against what the file is allowed.
fn take_divergences<'a>(lines: &[&'a str]) -> (Vec<&'a str>, usize) {
let mut out = Vec::with_capacity(lines.len());
let mut removed = 0;
let mut i = 0;
while i < lines.len() {
if lines[i].contains(DIVERGES) {
removed += 1;
while i < lines.len() && lines[i].trim_start().starts_with("//") {
i += 1;
}
// The single line the comment is ABOUT. A divergence that explains
// itself and then changes nothing would silently pass; one that
// changes two lines must say so twice.
i += 1;
continue;
}
out.push(lines[i]);
i += 1;
}
(out, removed)
}
/// Every copied file is its gunnar-ui original plus a header, plus — for
/// `cdp.rs` — exactly one marked divergence.
#[test]
fn the_copied_clients_match_gunnar_uis_own() {
let Some(theirs) = gunnar_ui_src() else {
eprintln!(
"gunnar-ui is not checked out beside this repository; the copied \
clients' drift is NOT checked. Set GUNNAR_UI_CHECKOUT to refuse \
instead of skipping."
);
return;
};
let ours = Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
// `cdp.rs` is the only file with a sanctioned divergence, and the count is
// pinned: a second one has to be argued for in a diff, not slipped in.
let allowed = |f: &str| if f == "cdp.rs" { 1 } else { 0 };
for f in COPIED {
let mine = std::fs::read_to_string(ours.join(f))
.unwrap_or_else(|e| panic!("read {}: {e}", ours.join(f).display()));
let theirs_text = std::fs::read_to_string(theirs.join(f))
.unwrap_or_else(|e| panic!("read {}: {e}", theirs.join(f).display()));
let (mine_lines, header) = strip_header(&mine);
assert!(
header > 0,
"{f} carries no `{HEADER}…` attribution. A copy that does not say \
what it is a copy of is the twin nobody finds."
);
let (mine_lines, diverged) = take_divergences(&mine_lines);
assert_eq!(
diverged,
allowed(f),
"{f}: {diverged} block(s) marked `{DIVERGES}`, {} allowed. A new \
divergence is a decision and belongs in a diff someone read.",
allowed(f)
);
let theirs_lines: Vec<&str> = theirs_text.lines().collect();
assert_eq!(
mine_lines.len(),
theirs_lines.len(),
"{f}: {} line(s) here against {} in gunnar-ui/uitest/src/{f}, after \
the header and {diverged} sanctioned divergence(s). The two are \
kept in step BY COPYING; copy it again.",
mine_lines.len(),
theirs_lines.len()
);
for (n, (a, b)) in mine_lines.iter().zip(theirs_lines.iter()).enumerate() {
assert_eq!(
a,
b,
"{f} line {} differs from gunnar-ui's:\n here: {a}\n gunnar-ui: {b}\n\
Either copy gunnar-ui's file over this one, or mark the change \
with a `{DIVERGES}` comment saying what was measured.",
n + 1
);
}
}
}
#[cfg(test)]
mod unit {
use super::*;
/// The header stripper takes the attribution and the `allow`, and NOTHING
/// else — a `//!` module doc that is not the attribution must survive, or
/// the guard would compare two files it had silently truncated.
#[test]
fn strip_header_takes_only_the_attribution() {
let text = "//! Copied from gunnar-ui/uitest/src/cdp.rs (one implementation)\n\
#![allow(dead_code)] // copied whole\n\
//! A real doc line.\n\
fn f() {}\n";
let (lines, dropped) = strip_header(text);
assert_eq!(dropped, 2);
assert_eq!(lines, vec!["//! A real doc line.", "fn f() {}"]);
let (lines, dropped) = strip_header("fn f() {}\n");
assert_eq!(dropped, 0, "no attribution is 0, and the test asserts on it");
assert_eq!(lines, vec!["fn f() {}"]);
}
/// A divergence eats its comment run and exactly one code line. RED when
/// broken on both halves: eating zero code lines would let a marked comment
/// hide a whole added block, and eating the rest of the file would let it
/// hide everything after it.
#[test]
fn take_divergences_eats_the_comment_run_and_one_line() {
let lines = vec![
" a,",
" // DIVERGES from the gunnar-ui copy, on a measurement:",
" // second comment line",
" \"--flag\",",
" b,",
];
let (kept, n) = take_divergences(&lines);
assert_eq!(n, 1);
assert_eq!(kept, vec![" a,", " b,"]);
let none = vec![" a,", " b,"];
let (kept, n) = take_divergences(&none);
assert_eq!(n, 0);
assert_eq!(kept, none);
}
}