store: tests for mutation survivors; drop pre-checks the rehearsal covers
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
From the first store mutation run (324 caught of 396 viable): - receive_payment and pay_bill repeated the engine's refusals by hand after rehearsing the engine itself, so those checks could never fire (their mutants survived). Removed: the rehearsal is the check. - New hand-computed tests: a disposal's final catch-up after some depreciation was posted (200 of 300, gain 100); a disposal on the purchase date (allowed) or the day before (refused); a retained earnings close with a sweep replays it; a float inside an array is refused; the viewer's journal and head hash. - The concurrency test's reader stops when the writer thread ends, not only when it says it's done, so a mutant that kills the writer fails the test at once instead of spinning to the five-minute timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
1 parent
db00b74e82
commit
0cf8fb842f
3 files changed
+160
-48
No files matched your search
@@ -1474,31 +1474,8 @@ impl Store {
|
||||
ensure_on(l, &ledger_core::RECEIVABLES)?;
|
||||
l.receive_payment(invoice_id, date, amount, cash_account)
|
||||
})?;
|
||||
// Pure pre-validation mirroring Ledger::receive_payment, plus the
|
||||
// account checks post_entry would perform: a failed post after the
|
||||
// journal writes would leave the journal ahead of the ledger.
|
||||
if amount <= Decimal::ZERO {
|
||||
return Err(LedgerError::InvalidPaymentAmount(amount).into());
|
||||
}
|
||||
let balance = self
|
||||
.ledger
|
||||
.get_invoice(invoice_id)
|
||||
.ok_or(LedgerError::UnknownInvoice(invoice_id))?
|
||||
.balance();
|
||||
if amount > balance {
|
||||
return Err(LedgerError::Overpayment(amount, balance).into());
|
||||
}
|
||||
if let Some(pid) = self.ledger.closed_period_containing(date) {
|
||||
return Err(LedgerError::ClosedPeriod(pid, date.to_string()).into());
|
||||
}
|
||||
let cash = self
|
||||
.ledger
|
||||
.chart()
|
||||
.get(cash_account)
|
||||
.ok_or(LedgerError::UnknownAccount(cash_account))?;
|
||||
if cash.placeholder {
|
||||
return Err(LedgerError::PlaceholderAccount(cash.code.clone()).into());
|
||||
}
|
||||
// The rehearsal above is the whole check: hand-written mirrors of
|
||||
// the engine's refusals drift from it (and were never reached).
|
||||
let ar = self.ensure_control_account(&ledger_core::RECEIVABLES)?;
|
||||
let description = format!("Payment on invoice {invoice_id}");
|
||||
let (entry_id, mut journaled) =
|
||||
@@ -1536,28 +1513,6 @@ impl Store {
|
||||
ensure_on(l, &ledger_core::PAYABLES)?;
|
||||
l.pay_bill(bill_id, date, amount, cash_account)
|
||||
})?;
|
||||
if amount <= Decimal::ZERO {
|
||||
return Err(LedgerError::InvalidPaymentAmount(amount).into());
|
||||
}
|
||||
let balance = self
|
||||
.ledger
|
||||
.get_bill(bill_id)
|
||||
.ok_or(LedgerError::UnknownBill(bill_id))?
|
||||
.balance();
|
||||
if amount > balance {
|
||||
return Err(LedgerError::Overpayment(amount, balance).into());
|
||||
}
|
||||
if let Some(pid) = self.ledger.closed_period_containing(date) {
|
||||
return Err(LedgerError::ClosedPeriod(pid, date.to_string()).into());
|
||||
}
|
||||
let cash = self
|
||||
.ledger
|
||||
.chart()
|
||||
.get(cash_account)
|
||||
.ok_or(LedgerError::UnknownAccount(cash_account))?;
|
||||
if cash.placeholder {
|
||||
return Err(LedgerError::PlaceholderAccount(cash.code.clone()).into());
|
||||
}
|
||||
let ap = self.ensure_control_account(&ledger_core::PAYABLES)?;
|
||||
let description = format!("Payment on bill {bill_id}");
|
||||
let (entry_id, mut journaled) =
|
||||
|
||||
Reference in new issue
Block a user