Add ledger_data RPC tests (RIPD-1260):

Migrate ledger-data-test.js to cpp tests. Provide coverage for
paging limits and input error cases.
This commit is contained in:
Mike Ellery
2016-08-09 14:56:47 -07:00
committed by Nik Bougalis
parent cf8b6be494
commit 8f41817cb9
4 changed files with 245 additions and 0 deletions

View File

@@ -3399,6 +3399,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\tests\LedgerData.test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\tests\LedgerRequestRPC.test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>

View File

@@ -3852,6 +3852,9 @@
<ClCompile Include="..\..\src\ripple\rpc\tests\KeyGeneration.test.cpp">
<Filter>ripple\rpc\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\tests\LedgerData.test.cpp">
<Filter>ripple\rpc\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\tests\LedgerRequestRPC.test.cpp">
<Filter>ripple\rpc\tests</Filter>
</ClCompile>

View File

@@ -0,0 +1,237 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2016 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/protocol/JsonFields.h>
#include <ripple/test/jtx.h>
namespace ripple {
class LedgerData_test : public beast::unit_test::suite
{
public:
static
std::unique_ptr<Config>
makeConfig(bool setup_admin)
{
auto p = std::make_unique<Config>();
test::setupConfigForUnitTests(*p);
// the default config has admin active
// ...we remove them if setup_admin is false
if (! setup_admin)
{
(*p)["port_rpc"].set("admin","");
(*p)["port_ws"].set("admin","");
}
return p;
}
// test helper
static bool checkArraySize(Json::Value const& val, unsigned int size)
{
return val.isArray() &&
val.size() == size;
}
// test helper
static bool checkMarker(Json::Value const& val)
{
return val.isMember(jss::marker) &&
val[jss::marker].isString() &&
val[jss::marker].asString().size() > 0;
}
void testCurrentLedgerToLimits(bool as_admin)
{
using namespace test::jtx;
Env env {*this, makeConfig(as_admin)};
Account const gw {"gateway"};
auto const USD = gw["USD"];
env.fund(XRP(100000), gw);
int const max_limit = 256; //would be 2048 for binary requests, no need to test that here
for (auto i = 0; i < max_limit + 10; i++)
{
Account const bob {std::string("bob") + std::to_string(i)};
env.fund(XRP(1000), bob);
}
env.close();
// no limit specified
// with no limit specified, we get the max_limit if the total number of
// accounts is greater than max, which it is here
Json::Value jvParams;
jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false;
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(
jrr[jss::ledger_current_index].isIntegral() &&
jrr[jss::ledger_current_index].asInt() > 0 );
BEAST_EXPECT( checkMarker(jrr) );
BEAST_EXPECT( checkArraySize(jrr[jss::state], max_limit) );
// check limits values around the max_limit (+/- 1)
for (auto delta = -1; delta <= 1; delta++)
{
jvParams[jss::limit] = max_limit + delta;
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(
checkArraySize( jrr[jss::state],
(delta > 0 && !as_admin) ? max_limit : max_limit + delta ));
}
}
void testCurrentLedgerBinary()
{
using namespace test::jtx;
Env env { *this, makeConfig(false) };
Account const gw { "gateway" };
auto const USD = gw["USD"];
env.fund(XRP(100000), gw);
int const num_accounts = 10;
for (auto i = 0; i < num_accounts; i++)
{
Account const bob { std::string("bob") + std::to_string(i) };
env.fund(XRP(1000), bob);
}
env.close();
// no limit specified
// with no limit specified, we should get all of our fund entries
// plus three more related to the gateway setup
Json::Value jvParams;
jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = true;
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(
jrr[jss::ledger_current_index].isIntegral() &&
jrr[jss::ledger_current_index].asInt() > 0);
BEAST_EXPECT( ! jrr.isMember(jss::marker) );
BEAST_EXPECT( checkArraySize(jrr[jss::state], num_accounts + 3) );
}
void testBadInput()
{
using namespace test::jtx;
Env env { *this };
Account const gw { "gateway" };
auto const USD = gw["USD"];
Account const bob { "bob" };
env.fund(XRP(10000), gw, bob);
env.trust(USD(1000), bob);
{
// bad limit
Json::Value jvParams;
jvParams[jss::limit] = "0"; // NOT an integer
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit', not integer.");
}
{
// invalid marker
Json::Value jvParams;
jvParams[jss::marker] = "NOT_A_MARKER";
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid.");
}
{
// invalid marker - not a string
Json::Value jvParams;
jvParams[jss::marker] = 1;
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(jrr[jss::error] == "invalidParams");
BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid.");
}
{
// ask for a bad ledger index
Json::Value jvParams;
jvParams[jss::ledger_index] = 10u;
auto const jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT(jrr[jss::error] == "lgrNotFound");
BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound");
}
}
void testMarkerFollow()
{
using namespace test::jtx;
Env env { *this, makeConfig(false) };
Account const gw { "gateway" };
auto const USD = gw["USD"];
env.fund(XRP(100000), gw);
int const num_accounts = 20;
for (auto i = 0; i < num_accounts; i++)
{
Account const bob { std::string("bob") + std::to_string(i) };
env.fund(XRP(1000), bob);
}
env.close();
// no limit specified
// with no limit specified, we should get all of our fund entries
// plus three more related to the gateway setup
Json::Value jvParams;
jvParams[jss::ledger_index] = "current";
jvParams[jss::binary] = false;
auto jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
auto const total_count = jrr[jss::state].size();
// now make request with a limit and loop until we get all
jvParams[jss::limit] = 5;
jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
BEAST_EXPECT( checkMarker(jrr) );
auto running_total = jrr[jss::state].size();
while ( jrr.isMember(jss::marker) )
{
jvParams[jss::marker] = jrr[jss::marker];
jrr = env.rpc ( "json", "ledger_data", jvParams.toStyledString() ) [jss::result];
running_total += jrr[jss::state].size();
}
BEAST_EXPECT( running_total == total_count );
}
void run()
{
testCurrentLedgerToLimits(true);
testCurrentLedgerToLimits(false);
testCurrentLedgerBinary();
testBadInput();
testMarkerFollow();
}
};
BEAST_DEFINE_TESTSUITE(LedgerData,app,ripple);
}

View File

@@ -105,6 +105,7 @@
#include <ripple/rpc/tests/JSONRPC.test.cpp>
#include <ripple/rpc/tests/GatewayBalances.test.cpp>
#include <ripple/rpc/tests/LedgerRequestRPC.test.cpp>
#include <ripple/rpc/tests/LedgerData.test.cpp>
#include <ripple/rpc/tests/KeyGeneration.test.cpp>
#include <ripple/rpc/tests/RobustTransaction.test.cpp>
#include <ripple/rpc/tests/ServerInfo.test.cpp>