diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj index 4ba16d1b5a..9f3e25ebe8 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj +++ b/Builds/VisualStudio2015/RippleD.vcxproj @@ -5023,6 +5023,10 @@ True True + + True + True + True True diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters index f2b675c5b5..1e641ad67e 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters @@ -5742,6 +5742,9 @@ test\rpc + + test\rpc + test\rpc diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp index c1a6c5c6c9..ab69deb1b1 100644 --- a/src/ripple/rpc/handlers/AccountTx.cpp +++ b/src/ripple/rpc/handlers/AccountTx.cpp @@ -91,7 +91,8 @@ Json::Value doAccountTx (RPC::Context& context) if (uLedgerMax < uLedgerMin) return rpcError (rpcLGR_IDXS_INVALID); } - else + else if(params.isMember (jss::ledger_hash) || + params.isMember (jss::ledger_index)) { std::shared_ptr ledger; auto ret = RPC::lookupLedger (ledger, context); @@ -108,6 +109,11 @@ Json::Value doAccountTx (RPC::Context& context) uLedgerMin = uLedgerMax = ledger->info().seq; } + else + { + uLedgerMin = uValidatedMin; + uLedgerMax = uValidatedMax; + } Json::Value resumeToken; diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp new file mode 100644 index 0000000000..cdab8ee7d4 --- /dev/null +++ b/src/test/rpc/AccountTx_test.cpp @@ -0,0 +1,178 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2017 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 +#include +#include +#include + +namespace ripple { + +namespace test { + +class AccountTX_test : public beast::unit_test::suite +{ + void + testParameters() + { + using namespace test::jtx; + + Env env(*this); + Account A1{"A1"}; + env.fund(XRP(10000), A1); + env.close(); + + // Ledger 3 has the two txs associated with funding the account + // All other ledgers have no txs + + auto hasTxs = [](Json::Value const& j) { + return j.isMember(jss::result) && + (j[jss::result][jss::status] == "success") && + (j[jss::result][jss::transactions].size() == 2) && + (j[jss::result][jss::transactions][0u][jss::tx] + [jss::TransactionType] == "AccountSet") && + (j[jss::result][jss::transactions][1u][jss::tx] + [jss::TransactionType] == "Payment"); + }; + + auto noTxs = [](Json::Value const& j) { + return j.isMember(jss::result) && + (j[jss::result][jss::status] == "success") && + (j[jss::result][jss::transactions].size() == 0); + }; + + auto isErr = [](Json::Value const& j, error_code_i code) { + return j.isMember(jss::result) && + j[jss::result].isMember(jss::error) && + j[jss::result][jss::error] == RPC::get_error_info(code).token; + }; + + Json::Value jParms; + + BEAST_EXPECT(isErr( + env.rpc("json", "account_tx", to_string(jParms)), + rpcINVALID_PARAMS)); + + jParms[jss::account] = "0xDEADBEEF"; + + BEAST_EXPECT(isErr( + env.rpc("json", "account_tx", to_string(jParms)), + rpcACT_MALFORMED)); + + jParms[jss::account] = A1.human(); + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(jParms)))); + + // Ledger min/max index + { + Json::Value p{jParms}; + p[jss::ledger_index_min] = -1; + p[jss::ledger_index_max] = -1; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_min] = 0; + p[jss::ledger_index_max] = 100; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_min] = 1; + p[jss::ledger_index_max] = 2; + BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_min] = 2; + p[jss::ledger_index_max] = 1; + BEAST_EXPECT(isErr( + env.rpc("json", "account_tx", to_string(p)), + rpcLGR_IDXS_INVALID)); + } + + // Ledger index min only + { + Json::Value p{jParms}; + p[jss::ledger_index_min] = -1; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_min] = 1; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_min] = env.current()->info().seq; + BEAST_EXPECT(isErr( + env.rpc("json", "account_tx", to_string(p)), + rpcLGR_IDXS_INVALID)); + } + + // Ledger index max only + { + Json::Value p{jParms}; + p[jss::ledger_index_max] = -1; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_max] = env.current()->info().seq; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_max] = env.closed()->info().seq; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index_max] = env.closed()->info().seq - 1 ; + BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); + } + + // Ledger Sequence + { + Json::Value p{jParms}; + + p[jss::ledger_index] = env.closed()->info().seq; + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index] = env.closed()->info().seq - 1; + BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_index] = env.current()->info().seq; + BEAST_EXPECT(isErr( + env.rpc("json", "account_tx", to_string(p)), + rpcLGR_NOT_VALIDATED)); + + p[jss::ledger_index] = env.current()->info().seq + 1; + BEAST_EXPECT(isErr( + env.rpc("json", "account_tx", to_string(p)), + rpcLGR_NOT_FOUND)); + } + + // Ledger Hash + { + Json::Value p{jParms}; + + p[jss::ledger_hash] = to_string(env.closed()->info().hash); + BEAST_EXPECT(hasTxs(env.rpc("json", "account_tx", to_string(p)))); + + p[jss::ledger_hash] = to_string(env.closed()->info().parentHash); + BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); + } + } + +public: + void + run() + { + testParameters(); + } +}; +BEAST_DEFINE_TESTSUITE(AccountTX, app, ripple); + +} // namespace test + +} // namespace ripple diff --git a/src/test/unity/rpc_test_unity.cpp b/src/test/unity/rpc_test_unity.cpp index 8ebbf2d9eb..237f0b77aa 100644 --- a/src/test/unity/rpc_test_unity.cpp +++ b/src/test/unity/rpc_test_unity.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include