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

nordisk/monetize

crates/monetize-server/src/oversell/tests.rs

//! The sold-capacity gate on the host. The customer-facing half — the words a
//! refused buyer reads, over the real wire — is
//! `tests/paid_signup.rs::a_fleet_sold_past_its_allowance_mints_no_checkout…`.

use std::collections::BTreeMap;
use std::sync::Arc;

use monetize_product::{EntitlementFact, Growth, Servable, State, TenantId, Usage};

use super::*;
use crate::registry::Registry;

const GIB: u64 = 1 << 30;
/// The plan every fixture here sells: gunnar's 10 GiB month.
const CAP: u64 = 10 * GIB;

/// **The live front's shape, measured 2026-09-18**: a data set that holds
/// ~38 GiB, tenants with 10 GiB caps, and every one of them nearly empty — which
/// is why `can_absorb` answered yes to all of them. `tenants` of them exist
/// already, each holding a quarter of a gigabyte of its ten.
fn a_fleet_of(tenants: usize) -> (AppState, Arc<monetize::testing::MockProduct>) {
    let product = Arc::new(monetize::testing::MockProduct::gunnar());
    // 38 GiB of iron, whatever the tenants are holding: each has written a
    // quarter of a gigabyte of its ten, and `servable` is what is left beyond
    // that — which is how gunnar reports it.
    let each = GIB / 4;
    let written = each * tenants as u64;
    *product.servable.lock().unwrap() = Some(Servable::Measured {
        servable_bytes: 38 * GIB - written,
        total_bytes: 38 * GIB,
        growth: Growth::Unknown("not asked in this fixture".into()),
        ceilings: Default::default(),
    });
    let state = AppState::in_memory(Registry::new().shared_product(product.clone()));
    for i in 0..tenants {
        let tenant = format!("t{i}");
        state
            .usage
            .put(
                "gunnar",
                &tenant,
                &Usage {
                    meters: [("pack_bytes".to_string(), each)].into(),
                    measured_at_unix_ms: 1,
                },
            )
            .unwrap();
        state
            .ledger
            .set_entitlement(
                "gunnar",
                &state.signer_for("gunnar").sign_fact(EntitlementFact {
                    tenant: TenantId(tenant),
                    plan: "gunnar/10gb-1m".into(),
                    state: State::Paid,
                    paid_until_unix_ms: Some(2),
                    caps: BTreeMap::from([("pack_bytes".to_string(), CAP)]),
                    source: "payment:mockpay:x".into(),
                    signature: Vec::new(),
                    issued_unix_ms: None,
                    issued_signature: Vec::new(),
                }),
            )
            .unwrap();
    }
    (state, product)
}

fn the_product(state: &AppState) -> monetize_product::Served<'_> {
    state.registry.products().next().unwrap()
}

