crates/monetize-server/src/estate_order/tests/site_dropped.rs
//! ★ **PROD-FIX 2 (prod ONE box 2026-10-26 17:19Z)**: `estate order estate/test3holgerrs:
//! REFUSED [estate-undeclared] test3-holger-rs is not a site this monetize sells GUNNAR for`,
//! every 2 s. A HOLGER site's run was looked up as GUNNAR: once its site left the feed, the
//! run's product fell back to the shop's default. And the refusal was asked again on every
//! tick. Now the run's product comes from its own site and order, never a default; a refusal
//! of that kind is final: the run is stopped by name, marked, ALERTed once, and looked at again
//! only after a back-off (or once the feed declares its site again).
use super::*;
/// A shop that sells Gunnar with Holger sites: `holger-rs` stays declared, `test3-holger-rs`
/// leaves the feed after its estate was laid.
fn dropped_rig(name: &str) -> Rig {
let dir = tmp(name);
let pay = HoldPay::default();
let cloud = Arc::new(MockCloud::new());
let kit = FakeKit::new("PASS");
let site = |product: &str, site: &str| crate::config::EstateConfig {
product: product.into(),
vendor: "holdpay".into(),
site: site.into(),
..Default::default()
};
let reg = Registry::new()
.sells("gunnar", pay.clone())
.cloud(cloud.clone())
.shared_product(shop_product())
.home("gunnar", "gunnar-rs")
.estate("gunnar-rs", site("gunnar", "gunnar.rs"))
.estate("holger-rs", site("holger", "holger.rs"))
.estate("test3-holger-rs", site("holger", "test3.holger.rs"));
let (state, clock, mails, health) = build_in(
reg,
&dir,
EstateOrderConfig {
vendor: String::new(),
apex: String::new(),
lifecycle: "gunnar".into(),
..cfg()
},
kit.clone(),
None,
None,
);
let r = Rig {
state,
pay,
cloud,
kit,
dir,
clock,
mails,
health,
};
start_on(
&r.state,
Some("test3-holger-rs"),
"test3holgerrs",
"ops@mock.invalid",
"",
"ignalina",
&EstateSizes::default(),
)
.unwrap();
r.pay.authorize(&handle_of(&r, "test3holgerrs"));
drive(&r.state, "test3holgerrs");
drive(&r.state, "test3holgerrs");
assert_eq!(
r.state.estates.get("test3holgerrs").unwrap().phase,
phase::CAPTURED
);
// The feed no longer declares the site.
r.state.registry.forget_estate("test3-holger-rs");
r
}
/// ★ RED: the run's refusal names ITS product (holger), never the shop's default.
#[test]
fn a_run_whose_site_left_the_feed_is_refused_as_its_own_product_never_the_shops_default() {
let r = dropped_rig("site-dropped-product");
let run = r.state.estates.get("test3holgerrs").unwrap();
let why = terms_of(&r.state, r.state.estates.cfg.as_ref().unwrap(), &run)
.expect_err("its site is gone");
assert!(
why.contains("[estate-undeclared]") && why.contains("sells holger for"),
"the Holger site's run is looked up as Holger: {why}"
);
assert!(!why.contains("gunnar"), "never as the shop's Gunnar: {why}");
}
/// ★ RED: the refusal is FINAL — a minute of 2 s ticks stops the run by name ONCE (marked,
/// one ALERT, said once), never asks again on every poll; the back-off looks again later, and
/// a site declared again resumes it.
#[test]
fn a_final_refusal_stops_its_run_once_alerts_once_and_backs_off() {
let r = dropped_rig("site-dropped-stop");
for _ in 0..30 {
r.clock.fetch_add(2_000, Ordering::SeqCst);
tick(&r.state);
}
let run = r.state.estates.get("test3holgerrs").unwrap();
assert!(
run.why.contains("[estate-undeclared]") && run.why.contains("stopped"),
"the run is marked: {}",
run.why
);
let alerts: Vec<_> = run
.history
.iter()
.filter(|t| t.note.contains("ALERT"))
.collect();
assert_eq!(
alerts.len(),
1,
"ALERTed once in a minute of ticks: {:#?}",
run.history
);
assert_eq!(
run.phase,
phase::CAPTURED,
"its phase is kept: nothing of it is given back or billed by the stop"
);
assert!(
!r.state.estates.terms_said.lock().unwrap().is_empty()
|| run.history.iter().any(|t| t.note.contains("stopped")),
"said once"
);
// The feed declares the site again: the next look after the back-off resumes the run.
r.state.registry.declare_estate(
"test3-holger-rs",
crate::config::EstateConfig {
product: "holger".into(),
vendor: "holdpay".into(),
site: "test3.holger.rs".into(),
..Default::default()
},
);
r.clock.fetch_add(11 * 60_000, Ordering::SeqCst);
tick(&r.state);
let run = r.state.estates.get("test3holgerrs").unwrap();
assert!(
!run.why.contains("stopped"),
"resumed once its site is declared again: {}",
run.why
);
}
/// ★ **OVW-2 (prod 2026-10-29): a GONE run's terms are never asked** — prod logged `REFUSED
/// [estate-undeclared] test3-holger-rs` once per process: the run of estate/test3holgerrs,
/// terminated on 2026-10-23, is kept, its site left the feed, and every tick's booking of every
/// run (`book`) still asked its terms. A gone run has nothing more to bill: the ticks say
/// nothing of it, stop nothing and book no row for it.
#[test]
fn a_gone_runs_terms_are_never_asked_once_its_site_left_the_feed() {
let r = dropped_rig("site-dropped-gone");
{
let _pen = r.state.estates.pen("test3holgerrs");
let mut run = r.state.estates.get("test3holgerrs").unwrap();
run.phase = phase::TERMINATED.into();
run.history.push(Transition {
phase: phase::TERMINATED.into(),
at_ms: r.state.now(),
note: "terminated by the operator".into(),
});
save(&r.state, &run).unwrap();
}
let rows = |r: &Rig| -> usize {
r.state
.ledger
.references_with_prefix("")
.unwrap()
.iter()
.map(|re| r.state.ledger.rows(re).unwrap().len())
.sum()
};
let before = rows(&r);
for _ in 0..10 {
r.clock.fetch_add(2_000, Ordering::SeqCst);
tick(&r.state);
}
let said = r.state.estates.terms_said.lock().unwrap().clone();
assert!(
!said.contains_key("estate/test3holgerrs"),
"a gone run's terms are not asked: {said:?}"
);
let run = r.state.estates.get("test3holgerrs").unwrap();
assert!(
run.stopped_why.is_empty() && run.phase == phase::TERMINATED,
"a gone run is neither stopped nor moved: {run:?}"
);
assert_eq!(
rows(&r),
before,
"no row is booked for a gone run whose site left the feed"
);
}