rippled
Loading...
Searching...
No Matches
TestHelpers.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2023 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#ifndef RIPPLE_TEST_JTX_TESTHELPERS_H_INCLUDED
21#define RIPPLE_TEST_JTX_TESTHELPERS_H_INCLUDED
22
23#include <test/jtx/Env.h>
24
25#include <xrpl/basics/base_uint.h>
26#include <xrpl/beast/unit_test/suite.h>
27#include <xrpl/json/json_value.h>
28#include <xrpl/protocol/AccountID.h>
29#include <xrpl/protocol/Quality.h>
30#include <xrpl/protocol/TxFlags.h>
31#include <xrpl/protocol/jss.h>
32
33#include <vector>
34
35#if (defined(__clang_major__) && __clang_major__ < 15)
36#include <experimental/source_location>
38#else
39#include <source_location>
41#endif
42
43namespace ripple {
44namespace test {
45namespace jtx {
46
47// TODO We only need this long "requires" clause as polyfill, for C++20
48// implementations which are missing <ranges> header. Replace with
49// `std::ranges::range<Input>`, and accordingly use std::ranges::begin/end
50// when we have moved to better compilers.
51template <typename Input>
52auto
53make_vector(Input const& input)
54 requires requires(Input& v) {
55 std::begin(v);
56 std::end(v);
57 }
58{
59 return std::vector(std::begin(input), std::end(input));
60}
61
62// Functions used in debugging
64getAccountOffers(Env& env, AccountID const& acct, bool current = false);
65
66inline Json::Value
67getAccountOffers(Env& env, Account const& acct, bool current = false)
68{
69 return getAccountOffers(env, acct.id(), current);
70}
71
73getAccountLines(Env& env, AccountID const& acctId);
74
75inline Json::Value
76getAccountLines(Env& env, Account const& acct)
77{
78 return getAccountLines(env, acct.id());
79}
80
81template <typename... IOU>
83getAccountLines(Env& env, AccountID const& acctId, IOU... ious)
84{
85 auto const jrr = getAccountLines(env, acctId);
86 Json::Value res;
87 for (auto const& line : jrr[jss::lines])
88 {
89 for (auto const& iou : {ious...})
90 {
91 if (line[jss::currency].asString() == to_string(iou.currency))
92 {
94 v[jss::currency] = line[jss::currency];
95 v[jss::balance] = line[jss::balance];
96 v[jss::limit] = line[jss::limit];
97 v[jss::account] = line[jss::account];
98 res[jss::lines].append(v);
99 }
100 }
101 }
102 if (!res.isNull())
103 return res;
104 return jrr;
105}
106
107[[nodiscard]] bool
108checkArraySize(Json::Value const& val, unsigned int size);
109
110// Helper function that returns the owner count on an account.
112ownerCount(test::jtx::Env const& env, test::jtx::Account const& account);
113
114/* Path finding */
115/******************************************************************************/
116void
117stpath_append_one(STPath& st, Account const& account);
118
119template <class T>
121stpath_append_one(STPath& st, T const& t)
122{
124}
125
126void
128
129template <class T, class... Args>
130void
131stpath_append(STPath& st, T const& t, Args const&... args)
132{
133 stpath_append_one(st, t);
134 if constexpr (sizeof...(args) > 0)
135 stpath_append(st, args...);
136}
137
138template <class... Args>
139void
140stpathset_append(STPathSet& st, STPath const& p, Args const&... args)
141{
142 st.push_back(p);
143 if constexpr (sizeof...(args) > 0)
144 stpathset_append(st, args...);
145}
146
147bool
148equal(STAmount const& sa1, STAmount const& sa2);
149
150// Issue path element
152IPE(Issue const& iss);
153
154template <class... Args>
155STPath
156stpath(Args const&... args)
157{
158 STPath st;
159 stpath_append(st, args...);
160 return st;
161}
162
163template <class... Args>
164bool
165same(STPathSet const& st1, Args const&... args)
166{
167 STPathSet st2;
168 stpathset_append(st2, args...);
169 if (st1.size() != st2.size())
170 return false;
171
172 for (auto const& p : st2)
173 {
174 if (std::find(st1.begin(), st1.end(), p) == st1.end())
175 return false;
176 }
177 return true;
178}
179
180/******************************************************************************/
181
183txfee(Env const& env, std::uint16_t n);
184
186xrpMinusFee(Env const& env, std::int64_t xrpAmount);
187
188bool
190 Env& env,
191 AccountID const& account,
192 STAmount const& value,
193 bool defaultLimits = false);
194
195template <typename... Amts>
196bool
198 Env& env,
199 AccountID const& account,
200 STAmount const& value,
201 Amts const&... amts)
202{
203 return expectLine(env, account, value, false) &&
204 expectLine(env, account, amts...);
205}
206
207bool
208expectLine(Env& env, AccountID const& account, None const& value);
209
210bool
212 Env& env,
213 AccountID const& account,
214 std::uint16_t size,
215 std::vector<Amounts> const& toMatch = {});
216
218ledgerEntryRoot(Env& env, Account const& acct);
219
222 Env& env,
223 Account const& acct_a,
224 Account const& acct_b,
225 std::string const& currency);
226
228accountBalance(Env& env, Account const& acct);
229
230[[nodiscard]] bool
232 Env& env,
233 Account const& acct,
234 STAmount const& expectedValue);
235
236/* Payment Channel */
237/******************************************************************************/
238
240create(
241 AccountID const& account,
242 AccountID const& to,
243 STAmount const& amount,
244 NetClock::duration const& settleDelay,
245 PublicKey const& pk,
246 std::optional<NetClock::time_point> const& cancelAfter = std::nullopt,
247 std::optional<std::uint32_t> const& dstTag = std::nullopt);
248
249inline Json::Value
251 Account const& account,
252 Account const& to,
253 STAmount const& amount,
254 NetClock::duration const& settleDelay,
255 PublicKey const& pk,
256 std::optional<NetClock::time_point> const& cancelAfter = std::nullopt,
257 std::optional<std::uint32_t> const& dstTag = std::nullopt)
258{
259 return create(
260 account.id(), to.id(), amount, settleDelay, pk, cancelAfter, dstTag);
261}
262
264fund(
265 AccountID const& account,
266 uint256 const& channel,
267 STAmount const& amount,
268 std::optional<NetClock::time_point> const& expiration = std::nullopt);
269
271claim(
272 AccountID const& account,
273 uint256 const& channel,
274 std::optional<STAmount> const& balance = std::nullopt,
275 std::optional<STAmount> const& amount = std::nullopt,
276 std::optional<Slice> const& signature = std::nullopt,
277 std::optional<PublicKey> const& pk = std::nullopt);
278
280channel(
281 AccountID const& account,
282 AccountID const& dst,
283 std::uint32_t seqProxyValue);
284
285inline uint256
286channel(Account const& account, Account const& dst, std::uint32_t seqProxyValue)
287{
288 return channel(account.id(), dst.id(), seqProxyValue);
289}
290
292channelBalance(ReadView const& view, uint256 const& chan);
293
294bool
295channelExists(ReadView const& view, uint256 const& chan);
296
297/* Crossing Limits */
298/******************************************************************************/
299
300void
302 Env& env,
303 std::size_t n,
304 Account const& account,
305 STAmount const& in,
306 STAmount const& out);
307
308/* Pay Strand */
309/***************************************************************/
310
311// Currency path element
313cpe(Currency const& c);
314
315// All path element
317allpe(AccountID const& a, Issue const& iss);
318/***************************************************************/
319
320/* Check */
321/***************************************************************/
322namespace check {
323
325// clang-format off
326template <typename A>
327 requires std::is_same_v<A, AccountID>
329create(A const& account, A const& dest, STAmount const& sendMax)
330{
331 Json::Value jv;
332 jv[sfAccount.jsonName] = to_string(account);
333 jv[sfSendMax.jsonName] = sendMax.getJson(JsonOptions::none);
334 jv[sfDestination.jsonName] = to_string(dest);
335 jv[sfTransactionType.jsonName] = jss::CheckCreate;
336 return jv;
337}
338// clang-format on
339
340inline Json::Value
342 jtx::Account const& account,
343 jtx::Account const& dest,
344 STAmount const& sendMax)
345{
346 return create(account.id(), dest.id(), sendMax);
347}
348
349} // namespace check
350
351static constexpr FeeLevel64 baseFeeLevel{256};
353
354template <class Suite>
355void
357 Suite& test,
358 jtx::Env& env,
359 std::size_t expectedCount,
360 std::optional<std::size_t> expectedMaxCount,
361 std::size_t expectedInLedger,
362 std::size_t expectedPerLedger,
363 std::uint64_t expectedMinFeeLevel = baseFeeLevel.fee(),
364 std::uint64_t expectedMedFeeLevel = minEscalationFeeLevel.fee(),
365 source_location const location = source_location::current())
366{
367 int line = location.line();
368 char const* file = location.file_name();
369 FeeLevel64 const expectedMin{expectedMinFeeLevel};
370 FeeLevel64 const expectedMed{expectedMedFeeLevel};
371 auto const metrics = env.app().getTxQ().getMetrics(*env.current());
372 using namespace std::string_literals;
373
375 ? test.pass()
376 : test.fail(
377 "reference: "s +
378 std::to_string(metrics.referenceFeeLevel.value()) + "/" +
380 file,
381 line);
382
383 metrics.txCount == expectedCount
384 ? test.pass()
385 : test.fail(
386 "txCount: "s + std::to_string(metrics.txCount) + "/" +
387 std::to_string(expectedCount),
388 file,
389 line);
390
391 metrics.txQMaxSize == expectedMaxCount
392 ? test.pass()
393 : test.fail(
394 "txQMaxSize: "s + std::to_string(metrics.txQMaxSize.value_or(0)) +
395 "/" + std::to_string(expectedMaxCount.value_or(0)),
396 file,
397 line);
398
399 metrics.txInLedger == expectedInLedger
400 ? test.pass()
401 : test.fail(
402 "txInLedger: "s + std::to_string(metrics.txInLedger) + "/" +
403 std::to_string(expectedInLedger),
404 file,
405 line);
406
407 metrics.txPerLedger == expectedPerLedger
408 ? test.pass()
409 : test.fail(
410 "txPerLedger: "s + std::to_string(metrics.txPerLedger) + "/" +
411 std::to_string(expectedPerLedger),
412 file,
413 line);
414
415 metrics.minProcessingFeeLevel == expectedMin
416 ? test.pass()
417 : test.fail(
418 "minProcessingFeeLevel: "s +
419 std::to_string(metrics.minProcessingFeeLevel.value()) + "/" +
420 std::to_string(expectedMin.value()),
421 file,
422 line);
423
424 metrics.medFeeLevel == expectedMed
425 ? test.pass()
426 : test.fail(
427 "medFeeLevel: "s + std::to_string(metrics.medFeeLevel.value()) +
428 "/" + std::to_string(expectedMed.value()),
429 file,
430 line);
431
432 auto const expectedCurFeeLevel = expectedInLedger > expectedPerLedger
433 ? expectedMed * expectedInLedger * expectedInLedger /
434 (expectedPerLedger * expectedPerLedger)
435 : metrics.referenceFeeLevel;
436
437 metrics.openLedgerFeeLevel == expectedCurFeeLevel
438 ? test.pass()
439 : test.fail(
440 "openLedgerFeeLevel: "s +
441 std::to_string(metrics.openLedgerFeeLevel.value()) + "/" +
442 std::to_string(expectedCurFeeLevel.value()),
443 file,
444 line);
445}
446
447} // namespace jtx
448} // namespace test
449} // namespace ripple
450
451#endif // RIPPLE_TEST_JTX_TESTHELPERS_H_INCLUDED
T begin(T... args)
Represents a JSON value.
Definition: json_value.h:149
Value & append(Value const &value)
Append value to array at the end.
Definition: json_value.cpp:910
bool isNull() const
isNull() tests to see if this field is null.
Definition: json_value.cpp:999
virtual TxQ & getTxQ()=0
A currency issued by an account.
Definition: Issue.h:33
A public key.
Definition: PublicKey.h:61
A view into a ledger.
Definition: ReadView.h:52
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition: STAmount.cpp:795
std::vector< STPath >::const_iterator end() const
Definition: STPathSet.h:496
void push_back(STPath const &e)
Definition: STPathSet.h:514
std::vector< STPath >::const_iterator begin() const
Definition: STPathSet.h:490
std::vector< STPath >::size_type size() const
Definition: STPathSet.h:502
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
Definition: TxQ.cpp:1778
constexpr value_type value() const
Returns the underlying value.
Definition: FeeUnits.h:318
constexpr value_type fee() const
Returns the number of drops.
Definition: FeeUnits.h:272
Immutable cryptographic account descriptor.
Definition: Account.h:39
AccountID id() const
Returns the Account ID.
Definition: Account.h:107
A transaction testing environment.
Definition: Env.h:121
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:331
Application & app()
Definition: Env.h:261
Converts to IOU Issue or STAmount.
A balance matches.
Definition: balance.h:39
Set Expiration on a JTx.
Definition: Check_test.cpp:31
T end(T... args)
T find(T... args)
Json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
Definition: TestHelpers.h:329
static constexpr FeeLevel64 minEscalationFeeLevel
Definition: TestHelpers.h:352
bool checkArraySize(Json::Value const &val, unsigned int size)
Definition: TestHelpers.cpp:48
std::uint32_t ownerCount(Env const &env, Account const &account)
Definition: TestHelpers.cpp:54
Json::Value ledgerEntryRoot(Env &env, Account const &acct)
auto make_vector(Input const &input)
Definition: TestHelpers.h:53
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
STAmount channelBalance(ReadView const &view, uint256 const &chan)
uint256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
PrettyAmount xrpMinusFee(Env const &env, std::int64_t xrpAmount)
Definition: TestHelpers.cpp:99
bool expectLine(Env &env, AccountID const &account, STAmount const &value, bool defaultLimits)
bool equal(STAmount const &sa1, STAmount const &sa2)
Definition: TestHelpers.cpp:74
Json::Value getAccountLines(Env &env, AccountID const &acctId)
Definition: TestHelpers.cpp:40
bool same(STPathSet const &st1, Args const &... args)
Definition: TestHelpers.h:165
Json::Value ledgerEntryState(Env &env, Account const &acct_a, Account const &acct_b, std::string const &currency)
void stpath_append_one(STPath &st, Account const &account)
Definition: TestHelpers.cpp:62
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
Definition: AMMTest.cpp:37
void stpath_append(STPath &st, T const &t, Args const &... args)
Definition: TestHelpers.h:131
void n_offers(Env &env, std::size_t n, Account const &account, STAmount const &in, STAmount const &out)
Json::Value accountBalance(Env &env, Account const &acct)
STPathElement IPE(Issue const &iss)
Definition: TestHelpers.cpp:81
void checkMetrics(Suite &test, jtx::Env &env, std::size_t expectedCount, std::optional< std::size_t > expectedMaxCount, std::size_t expectedInLedger, std::size_t expectedPerLedger, std::uint64_t expectedMinFeeLevel=baseFeeLevel.fee(), std::uint64_t expectedMedFeeLevel=minEscalationFeeLevel.fee(), source_location const location=source_location::current())
Definition: TestHelpers.h:356
Json::Value claim(AccountID const &account, uint256 const &channel, std::optional< STAmount > const &balance, std::optional< STAmount > const &amount, std::optional< Slice > const &signature, std::optional< PublicKey > const &pk)
static constexpr FeeLevel64 baseFeeLevel
Definition: TestHelpers.h:351
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
void stpathset_append(STPathSet &st, STPath const &p, Args const &... args)
Definition: TestHelpers.h:140
STPathElement cpe(Currency const &c)
bool expectLedgerEntryRoot(Env &env, Account const &acct, STAmount const &expectedValue)
STPathElement allpe(AccountID const &a, Issue const &iss)
bool channelExists(ReadView const &view, uint256 const &chan)
XRPAmount txfee(Env const &env, std::uint16_t n)
Definition: TestHelpers.cpp:93
STPath stpath(Args const &... args)
Definition: TestHelpers.h:156
Json::Value getAccountOffers(Env &env, AccountID const &acct, bool current)
Definition: TestHelpers.cpp:32
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:25
@ current
This was a new validation and was added.
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
FeeLevel64 referenceFeeLevel
Reference transaction fee level.
Definition: TxQ.h:178
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
T to_string(T... args)
T value_or(T... args)