/// (r) **A FLEET SOLD PAST ITS ALLOWANCE REFUSES THE NEXT SIGNUP — and the
/// allowance is a number the operator chose.**
///
/// The fixture is the front: eleven tenants at 10 GiB against 38 GiB of iron,
/// all of them nearly empty. `can_absorb` — the only gate there was — answers
/// yes to every one of them, because 35 GiB really is free; the promise is what
/// is gone. At the default 300 % the eleven that exist are inside the allowance
/// (110 GiB of 114) and the TWELFTH is refused, which is exactly the shape a
/// default has to have: it does not break the deployment that exists and it
/// does not let it grow without limit.
///
/// Asserted on the BYTES and on the allowance, not on the arm: a gate that
/// refused everything would satisfy "refuses when oversold" and sell nothing.
#[test]
fn a_fleet_sold_past_the_allowance_refuses_the_next_signup_and_the_allowance_is_configurable() {
    let (state, _p) = a_fleet_of(11);
    let product = the_product(&state);

    // 110 GiB promised, 38 GiB of iron, 114 GiB permitted at the default.
    let twelfth = room(&state, product, CAP, 0, DEFAULT_MAX_SOLD_PERCENT);
    match twelfth {
        Room::Oversold {
            by,
            over_allowance,
            promised,
            capacity,
            allowed,
            ..
        } => {
            assert_eq!(promised, 120 * GIB, "eleven caps plus the one being sold");
            assert_eq!(
                capacity,
                38 * GIB,
                "what the tenants hold plus what is still servable beyond it"
            );
            assert_eq!(allowed, 114 * GIB, "300 % of the iron");
            assert_eq!(
                by,
                82 * GIB,
                "the raw oversell: 120 GiB promised against 38 GiB of iron"
            );
            assert_eq!(
                over_allowance,
                6 * GIB,
                "and 6 GiB of it is past what this deployment permits"
            );
        }
        other => panic!("the twelfth 10 GiB plan must not be sold at 300 %: {other:?}"),
    }

    // The ELEVEN that exist were inside it — the default does not break the
    // deployment it found.
    assert!(
        matches!(room(&state, product, 0, 0, DEFAULT_MAX_SOLD_PERCENT), Room::Fits { promised, .. } if promised == 110 * GIB)
    );

    // **The operator's number is honoured, both ways.** 400 % sells the twelfth;
    // 100 % — never promise a byte that does not exist — refuses even the fleet
    // as it stands.
    assert!(
        matches!(room(&state, product, CAP, 0, 400), Room::Fits { allowed, .. } if allowed == 152 * GIB),
        "{:?}",
        room(&state, product, CAP, 0, 400)
    );
    match room(&state, product, 0, 0, 100) {
        Room::Oversold {
            allowed,
            over_allowance,
            ..
        } => assert_eq!((allowed, over_allowance), (38 * GIB, 72 * GIB)),
        other => {
            panic!("at 100 % a fleet holding 110 GiB of caps on 38 GiB is oversold: {other:?}")
        }
    }

    // A box with room for all of it is not refused at any of them.
    let (roomy, product_handle) = a_fleet_of(11);
    *product_handle.servable.lock().unwrap() = Some(Servable::Measured {
        servable_bytes: 500 * GIB,
        total_bytes: 512 * GIB,
        growth: Growth::Unknown("x".into()),
        ceilings: Default::default(),
    });
    assert!(matches!(
        room(&roomy, the_product(&roomy), CAP, 0, 100),
        Room::Fits { .. }
    ));
}

/// (r) **The gate and the Usage page are ONE arithmetic.**
///
/// `monetize::fleet::Oversell` was already computed and rendered
/// (`services::usage::fleet_meter_to_pb`); the bug was that it gated nothing. A
/// gate that grew its own sum would be a second number that could disagree with
/// the screen an operator is arguing with, so this holds the fold with no sale
/// added against `FleetTotal::oversell` itself, byte for byte.
#[test]
fn the_gate_reads_the_same_oversell_number_the_usage_page_renders() {
    let (state, product) = a_fleet_of(11);
    let meter = monetize::testing::MockProduct::GUNNAR_METERS
        .iter()
        .find(|m| m.name == "pack_bytes")
        .unwrap();
    let usages = state.usage.all("gunnar").unwrap();
    let facts = state.ledger.entitlements("gunnar").unwrap();
    let report = monetize::fleet::total(meter, &usages, &facts, &product.servable())
        .expect("pack_bytes is per tenant");

    let monetize::fleet::Oversell::Oversold { by: reported } = report.oversell() else {
        panic!("the fixture is oversold: {:?}", report.oversell())
    };
    match room(&state, the_product(&state), 0, 0, 100) {
        Room::Oversold {
            by,
            promised,
            capacity,
            ..
        } => {
            assert_eq!(
                by, reported,
                "the gate measured a different oversell from the one the page shows"
            );
            assert_eq!(
                (promised, capacity),
                (report.allowance, report.capacity().unwrap())
            );
        }
        other => panic!("{other:?}"),
    }
    // And the sale under consideration is the only difference between them.
    let with_sale = room(&state, the_product(&state), CAP, 0, 100);
    assert!(
        matches!(with_sale, Room::Oversold { by, .. } if by == reported + CAP),
        "{with_sale:?}"
    );
}

