xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
test
app
LedgerLoad_test.cpp
1
#include <test/jtx/Account.h>
2
#include <test/jtx/Env.h>
3
#include <test/jtx/amount.h>
4
#include <test/jtx/envconfig.h>
5
#include <test/jtx/offer.h>
6
#include <test/jtx/pay.h>
7
8
#include <xrpld/core/Config.h>
9
10
#include <xrpl/basics/FileUtilities.h>
11
#include <xrpl/basics/base_uint.h>
12
#include <xrpl/beast/unit_test/suite.h>
13
#include <xrpl/beast/utility/Journal.h>
14
#include <xrpl/core/StartUpType.h>
15
#include <xrpl/json/json_value.h>
16
#include <xrpl/json/to_string.h>
17
#include <xrpl/protocol/SField.h>
18
#include <xrpl/protocol/jss.h>
19
20
#include <boost/algorithm/string/erase.hpp>
21
22
#include <
cassert
>
23
#include <
filesystem
>
24
#include <
fstream
>
25
#include <
ios
>
26
#include <
memory
>
27
#include <
optional
>
28
#include <
stdexcept
>
29
#include <
string
>
30
#include <
system_error
>
31
32
namespace
xrpl
{
33
34
class
LedgerLoad_test
:
public
beast::unit_test::Suite
35
{
36
auto
static
ledgerConfig
(
37
std::unique_ptr<Config>
cfg,
38
std::string
const
& dbPath,
39
std::string
const
& ledger,
40
StartUpType
type,
41
std::optional<UInt256>
trapTxHash)
42
{
43
cfg->startLedger = ledger;
44
cfg->startUp = type;
45
cfg->trapTxHash = trapTxHash;
46
assert(!dbPath.
empty
());
47
cfg->legacy(
"database_path"
, dbPath);
48
return
cfg;
49
}
50
51
// setup for test cases
52
struct
SetupData
53
{
54
std::string
const
dbPath
;
55
// NOLINTBEGIN(readability-redundant-member-init)
56
std::string
ledgerFile
= {};
57
json::Value
ledger
= {};
58
json::Value
hashes
= {};
59
UInt256
trapTxHash
= {};
60
// NOLINTEND(readability-redundant-member-init)
61
};
62
63
SetupData
64
setupLedger
(
TempDir
const
& td)
65
{
66
using namespace
test::jtx
;
67
SetupData
retval = {.dbPath = td.
path
()};
68
69
retval.
ledgerFile
= td.
file
(
"ledgerdata.json"
);
70
71
Env env{*
this
};
72
std::optional<Account>
prev;
73
74
for
(
auto
i = 0; i < 20; ++i)
75
{
76
Account
const
acct{
"A"
+
std::to_string
(i)};
77
env.fund(XRP(10000), acct);
78
env.close();
79
if
(i > 0 && BEAST_EXPECT(prev.has_value()))
80
{
81
env.trust(acct[
"USD"
](1000), *prev);
// NOLINT(bugprone-unchecked-optional-access)
82
env(pay(
83
acct, *prev, acct[
"USD"
](5)));
// NOLINT(bugprone-unchecked-optional-access)
84
}
85
env(offer(acct, XRP(100), acct[
"USD"
](1)));
86
env.close();
87
prev.emplace(acct);
88
}
89
90
retval.
ledger
= env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
91
BEAST_EXPECT(retval.
ledger
[jss::ledger][jss::accountState].
size
() == 102);
92
93
retval.
hashes
= [&] {
94
for
(
auto
const
& it : retval.
ledger
[jss::ledger][jss::accountState])
95
{
96
if
(it[sfLedgerEntryType.fieldName] == jss::LedgerHashes)
97
return
it[sfHashes.fieldName];
98
}
99
return
json::Value
{};
100
}();
101
102
BEAST_EXPECT(retval.
hashes
.
size
() == 41);
103
retval.
trapTxHash
= [&]() {
104
auto
const
txs = env.rpc(
105
"ledger"
,
std::to_string
(41),
"tx"
)[jss::result][jss::ledger][jss::transactions];
106
BEAST_EXPECT(txs.isArray() && txs.size() > 0);
107
UInt256
tmp;
108
BEAST_EXPECT(tmp.
parseHex
(txs[0u][jss::hash].asString()));
109
return
tmp;
110
}();
111
112
// write this ledger data to a file.
113
std::ofstream
o(retval.
ledgerFile
, std::ios::out | std::ios::trunc);
114
o <<
to_string
(retval.
ledger
);
115
o.
close
();
116
return
retval;
117
}
118
119
void
120
testLoad
(
SetupData
const
& sd)
121
{
122
testcase
(
"Load a saved ledger"
);
123
using namespace
test::jtx
;
124
125
// create a new env with the ledger file specified for startup
126
Env env(
127
*
this
,
128
envconfig(
ledgerConfig
, sd.
dbPath
, sd.
ledgerFile
,
StartUpType::LoadFile
, std::nullopt),
129
nullptr
,
130
beast::Severity::Disabled
);
131
auto
jrb = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
132
BEAST_EXPECT(
133
sd.
ledger
[jss::ledger][jss::accountState].
size
() ==
134
jrb[jss::ledger][jss::accountState].size());
135
}
136
137
void
138
testBadFiles
(
SetupData
const
& sd)
139
{
140
testcase
(
"Load ledger: Bad Files"
);
141
using namespace
test::jtx
;
142
using namespace
std::filesystem
;
143
144
// empty path
145
except
([&] {
146
Env
const
env(
147
*
this
,
148
envconfig(
ledgerConfig
, sd.
dbPath
,
""
,
StartUpType::LoadFile
, std::nullopt),
149
nullptr
,
150
beast::Severity::Disabled
);
151
});
152
153
// file does not exist
154
except
([&] {
155
Env
const
env(
156
*
this
,
157
envconfig(
158
ledgerConfig
, sd.
dbPath
,
"badfile.json"
,
StartUpType::LoadFile
, std::nullopt),
159
nullptr
,
160
beast::Severity::Disabled
);
161
});
162
163
// make a corrupted version of the ledger file (last 10 bytes removed).
164
std::error_code
ec;
165
auto
ledgerFileCorrupt =
std::filesystem::path
{sd.
dbPath
} /
"ledgerdata_bad.json"
;
166
copy_file
(sd.
ledgerFile
, ledgerFileCorrupt, copy_options::overwrite_existing, ec);
167
if
(!BEAST_EXPECTS(!ec, ec.message()))
168
return
;
169
auto
filesize =
file_size
(ledgerFileCorrupt, ec);
170
if
(!BEAST_EXPECTS(!ec, ec.message()))
171
return
;
172
resize_file
(ledgerFileCorrupt, filesize - 10, ec);
173
if
(!BEAST_EXPECTS(!ec, ec.message()))
174
return
;
175
176
except
([&] {
177
Env
const
env(
178
*
this
,
179
envconfig(
180
ledgerConfig
,
181
sd.
dbPath
,
182
ledgerFileCorrupt.
string
(),
183
StartUpType::LoadFile
,
184
std::nullopt),
185
nullptr
,
186
beast::Severity::Disabled
);
187
});
188
}
189
190
void
191
testLoadByHash
(
SetupData
const
& sd)
192
{
193
testcase
(
"Load by hash"
);
194
using namespace
test::jtx
;
195
196
// create a new env with the ledger hash specified for startup
197
auto
ledgerHash =
to_string
(sd.
hashes
[sd.
hashes
.
size
() - 1]);
198
boost::erase_all(ledgerHash,
"\""
);
199
Env env(
200
*
this
,
201
envconfig(
ledgerConfig
, sd.
dbPath
, ledgerHash,
StartUpType::Load
, std::nullopt),
202
nullptr
,
203
beast::Severity::Disabled
);
204
auto
jrb = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
205
BEAST_EXPECT(jrb[jss::ledger][jss::accountState].
size
() == 98);
206
BEAST_EXPECT(
207
jrb[jss::ledger][jss::accountState].
size
() <=
208
sd.
ledger
[jss::ledger][jss::accountState].
size
());
209
}
210
211
void
212
testReplay
(
SetupData
const
& sd)
213
{
214
testcase
(
"Load and replay by hash"
);
215
using namespace
test::jtx
;
216
217
// create a new env with the ledger hash specified for startup
218
auto
ledgerHash =
to_string
(sd.
hashes
[sd.
hashes
.
size
() - 1]);
219
boost::erase_all(ledgerHash,
"\""
);
220
Env env(
221
*
this
,
222
envconfig(
ledgerConfig
, sd.
dbPath
, ledgerHash,
StartUpType::Replay
, std::nullopt),
223
nullptr
,
224
beast::Severity::Disabled
);
225
auto
const
jrb = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
226
BEAST_EXPECT(jrb[jss::ledger][jss::accountState].
size
() == 97);
227
// in replace mode do not automatically accept the ledger being replayed
228
229
env.close();
230
auto
const
closed = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
231
BEAST_EXPECT(closed[jss::ledger][jss::accountState].
size
() == 98);
232
BEAST_EXPECT(
233
closed[jss::ledger][jss::accountState].
size
() <=
234
sd.
ledger
[jss::ledger][jss::accountState].
size
());
235
}
236
237
void
238
testReplayTx
(
SetupData
const
& sd)
239
{
240
testcase
(
"Load and replay transaction by hash"
);
241
using namespace
test::jtx
;
242
243
// create a new env with the ledger hash specified for startup
244
auto
ledgerHash =
to_string
(sd.
hashes
[sd.
hashes
.
size
() - 1]);
245
boost::erase_all(ledgerHash,
"\""
);
246
Env env(
247
*
this
,
248
envconfig(
ledgerConfig
, sd.
dbPath
, ledgerHash,
StartUpType::Replay
, sd.
trapTxHash
),
249
nullptr
,
250
beast::Severity::Disabled
);
251
auto
const
jrb = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
252
BEAST_EXPECT(jrb[jss::ledger][jss::accountState].
size
() == 97);
253
// in replace mode do not automatically accept the ledger being replayed
254
255
env.close();
256
auto
const
closed = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
257
BEAST_EXPECT(closed[jss::ledger][jss::accountState].
size
() == 98);
258
BEAST_EXPECT(
259
closed[jss::ledger][jss::accountState].
size
() <=
260
sd.
ledger
[jss::ledger][jss::accountState].
size
());
261
}
262
263
void
264
testReplayTxFail
(
SetupData
const
& sd)
265
{
266
testcase
(
"Load and replay transaction by hash failure"
);
267
using namespace
test::jtx
;
268
269
// create a new env with the ledger hash specified for startup
270
auto
ledgerHash =
to_string
(sd.
hashes
[sd.
hashes
.
size
() - 1]);
271
boost::erase_all(ledgerHash,
"\""
);
272
try
273
{
274
// will throw an exception, because we cannot load a ledger for
275
// replay when trapTxHash is set to an invalid transaction
276
Env
const
env(
277
*
this
,
278
envconfig(
ledgerConfig
, sd.
dbPath
, ledgerHash,
StartUpType::Replay
, ~sd.
trapTxHash
),
279
nullptr
,
280
beast::Severity::Disabled
);
281
BEAST_EXPECT(
false
);
282
}
283
catch
(
std::runtime_error
const
&)
284
{
285
BEAST_EXPECT(
true
);
286
}
287
catch
(...)
288
{
289
BEAST_EXPECT(
false
);
290
}
291
}
292
293
void
294
testLoadLatest
(
SetupData
const
& sd)
295
{
296
testcase
(
"Load by keyword"
);
297
using namespace
test::jtx
;
298
299
// create a new env with the ledger "latest" specified for startup
300
Env env(
301
*
this
,
302
envconfig(
ledgerConfig
, sd.
dbPath
,
"latest"
,
StartUpType::Load
, std::nullopt),
303
nullptr
,
304
beast::Severity::Disabled
);
305
auto
jrb = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
306
BEAST_EXPECT(
307
sd.
ledger
[jss::ledger][jss::accountState].
size
() ==
308
jrb[jss::ledger][jss::accountState].size());
309
}
310
311
void
312
testLoadIndex
(
SetupData
const
& sd)
313
{
314
testcase
(
"Load by index"
);
315
using namespace
test::jtx
;
316
317
// create a new env with specific ledger index at startup
318
Env env(
319
*
this
,
320
envconfig(
ledgerConfig
, sd.
dbPath
,
"43"
,
StartUpType::Load
, std::nullopt),
321
nullptr
,
322
beast::Severity::Disabled
);
323
auto
jrb = env.rpc(
"ledger"
,
"current"
,
"full"
)[jss::result];
324
BEAST_EXPECT(
325
sd.
ledger
[jss::ledger][jss::accountState].
size
() ==
326
jrb[jss::ledger][jss::accountState].size());
327
}
328
329
public
:
330
void
331
run
()
override
332
{
333
TempDir
const
td;
334
auto
sd =
setupLedger
(td);
335
336
// test cases
337
testLoad
(sd);
338
testBadFiles
(sd);
339
testLoadByHash
(sd);
340
testReplay
(sd);
341
testReplayTx
(sd);
342
testReplayTxFail
(sd);
343
testLoadLatest
(sd);
344
testLoadIndex
(sd);
345
}
346
};
347
348
BEAST_DEFINE_TESTSUITE
(LedgerLoad, app,
xrpl
);
349
350
}
// namespace xrpl
std::ofstream
std::string
cassert
beast::unit_test::Suite
A testsuite class.
Definition
suite.h:52
beast::unit_test::Suite::except
bool except(F &&f, String const &reason)
Definition
suite.h:465
beast::unit_test::Suite::testcase
TestcaseT testcase
Memberspace for declaring test cases.
Definition
suite.h:155
json::Value
Represents a JSON value.
Definition
json_value.h:117
json::Value::size
UInt size() const
Number of values in array or object.
Definition
json_value.cpp:801
xrpl::BaseUInt::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition
base_uint.h:525
xrpl::LedgerLoad_test
Definition
LedgerLoad_test.cpp:35
xrpl::LedgerLoad_test::testLoadLatest
void testLoadLatest(SetupData const &sd)
Definition
LedgerLoad_test.cpp:294
xrpl::LedgerLoad_test::setupLedger
SetupData setupLedger(TempDir const &td)
Definition
LedgerLoad_test.cpp:64
xrpl::LedgerLoad_test::testReplay
void testReplay(SetupData const &sd)
Definition
LedgerLoad_test.cpp:212
xrpl::LedgerLoad_test::testReplayTxFail
void testReplayTxFail(SetupData const &sd)
Definition
LedgerLoad_test.cpp:264
xrpl::LedgerLoad_test::run
void run() override
Runs the suite.
Definition
LedgerLoad_test.cpp:331
xrpl::LedgerLoad_test::testBadFiles
void testBadFiles(SetupData const &sd)
Definition
LedgerLoad_test.cpp:138
xrpl::LedgerLoad_test::testReplayTx
void testReplayTx(SetupData const &sd)
Definition
LedgerLoad_test.cpp:238
xrpl::LedgerLoad_test::ledgerConfig
static auto ledgerConfig(std::unique_ptr< Config > cfg, std::string const &dbPath, std::string const &ledger, StartUpType type, std::optional< UInt256 > trapTxHash)
Definition
LedgerLoad_test.cpp:36
xrpl::LedgerLoad_test::testLoadByHash
void testLoadByHash(SetupData const &sd)
Definition
LedgerLoad_test.cpp:191
xrpl::LedgerLoad_test::testLoadIndex
void testLoadIndex(SetupData const &sd)
Definition
LedgerLoad_test.cpp:312
xrpl::LedgerLoad_test::testLoad
void testLoad(SetupData const &sd)
Definition
LedgerLoad_test.cpp:120
xrpl::TempDir
RAII temporary directory.
Definition
FileUtilities.h:44
xrpl::TempDir::path
std::string path() const
Get the native path for the temporary directory.
Definition
libxrpl/basics/FileUtilities.cpp:130
xrpl::TempDir::file
std::string file(std::string const &name) const
Get the native path for a file.
Definition
libxrpl/basics/FileUtilities.cpp:136
std::ofstream::close
T close(T... args)
std::filesystem::copy_file
T copy_file(T... args)
std::string::empty
T empty(T... args)
std::error_code
std::filesystem::file_size
T file_size(T... args)
filesystem
fstream
ios
memory
beast::Severity::Disabled
@ Disabled
Definition
Journal.h:26
std::filesystem
xrpl::test::jtx
Definition
Oracle_test.cpp:34
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::to_string
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition
base_uint.h:657
xrpl::UInt256
BaseUInt< 256 > UInt256
Definition
base_uint.h:580
xrpl::FeePayerType::Account
@ Account
Definition
Transactor.h:145
xrpl::StartUpType
StartUpType
Definition
StartUpType.h:8
xrpl::StartUpType::Replay
@ Replay
Definition
StartUpType.h:8
xrpl::StartUpType::Load
@ Load
Definition
StartUpType.h:8
xrpl::StartUpType::LoadFile
@ LoadFile
Definition
StartUpType.h:8
xrpl::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
optional
std::filesystem::path
std::filesystem::resize_file
T resize_file(T... args)
std::runtime_error
std::size
T size(T... args)
stdexcept
string
xrpl::LedgerLoad_test::SetupData
Definition
LedgerLoad_test.cpp:53
xrpl::LedgerLoad_test::SetupData::dbPath
std::string const dbPath
Definition
LedgerLoad_test.cpp:54
xrpl::LedgerLoad_test::SetupData::ledger
json::Value ledger
Definition
LedgerLoad_test.cpp:57
xrpl::LedgerLoad_test::SetupData::trapTxHash
UInt256 trapTxHash
Definition
LedgerLoad_test.cpp:59
xrpl::LedgerLoad_test::SetupData::ledgerFile
std::string ledgerFile
Definition
LedgerLoad_test.cpp:56
xrpl::LedgerLoad_test::SetupData::hashes
json::Value hashes
Definition
LedgerLoad_test.cpp:58
system_error
std::to_string
T to_string(T... args)
std::unique_ptr
Generated by
1.17.0