diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj index 6789b0a4da..dace055e2f 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj +++ b/Builds/VisualStudio2015/RippleD.vcxproj @@ -4979,6 +4979,10 @@ True True + + True + True + True True diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters index 1d1260f319..f23bc5e24e 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters @@ -5682,6 +5682,9 @@ test\rpc + + test\rpc + test\rpc diff --git a/src/test/rpc/OwnerInfo_test.cpp b/src/test/rpc/OwnerInfo_test.cpp new file mode 100644 index 0000000000..fd99ceb972 --- /dev/null +++ b/src/test/rpc/OwnerInfo_test.cpp @@ -0,0 +1,216 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2017 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== +#include + +#include +#include +#include +#include + +namespace ripple { + +class OwnerInfo_test : public beast::unit_test::suite +{ + void + testBadInput () + { + testcase ("Bad input to owner_info"); + + using namespace test::jtx; + Env env {*this}; + + auto const alice = Account {"alice"}; + env.fund (XRP(10000), alice); + env.close (); + + { // missing account field + auto const result = + env.rpc ("json", "owner_info", "{}") [jss::result]; + BEAST_EXPECT (result[jss::error] == "invalidParams"); + BEAST_EXPECT (result[jss::error_message] == + "Missing field 'account'."); + } + + { // ask for empty account + Json::Value params; + params[jss::account] = ""; + auto const result = env.rpc ("json", "owner_info", + to_string(params)) [jss::result]; + if (BEAST_EXPECT ( + result.isMember(jss::accepted) && + result.isMember(jss::current))) + { + BEAST_EXPECT (result[jss::accepted][jss::error] == "badSeed"); + BEAST_EXPECT (result[jss::accepted][jss::error_message] == + "Disallowed seed."); + BEAST_EXPECT (result[jss::current][jss::error] == "badSeed"); + BEAST_EXPECT (result[jss::current][jss::error_message] == + "Disallowed seed."); + } + } + + { // ask for nonexistent account + // this seems like it should be an error, but current impl + // (deprecated) does not return an error, just empty fields. + Json::Value params; + params[jss::account] = Account{"bob"}.human(); + auto const result = env.rpc ("json", "owner_info", + to_string(params)) [jss::result]; + BEAST_EXPECT (result[jss::accepted] == Json::objectValue); + BEAST_EXPECT (result[jss::current] == Json::objectValue); + BEAST_EXPECT (result[jss::status] == "success"); + } + } + + void + testBasic () + { + testcase ("Basic request for owner_info"); + + using namespace test::jtx; + Env env {*this}; + + auto const alice = Account {"alice"}; + auto const gw = Account {"gateway"}; + env.fund (XRP(10000), alice, gw); + auto const USD = gw["USD"]; + auto const CNY = gw["CNY"]; + env(trust(alice, USD(1000))); + env(trust(alice, CNY(1000))); + env(offer(alice, USD(1), XRP(1000))); + env.close(); + + env(pay(gw, alice, USD(50))); + env(pay(gw, alice, CNY(50))); + env(offer(alice, CNY(2), XRP(1000))); + + Json::Value params; + params[jss::account] = alice.human(); + auto const result = env.rpc ("json", "owner_info", + to_string(params)) [jss::result]; + if (! BEAST_EXPECT ( + result.isMember(jss::accepted) && + result.isMember(jss::current))) + { + return; + } + + // accepted ledger entry + if (! BEAST_EXPECT (result[jss::accepted].isMember(jss::ripple_lines))) + return; + auto lines = result[jss::accepted][jss::ripple_lines]; + if (! BEAST_EXPECT (lines.isArray() && lines.size() == 2)) + return; + + BEAST_EXPECT ( + lines[0u][sfBalance.fieldName] == + (STAmount{Issue{to_currency("USD"), noAccount()}, 0} + .value().getJson(0))); + BEAST_EXPECT ( + lines[0u][sfHighLimit.fieldName] == + alice["USD"](1000).value().getJson(0)); + BEAST_EXPECT ( + lines[0u][sfLowLimit.fieldName] == + USD(0).value().getJson(0)); + + BEAST_EXPECT ( + lines[1u][sfBalance.fieldName] == + (STAmount{Issue{to_currency("CNY"), noAccount()}, 0} + .value().getJson(0))); + BEAST_EXPECT ( + lines[1u][sfHighLimit.fieldName] == + alice["CNY"](1000).value().getJson(0)); + BEAST_EXPECT ( + lines[1u][sfLowLimit.fieldName] == + gw["CNY"](0).value().getJson(0)); + + if (! BEAST_EXPECT (result[jss::accepted].isMember(jss::offers))) + return; + auto offers = result[jss::accepted][jss::offers]; + if (! BEAST_EXPECT (offers.isArray() && offers.size() == 1)) + return; + + BEAST_EXPECT ( + offers[0u][jss::Account] == alice.human()); + BEAST_EXPECT ( + offers[0u][sfTakerGets.fieldName] == XRP(1000).value().getJson(0)); + BEAST_EXPECT ( + offers[0u][sfTakerPays.fieldName] == USD(1).value().getJson(0)); + + + // current ledger entry + if (! BEAST_EXPECT (result[jss::current].isMember(jss::ripple_lines))) + return; + lines = result[jss::current][jss::ripple_lines]; + if (! BEAST_EXPECT (lines.isArray() && lines.size() == 2)) + return; + + BEAST_EXPECT ( + lines[0u][sfBalance.fieldName] == + (STAmount{Issue{to_currency("USD"), noAccount()}, -50} + .value().getJson(0))); + BEAST_EXPECT ( + lines[0u][sfHighLimit.fieldName] == + alice["USD"](1000).value().getJson(0)); + BEAST_EXPECT ( + lines[0u][sfLowLimit.fieldName] == + gw["USD"](0).value().getJson(0)); + + BEAST_EXPECT ( + lines[1u][sfBalance.fieldName] == + (STAmount{Issue{to_currency("CNY"), noAccount()}, -50} + .value().getJson(0))); + BEAST_EXPECT ( + lines[1u][sfHighLimit.fieldName] == + alice["CNY"](1000).value().getJson(0)); + BEAST_EXPECT ( + lines[1u][sfLowLimit.fieldName] == + gw["CNY"](0).value().getJson(0)); + + if (! BEAST_EXPECT (result[jss::current].isMember(jss::offers))) + return; + offers = result[jss::current][jss::offers]; + // 1 additional offer in current, (2 total) + if (! BEAST_EXPECT (offers.isArray() && offers.size() == 2)) + return; + + // first offer is same as in accepted. + BEAST_EXPECT ( + offers[0u] == result[jss::accepted][jss::offers][0u]); + // second offer, for CNY + BEAST_EXPECT ( + offers[1u][jss::Account] == alice.human()); + BEAST_EXPECT ( + offers[1u][sfTakerGets.fieldName] == XRP(1000).value().getJson(0)); + BEAST_EXPECT ( + offers[1u][sfTakerPays.fieldName] == CNY(2).value().getJson(0)); + } + +public: + void run () + { + testBadInput (); + testBasic (); + } +}; + +BEAST_DEFINE_TESTSUITE(OwnerInfo,app,ripple); + +} // ripple + diff --git a/src/test/unity/rpc_test_unity.cpp b/src/test/unity/rpc_test_unity.cpp index 5c24489747..181e845a42 100644 --- a/src/test/unity/rpc_test_unity.cpp +++ b/src/test/unity/rpc_test_unity.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include