/// (r) **TWO SIGNUPS RACING FOR THE LAST SLOT: exactly one is told yes.**
///
/// Before the hold, `Signup.Start` read the stored caps, decided, and returned;
/// two calls that overlapped both read the same fleet and both minted a live
/// checkout for the same last slot. The fold and the hold are now one critical
/// section, so the loser counts the winner's bytes.
///
/// Ten tenants at 10 GiB on 38 GiB of iron: 114 GiB permitted, so ONE more plan
/// fits (110) and two do not (120). Both threads ask at once.
#[test]
fn two_signups_racing_for_the_last_slot_are_not_both_told_yes() {
    let (state, _p) = a_fleet_of(10);
    let product = the_product(&state);
    assert!(
        matches!(
            room(&state, product, CAP, 0, DEFAULT_MAX_SOLD_PERCENT),
            Room::Fits { .. }
        ),
        "the fixture has room for exactly one"
    );
    assert!(
        matches!(
            room(&state, product, 2 * CAP, 0, DEFAULT_MAX_SOLD_PERCENT),
            Room::Oversold { .. }
        ),
        "and not for two"
    );

    // The single-threaded statement of the same rule, which is the one that
    // fails for good if the hold is ever taken after the fold instead of with
    // it: one `Start` is inside the gate (its hold alive, nothing minted yet)
    // and the next is refused.
    {
        let _first = admit(&state, product, CAP).expect("the first takes the last slot");
        assert!(
            admit(&state, the_product(&state), CAP).is_err(),
            "the slot being paid for was not counted"
        );
    }
    assert_eq!(
        state.signup_reservations.held_bytes("gunnar"),
        0,
        "the first hold was dropped with the scope"
    );

    // Both threads KEEP their answer while the other asks — the barrier is what
    // makes the overlap real rather than two calls that happened to be on
    // different threads. A hold dropped before the second thread ran would
    // prove nothing, because the slot would be free again.
    let gate = std::sync::Barrier::new(2);
    let outcomes: Vec<Result<u64, String>> = std::thread::scope(|scope| {
        let handles: Vec<_> = (0..2)
            .map(|_| {
                scope.spawn(|| {
                    let held = admit(&state, the_product(&state), CAP);
                    gate.wait();
                    held.map(|h| h.bytes)
                })
            })
            .collect();
        handles.into_iter().map(|h| h.join().unwrap()).collect()
    });
    let sold = outcomes.iter().filter(|o| o.is_ok()).count();
    assert_eq!(sold, 1, "both racers were sold the last slot: {outcomes:?}");
    let why = outcomes.iter().find_map(|o| o.as_ref().err()).unwrap();
    assert!(
        why.contains("max_sold_percent_of_capacity=300"),
        "the refusal names the knob that decided it: {why}"
    );

    // Both holds are gone with the threads, so the slot is free again: a
    // customer who closed the tab must not cost the shop a slot for ever.
    assert_eq!(state.signup_reservations.held_bytes("gunnar"), 0);
    assert!(admit(&state, the_product(&state), CAP).is_ok());
}

