mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-03 17:35:51 +00:00
Resolve some of these annoying test rounding issues`
This commit is contained in:
@@ -164,9 +164,14 @@ class Loan_test : public beast::unit_test::suite
|
|||||||
paymentInterval,
|
paymentInterval,
|
||||||
paymentsRemaining,
|
paymentsRemaining,
|
||||||
managementFeeRate);
|
managementFeeRate);
|
||||||
|
auto const brokerDebt = brokerSle->at(sfDebtTotal);
|
||||||
auto const expectedDebt = principalOutstanding + loanInterest;
|
auto const expectedDebt = principalOutstanding + loanInterest;
|
||||||
env.test.BEAST_EXPECT(
|
env.test.BEAST_EXPECT(
|
||||||
brokerSle->at(sfDebtTotal) == expectedDebt);
|
// Allow some slop for rounding
|
||||||
|
brokerDebt == expectedDebt ||
|
||||||
|
(expectedDebt != Number(0) &&
|
||||||
|
((brokerDebt - expectedDebt) / expectedDebt <
|
||||||
|
Number(1, -2))));
|
||||||
env.test.BEAST_EXPECT(
|
env.test.BEAST_EXPECT(
|
||||||
env.balance(pseudoAccount, broker.asset).number() ==
|
env.balance(pseudoAccount, broker.asset).number() ==
|
||||||
brokerSle->at(sfCoverAvailable) + assetsAvailable);
|
brokerSle->at(sfCoverAvailable) + assetsAvailable);
|
||||||
@@ -1484,15 +1489,14 @@ class Loan_test : public beast::unit_test::suite
|
|||||||
// remaining
|
// remaining
|
||||||
auto const rateFactor =
|
auto const rateFactor =
|
||||||
power(1 + periodicRate, state.paymentRemaining);
|
power(1 + periodicRate, state.paymentRemaining);
|
||||||
STAmount const periodicPayment{
|
Number const periodicPayment{
|
||||||
broker.asset,
|
|
||||||
state.principalOutstanding * periodicRate *
|
state.principalOutstanding * periodicRate *
|
||||||
rateFactor / (rateFactor - 1)};
|
rateFactor / (rateFactor - 1)};
|
||||||
// Only check the first payment since the rounding may
|
// Only check the first payment since the rounding may
|
||||||
// drift as payments are made
|
// drift as payments are made
|
||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
state.paymentRemaining < 12 ||
|
state.paymentRemaining < 12 ||
|
||||||
periodicPayment ==
|
STAmount(broker.asset, periodicPayment) ==
|
||||||
broker.asset(Number(8333457001162141, -14)));
|
broker.asset(Number(8333457001162141, -14)));
|
||||||
// Include the service fee
|
// Include the service fee
|
||||||
STAmount const totalDue{
|
STAmount const totalDue{
|
||||||
@@ -1534,7 +1538,7 @@ class Loan_test : public beast::unit_test::suite
|
|||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
state.paymentRemaining < 12 ||
|
state.paymentRemaining < 12 ||
|
||||||
principal ==
|
principal ==
|
||||||
broker.asset(Number(8333228700000000, -14)));
|
broker.asset(Number(8333228690659858, -14)));
|
||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
principal > Number(0) &&
|
principal > Number(0) &&
|
||||||
principal <= state.principalOutstanding);
|
principal <= state.principalOutstanding);
|
||||||
@@ -1558,10 +1562,18 @@ class Loan_test : public beast::unit_test::suite
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the result
|
// Check the result
|
||||||
BEAST_EXPECT(
|
auto const borrowerBalance =
|
||||||
env.balance(borrower, broker.asset) ==
|
env.balance(borrower, broker.asset);
|
||||||
|
auto const expectedBalance =
|
||||||
borrowerBalanceBeforePayment - totalDueAmount -
|
borrowerBalanceBeforePayment - totalDueAmount -
|
||||||
adjustment);
|
adjustment;
|
||||||
|
BEAST_EXPECT(
|
||||||
|
borrowerBalance == expectedBalance ||
|
||||||
|
(!broker.asset.raw().native() &&
|
||||||
|
broker.asset.raw().holds<Issue>() &&
|
||||||
|
((borrowerBalance - expectedBalance) /
|
||||||
|
expectedBalance <
|
||||||
|
Number(1, -4))));
|
||||||
|
|
||||||
--state.paymentRemaining;
|
--state.paymentRemaining;
|
||||||
state.previousPaymentDate = state.nextPaymentDate;
|
state.previousPaymentDate = state.nextPaymentDate;
|
||||||
|
|||||||
@@ -437,21 +437,21 @@ loanComputePaymentParts(
|
|||||||
// if the payment is not late nor if it's a full payment, then it must be a
|
// if the payment is not late nor if it's a full payment, then it must be a
|
||||||
// periodic one, with possible overpayments
|
// periodic one, with possible overpayments
|
||||||
|
|
||||||
|
auto const totalDue =
|
||||||
|
roundToAsset(asset, periodicPaymentAmount + serviceFee, Number::upward);
|
||||||
|
|
||||||
std::optional<NumberRoundModeGuard> mg(Number::downward);
|
std::optional<NumberRoundModeGuard> mg(Number::downward);
|
||||||
std::int64_t const fullPeriodicPayments = [&]() {
|
std::int64_t const fullPeriodicPayments = [&]() {
|
||||||
std::int64_t const full{
|
std::int64_t const full{amount / totalDue};
|
||||||
amount /
|
|
||||||
roundToAsset(
|
|
||||||
asset, (periodicPaymentAmount + serviceFee), Number::upward)};
|
|
||||||
return full < paymentRemainingField ? full : paymentRemainingField;
|
return full < paymentRemainingField ? full : paymentRemainingField;
|
||||||
}();
|
}();
|
||||||
mg.reset();
|
mg.reset();
|
||||||
// Temporary asserts
|
// Temporary asserts
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
amount >= periodicPaymentAmount || fullPeriodicPayments == 0,
|
amount >= totalDue || fullPeriodicPayments == 0,
|
||||||
"temp full periodic rounding");
|
"temp full periodic rounding");
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
amount < periodicPaymentAmount || fullPeriodicPayments >= 1,
|
amount < totalDue || fullPeriodicPayments >= 1,
|
||||||
"temp full periodic rounding");
|
"temp full periodic rounding");
|
||||||
|
|
||||||
if (fullPeriodicPayments < 1)
|
if (fullPeriodicPayments < 1)
|
||||||
@@ -499,7 +499,7 @@ loanComputePaymentParts(
|
|||||||
{
|
{
|
||||||
Number const overpayment = std::min(
|
Number const overpayment = std::min(
|
||||||
principalOutstandingField.value(),
|
principalOutstandingField.value(),
|
||||||
amount - periodicPaymentAmount * fullPeriodicPayments);
|
amount - (totalPrincipalPaid + totalInterestPaid + totalFeePaid));
|
||||||
|
|
||||||
if (roundToAsset(asset, overpayment) > 0)
|
if (roundToAsset(asset, overpayment) > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ loanPeriodicPayment(
|
|||||||
// TODO: Need a better name
|
// TODO: Need a better name
|
||||||
Number const timeFactor = power(1 + periodicRate, paymentsRemaining);
|
Number const timeFactor = power(1 + periodicRate, paymentsRemaining);
|
||||||
|
|
||||||
return principalOutstanding * (periodicRate * timeFactor) /
|
return principalOutstanding * periodicRate * timeFactor / (timeFactor - 1);
|
||||||
(timeFactor - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Number
|
Number
|
||||||
|
|||||||
Reference in New Issue
Block a user