mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 11:35:53 +00:00
Add a distinction between a "valid" and a "representable" Number
- "valid" means the value is <= Number::maxIntValue, which has been changed to maxMantissa / 100. A valid number could get bigger and be ok - such as when paying late interest on a loan. - "representable" means the value is <= Number::maxMantissa. An unrepresentable number WILL be rounded or truncated. - Adds a fourth level of enforcement: "compatible". It is used for converting XRP to Number (for AMM), and when doing explicit checks. - "weak" will now throw if the number is unrepresentable.
This commit is contained in:
@@ -737,28 +737,87 @@ public:
|
||||
Number a{100};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::none);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{1, 30};
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = -100;
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
{
|
||||
Number a{100, Number::compatible};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::compatible);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{1, 15};
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{1, 30, Number::none};
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
a = -100;
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::compatible);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{5, Number::weak};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::weak);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{5, Number::strong};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::strong);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
{
|
||||
Number a{100, Number::weak};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::weak);
|
||||
BEAST_EXPECT(a.valid());
|
||||
a = Number{1, 30, Number::none};
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{1, 15};
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
try
|
||||
{
|
||||
a = Number{1, 30, Number::compatible};
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::overflow_error const& e)
|
||||
{
|
||||
BEAST_EXPECT(e.what() == "Number::operator= integer overflow"s);
|
||||
// The throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT((a == Number{1, 30}));
|
||||
}
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::weak);
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
a = -100;
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::weak);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
a = Number{5, Number::strong};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::strong);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
{
|
||||
Number a{100, Number::strong};
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::strong);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
try
|
||||
{
|
||||
a = Number{1, 15, Number::compatible};
|
||||
BEAST_EXPECT(false);
|
||||
}
|
||||
catch (std::overflow_error const& e)
|
||||
{
|
||||
BEAST_EXPECT(e.what() == "Number::operator= integer overflow"s);
|
||||
// The throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT((a == Number{1, 15}));
|
||||
}
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
try
|
||||
{
|
||||
a = Number{1, 30};
|
||||
@@ -771,15 +830,19 @@ public:
|
||||
BEAST_EXPECT((a == Number{1, 30}));
|
||||
}
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
a = -100;
|
||||
BEAST_EXPECT(a.integerEnforcement() == Number::strong);
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
{
|
||||
Number a{INITIAL_XRP.drops(), Number::weak};
|
||||
Number a{INITIAL_XRP.drops(), Number::compatible};
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
a = -a;
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
|
||||
try
|
||||
{
|
||||
@@ -795,6 +858,7 @@ public:
|
||||
// assigned to the Number
|
||||
BEAST_EXPECT(a == -INITIAL_XRP);
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -808,6 +872,7 @@ public:
|
||||
// assigned to the Number
|
||||
BEAST_EXPECT(a == -INITIAL_XRP);
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
}
|
||||
a = Number::maxIntValue;
|
||||
try
|
||||
@@ -821,6 +886,7 @@ public:
|
||||
// This time, the throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT(a == Number::maxIntValue + 1);
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
a = -Number::maxIntValue;
|
||||
try
|
||||
@@ -834,6 +900,7 @@ public:
|
||||
// This time, the throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT(a == -Number::maxIntValue - 1);
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
a = Number(1, 10);
|
||||
try
|
||||
@@ -848,6 +915,7 @@ public:
|
||||
// The throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT((a == Number{1, 20}));
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -860,6 +928,7 @@ public:
|
||||
// The throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT((a == Number::maxIntValue * 2));
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
try
|
||||
{
|
||||
@@ -872,6 +941,7 @@ public:
|
||||
// The Number doesn't get updated because the ctor throws
|
||||
BEAST_EXPECT((a == Number::maxIntValue * 2));
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
a = Number(1, 10);
|
||||
try
|
||||
@@ -885,10 +955,12 @@ public:
|
||||
// The throw is done _after_ the number is updated.
|
||||
BEAST_EXPECT((a == Number{1, 20}));
|
||||
BEAST_EXPECT(!a.valid());
|
||||
BEAST_EXPECT(!a.representable());
|
||||
}
|
||||
a /= Number(1, 15);
|
||||
BEAST_EXPECT((a == Number{1, 5}));
|
||||
BEAST_EXPECT(a.valid());
|
||||
BEAST_EXPECT(a.representable());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user