/// (r) **A minted checkout holds its slot until the session is decided** — and
/// a settled session releases it, so the caps are never counted twice.
///
/// The double count is not academic: the moment a signup is CREATED its cap is
/// in `signup_facts`, and a hold still standing beside it would refuse the next
/// customer for a plan that has already been counted.
#[test]
fn a_minted_checkout_holds_its_slot_until_the_webhook_settles_it() {
    let (state, _p) = a_fleet_of(10);
    let hold = admit(&state, the_product(&state), CAP).expect("there is room for one");
    hold.minted("mockpay", "cs_holding");
    assert_eq!(
        state.signup_reservations.held_bytes("gunnar"),
        CAP,
        "a minted checkout keeps the slot"
    );

    // With the slot held, the next buyer is refused: 110 GiB of caps plus 10
    // being paid for right now is 120, past the 114 permitted.
    assert!(
        admit(&state, the_product(&state), CAP).is_err(),
        "the held slot was not counted"
    );

    // The webhook lands and the session is decided. The record now carries the
    // caps, so the hold is dropped on the next fold.
    let mut signup = crate::signup::tests::a_signup("cs_holding", "bob");
    signup.plan = "gunnar/10gb-1m".into();
    state.signups.record_pending(&signup, 1).unwrap();
    assert_eq!(
        state.signup_reservations.held_bytes("gunnar"),
        CAP,
        "a PENDING session is still being paid for"
    );
    state
        .signups
        .set(
            "mockpay",
            "cs_holding",
            crate::signup::SignupState::Created {
                namespace: "bob".into(),
                username: "bob".into(),
                at_unix_ms: 2,
            },
        )
        .unwrap();
    // The fold prunes it — and the new tenant's own cap is now in the sum, so
    // the answer is the same refusal for a different and correct reason.
    let _ = admit(&state, the_product(&state), CAP);
    assert_eq!(
        state.signup_reservations.held_bytes("gunnar"),
        0,
        "a decided session's hold was kept as well as its record"
    );
}

/// (r) **A box that did not measure is not a yes and not a no: the gate says it
/// did not run.**
///
/// The live appliance answered `Servable::Unmeasured` for months (it predates
/// gunnar's `Admin.Capacity`), and every deployment is in that state for its
/// first poll tick. A fold with no figure has no second opinion to give — the
/// live `can_absorb` question has already been put to the box and answered — so
/// this arm exists to be REPORTED rather than to be turned into a verdict.
/// Asserted on the arm and on the product's own words travelling with it.
#[test]
fn an_unmeasured_box_leaves_the_gate_unrun_rather_than_answering_for_it() {
    let (state, product) = a_fleet_of(11);
    let why = "this gunnar has no Admin.Capacity RPC — it predates it";
    *product.servable.lock().unwrap() = Some(Servable::Unmeasured(why.into()));

    match room(&state, the_product(&state), CAP, 0, 100) {
        Room::NotChecked(said) => assert_eq!(
            said, why,
            "the product's own reason was replaced by a paraphrase"
        ),
        other => panic!("silence must not become a verdict: {other:?}"),
    }
    // It still admits — and the admission is the loud one, not a claim of room.
    assert!(admit(&state, the_product(&state), CAP).is_ok());

    // The MEASURED arm on the same fleet refuses, so the two are genuinely
    // different paths and not one arm nothing can reach.
    *product.servable.lock().unwrap() = Some(Servable::Measured {
        servable_bytes: 35 * GIB,
        total_bytes: 38 * GIB,
        growth: Growth::Unknown("x".into()),
        ceilings: Default::default(),
    });
    assert!(admit(&state, the_product(&state), CAP).is_err());
}

/// ★ **cov-10 (rung 3 2026-10-06): an order past the oversell ceiling names
/// the room left under it.** The KVM mock's 500 GiB plan, refused by
/// `max_sold_percent_of_capacity`, read "Not offered now: we could not measure
/// the room left here" — the refusal carried no room although the room was
/// measured. 110 GiB promised of the 114 GiB 300 % of 38 GiB permits: 4 GiB left.
#[test]
fn an_order_past_the_oversell_ceiling_names_the_room_left_under_it() {
    let (mut state, product) = a_fleet_of(11);
    state.signup_max_sold_percents = BTreeMap::from([("gunnar".to_string(), 300)]);
    state.health.set_servable("gunnar", product.servable(), 1);
    let current = BTreeMap::from([("pack_bytes".to_string(), CAP)]);
    let past = admit_order(
        &state,
        the_product(&state),
        &current,
        &BTreeMap::from([("pack_bytes".to_string(), 2 * CAP)]),
    )
    .unwrap_err();
    assert_eq!(
        past.room_left_bytes,
        114 * GIB - 110 * GIB,
        "the room under the ceiling: {past:?}"
    );
    assert!(
        past.why.contains("max_sold_percent_of_capacity=300"),
        "{past:?}"
    );
}

