130 testcase(
"No Params, None Enabled");
132 using namespace test::jtx;
137 auto jrr = env.rpc(
"feature")[jss::result];
138 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
140 for (
auto const& feature : jrr[jss::features])
142 if (!BEAST_EXPECT(feature.isMember(jss::name)))
146 bool const expectVeto =
148 bool const expectObsolete =
151 feature.isMember(jss::enabled) && !feature[jss::enabled].asBool(),
152 feature[jss::name].asString() +
" enabled");
154 feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete &&
155 (!feature[jss::vetoed].isBool() ||
156 feature[jss::vetoed].asBool() == expectVeto) &&
157 (feature[jss::vetoed].isBool() ||
158 feature[jss::vetoed].asString() ==
"Obsolete"),
159 feature[jss::name].asString() +
" vetoed");
161 feature.isMember(jss::supported) && feature[jss::supported].asBool(),
162 feature[jss::name].asString() +
" supported");
171 using namespace test::jtx;
175 auto jrr = env.rpc(
"feature", name)[jss::result];
176 BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status");
177 jrr.removeMember(jss::status);
178 BEAST_EXPECT(jrr.size() == 1);
180 char const sha[] =
"12523DF04B553A0B1AD74F42DDB741DE8DC06A03FC089A0EF197E2A87F1D8107";
181 BEAST_EXPECT(expected == sha);
182 BEAST_EXPECT(jrr.isMember(expected));
183 auto feature = *(jrr.begin());
185 BEAST_EXPECTS(feature[jss::name] == name,
"name");
186 BEAST_EXPECTS(!feature[jss::enabled].asBool(),
"enabled");
187 BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
"vetoed");
188 BEAST_EXPECTS(feature[jss::supported].asBool(),
"supported");
191 jrr = env.rpc(
"feature",
"fMM")[jss::result];
192 BEAST_EXPECT(jrr[jss::error] ==
"badFeature");
193 BEAST_EXPECT(jrr[jss::error_message] ==
"Feature unknown or invalid.");
196 constexpr auto ok63Name = [] {
197 return "123456789012345678901234567890123456789012345678901234567890123";
201 constexpr auto bad64Name = [] {
202 return "1234567890123456789012345678901234567890123456789012345678901234";
206 constexpr auto ok31Name = [] {
return "1234567890123456789012345678901"; };
209 constexpr auto bad32Name = [] {
return "12345678901234567890123456789012"; };
212 constexpr auto ok33Name = [] {
return "123456789012345678901234567890123"; };
216 constexpr auto okName = [] {
return "AMM_123"; };
220 constexpr auto badName = [] {
return "ΑMM_123"; };
223 constexpr auto badEmoji = [] {
return "🔥"; };
262 using namespace test::jtx;
264 (*cfg)[
"port_rpc"].set(
"admin",
"");
265 (*cfg)[
"port_ws"].set(
"admin",
"");
270 auto result = env.rpc(
"feature")[jss::result];
271 BEAST_EXPECT(result.isMember(jss::features));
275 BEAST_EXPECT(result[jss::features].size() >= 50);
276 for (
auto it = result[jss::features].begin(); it != result[jss::features].end(); ++it)
279 (void)
id.parseHex(it.key().asString().c_str());
280 if (!BEAST_EXPECT((*it).isMember(jss::name)))
282 bool const expectEnabled = env.app().getAmendmentTable().isEnabled(
id);
283 bool const expectSupported = env.app().getAmendmentTable().isSupported(
id);
285 (*it).isMember(jss::enabled) && (*it)[jss::enabled].asBool() == expectEnabled,
286 (*it)[jss::name].asString() +
" enabled");
288 (*it).isMember(jss::supported) &&
289 (*it)[jss::supported].asBool() == expectSupported,
290 (*it)[jss::name].asString() +
" supported");
291 BEAST_EXPECT(!(*it).isMember(jss::vetoed));
292 BEAST_EXPECT(!(*it).isMember(jss::majority));
293 BEAST_EXPECT(!(*it).isMember(jss::count));
294 BEAST_EXPECT(!(*it).isMember(jss::validations));
295 BEAST_EXPECT(!(*it).isMember(jss::threshold));
302 params[jss::feature] =
303 "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCD"
305 auto const result = env.rpc(
"json",
"feature",
to_string(params))[jss::result];
306 BEAST_EXPECTS(result[jss::error] ==
"badFeature", result.toStyledString());
307 BEAST_EXPECT(result[jss::error_message] ==
"Feature unknown or invalid.");
312 params[jss::feature] =
313 "93E516234E35E08CA689FA33A6D38E103881F8DCB53023F728C307AA89D515"
316 params[jss::vetoed] =
true;
317 auto const result = env.rpc(
"json",
"feature",
to_string(params))[jss::result];
318 BEAST_EXPECTS(result[jss::error] ==
"noPermission", result[jss::error].asString());
320 result[jss::error_message] ==
"You don't have permission for this command.");
327 testcase(
"No Params, Some Enabled");
329 using namespace test::jtx;
334 auto jrr = env.rpc(
"feature")[jss::result];
335 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
337 for (
auto it = jrr[jss::features].begin(); it != jrr[jss::features].end(); ++it)
340 (void)
id.parseHex(it.key().asString().c_str());
341 if (!BEAST_EXPECT((*it).isMember(jss::name)))
343 bool const expectEnabled = env.app().getAmendmentTable().isEnabled(
id);
344 bool const expectSupported = env.app().getAmendmentTable().isSupported(
id);
345 bool const expectVeto =
347 bool const expectObsolete =
350 (*it).isMember(jss::enabled) && (*it)[jss::enabled].asBool() == expectEnabled,
351 (*it)[jss::name].asString() +
" enabled");
355 !(*it).isMember(jss::vetoed), (*it)[jss::name].asString() +
" vetoed");
360 (*it).isMember(jss::vetoed) && (*it)[jss::vetoed].isBool() == !expectObsolete &&
361 (!(*it)[jss::vetoed].isBool() ||
362 (*it)[jss::vetoed].asBool() == expectVeto) &&
363 ((*it)[jss::vetoed].isBool() ||
364 (*it)[jss::vetoed].asString() ==
"Obsolete"),
365 (*it)[jss::name].asString() +
" vetoed");
368 (*it).isMember(jss::supported) && (*it)[jss::supported].asBool() == expectSupported,
369 (*it)[jss::name].asString() +
" supported");
378 using namespace test::jtx;
379 Env env{*
this, envconfig(validator,
"")};
381 auto jrr = env.rpc(
"feature")[jss::result];
382 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
387 for (
auto const& feature : jrr[jss::features])
389 if (!BEAST_EXPECT(feature.isMember(jss::name)))
392 !feature.isMember(jss::majority), feature[jss::name].asString() +
" majority");
393 BEAST_EXPECTS(!feature.isMember(jss::count), feature[jss::name].asString() +
" count");
395 !feature.isMember(jss::threshold), feature[jss::name].asString() +
" threshold");
397 !feature.isMember(jss::validations),
398 feature[jss::name].asString() +
" validations");
399 BEAST_EXPECTS(!feature.isMember(jss::vote), feature[jss::name].asString() +
" vote");
403 if (!BEAST_EXPECT(majorities.empty()))
407 for (
auto i = 0; i <= 256; ++i)
411 if (!majorities.empty())
417 BEAST_EXPECT(majorities.size() >= 2);
420 jrr = env.rpc(
"feature")[jss::result];
421 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
423 for (
auto const& feature : jrr[jss::features])
425 if (!BEAST_EXPECT(feature.isMember(jss::name)))
427 bool const expectVeto =
429 bool const expectObsolete =
432 (expectVeto || expectObsolete) ^ feature.isMember(jss::majority),
433 feature[jss::name].asString() +
" majority");
435 feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete &&
436 (!feature[jss::vetoed].isBool() ||
437 feature[jss::vetoed].asBool() == expectVeto) &&
438 (feature[jss::vetoed].isBool() ||
439 feature[jss::vetoed].asString() ==
"Obsolete"),
440 feature[jss::name].asString() +
" vetoed");
441 BEAST_EXPECTS(feature.isMember(jss::count), feature[jss::name].asString() +
" count");
443 feature.isMember(jss::threshold), feature[jss::name].asString() +
" threshold");
445 feature.isMember(jss::validations), feature[jss::name].asString() +
" validations");
446 BEAST_EXPECT(feature[jss::count] == ((expectVeto || expectObsolete) ? 0 : 1));
447 BEAST_EXPECT(feature[jss::threshold] == 1);
448 BEAST_EXPECT(feature[jss::validations] == 1);
450 expectVeto || expectObsolete || feature[jss::majority] == 2540,
451 "Majority: " + feature[jss::majority].asString());
460 using namespace test::jtx;
462 constexpr char const* featureName =
"fixAMMOverflowOffer";
464 auto jrr = env.rpc(
"feature", featureName)[jss::result];
465 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
467 jrr.removeMember(jss::status);
468 if (!BEAST_EXPECT(jrr.size() == 1))
470 auto feature = *(jrr.begin());
471 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
472 BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
"vetoed");
474 jrr = env.rpc(
"feature", featureName,
"reject")[jss::result];
475 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
477 jrr.removeMember(jss::status);
478 if (!BEAST_EXPECT(jrr.size() == 1))
480 feature = *(jrr.begin());
481 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
482 BEAST_EXPECTS(feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool(),
"vetoed");
484 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
485 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
487 jrr.removeMember(jss::status);
488 if (!BEAST_EXPECT(jrr.size() == 1))
490 feature = *(jrr.begin());
491 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
492 BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
"vetoed");
495 jrr = env.rpc(
"feature", featureName,
"maybe");
496 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
497 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");
505 using namespace test::jtx;
510 std::begin(supportedAmendments),
std::end(supportedAmendments), [](
auto const& pair) {
514 if (obsoleteFeature ==
std::end(supportedAmendments))
520 auto const featureName = obsoleteFeature->first;
522 auto jrr = env.rpc(
"feature", featureName)[jss::result];
523 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
525 jrr.removeMember(jss::status);
526 if (!BEAST_EXPECT(jrr.size() == 1))
528 auto feature = *(jrr.begin());
529 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
531 feature[jss::vetoed].isString() && feature[jss::vetoed].asString() ==
"Obsolete",
534 jrr = env.rpc(
"feature", featureName,
"reject")[jss::result];
535 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
537 jrr.removeMember(jss::status);
538 if (!BEAST_EXPECT(jrr.size() == 1))
540 feature = *(jrr.begin());
541 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
543 feature[jss::vetoed].isString() && feature[jss::vetoed].asString() ==
"Obsolete",
546 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
547 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
549 jrr.removeMember(jss::status);
550 if (!BEAST_EXPECT(jrr.size() == 1))
552 feature = *(jrr.begin());
553 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
555 feature[jss::vetoed].isString() && feature[jss::vetoed].asString() ==
"Obsolete",
559 jrr = env.rpc(
"feature", featureName,
"maybe");
560 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
561 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");