20 #include <ripple/app/misc/AmendmentTable.h>
21 #include <ripple/protocol/Feature.h>
22 #include <ripple/protocol/jss.h>
32 testcase(
"internals");
44 switch (amendment.second)
56 fail(
"Unknown VoteBehavior", __FILE__, __LINE__);
67 testcase(
"featureToName");
74 for (
auto const& [feature, vote] : supported)
78 if (BEAST_EXPECT(registered))
92 "0000000000000000000000000000000000000000000000000000000000000000");
105 "fixTakerDryOfferRemoval");
111 testcase(
"No Params, None Enabled");
113 using namespace test::jtx;
119 auto jrr = env.rpc(
"feature")[jss::result];
120 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
122 for (
auto const& feature : jrr[jss::features])
124 if (!BEAST_EXPECT(feature.isMember(jss::name)))
129 (votes.
at(feature[jss::name].asString()) ==
131 bool expectObsolete =
132 (votes.
at(feature[jss::name].asString()) ==
135 feature.isMember(jss::enabled) &&
136 !feature[jss::enabled].asBool(),
137 feature[jss::name].asString() +
" enabled");
139 feature.isMember(jss::vetoed) &&
140 feature[jss::vetoed].isBool() == !expectObsolete &&
141 (!feature[jss::vetoed].isBool() ||
142 feature[jss::vetoed].asBool() == expectVeto) &&
143 (feature[jss::vetoed].isBool() ||
144 feature[jss::vetoed].asString() ==
"Obsolete"),
145 feature[jss::name].asString() +
" vetoed");
147 feature.isMember(jss::supported) &&
148 feature[jss::supported].asBool(),
149 feature[jss::name].asString() +
" supported");
156 testcase(
"Feature Param");
158 using namespace test::jtx;
161 auto jrr = env.rpc(
"feature",
"MultiSignReserve")[jss::result];
162 BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status");
163 jrr.removeMember(jss::status);
164 BEAST_EXPECT(jrr.size() == 1);
166 jrr.isMember(
"586480873651E106F1D6339B0C4A8945BA705A777F3F4524626FF"
168 auto feature = *(jrr.begin());
170 BEAST_EXPECTS(feature[jss::name] ==
"MultiSignReserve",
"name");
171 BEAST_EXPECTS(!feature[jss::enabled].asBool(),
"enabled");
173 feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
175 BEAST_EXPECTS(feature[jss::supported].asBool(),
"supported");
178 jrr = env.rpc(
"feature",
"multiSignReserve")[jss::result];
179 BEAST_EXPECT(jrr[jss::error] ==
"badFeature");
180 BEAST_EXPECT(jrr[jss::error_message] ==
"Feature unknown or invalid.");
186 testcase(
"Invalid Feature");
188 using namespace test::jtx;
191 auto jrr = env.rpc(
"feature",
"AllTheThings")[jss::result];
192 BEAST_EXPECT(jrr[jss::error] ==
"badFeature");
193 BEAST_EXPECT(jrr[jss::error_message] ==
"Feature unknown or invalid.");
199 testcase(
"Feature Without Admin");
201 using namespace test::jtx;
203 (*cfg)[
"port_rpc"].set(
"admin",
"");
204 (*cfg)[
"port_ws"].set(
"admin",
"");
209 auto result = env.rpc(
"feature")[jss::result];
210 BEAST_EXPECT(result.isMember(jss::features));
214 BEAST_EXPECT(result[jss::features].size() >= 50);
215 for (
auto it = result[jss::features].begin();
216 it != result[jss::features].end();
220 (void)
id.parseHex(it.key().asString().c_str());
221 if (!BEAST_EXPECT((*it).isMember(jss::name)))
224 env.app().getAmendmentTable().isEnabled(
id);
225 bool expectSupported =
226 env.app().getAmendmentTable().isSupported(
id);
228 (*it).isMember(jss::enabled) &&
229 (*it)[jss::enabled].asBool() == expectEnabled,
230 (*it)[jss::name].asString() +
" enabled");
232 (*it).isMember(jss::supported) &&
233 (*it)[jss::supported].asBool() == expectSupported,
234 (*it)[jss::name].asString() +
" supported");
235 BEAST_EXPECT(!(*it).isMember(jss::vetoed));
236 BEAST_EXPECT(!(*it).isMember(jss::majority));
237 BEAST_EXPECT(!(*it).isMember(jss::count));
238 BEAST_EXPECT(!(*it).isMember(jss::validations));
239 BEAST_EXPECT(!(*it).isMember(jss::threshold));
246 params[jss::feature] =
247 "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCD"
249 auto const result = env.rpc(
252 boost::lexical_cast<std::string>(params))[jss::result];
254 result[jss::error] ==
"badFeature", result.toStyledString());
256 result[jss::error_message] ==
"Feature unknown or invalid.");
261 params[jss::feature] =
262 "93E516234E35E08CA689FA33A6D38E103881F8DCB53023F728C307AA89D515"
265 params[jss::vetoed] =
true;
266 auto const result = env.rpc(
269 boost::lexical_cast<std::string>(params))[jss::result];
271 result[jss::error] ==
"noPermission",
272 result[jss::error].asString());
274 result[jss::error_message] ==
275 "You don't have permission for this command.");
280 "C4483A1896170C66C098DEA5B0E024309C60DC960DE5F01CD7AF986AA3D9AD"
283 params[jss::feature] = feature;
284 auto const result = env.rpc(
287 boost::lexical_cast<std::string>(params))[jss::result];
288 BEAST_EXPECT(result.isMember(feature));
289 auto const amendmentResult = result[feature];
290 BEAST_EXPECT(amendmentResult[jss::enabled].asBool() ==
false);
291 BEAST_EXPECT(amendmentResult[jss::supported].asBool() ==
true);
293 amendmentResult[jss::name].asString() ==
294 "fixMasterKeyAsRegularKey");
301 testcase(
"No Params, Some Enabled");
303 using namespace test::jtx;
310 auto jrr = env.rpc(
"feature")[jss::result];
311 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
313 for (
auto it = jrr[jss::features].begin();
314 it != jrr[jss::features].end();
318 (void)
id.parseHex(it.key().asString().c_str());
319 if (!BEAST_EXPECT((*it).isMember(jss::name)))
321 bool expectEnabled = env.app().getAmendmentTable().isEnabled(
id);
322 bool expectSupported =
323 env.app().getAmendmentTable().isSupported(
id);
325 (votes.
at((*it)[jss::name].asString()) ==
327 bool expectObsolete =
328 (votes.
at((*it)[jss::name].asString()) ==
331 (*it).isMember(jss::enabled) &&
332 (*it)[jss::enabled].asBool() == expectEnabled,
333 (*it)[jss::name].asString() +
" enabled");
336 !(*it).isMember(jss::vetoed),
337 (*it)[jss::name].asString() +
" vetoed");
340 (*it).isMember(jss::vetoed) &&
341 (*it)[jss::vetoed].isBool() == !expectObsolete &&
342 (!(*it)[jss::vetoed].isBool() ||
343 (*it)[jss::vetoed].asBool() == expectVeto) &&
344 ((*it)[jss::vetoed].isBool() ||
345 (*it)[jss::vetoed].asString() ==
"Obsolete"),
346 (*it)[jss::name].asString() +
" vetoed");
348 (*it).isMember(jss::supported) &&
349 (*it)[jss::supported].asBool() == expectSupported,
350 (*it)[jss::name].asString() +
" supported");
357 testcase(
"With Majorities");
359 using namespace test::jtx;
360 Env env{*
this, envconfig(validator,
"")};
362 auto jrr = env.rpc(
"feature")[jss::result];
363 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
368 for (
auto const& feature : jrr[jss::features])
370 if (!BEAST_EXPECT(feature.isMember(jss::name)))
373 !feature.isMember(jss::majority),
374 feature[jss::name].asString() +
" majority");
376 !feature.isMember(jss::count),
377 feature[jss::name].asString() +
" count");
379 !feature.isMember(jss::threshold),
380 feature[jss::name].asString() +
" threshold");
382 !feature.isMember(jss::validations),
383 feature[jss::name].asString() +
" validations");
385 !feature.isMember(jss::vote),
386 feature[jss::name].asString() +
" vote");
390 if (!BEAST_EXPECT(majorities.empty()))
394 for (
auto i = 0; i <= 256; ++i)
398 if (!majorities.empty())
404 BEAST_EXPECT(majorities.size() >= 5);
408 jrr = env.rpc(
"feature")[jss::result];
409 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
411 for (
auto const& feature : jrr[jss::features])
413 if (!BEAST_EXPECT(feature.isMember(jss::name)))
416 (votes.
at(feature[jss::name].asString()) ==
418 bool expectObsolete =
419 (votes.
at(feature[jss::name].asString()) ==
422 (expectVeto || expectObsolete) ^
423 feature.isMember(jss::majority),
424 feature[jss::name].asString() +
" majority");
426 feature.isMember(jss::vetoed) &&
427 feature[jss::vetoed].isBool() == !expectObsolete &&
428 (!feature[jss::vetoed].isBool() ||
429 feature[jss::vetoed].asBool() == expectVeto) &&
430 (feature[jss::vetoed].isBool() ||
431 feature[jss::vetoed].asString() ==
"Obsolete"),
432 feature[jss::name].asString() +
" vetoed");
434 feature.isMember(jss::count),
435 feature[jss::name].asString() +
" count");
437 feature.isMember(jss::threshold),
438 feature[jss::name].asString() +
" threshold");
440 feature.isMember(jss::validations),
441 feature[jss::name].asString() +
" validations");
443 feature[jss::count] ==
444 ((expectVeto || expectObsolete) ? 0 : 1));
445 BEAST_EXPECT(feature[jss::threshold] == 1);
446 BEAST_EXPECT(feature[jss::validations] == 1);
448 expectVeto || expectObsolete || feature[jss::majority] == 2540,
449 "Majority: " + feature[jss::majority].asString());
458 using namespace test::jtx;
460 constexpr
const char* featureName =
"MultiSignReserve";
462 auto jrr = env.rpc(
"feature", featureName)[jss::result];
463 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
465 jrr.removeMember(jss::status);
466 if (!BEAST_EXPECT(jrr.size() == 1))
468 auto feature = *(jrr.begin());
469 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
471 feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
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");
483 feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool(),
486 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
487 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
489 jrr.removeMember(jss::status);
490 if (!BEAST_EXPECT(jrr.size() == 1))
492 feature = *(jrr.begin());
493 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
495 feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
499 jrr = env.rpc(
"feature", featureName,
"maybe");
500 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
501 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");
507 testcase(
"Obsolete");
509 using namespace test::jtx;
511 constexpr
const char* featureName =
"NonFungibleTokensV1";
513 auto jrr = env.rpc(
"feature", featureName)[jss::result];
514 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
516 jrr.removeMember(jss::status);
517 if (!BEAST_EXPECT(jrr.size() == 1))
519 auto feature = *(jrr.begin());
520 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
522 feature[jss::vetoed].isString() &&
523 feature[jss::vetoed].asString() ==
"Obsolete",
526 jrr = env.rpc(
"feature", featureName,
"reject")[jss::result];
527 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
529 jrr.removeMember(jss::status);
530 if (!BEAST_EXPECT(jrr.size() == 1))
532 feature = *(jrr.begin());
533 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
535 feature[jss::vetoed].isString() &&
536 feature[jss::vetoed].asString() ==
"Obsolete",
539 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
540 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
542 jrr.removeMember(jss::status);
543 if (!BEAST_EXPECT(jrr.size() == 1))
545 feature = *(jrr.begin());
546 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
548 feature[jss::vetoed].isString() &&
549 feature[jss::vetoed].asString() ==
"Obsolete",
553 jrr = env.rpc(
"feature", featureName,
"maybe");
554 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
555 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");