/// (r) ★ **AN ORDER PAST THE ALLOWANCE IS REFUSED LIKE A SIGNUP**
/// (a-ceiling-s3, owner 2026-09-28: "an oversell ceiling"). The gate stood
/// in front of `Signup.Start` only; a bundle ORDER raised a tenant's cap
/// with `can_absorb` alone — free space, not the promise — so the shop went
/// on selling room past `max_sold_percent_of_capacity` one bundle at a time.
#[test]
fn an_order_past_the_allowance_is_refused_like_a_signup_and_one_inside_it_is_not() {
    let (mut state, product) = a_fleet_of(11);
    state.signup_max_sold_percents = BTreeMap::from([("gunnar".to_string(), 300)]);
    // The figure the poller cached (an order never asks the product twice).
    state.health.set_servable("gunnar", product.servable(), 1);
    let current = BTreeMap::from([("pack_bytes".to_string(), CAP)]);
    // 110 GiB promised of the 114 GiB 300 % of 38 GiB permits: +10 is 120.
    let past = admit_order(
        &state,
        the_product(&state),
        &current,
        &BTreeMap::from([("pack_bytes".to_string(), 2 * CAP)]),
    )
    .unwrap_err();
    assert!(
        past.why.contains("max_sold_percent_of_capacity=300"),
        "refused by name, with the number: {past:?}"
    );
    // +2 GiB fits (112 ≤ 114).
    admit_order(
        &state,
        the_product(&state),
        &current,
        &BTreeMap::from([("pack_bytes".to_string(), CAP + 2 * GIB)]),
    )
    .expect("an order inside the allowance is sold");
    // An order that raises nothing sold (another meter) is not this gate's.
    admit_order(&state, the_product(&state), &current, &current)
        .expect("no new promise, nothing to refuse");
}

/// gunnar-common `stderr_capture::is_warning`: the words that make a captured
/// stderr line a WARN on the front (and count toward the log gate's spam).
fn is_warning(line: &str) -> bool {
    line.contains("FAILED")
        || line.contains("REFUSED")
        || line.contains("panicked")
        || line.to_ascii_lowercase().contains(" error")
}

/// ★ **A queued order is said ONCE, as INFO** (round 5.3, coordinator
/// 2026-10-08: test2's receipt went red on `order capacity: REFUSED` WARN ×7
/// in 60 s — the window quoting the 500 GiB row on every load): the first
/// time an order queues its line names the reference and the reason and is
/// no WARN; the same order again says nothing; another order says its own.
#[test]
fn a_queued_order_is_said_once_as_info_with_its_reference_and_reason() {
    let why = "gunnar: this order would promise 500.0 GiB more, 630.0 GiB in all against 56.5 GiB of iron — 290.8 GiB past the 339.1 GiB this deployment permits (max_sold_percent_of_capacity=600). Raise the number only if the overselling is deliberate, or give the box more disk";
    let r1 = "gunnar/covd1/2026-10-08+pack_bytes=536870912000+plan:year";
    let line = queue_note(r1, "gunnar/covd1", why).expect("the first time it queues, it is said");
    assert!(
        line.contains(r1)
            && line.contains("queued: waits for room")
            && line.contains("290.8 GiB past"),
        "{line}"
    );
    assert!(
        !is_warning(&line),
        "a queued order is not a refusal: {line}"
    );
    assert_eq!(
        queue_note(r1, "gunnar/covd1", why),
        None,
        "the same order is said once"
    );
    assert_eq!(
        queue_note(r1, "gunnar/covd1", why),
        None,
        "and not on the next window load either"
    );
    let r2 = "gunnar/covd2/2026-10-08+pack_bytes=536870912000+plan:year";
    assert!(
        queue_note(r2, "gunnar/covd2", why).is_some(),
        "another order says its own line"
    );
    let loud = queue_note(
        "gunnar/covd3/x",
        "gunnar/covd3",
        "REFUSED by the wall: an error FAILED and panicked",
    )
    .unwrap();
    assert!(
        !is_warning(&loud),
        "a reason carrying WARN words is said without them: {loud}"
    );
}

