#include #include #include namespace xrpl { class Version_test : public beast::unit_test::suite { void testCorrectVersionNumber() { testcase("right api_version: explicitly specified or filled by parser"); using namespace test::jtx; Env env{*this}; auto isCorrectReply = [](Json::Value const& re) -> bool { if (re.isMember(jss::error)) return false; return re.isMember(jss::version); }; auto jrr = env.rpc( "json", "version", "{\"api_version\": " + std::to_string(RPC::apiMaximumSupportedVersion) + "}")[jss::result]; BEAST_EXPECT(isCorrectReply(jrr)); jrr = env.rpc("version")[jss::result]; BEAST_EXPECT(isCorrectReply(jrr)); } void testWrongVersionNumber() { testcase("wrong api_version: too low, too high, or wrong format"); using namespace test::jtx; Env env{*this}; auto badVersion = [](Json::Value const& re) -> bool { if (re.isMember("error_what")) if (re["error_what"].isString()) { return re["error_what"].asString().find( jss::invalid_API_version.c_str()) == 0; } return false; }; auto re = env.rpc( "json", "version", "{\"api_version\": " + std::to_string(RPC::apiMinimumSupportedVersion - 1) + "}"); BEAST_EXPECT(badVersion(re)); BEAST_EXPECT(env.app().config().BETA_RPC_API); re = env.rpc( "json", "version", "{\"api_version\": " + std::to_string( std::max( RPC::apiMaximumSupportedVersion.value, RPC::apiBetaVersion.value) + 1) + "}"); BEAST_EXPECT(badVersion(re)); re = env.rpc("json", "version", "{\"api_version\": \"a\"}"); BEAST_EXPECT(badVersion(re)); } void testGetAPIVersionNumber() { testcase("test getAPIVersionNumber function"); unsigned int versionIfUnspecified = RPC::apiVersionIfUnspecified < RPC::apiMinimumSupportedVersion ? RPC::apiInvalidVersion : RPC::apiVersionIfUnspecified; Json::Value j_array = Json::Value(Json::arrayValue); Json::Value j_null = Json::Value(Json::nullValue); BEAST_EXPECT( RPC::getAPIVersionNumber(j_array, false) == versionIfUnspecified); BEAST_EXPECT( RPC::getAPIVersionNumber(j_null, false) == versionIfUnspecified); Json::Value j_object = Json::Value(Json::objectValue); BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); j_object[jss::api_version] = RPC::apiVersionIfUnspecified.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); j_object[jss::api_version] = RPC::apiMinimumSupportedVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiMinimumSupportedVersion); j_object[jss::api_version] = RPC::apiMaximumSupportedVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiMaximumSupportedVersion); j_object[jss::api_version] = RPC::apiMinimumSupportedVersion - 1; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); j_object[jss::api_version] = RPC::apiMaximumSupportedVersion + 1; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); j_object[jss::api_version] = RPC::apiBetaVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, true) == RPC::apiBetaVersion); j_object[jss::api_version] = RPC::apiBetaVersion + 1; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, true) == RPC::apiInvalidVersion); j_object[jss::api_version] = RPC::apiInvalidVersion.value; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); j_object[jss::api_version] = "a"; BEAST_EXPECT( RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); } void testBatch() { testcase("batch, all good request"); using namespace test::jtx; Env env{*this}; auto const without_api_verion = std::string("{ ") + "\"jsonrpc\": \"2.0\", " "\"ripplerpc\": \"2.0\", " "\"id\": 5, " "\"method\": \"version\", " "\"params\": {}}"; auto const with_api_verion = std::string("{ ") + "\"jsonrpc\": \"2.0\", " "\"ripplerpc\": \"2.0\", " "\"id\": 6, " "\"method\": \"version\", " "\"params\": { " "\"api_version\": " + std::to_string(RPC::apiMaximumSupportedVersion) + "}}"; auto re = env.rpc( "json2", '[' + without_api_verion + ", " + with_api_verion + ']'); if (!BEAST_EXPECT(re.isArray())) return; if (!BEAST_EXPECT(re.size() == 2)) return; BEAST_EXPECT( re[0u].isMember(jss::result) && re[0u][jss::result].isMember(jss::version)); BEAST_EXPECT( re[1u].isMember(jss::result) && re[1u][jss::result].isMember(jss::version)); } void testBatchFail() { testcase("batch, with a bad request"); using namespace test::jtx; Env env{*this}; BEAST_EXPECT(env.app().config().BETA_RPC_API); auto const without_api_verion = std::string("{ ") + "\"jsonrpc\": \"2.0\", " "\"ripplerpc\": \"2.0\", " "\"id\": 5, " "\"method\": \"version\", " "\"params\": {}}"; auto const with_wrong_api_verion = std::string("{ ") + "\"jsonrpc\": \"2.0\", " "\"ripplerpc\": \"2.0\", " "\"id\": 6, " "\"method\": \"version\", " "\"params\": { " "\"api_version\": " + std::to_string(std::max( RPC::apiMaximumSupportedVersion.value, RPC::apiBetaVersion.value) + 1) + "}}"; auto re = env.rpc( "json2", '[' + without_api_verion + ", " + with_wrong_api_verion + ']'); if (!BEAST_EXPECT(re.isArray())) return; if (!BEAST_EXPECT(re.size() == 2)) return; BEAST_EXPECT( re[0u].isMember(jss::result) && re[0u][jss::result].isMember(jss::version)); BEAST_EXPECT(re[1u].isMember(jss::error)); } void testConfig() { testcase("config test"); { Config c; BEAST_EXPECT(c.BETA_RPC_API == false); } { Config c; c.loadFromString("\n[beta_rpc_api]\n1\n"); BEAST_EXPECT(c.BETA_RPC_API == true); } { Config c; c.loadFromString("\n[beta_rpc_api]\n0\n"); BEAST_EXPECT(c.BETA_RPC_API == false); } } void testVersionRPCV2() { testcase("test version RPC with api_version >= 2"); using namespace test::jtx; Env env{*this, envconfig([](std::unique_ptr c) { c->loadFromString("\n[beta_rpc_api]\n1\n"); return c; })}; if (!BEAST_EXPECT(env.app().config().BETA_RPC_API == true)) return; auto jrr = env.rpc( "json", "version", "{\"api_version\": " + std::to_string(RPC::apiBetaVersion) + "}")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::version))) return; if (!BEAST_EXPECT(jrr[jss::version].isMember(jss::first)) && jrr[jss::version].isMember(jss::last)) return; BEAST_EXPECT( jrr[jss::version][jss::first] == RPC::apiMinimumSupportedVersion.value); BEAST_EXPECT(jrr[jss::version][jss::last] == RPC::apiBetaVersion.value); } public: void run() override { testCorrectVersionNumber(); testWrongVersionNumber(); testGetAPIVersionNumber(); testBatch(); testBatchFail(); testConfig(); testVersionRPCV2(); } }; BEAST_DEFINE_TESTSUITE(Version, rpc, xrpl); } // namespace xrpl