rippled
Loading...
Searching...
No Matches
TransactionHistory_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2017 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <test/jtx.h>
21#include <test/jtx/Env.h>
22#include <test/jtx/envconfig.h>
23#include <xrpl/protocol/jss.h>
24
25#include <boost/container/static_vector.hpp>
26
27#include <algorithm>
28
29namespace ripple {
30
32{
33 void
35 {
36 testcase("Invalid request params");
37 using namespace test::jtx;
38 Env env{*this, envconfig(no_admin)};
39
40 {
41 // no params
42 auto const result =
43 env.client().invoke("tx_history", {})[jss::result];
44 BEAST_EXPECT(result[jss::error] == "invalidParams");
45 BEAST_EXPECT(result[jss::status] == "error");
46 }
47
48 {
49 // test at 1 greater than the allowed non-admin limit
51 params[jss::start] = 10001; // limited to <= 10000 for non admin
52 auto const result =
53 env.client().invoke("tx_history", params)[jss::result];
54 BEAST_EXPECT(result[jss::error] == "noPermission");
55 BEAST_EXPECT(result[jss::status] == "error");
56 }
57 }
58
59 void
61 {
62 testcase("Command retired from API v2");
63 using namespace test::jtx;
64 Env env{*this, envconfig(no_admin)};
65
67 params[jss::api_version] = 2;
68 auto const result =
69 env.client().invoke("tx_history", params)[jss::result];
70 BEAST_EXPECT(result[jss::error] == "unknownCmd");
71 BEAST_EXPECT(result[jss::status] == "error");
72 }
73
74 void
76 {
77 testcase("Basic request");
78 using namespace test::jtx;
79 Env env{*this};
80
81 // create enough transactions to provide some
82 // history...
83 size_t const numAccounts = 20;
84 boost::container::static_vector<Account, numAccounts> accounts;
85 for (size_t i = 0; i < numAccounts; ++i)
86 {
87 accounts.emplace_back("A" + std::to_string(i));
88 auto const& acct = accounts.back();
89 env.fund(XRP(10000), acct);
90 env.close();
91 if (i > 0)
92 {
93 auto const& prev = accounts[i - 1];
94 env.trust(acct["USD"](1000), prev);
95 env(pay(acct, prev, acct["USD"](5)));
96 }
97 env(offer(acct, XRP(100), acct["USD"](1)));
98 env.close();
99
100 // verify the latest transaction in env (offer)
101 // is available in tx_history.
103 params[jss::start] = 0;
104 auto result =
105 env.client().invoke("tx_history", params)[jss::result];
106 if (!BEAST_EXPECT(
107 result[jss::txs].isArray() && result[jss::txs].size() > 0))
108 return;
109
110 // search for a tx in history matching the last offer
111 bool const txFound = [&] {
112 auto const toFind = env.tx()->getJson(JsonOptions::none);
113 for (auto tx : result[jss::txs])
114 {
115 tx.removeMember(jss::inLedger);
116 tx.removeMember(jss::ledger_index);
117 if (toFind == tx)
118 return true;
119 }
120 return false;
121 }();
122 BEAST_EXPECT(txFound);
123 }
124
125 unsigned int start = 0;
126 unsigned int total = 0;
127 // also summarize the transaction types in this map
129 while (start < 120)
130 {
132 params[jss::start] = start;
133 auto result =
134 env.client().invoke("tx_history", params)[jss::result];
135 if (!BEAST_EXPECT(
136 result[jss::txs].isArray() && result[jss::txs].size() > 0))
137 break;
138 total += result[jss::txs].size();
139 start += 20;
140 for (auto const& t : result[jss::txs])
141 {
142 typeCounts[t[sfTransactionType.fieldName].asString()]++;
143 }
144 }
145 BEAST_EXPECT(total == 117);
146 BEAST_EXPECT(typeCounts[jss::AccountSet.c_str()] == 20);
147 BEAST_EXPECT(typeCounts[jss::TrustSet.c_str()] == 19);
148 BEAST_EXPECT(typeCounts[jss::Payment.c_str()] == 58);
149 BEAST_EXPECT(typeCounts[jss::OfferCreate.c_str()] == 20);
150
151 // also, try a request with max non-admin start value
152 {
154 params[jss::start] = 10000; // limited to <= 10000 for non admin
155 auto const result =
156 env.client().invoke("tx_history", params)[jss::result];
157 BEAST_EXPECT(result[jss::status] == "success");
158 BEAST_EXPECT(result[jss::index] == 10000);
159 }
160 }
161
162public:
163 void
164 run() override
165 {
166 testBadInput();
167 testRequest();
169 }
170};
171
172BEAST_DEFINE_TESTSUITE(TransactionHistory, rpc, ripple);
173
174} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
A testsuite class.
Definition: suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:155
void run() override
Runs the suite.
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:44
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
T to_string(T... args)