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",
"");
208 auto jrr = env.rpc(
"feature")[jss::result];
212 BEAST_EXPECT(jrr.isNull());
218 testcase(
"No Params, Some Enabled");
220 using namespace test::jtx;
227 auto jrr = env.rpc(
"feature")[jss::result];
228 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
230 for (
auto it = jrr[jss::features].begin();
231 it != jrr[jss::features].end();
235 (void)
id.parseHex(it.key().asString().c_str());
236 if (!BEAST_EXPECT((*it).isMember(jss::name)))
238 bool expectEnabled = env.app().getAmendmentTable().isEnabled(
id);
239 bool expectSupported =
240 env.app().getAmendmentTable().isSupported(
id);
242 (votes.
at((*it)[jss::name].asString()) ==
244 bool expectObsolete =
245 (votes.
at((*it)[jss::name].asString()) ==
248 (*it).isMember(jss::enabled) &&
249 (*it)[jss::enabled].asBool() == expectEnabled,
250 (*it)[jss::name].asString() +
" enabled");
253 !(*it).isMember(jss::vetoed),
254 (*it)[jss::name].asString() +
" vetoed");
257 (*it).isMember(jss::vetoed) &&
258 (*it)[jss::vetoed].isBool() == !expectObsolete &&
259 (!(*it)[jss::vetoed].isBool() ||
260 (*it)[jss::vetoed].asBool() == expectVeto) &&
261 ((*it)[jss::vetoed].isBool() ||
262 (*it)[jss::vetoed].asString() ==
"Obsolete"),
263 (*it)[jss::name].asString() +
" vetoed");
265 (*it).isMember(jss::supported) &&
266 (*it)[jss::supported].asBool() == expectSupported,
267 (*it)[jss::name].asString() +
" supported");
274 testcase(
"With Majorities");
276 using namespace test::jtx;
277 Env env{*
this, envconfig(validator,
"")};
279 auto jrr = env.rpc(
"feature")[jss::result];
280 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
285 for (
auto const& feature : jrr[jss::features])
287 if (!BEAST_EXPECT(feature.isMember(jss::name)))
290 !feature.isMember(jss::majority),
291 feature[jss::name].asString() +
" majority");
293 !feature.isMember(jss::count),
294 feature[jss::name].asString() +
" count");
296 !feature.isMember(jss::threshold),
297 feature[jss::name].asString() +
" threshold");
299 !feature.isMember(jss::validations),
300 feature[jss::name].asString() +
" validations");
302 !feature.isMember(jss::vote),
303 feature[jss::name].asString() +
" vote");
307 if (!BEAST_EXPECT(majorities.empty()))
311 for (
auto i = 0; i <= 256; ++i)
315 if (!majorities.empty())
321 BEAST_EXPECT(majorities.size() >= 5);
325 jrr = env.rpc(
"feature")[jss::result];
326 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
328 for (
auto const& feature : jrr[jss::features])
330 if (!BEAST_EXPECT(feature.isMember(jss::name)))
333 (votes.
at(feature[jss::name].asString()) ==
335 bool expectObsolete =
336 (votes.
at(feature[jss::name].asString()) ==
339 (expectVeto || expectObsolete) ^
340 feature.isMember(jss::majority),
341 feature[jss::name].asString() +
" majority");
343 feature.isMember(jss::vetoed) &&
344 feature[jss::vetoed].isBool() == !expectObsolete &&
345 (!feature[jss::vetoed].isBool() ||
346 feature[jss::vetoed].asBool() == expectVeto) &&
347 (feature[jss::vetoed].isBool() ||
348 feature[jss::vetoed].asString() ==
"Obsolete"),
349 feature[jss::name].asString() +
" vetoed");
351 feature.isMember(jss::count),
352 feature[jss::name].asString() +
" count");
354 feature.isMember(jss::threshold),
355 feature[jss::name].asString() +
" threshold");
357 feature.isMember(jss::validations),
358 feature[jss::name].asString() +
" validations");
360 feature[jss::count] ==
361 ((expectVeto || expectObsolete) ? 0 : 1));
362 BEAST_EXPECT(feature[jss::threshold] == 1);
363 BEAST_EXPECT(feature[jss::validations] == 1);
365 expectVeto || expectObsolete || feature[jss::majority] == 2540,
366 "Majority: " + feature[jss::majority].asString());
375 using namespace test::jtx;
377 constexpr
const char* featureName =
"MultiSignReserve";
379 auto jrr = env.rpc(
"feature", featureName)[jss::result];
380 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
382 jrr.removeMember(jss::status);
383 if (!BEAST_EXPECT(jrr.size() == 1))
385 auto feature = *(jrr.begin());
386 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
388 feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
391 jrr = env.rpc(
"feature", featureName,
"reject")[jss::result];
392 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
394 jrr.removeMember(jss::status);
395 if (!BEAST_EXPECT(jrr.size() == 1))
397 feature = *(jrr.begin());
398 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
400 feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool(),
403 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
404 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
406 jrr.removeMember(jss::status);
407 if (!BEAST_EXPECT(jrr.size() == 1))
409 feature = *(jrr.begin());
410 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
412 feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
416 jrr = env.rpc(
"feature", featureName,
"maybe");
417 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
418 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");
424 testcase(
"Obsolete");
426 using namespace test::jtx;
428 constexpr
const char* featureName =
"NonFungibleTokensV1";
430 auto jrr = env.rpc(
"feature", featureName)[jss::result];
431 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
433 jrr.removeMember(jss::status);
434 if (!BEAST_EXPECT(jrr.size() == 1))
436 auto feature = *(jrr.begin());
437 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
439 feature[jss::vetoed].isString() &&
440 feature[jss::vetoed].asString() ==
"Obsolete",
443 jrr = env.rpc(
"feature", featureName,
"reject")[jss::result];
444 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
446 jrr.removeMember(jss::status);
447 if (!BEAST_EXPECT(jrr.size() == 1))
449 feature = *(jrr.begin());
450 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
452 feature[jss::vetoed].isString() &&
453 feature[jss::vetoed].asString() ==
"Obsolete",
456 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
457 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
459 jrr.removeMember(jss::status);
460 if (!BEAST_EXPECT(jrr.size() == 1))
462 feature = *(jrr.begin());
463 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
465 feature[jss::vetoed].isString() &&
466 feature[jss::vetoed].asString() ==
"Obsolete",
470 jrr = env.rpc(
"feature", featureName,
"maybe");
471 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
472 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");