mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Price Oracle: validate input parameters and extend test coverage: (#5013)
* Price Oracle: validate input parameters and extend test coverage: Validate trim, time_threshold, document_id are valid Int, UInt, or string convertible to UInt. Validate base_asset and quote_asset are valid currency. Update error codes. Extend Oracle and GetAggregatePrice unit-tests. Denote unreachable coverage code. * Set one-line LCOV_EXCL_LINE * Move ledger_entry tests to LedgerRPC_test.cpp * Add constants for "None" * Fix LedgerRPC test --------- Co-authored-by: Scott Determan <scott.determan@yahoo.com>
This commit is contained in:
committed by
GitHub
parent
f650949573
commit
f4da2e31d9
@@ -163,7 +163,7 @@ private:
|
||||
env.fund(XRP(1'000), owner);
|
||||
Oracle oracle(env, {.owner = owner}, false);
|
||||
|
||||
// Symbol class or provider not included on create
|
||||
// Asset class or provider not included on create
|
||||
oracle.set(CreateArg{
|
||||
.assetClass = std::nullopt,
|
||||
.provider = "provider",
|
||||
@@ -174,7 +174,7 @@ private:
|
||||
.uri = "URI",
|
||||
.err = ter(temMALFORMED)});
|
||||
|
||||
// Symbol class or provider are included on update
|
||||
// Asset class or provider are included on update
|
||||
// and don't match the current values
|
||||
oracle.set(CreateArg{});
|
||||
BEAST_EXPECT(oracle.exists());
|
||||
@@ -194,7 +194,7 @@ private:
|
||||
Oracle oracle(env, {.owner = owner}, false);
|
||||
|
||||
// Fields too long
|
||||
// Symbol class
|
||||
// Asset class
|
||||
std::string assetClass(17, '0');
|
||||
oracle.set(
|
||||
CreateArg{.assetClass = assetClass, .err = ter(temMALFORMED)});
|
||||
@@ -203,6 +203,13 @@ private:
|
||||
oracle.set(CreateArg{.provider = large, .err = ter(temMALFORMED)});
|
||||
// URI
|
||||
oracle.set(CreateArg{.uri = large, .err = ter(temMALFORMED)});
|
||||
// Empty field
|
||||
// Asset class
|
||||
oracle.set(CreateArg{.assetClass = "", .err = ter(temMALFORMED)});
|
||||
// provider
|
||||
oracle.set(CreateArg{.provider = "", .err = ter(temMALFORMED)});
|
||||
// URI
|
||||
oracle.set(CreateArg{.uri = "", .err = ter(temMALFORMED)});
|
||||
}
|
||||
|
||||
{
|
||||
@@ -224,6 +231,12 @@ private:
|
||||
// Invalid update time
|
||||
using namespace std::chrono;
|
||||
Env env(*this);
|
||||
auto closeTime = [&]() {
|
||||
return duration_cast<seconds>(
|
||||
env.current()->info().closeTime.time_since_epoch() -
|
||||
10'000s)
|
||||
.count();
|
||||
};
|
||||
env.fund(XRP(1'000), owner);
|
||||
Oracle oracle(env, {.owner = owner});
|
||||
BEAST_EXPECT(oracle.exists());
|
||||
@@ -231,20 +244,25 @@ private:
|
||||
// Less than the last close time - 300s
|
||||
oracle.set(UpdateArg{
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.lastUpdateTime = testStartTime.count() + 400 - 301,
|
||||
.lastUpdateTime = static_cast<std::uint32_t>(closeTime() - 301),
|
||||
.err = ter(tecINVALID_UPDATE_TIME)});
|
||||
// Greater than last close time + 300s
|
||||
oracle.set(UpdateArg{
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.lastUpdateTime = testStartTime.count() + 400 + 301,
|
||||
.lastUpdateTime = static_cast<std::uint32_t>(closeTime() + 311),
|
||||
.err = ter(tecINVALID_UPDATE_TIME)});
|
||||
oracle.set(UpdateArg{.series = {{"XRP", "USD", 740, 1}}});
|
||||
BEAST_EXPECT(
|
||||
oracle.expectLastUpdateTime(testStartTime.count() + 450));
|
||||
BEAST_EXPECT(oracle.expectLastUpdateTime(
|
||||
static_cast<std::uint32_t>(testStartTime.count() + 450)));
|
||||
// Less than the previous lastUpdateTime
|
||||
oracle.set(UpdateArg{
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.lastUpdateTime = testStartTime.count() + 449,
|
||||
.lastUpdateTime = static_cast<std::uint32_t>(449),
|
||||
.err = ter(tecINVALID_UPDATE_TIME)});
|
||||
// Less than the epoch time
|
||||
oracle.set(UpdateArg{
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.lastUpdateTime = static_cast<int>(epoch_offset.count() - 1),
|
||||
.err = ter(tecINVALID_UPDATE_TIME)});
|
||||
}
|
||||
|
||||
@@ -284,6 +302,38 @@ private:
|
||||
.series = {{"USD", "BTC", 740, maxPriceScale + 1}},
|
||||
.err = ter(temMALFORMED)});
|
||||
}
|
||||
|
||||
{
|
||||
// Updating token pair to add and delete
|
||||
Env env(*this);
|
||||
env.fund(XRP(1'000), owner);
|
||||
Oracle oracle(env, {.owner = owner});
|
||||
oracle.set(UpdateArg{
|
||||
.series =
|
||||
{{"XRP", "EUR", std::nullopt, std::nullopt},
|
||||
{"XRP", "EUR", 740, 1}},
|
||||
.err = ter(temMALFORMED)});
|
||||
// Delete token pair that doesn't exist in this oracle
|
||||
oracle.set(UpdateArg{
|
||||
.series = {{"XRP", "EUR", std::nullopt, std::nullopt}},
|
||||
.err = ter(tecTOKEN_PAIR_NOT_FOUND)});
|
||||
// Delete token pair in oracle, which is not in the ledger
|
||||
oracle.set(UpdateArg{
|
||||
.documentID = 10,
|
||||
.series = {{"XRP", "EUR", std::nullopt, std::nullopt}},
|
||||
.err = ter(temMALFORMED)});
|
||||
}
|
||||
|
||||
{
|
||||
// Bad fee
|
||||
Env env(*this);
|
||||
env.fund(XRP(1'000), owner);
|
||||
Oracle oracle(
|
||||
env, {.owner = owner, .fee = -1, .err = ter(temBAD_FEE)});
|
||||
Oracle oracle1(env, {.owner = owner});
|
||||
oracle.set(
|
||||
UpdateArg{.owner = owner, .fee = -1, .err = ter(temBAD_FEE)});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -356,13 +406,19 @@ private:
|
||||
{.owner = bad, .seq = seq(1), .err = ter(terNO_ACCOUNT)});
|
||||
}
|
||||
|
||||
// Invalid Sequence
|
||||
// Invalid DocumentID
|
||||
oracle.remove({.documentID = 2, .err = ter(tecNO_ENTRY)});
|
||||
|
||||
// Invalid owner
|
||||
Account const invalid("invalid");
|
||||
env.fund(XRP(1'000), invalid);
|
||||
oracle.remove({.owner = invalid, .err = ter(tecNO_ENTRY)});
|
||||
|
||||
// Invalid flags
|
||||
oracle.remove({.flags = tfSellNFToken, .err = ter(temINVALID_FLAG)});
|
||||
|
||||
// Bad fee
|
||||
oracle.remove({.fee = -1, .err = ter(temBAD_FEE)});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -622,50 +678,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testLedgerEntry()
|
||||
{
|
||||
testcase("Ledger Entry");
|
||||
using namespace jtx;
|
||||
|
||||
Env env(*this);
|
||||
std::vector<AccountID> accounts;
|
||||
std::vector<std::uint32_t> oracles;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
Account const owner(std::string("owner") + std::to_string(i));
|
||||
env.fund(XRP(1'000), owner);
|
||||
// different accounts can have the same asset pair
|
||||
Oracle oracle(env, {.owner = owner, .documentID = i});
|
||||
accounts.push_back(owner.id());
|
||||
oracles.push_back(oracle.documentID());
|
||||
// same account can have different asset pair
|
||||
Oracle oracle1(env, {.owner = owner, .documentID = i + 10});
|
||||
accounts.push_back(owner.id());
|
||||
oracles.push_back(oracle1.documentID());
|
||||
}
|
||||
for (int i = 0; i < accounts.size(); ++i)
|
||||
{
|
||||
auto const jv = [&]() {
|
||||
// document id is uint32
|
||||
if (i % 2)
|
||||
return Oracle::ledgerEntry(env, accounts[i], oracles[i]);
|
||||
// document id is string
|
||||
return Oracle::ledgerEntry(
|
||||
env, accounts[i], std::to_string(oracles[i]));
|
||||
}();
|
||||
try
|
||||
{
|
||||
BEAST_EXPECT(
|
||||
jv[jss::node][jss::Owner] == to_string(accounts[i]));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
@@ -683,7 +695,6 @@ public:
|
||||
all - featureMultiSignReserve - featureExpandedSignerList,
|
||||
all - featureExpandedSignerList})
|
||||
testMultisig(features);
|
||||
testLedgerEntry();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user