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>
37using source_location = std::experimental::source_location;
38#else
39#include <source_location>
40using std::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/* Escrow */
237/******************************************************************************/
238
240escrow(AccountID const& account, AccountID const& to, STAmount const& amount);
241
242inline Json::Value
243escrow(Account const& account, Account const& to, STAmount const& amount)
244{
245 return escrow(account.id(), to.id(), amount);
246}
247
249finish(AccountID const& account, AccountID const& from, std::uint32_t seq);
250
251inline Json::Value
252finish(Account const& account, Account const& from, std::uint32_t seq)
253{
254 return finish(account.id(), from.id(), seq);
255}
256
258cancel(AccountID const& account, Account const& from, std::uint32_t seq);
259
260inline Json::Value
261cancel(Account const& account, Account const& from, std::uint32_t seq)
262{
263 return cancel(account.id(), from, seq);
264}
265
267 {0xA0, 0x25, 0x80, 0x20, 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC,
268 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
269 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95,
270 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55, 0x81, 0x01, 0x00}};
271
272// A PreimageSha256 fulfillments and its associated condition.
273std::array<std::uint8_t, 4> const fb1 = {{0xA0, 0x02, 0x80, 0x00}};
274
277{
278private:
280
281public:
282 explicit finish_time(NetClock::time_point const& value) : value_(value)
283 {
284 }
285
286 void
287 operator()(Env&, JTx& jt) const
288 {
289 jt.jv[sfFinishAfter.jsonName] = value_.time_since_epoch().count();
290 }
291};
292
295{
296private:
298
299public:
300 explicit cancel_time(NetClock::time_point const& value) : value_(value)
301 {
302 }
303
304 void
306 {
307 jt.jv[sfCancelAfter.jsonName] = value_.time_since_epoch().count();
308 }
309};
310
312{
313private:
315
316public:
317 explicit condition(Slice const& cond) : value_(strHex(cond))
318 {
319 }
320
321 template <size_t N>
323 : condition(makeSlice(c))
324 {
325 }
326
327 void
328 operator()(Env&, JTx& jt) const
329 {
330 jt.jv[sfCondition.jsonName] = value_;
331 }
332};
333
335{
336private:
338
339public:
341 {
342 }
343
344 template <size_t N>
347 {
348 }
349
350 void
351 operator()(Env&, JTx& jt) const
352 {
353 jt.jv[sfFulfillment.jsonName] = value_;
354 }
355};
356
357/* Payment Channel */
358/******************************************************************************/
359
361create(
362 AccountID const& account,
363 AccountID const& to,
364 STAmount const& amount,
365 NetClock::duration const& settleDelay,
366 PublicKey const& pk,
367 std::optional<NetClock::time_point> const& cancelAfter = std::nullopt,
368 std::optional<std::uint32_t> const& dstTag = std::nullopt);
369
370inline Json::Value
372 Account const& account,
373 Account const& to,
374 STAmount const& amount,
375 NetClock::duration const& settleDelay,
376 PublicKey const& pk,
377 std::optional<NetClock::time_point> const& cancelAfter = std::nullopt,
378 std::optional<std::uint32_t> const& dstTag = std::nullopt)
379{
380 return create(
381 account.id(), to.id(), amount, settleDelay, pk, cancelAfter, dstTag);
382}
383
385fund(
386 AccountID const& account,
387 uint256 const& channel,
388 STAmount const& amount,
389 std::optional<NetClock::time_point> const& expiration = std::nullopt);
390
392claim(
393 AccountID const& account,
394 uint256 const& channel,
395 std::optional<STAmount> const& balance = std::nullopt,
396 std::optional<STAmount> const& amount = std::nullopt,
397 std::optional<Slice> const& signature = std::nullopt,
398 std::optional<PublicKey> const& pk = std::nullopt);
399
401channel(
402 AccountID const& account,
403 AccountID const& dst,
404 std::uint32_t seqProxyValue);
405
406inline uint256
407channel(Account const& account, Account const& dst, std::uint32_t seqProxyValue)
408{
409 return channel(account.id(), dst.id(), seqProxyValue);
410}
411
413channelBalance(ReadView const& view, uint256 const& chan);
414
415bool
416channelExists(ReadView const& view, uint256 const& chan);
417
418/* Crossing Limits */
419/******************************************************************************/
420
421void
423 Env& env,
424 std::size_t n,
425 Account const& account,
426 STAmount const& in,
427 STAmount const& out);
428
429/* Pay Strand */
430/***************************************************************/
431
432// Currency path element
434cpe(Currency const& c);
435
436// All path element
438allpe(AccountID const& a, Issue const& iss);
439/***************************************************************/
440
441/* Check */
442/***************************************************************/
443namespace check {
444
446// clang-format off
447template <typename A>
448 requires std::is_same_v<A, AccountID>
450create(A const& account, A const& dest, STAmount const& sendMax)
451{
452 Json::Value jv;
453 jv[sfAccount.jsonName] = to_string(account);
454 jv[sfSendMax.jsonName] = sendMax.getJson(JsonOptions::none);
455 jv[sfDestination.jsonName] = to_string(dest);
456 jv[sfTransactionType.jsonName] = jss::CheckCreate;
457 return jv;
458}
459// clang-format on
460
461inline Json::Value
463 jtx::Account const& account,
464 jtx::Account const& dest,
465 STAmount const& sendMax)
466{
467 return create(account.id(), dest.id(), sendMax);
468}
469
470} // namespace check
471
472static constexpr FeeLevel64 baseFeeLevel{256};
474
475template <class Suite>
476void
478 Suite& test,
479 jtx::Env& env,
480 std::size_t expectedCount,
481 std::optional<std::size_t> expectedMaxCount,
482 std::size_t expectedInLedger,
483 std::size_t expectedPerLedger,
484 std::uint64_t expectedMinFeeLevel = baseFeeLevel.fee(),
485 std::uint64_t expectedMedFeeLevel = minEscalationFeeLevel.fee(),
486 source_location const location = source_location::current())
487{
488 int line = location.line();
489 char const* file = location.file_name();
490 FeeLevel64 const expectedMin{expectedMinFeeLevel};
491 FeeLevel64 const expectedMed{expectedMedFeeLevel};
492 auto const metrics = env.app().getTxQ().getMetrics(*env.current());
493 using namespace std::string_literals;
494
496 ? test.pass()
497 : test.fail(
498 "reference: "s +
499 std::to_string(metrics.referenceFeeLevel.value()) + "/" +
501 file,
502 line);
503
504 metrics.txCount == expectedCount
505 ? test.pass()
506 : test.fail(
507 "txCount: "s + std::to_string(metrics.txCount) + "/" +
508 std::to_string(expectedCount),
509 file,
510 line);
511
512 metrics.txQMaxSize == expectedMaxCount
513 ? test.pass()
514 : test.fail(
515 "txQMaxSize: "s + std::to_string(metrics.txQMaxSize.value_or(0)) +
516 "/" + std::to_string(expectedMaxCount.value_or(0)),
517 file,
518 line);
519
520 metrics.txInLedger == expectedInLedger
521 ? test.pass()
522 : test.fail(
523 "txInLedger: "s + std::to_string(metrics.txInLedger) + "/" +
524 std::to_string(expectedInLedger),
525 file,
526 line);
527
528 metrics.txPerLedger == expectedPerLedger
529 ? test.pass()
530 : test.fail(
531 "txPerLedger: "s + std::to_string(metrics.txPerLedger) + "/" +
532 std::to_string(expectedPerLedger),
533 file,
534 line);
535
536 metrics.minProcessingFeeLevel == expectedMin
537 ? test.pass()
538 : test.fail(
539 "minProcessingFeeLevel: "s +
540 std::to_string(metrics.minProcessingFeeLevel.value()) + "/" +
541 std::to_string(expectedMin.value()),
542 file,
543 line);
544
545 metrics.medFeeLevel == expectedMed
546 ? test.pass()
547 : test.fail(
548 "medFeeLevel: "s + std::to_string(metrics.medFeeLevel.value()) +
549 "/" + std::to_string(expectedMed.value()),
550 file,
551 line);
552
553 auto const expectedCurFeeLevel = expectedInLedger > expectedPerLedger
554 ? expectedMed * expectedInLedger * expectedInLedger /
555 (expectedPerLedger * expectedPerLedger)
556 : metrics.referenceFeeLevel;
557
558 metrics.openLedgerFeeLevel == expectedCurFeeLevel
559 ? test.pass()
560 : test.fail(
561 "openLedgerFeeLevel: "s +
562 std::to_string(metrics.openLedgerFeeLevel.value()) + "/" +
563 std::to_string(expectedCurFeeLevel.value()),
564 file,
565 line);
566}
567
568} // namespace jtx
569} // namespace test
570} // namespace ripple
571
572#endif // RIPPLE_TEST_JTX_TESTHELPERS_H_INCLUDED
T begin(T... args)
Represents a JSON value.
Definition: json_value.h:150
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:36
A public key.
Definition: PublicKey.h:62
A view into a ledger.
Definition: ReadView.h:52
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition: STAmount.cpp:639
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
An immutable linear range of bytes.
Definition: Slice.h:46
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:323
constexpr value_type fee() const
Returns the number of drops.
Definition: FeeUnits.h:277
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:450
static constexpr FeeLevel64 minEscalationFeeLevel
Definition: TestHelpers.h:473
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
Json::Value escrow(AccountID const &account, AccountID const &to, STAmount const &amount)
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)
std::array< std::uint8_t, 4 > const fb1
Definition: TestHelpers.h:273
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:36
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)
Json::Value cancel(AccountID const &account, Account const &from, std::uint32_t seq)
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:477
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)
Json::Value finish(AccountID const &account, AccountID const &from, std::uint32_t seq)
std::array< std::uint8_t, 39 > constexpr cb1
Definition: TestHelpers.h:266
static constexpr FeeLevel64 baseFeeLevel
Definition: TestHelpers.h:472
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:26
@ current
This was a new validation and was added.
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:244
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
Execution context for applying a JSON transaction.
Definition: JTx.h:45
Json::Value jv
Definition: JTx.h:46
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Set the "CancelAfter" time tag on a JTx.
Definition: TestHelpers.h:295
NetClock::time_point value_
Definition: TestHelpers.h:297
cancel_time(NetClock::time_point const &value)
Definition: TestHelpers.h:300
void operator()(jtx::Env &, jtx::JTx &jt) const
Definition: TestHelpers.h:305
void operator()(Env &, JTx &jt) const
Definition: TestHelpers.h:328
condition(Slice const &cond)
Definition: TestHelpers.h:317
condition(std::array< std::uint8_t, N > const &c)
Definition: TestHelpers.h:322
Set the "FinishAfter" time tag on a JTx.
Definition: TestHelpers.h:277
finish_time(NetClock::time_point const &value)
Definition: TestHelpers.h:282
void operator()(Env &, JTx &jt) const
Definition: TestHelpers.h:287
NetClock::time_point value_
Definition: TestHelpers.h:279
fulfillment(Slice condition)
Definition: TestHelpers.h:340
fulfillment(std::array< std::uint8_t, N > f)
Definition: TestHelpers.h:345
void operator()(Env &, JTx &jt) const
Definition: TestHelpers.h:351
Set the sequence number on a JTx.
Definition: seq.h:34
T time_since_epoch(T... args)
T to_string(T... args)
T value_or(T... args)