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;
374 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
375 return jv[jss::type] ==
"validationReceived" &&
376 jv[jss::validation_public_key].asString() == valPublicKey &&
377 jv[jss::ledger_hash] ==
378 to_string(env.closed()->info().hash) &&
379 jv[jss::ledger_index] ==
380 std::to_string(env.closed()->info().seq) &&
382 (vfFullyCanonicalSig | vfFullValidation) &&
383 jv[jss::full] == true && !jv.isMember(jss::load_fee) &&
384 jv[jss::signature] && jv[jss::signing_time];
389 auto jv = wsc->invoke(
"unsubscribe", stream);
390 if (wsc->version() == 2)
393 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
395 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
396 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
398 BEAST_EXPECT(jv[jss::status] ==
"success");
405 testcase(
"Subscribe by url");
409 jv[jss::url] =
"http://localhost/events";
410 jv[jss::url_username] =
"admin";
411 jv[jss::url_password] =
"password";
413 jv[jss::streams][0u] =
"validations";
414 auto jr = env.rpc(
"json",
"subscribe",
to_string(jv))[jss::result];
415 BEAST_EXPECT(jr[jss::status] ==
"success");
417 jv[jss::streams][0u] =
"ledger";
418 jr = env.rpc(
"json",
"subscribe",
to_string(jv))[jss::result];
419 BEAST_EXPECT(jr[jss::status] ==
"success");
421 jr = env.rpc(
"json",
"unsubscribe",
to_string(jv))[jss::result];
422 BEAST_EXPECT(jr[jss::status] ==
"success");
424 jv[jss::streams][0u] =
"validations";
425 jr = env.rpc(
"json",
"unsubscribe",
to_string(jv))[jss::result];
426 BEAST_EXPECT(jr[jss::status] ==
"success");
433 auto const method = subscribe ?
"subscribe" :
"unsubscribe";
434 testcase <<
"Error cases for " << method;
440 auto jr = env.rpc(
"json", method,
"{}")[jss::result];
441 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
442 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
447 jv[jss::url] =
"not-a-url";
448 jv[jss::username] =
"admin";
449 jv[jss::password] =
"password";
450 auto jr = env.rpc(
"json", method,
to_string(jv))[jss::result];
453 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
454 BEAST_EXPECT(jr[jss::error_message] ==
"Failed to parse url.");
462 jv[jss::url] =
"ftp://scheme.not.supported.tld";
463 auto jr = env.rpc(
"json", method,
to_string(jv))[jss::result];
466 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
468 jr[jss::error_message] ==
469 "Only http and https is supported.");
476 jv[jss::url] =
"no-url";
478 env_nonadmin.rpc(
"json", method,
to_string(jv))[jss::result];
479 BEAST_EXPECT(jr[jss::error] ==
"noPermission");
481 jr[jss::error_message] ==
482 "You don't have permission for this command.");
494 for (
auto const& f : {jss::accounts_proposed, jss::accounts})
496 for (
auto const& nonArray : nonArrays)
500 auto jr = wsc->invoke(method, jv)[jss::result];
501 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
502 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
508 auto jr = wsc->invoke(method, jv)[jss::result];
509 BEAST_EXPECT(jr[jss::error] ==
"actMalformed");
510 BEAST_EXPECT(jr[jss::error_message] ==
"Account malformed.");
514 for (
auto const& nonArray : nonArrays)
517 jv[jss::books] = nonArray;
518 auto jr = wsc->invoke(method, jv)[jss::result];
519 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
520 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
526 jv[jss::books][0u] = 1;
527 auto jr = wsc->invoke(method, jv)[jss::result];
528 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
529 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
538 auto jr = wsc->invoke(method, jv)[jss::result];
539 BEAST_EXPECT(jr[jss::error] ==
"srcCurMalformed");
541 jr[jss::error_message] ==
"Source currency is malformed.");
550 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"ZZZZ";
551 auto jr = wsc->invoke(method, jv)[jss::result];
552 BEAST_EXPECT(jr[jss::error] ==
"srcCurMalformed");
554 jr[jss::error_message] ==
"Source currency is malformed.");
563 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"USD";
564 jv[jss::books][0u][jss::taker_pays][jss::issuer] = 1;
565 auto jr = wsc->invoke(method, jv)[jss::result];
566 BEAST_EXPECT(jr[jss::error] ==
"srcIsrMalformed");
568 jr[jss::error_message] ==
"Source issuer is malformed.");
577 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"USD";
578 jv[jss::books][0u][jss::taker_pays][jss::issuer] =
580 auto jr = wsc->invoke(method, jv)[jss::result];
581 BEAST_EXPECT(jr[jss::error] ==
"srcIsrMalformed");
583 jr[jss::error_message] ==
"Source issuer is malformed.");
590 jv[jss::books][0u][jss::taker_pays] =
591 Account{
"gateway"}[
"USD"](1).value().getJson(
594 auto jr = wsc->invoke(method, jv)[jss::result];
597 BEAST_EXPECT(jr[jss::error] ==
"dstAmtMalformed");
599 jr[jss::error_message] ==
600 "Destination amount/currency/issuer is malformed.");
607 jv[jss::books][0u][jss::taker_pays] =
608 Account{
"gateway"}[
"USD"](1).value().getJson(
610 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"ZZZZ";
611 auto jr = wsc->invoke(method, jv)[jss::result];
614 BEAST_EXPECT(jr[jss::error] ==
"dstAmtMalformed");
616 jr[jss::error_message] ==
617 "Destination amount/currency/issuer is malformed.");
624 jv[jss::books][0u][jss::taker_pays] =
625 Account{
"gateway"}[
"USD"](1).value().getJson(
627 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"USD";
628 jv[jss::books][0u][jss::taker_gets][jss::issuer] = 1;
629 auto jr = wsc->invoke(method, jv)[jss::result];
630 BEAST_EXPECT(jr[jss::error] ==
"dstIsrMalformed");
632 jr[jss::error_message] ==
"Destination issuer is malformed.");
639 jv[jss::books][0u][jss::taker_pays] =
640 Account{
"gateway"}[
"USD"](1).value().getJson(
642 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"USD";
643 jv[jss::books][0u][jss::taker_gets][jss::issuer] =
645 auto jr = wsc->invoke(method, jv)[jss::result];
646 BEAST_EXPECT(jr[jss::error] ==
"dstIsrMalformed");
648 jr[jss::error_message] ==
"Destination issuer is malformed.");
655 jv[jss::books][0u][jss::taker_pays] =
656 Account{
"gateway"}[
"USD"](1).value().getJson(
658 jv[jss::books][0u][jss::taker_gets] =
659 Account{
"gateway"}[
"USD"](1).value().getJson(
661 auto jr = wsc->invoke(method, jv)[jss::result];
662 BEAST_EXPECT(jr[jss::error] ==
"badMarket");
663 BEAST_EXPECT(jr[jss::error_message] ==
"No such market.");
666 for (
auto const& nonArray : nonArrays)
669 jv[jss::streams] = nonArray;
670 auto jr = wsc->invoke(method, jv)[jss::result];
671 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
672 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
678 jv[jss::streams][0u] = 1;
679 auto jr = wsc->invoke(method, jv)[jss::result];
680 BEAST_EXPECT(jr[jss::error] ==
"malformedStream");
681 BEAST_EXPECT(jr[jss::error_message] ==
"Stream malformed.");
687 jv[jss::streams][0u] =
"not_a_stream";
688 auto jr = wsc->invoke(method, jv)[jss::result];
689 BEAST_EXPECT(jr[jss::error] ==
"malformedStream");
690 BEAST_EXPECT(jr[jss::error_message] ==
"Stream malformed.");