18 #include <ripple/app/main/LoadManager.h>
19 #include <ripple/app/misc/LoadFeeTrack.h>
20 #include <ripple/app/misc/NetworkOPs.h>
21 #include <ripple/beast/unit_test.h>
22 #include <ripple/core/ConfigSections.h>
23 #include <ripple/protocol/jss.h>
25 #include <test/jtx/WSClient.h>
26 #include <test/jtx/envconfig.h>
37 using namespace std::chrono_literals;
46 stream[jss::streams].append(
"server");
47 auto jv = wsc->invoke(
"subscribe", stream);
48 if (wsc->version() == 2)
51 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
53 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
54 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
56 BEAST_EXPECT(jv[jss::status] ==
"success");
68 for (
int i = 0; i < 5; ++i)
73 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
74 return jv[jss::type] ==
"serverStatus";
80 auto jv = wsc->invoke(
"unsubscribe", stream);
81 if (wsc->version() == 2)
84 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
86 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
87 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
89 BEAST_EXPECT(jv[jss::status] ==
"success");
95 for (
int i = 0; i < 5; ++i)
100 auto jvo = wsc->getMsg(10ms);
101 BEAST_EXPECTS(!jvo,
"getMsg: " +
to_string(jvo.get()));
108 using namespace std::chrono_literals;
117 stream[jss::streams].append(
"ledger");
118 auto jv = wsc->invoke(
"subscribe", stream);
119 if (wsc->version() == 2)
122 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
124 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
125 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
127 BEAST_EXPECT(jv[jss::result][jss::ledger_index] == 2);
135 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
136 return jv[jss::ledger_index] == 3;
145 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
146 return jv[jss::ledger_index] == 4;
151 auto jv = wsc->invoke(
"unsubscribe", stream);
152 if (wsc->version() == 2)
155 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
157 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
158 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
160 BEAST_EXPECT(jv[jss::status] ==
"success");
166 using namespace std::chrono_literals;
175 stream[jss::streams].append(
"transactions");
176 auto jv = wsc->invoke(
"subscribe", stream);
177 if (wsc->version() == 2)
180 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
182 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
183 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
185 BEAST_EXPECT(jv[jss::status] ==
"success");
193 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
194 return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
195 [
"NewFields"][jss::Account] ==
196 Account(
"alice").human();
200 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
201 return jv[jss::meta][
"AffectedNodes"][0u][
"ModifiedNode"]
202 [
"FinalFields"][jss::Account] ==
203 Account(
"alice").human();
210 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
211 return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
212 [
"NewFields"][jss::Account] == Account(
"bob").human();
216 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
217 return jv[jss::meta][
"AffectedNodes"][0u][
"ModifiedNode"]
218 [
"FinalFields"][jss::Account] ==
219 Account(
"bob").human();
225 auto jv = wsc->invoke(
"unsubscribe", stream);
226 if (wsc->version() == 2)
229 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
231 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
232 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
234 BEAST_EXPECT(jv[jss::status] ==
"success");
241 stream[jss::accounts].append(
Account(
"alice").human());
242 auto jv = wsc->invoke(
"subscribe", stream);
243 if (wsc->version() == 2)
246 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
248 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
249 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
251 BEAST_EXPECT(jv[jss::status] ==
"success");
258 BEAST_EXPECT(!wsc->getMsg(10ms));
265 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
266 return jv[jss::meta][
"AffectedNodes"][1u][
"ModifiedNode"]
267 [
"FinalFields"][jss::Account] ==
268 Account(
"alice").human();
271 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
272 return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
273 [
"NewFields"][
"LowLimit"][jss::issuer] ==
274 Account(
"alice").human();
279 auto jv = wsc->invoke(
"unsubscribe", stream);
280 if (wsc->version() == 2)
283 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
285 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
286 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
288 BEAST_EXPECT(jv[jss::status] ==
"success");
302 stream[jss::streams].append(
"manifests");
303 auto jv = wsc->invoke(
"subscribe", stream);
304 if (wsc->version() == 2)
307 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
309 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
310 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
312 BEAST_EXPECT(jv[jss::status] ==
"success");
316 auto jv = wsc->invoke(
"unsubscribe", stream);
317 if (wsc->version() == 2)
320 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
322 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
323 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
325 BEAST_EXPECT(jv[jss::status] ==
"success");
334 auto& cfg = env.app().config();
335 if (!BEAST_EXPECT(cfg.section(SECTION_VALIDATION_SEED).empty()))
337 auto const parsedseed =
338 parseBase58<Seed>(cfg.section(SECTION_VALIDATION_SEED).values()[0]);
339 if (!BEAST_EXPECT(parsedseed))
354 stream[jss::streams].append(
"validations");
355 auto jv = wsc->invoke(
"subscribe", stream);
356 if (wsc->version() == 2)
359 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
361 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
362 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
364 BEAST_EXPECT(jv[jss::status] ==
"success");
372 using namespace std::chrono_literals;
373 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
374 return jv[jss::type] ==
"validationReceived" &&
375 jv[jss::validation_public_key].asString() == valPublicKey &&
376 jv[jss::ledger_hash] ==
377 to_string(env.closed()->info().hash) &&
378 jv[jss::ledger_index] ==
379 std::to_string(env.closed()->info().seq) &&
381 (vfFullyCanonicalSig | STValidation::kFullFlag) &&
382 jv[jss::full] == true && !jv.isMember(jss::load_fee) &&
383 jv[jss::signature] && jv[jss::signing_time];
388 auto jv = wsc->invoke(
"unsubscribe", stream);
389 if (wsc->version() == 2)
392 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
394 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
395 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
397 BEAST_EXPECT(jv[jss::status] ==
"success");
404 testcase(
"Subscribe by url");
408 jv[jss::url] =
"http://localhost/events";
409 jv[jss::url_username] =
"admin";
410 jv[jss::url_password] =
"password";
412 jv[jss::streams][0u] =
"validations";
413 auto jr = env.rpc(
"json",
"subscribe",
to_string(jv))[jss::result];
414 BEAST_EXPECT(jr[jss::status] ==
"success");
416 jv[jss::streams][0u] =
"ledger";
417 jr = env.rpc(
"json",
"subscribe",
to_string(jv))[jss::result];
418 BEAST_EXPECT(jr[jss::status] ==
"success");
420 jr = env.rpc(
"json",
"unsubscribe",
to_string(jv))[jss::result];
421 BEAST_EXPECT(jr[jss::status] ==
"success");
423 jv[jss::streams][0u] =
"validations";
424 jr = env.rpc(
"json",
"unsubscribe",
to_string(jv))[jss::result];
425 BEAST_EXPECT(jr[jss::status] ==
"success");
432 auto const method = subscribe ?
"subscribe" :
"unsubscribe";
433 testcase <<
"Error cases for " << method;
439 auto jr = env.rpc(
"json", method,
"{}")[jss::result];
440 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
441 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
446 jv[jss::url] =
"not-a-url";
447 jv[jss::username] =
"admin";
448 jv[jss::password] =
"password";
449 auto jr = env.rpc(
"json", method,
to_string(jv))[jss::result];
452 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
453 BEAST_EXPECT(jr[jss::error_message] ==
"Failed to parse url.");
461 jv[jss::url] =
"ftp://scheme.not.supported.tld";
462 auto jr = env.rpc(
"json", method,
to_string(jv))[jss::result];
465 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
467 jr[jss::error_message] ==
468 "Only http and https is supported.");
475 jv[jss::url] =
"no-url";
477 env_nonadmin.rpc(
"json", method,
to_string(jv))[jss::result];
478 BEAST_EXPECT(jr[jss::error] ==
"noPermission");
480 jr[jss::error_message] ==
481 "You don't have permission for this command.");
493 for (
auto const& f : {jss::accounts_proposed, jss::accounts})
495 for (
auto const& nonArray : nonArrays)
499 auto jr = wsc->invoke(method, jv)[jss::result];
500 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
501 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
507 auto jr = wsc->invoke(method, jv)[jss::result];
508 BEAST_EXPECT(jr[jss::error] ==
"actMalformed");
509 BEAST_EXPECT(jr[jss::error_message] ==
"Account malformed.");
513 for (
auto const& nonArray : nonArrays)
516 jv[jss::books] = nonArray;
517 auto jr = wsc->invoke(method, jv)[jss::result];
518 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
519 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
525 jv[jss::books][0u] = 1;
526 auto jr = wsc->invoke(method, jv)[jss::result];
527 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
528 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
537 auto jr = wsc->invoke(method, jv)[jss::result];
538 BEAST_EXPECT(jr[jss::error] ==
"srcCurMalformed");
540 jr[jss::error_message] ==
"Source currency is malformed.");
549 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"ZZZZ";
550 auto jr = wsc->invoke(method, jv)[jss::result];
551 BEAST_EXPECT(jr[jss::error] ==
"srcCurMalformed");
553 jr[jss::error_message] ==
"Source currency is malformed.");
562 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"USD";
563 jv[jss::books][0u][jss::taker_pays][jss::issuer] = 1;
564 auto jr = wsc->invoke(method, jv)[jss::result];
565 BEAST_EXPECT(jr[jss::error] ==
"srcIsrMalformed");
567 jr[jss::error_message] ==
"Source issuer is malformed.");
576 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"USD";
577 jv[jss::books][0u][jss::taker_pays][jss::issuer] =
579 auto jr = wsc->invoke(method, jv)[jss::result];
580 BEAST_EXPECT(jr[jss::error] ==
"srcIsrMalformed");
582 jr[jss::error_message] ==
"Source issuer is malformed.");
589 jv[jss::books][0u][jss::taker_pays] =
590 Account{
"gateway"}[
"USD"](1).value().getJson(
593 auto jr = wsc->invoke(method, jv)[jss::result];
596 BEAST_EXPECT(jr[jss::error] ==
"dstAmtMalformed");
598 jr[jss::error_message] ==
599 "Destination amount/currency/issuer is malformed.");
606 jv[jss::books][0u][jss::taker_pays] =
607 Account{
"gateway"}[
"USD"](1).value().getJson(
609 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"ZZZZ";
610 auto jr = wsc->invoke(method, jv)[jss::result];
613 BEAST_EXPECT(jr[jss::error] ==
"dstAmtMalformed");
615 jr[jss::error_message] ==
616 "Destination amount/currency/issuer is malformed.");
623 jv[jss::books][0u][jss::taker_pays] =
624 Account{
"gateway"}[
"USD"](1).value().getJson(
626 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"USD";
627 jv[jss::books][0u][jss::taker_gets][jss::issuer] = 1;
628 auto jr = wsc->invoke(method, jv)[jss::result];
629 BEAST_EXPECT(jr[jss::error] ==
"dstIsrMalformed");
631 jr[jss::error_message] ==
"Destination issuer is malformed.");
638 jv[jss::books][0u][jss::taker_pays] =
639 Account{
"gateway"}[
"USD"](1).value().getJson(
641 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"USD";
642 jv[jss::books][0u][jss::taker_gets][jss::issuer] =
644 auto jr = wsc->invoke(method, jv)[jss::result];
645 BEAST_EXPECT(jr[jss::error] ==
"dstIsrMalformed");
647 jr[jss::error_message] ==
"Destination issuer is malformed.");
654 jv[jss::books][0u][jss::taker_pays] =
655 Account{
"gateway"}[
"USD"](1).value().getJson(
657 jv[jss::books][0u][jss::taker_gets] =
658 Account{
"gateway"}[
"USD"](1).value().getJson(
660 auto jr = wsc->invoke(method, jv)[jss::result];
661 BEAST_EXPECT(jr[jss::error] ==
"badMarket");
662 BEAST_EXPECT(jr[jss::error_message] ==
"No such market.");
665 for (
auto const& nonArray : nonArrays)
668 jv[jss::streams] = nonArray;
669 auto jr = wsc->invoke(method, jv)[jss::result];
670 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
671 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
677 jv[jss::streams][0u] = 1;
678 auto jr = wsc->invoke(method, jv)[jss::result];
679 BEAST_EXPECT(jr[jss::error] ==
"malformedStream");
680 BEAST_EXPECT(jr[jss::error_message] ==
"Stream malformed.");
686 jv[jss::streams][0u] =
"not_a_stream";
687 auto jr = wsc->invoke(method, jv)[jss::result];
688 BEAST_EXPECT(jr[jss::error] ==
"malformedStream");
689 BEAST_EXPECT(jr[jss::error_message] ==
"Stream malformed.");