/// The estate order's line, the moment it queues (the lay queue over the
/// cap): its reference, its reason, and no WARN.
#[test]
fn an_estate_order_queued_over_the_cap_is_said_as_info() {
    let l = crate::estate_order::queued_line(
        "estate/acme/2026-10-08",
        "orders wait: raise the cap: the upcloud cap REFUSED this estate",
    );
    assert!(
        l.contains("estate/acme/2026-10-08")
            && l.contains("queued: waits for the cap")
            && l.contains("orders wait: raise the cap"),
        "{l}"
    );
    assert!(!is_warning(&l), "{l}");
}

/// ★ ST-11 (STINKY 2026-10-11): **each site of the product is sold against its OWN box.** The
/// home (gunnar.rs) has sold its eleven 10 GiB plans against its 38 GiB; test2 has sold
/// nothing on its own 50 GiB. A test2 signup fits — test2's caps against test2's iron — and a
/// home signup is still the twelfth; test2's tenants are never counted on the home's box.
#[test]
fn each_site_is_sold_against_its_own_box() {
    let (state, product) = a_fleet_of(11);
    let product_ref = the_product(&state);
    state.registry.declare_home("gunnar", "gunnar-rs");
    product.servable_by_estate.lock().unwrap().insert(
        "test2-gunnar-rs".into(),
        Servable::Measured {
            servable_bytes: 50 * GIB,
            total_bytes: 50 * GIB,
            growth: Growth::Unknown("x".into()),
            ceilings: Default::default(),
        },
    );
    // One test2 tenant already holding a 10 GiB plan: counted on test2, never on the home.
    state
        .ledger
        .set_entitlement(
            "gunnar",
            &state.signer_for("gunnar").sign_fact(EntitlementFact {
                tenant: TenantId::on_estate("test2-gunnar-rs", "nina"),
                plan: "gunnar/10gb-1m".into(),
                state: State::Paid,
                paid_until_unix_ms: Some(2),
                caps: BTreeMap::from([("pack_bytes".to_string(), CAP)]),
                source: "payment:mockpay:x".into(),
                signature: Vec::new(),
                issued_unix_ms: None,
                issued_signature: Vec::new(),
            }),
        )
        .unwrap();
    match room_on(
        &state,
        product_ref,
        CAP,
        0,
        DEFAULT_MAX_SOLD_PERCENT,
        Some("test2-gunnar-rs"),
    ) {
        Room::Fits {
            promised, capacity, ..
        } => assert_eq!(
            (promised, capacity),
            (20 * GIB, 50 * GIB),
            "test2's own caps against test2's own box"
        ),
        other => panic!("test2 has room of its own: {other:?}"),
    }
    match room_on(&state, product_ref, CAP, 0, DEFAULT_MAX_SOLD_PERCENT, None) {
        Room::Oversold {
            promised, capacity, ..
        } => assert_eq!(
            (promised, capacity),
            (120 * GIB, 38 * GIB),
            "the home's eleven plus this one; test2's nina is not the home's"
        ),
        other => panic!("the home is still sold out: {other:?}"),
    }
}