From 9a0249e7934b806d90d188c677a8193816ac0293 Mon Sep 17 00:00:00 2001 From: Mike Ellery Date: Tue, 14 Feb 2017 13:50:14 -0800 Subject: [PATCH] Add unit test for tx_history RPC (RIPD-1402) --- Builds/VisualStudio2015/RippleD.vcxproj | 4 + .../VisualStudio2015/RippleD.vcxproj.filters | 3 + src/test/rpc/TransactionHistory_test.cpp | 154 ++++++++++++++++++ src/test/unity/rpc_test_unity.cpp | 1 + 4 files changed, 162 insertions(+) create mode 100644 src/test/rpc/TransactionHistory_test.cpp diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj index 42a7675f4..18cb38e2e 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj +++ b/Builds/VisualStudio2015/RippleD.vcxproj @@ -4931,6 +4931,10 @@ True True + + True + True + True True diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters index 05a39cca8..097689aec 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters @@ -5616,6 +5616,9 @@ test\rpc + + test\rpc + test\server diff --git a/src/test/rpc/TransactionHistory_test.cpp b/src/test/rpc/TransactionHistory_test.cpp new file mode 100644 index 000000000..78326cbf8 --- /dev/null +++ b/src/test/rpc/TransactionHistory_test.cpp @@ -0,0 +1,154 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012-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 +#include +#include + +namespace ripple { + +class TransactionHistory_test : public beast::unit_test::suite +{ + void + testBadInput() + { + testcase("Invalid request params"); + using namespace test::jtx; + Env env {*this, envconfig(no_admin)}; + + { + //no params + auto const result = env.client() + .invoke("tx_history", {})[jss::result]; + BEAST_EXPECT(result[jss::error] == "invalidParams"); + BEAST_EXPECT(result[jss::status] == "error"); + } + + { + // test at 1 greater than the allowed non-admin limit + Json::Value params {Json::objectValue}; + params[jss::start] = 10001; //limited to <= 10000 for non admin + auto const result = env.client() + .invoke("tx_history", params)[jss::result]; + BEAST_EXPECT(result[jss::error] == "noPermission"); + BEAST_EXPECT(result[jss::status] == "error"); + } + } + + void testRequest() + { + testcase("Basic request"); + using namespace test::jtx; + Env env {*this}; + + // create enough transactions to provide some + // history... + size_t const numAccounts = 20; + boost::container::static_vector accounts; + for(size_t i = 0; i 0) + { + auto const& prev=accounts[i-1]; + env.trust(acct["USD"](1000), prev); + env(pay(acct, prev, acct["USD"](5))); + } + env(offer(acct, XRP(100), acct["USD"](1))); + env.close(); + + // verify the latest transaction in env (offer) + // is available in tx_history. + Json::Value params {Json::objectValue}; + params[jss::start] = 0; + auto result = + env.client().invoke("tx_history", params)[jss::result]; + if(! BEAST_EXPECT(result[jss::txs].isArray() && + result[jss::txs].size() > 0)) + return; + + // search for a tx in history matching the last offer + bool const txFound = [&] { + auto const toFind = env.tx()->getJson(0); + for (auto tx : result[jss::txs]) + { + tx.removeMember(jss::inLedger); + tx.removeMember(jss::ledger_index); + if (toFind == tx) + return true; + } + return false; + }(); + BEAST_EXPECT(txFound); + } + + unsigned int start = 0; + unsigned int total = 0; + // also summarize the transaction types in this map + std::unordered_map typeCounts; + while(start < 120) + { + Json::Value params {Json::objectValue}; + params[jss::start] = start; + auto result = + env.client().invoke("tx_history", params)[jss::result]; + if(! BEAST_EXPECT(result[jss::txs].isArray() && + result[jss::txs].size() > 0)) + break; + total += result[jss::txs].size(); + start += 20; + for (auto const& t : result[jss::txs]) + { + typeCounts[t[sfTransactionType.fieldName].asString()]++; + } + } + BEAST_EXPECT(total == 117); + BEAST_EXPECT(typeCounts["AccountSet"] == 20); + BEAST_EXPECT(typeCounts["TrustSet"] == 19); + BEAST_EXPECT(typeCounts["Payment"] == 58); + BEAST_EXPECT(typeCounts["OfferCreate"] == 20); + + // also, try a request with max non-admin start value + { + Json::Value params {Json::objectValue}; + params[jss::start] = 10000; //limited to <= 10000 for non admin + auto const result = env.client() + .invoke("tx_history", params)[jss::result]; + BEAST_EXPECT(result[jss::status] == "success"); + BEAST_EXPECT(result[jss::index] == 10000); + } + } + +public: + void run () + { + testBadInput(); + testRequest(); + } +}; + +BEAST_DEFINE_TESTSUITE (TransactionHistory, rpc, ripple); + +} // ripple diff --git a/src/test/unity/rpc_test_unity.cpp b/src/test/unity/rpc_test_unity.cpp index cd154b986..3c4bf492e 100644 --- a/src/test/unity/rpc_test_unity.cpp +++ b/src/test/unity/rpc_test_unity.cpp @@ -40,3 +40,4 @@ #include #include #include +#include