rippled
OwnerInfo_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2017 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 #include <test/jtx.h>
20 
21 #include <ripple/beast/unit_test.h>
22 #include <ripple/protocol/AccountID.h>
23 #include <ripple/protocol/jss.h>
24 #include <ripple/protocol/STAmount.h>
25 
26 namespace ripple {
27 
28 class OwnerInfo_test : public beast::unit_test::suite
29 {
30  void
32  {
33  testcase ("Bad input to owner_info");
34 
35  using namespace test::jtx;
36  Env env {*this};
37 
38  auto const alice = Account {"alice"};
39  env.fund (XRP(10000), alice);
40  env.close ();
41 
42  { // missing account field
43  auto const result =
44  env.rpc ("json", "owner_info", "{}") [jss::result];
45  BEAST_EXPECT (result[jss::error] == "invalidParams");
46  BEAST_EXPECT (result[jss::error_message] ==
47  "Missing field 'account'.");
48  }
49 
50  { // ask for empty account
51  Json::Value params;
52  params[jss::account] = "";
53  auto const result = env.rpc ("json", "owner_info",
54  to_string(params)) [jss::result];
55  if (BEAST_EXPECT (
56  result.isMember(jss::accepted) &&
57  result.isMember(jss::current)))
58  {
59  BEAST_EXPECT (result[jss::accepted][jss::error] == "badSeed");
60  BEAST_EXPECT (result[jss::accepted][jss::error_message] ==
61  "Disallowed seed.");
62  BEAST_EXPECT (result[jss::current][jss::error] == "badSeed");
63  BEAST_EXPECT (result[jss::current][jss::error_message] ==
64  "Disallowed seed.");
65  }
66  }
67 
68  { // ask for nonexistent account
69  // this seems like it should be an error, but current impl
70  // (deprecated) does not return an error, just empty fields.
71  Json::Value params;
72  params[jss::account] = Account{"bob"}.human();
73  auto const result = env.rpc ("json", "owner_info",
74  to_string(params)) [jss::result];
75  BEAST_EXPECT (result[jss::accepted] == Json::objectValue);
76  BEAST_EXPECT (result[jss::current] == Json::objectValue);
77  BEAST_EXPECT (result[jss::status] == "success");
78  }
79  }
80 
81  void
83  {
84  testcase ("Basic request for owner_info");
85 
86  using namespace test::jtx;
87  Env env {*this};
88 
89  auto const alice = Account {"alice"};
90  auto const gw = Account {"gateway"};
91  env.fund (XRP(10000), alice, gw);
92  auto const USD = gw["USD"];
93  auto const CNY = gw["CNY"];
94  env(trust(alice, USD(1000)));
95  env(trust(alice, CNY(1000)));
96  env(offer(alice, USD(1), XRP(1000)));
97  env.close();
98 
99  env(pay(gw, alice, USD(50)));
100  env(pay(gw, alice, CNY(50)));
101  env(offer(alice, CNY(2), XRP(1000)));
102 
103  Json::Value params;
104  params[jss::account] = alice.human();
105  auto const result = env.rpc ("json", "owner_info",
106  to_string(params)) [jss::result];
107  if (! BEAST_EXPECT (
108  result.isMember(jss::accepted) &&
109  result.isMember(jss::current)))
110  {
111  return;
112  }
113 
114  // accepted ledger entry
115  if (! BEAST_EXPECT (result[jss::accepted].isMember(jss::ripple_lines)))
116  return;
117  auto lines = result[jss::accepted][jss::ripple_lines];
118  if (! BEAST_EXPECT (lines.isArray() && lines.size() == 2))
119  return;
120 
121  BEAST_EXPECT (
122  lines[0u][sfBalance.fieldName] ==
123  (STAmount{Issue{to_currency("CNY"), noAccount()}, 0}
125  BEAST_EXPECT (
126  lines[0u][sfHighLimit.fieldName] ==
127  alice["CNY"](1000).value().getJson(JsonOptions::none));
128  BEAST_EXPECT (
129  lines[0u][sfLowLimit.fieldName] ==
130  gw["CNY"](0).value().getJson(JsonOptions::none));
131 
132  BEAST_EXPECT (
133  lines[1u][sfBalance.fieldName] ==
134  (STAmount{Issue{to_currency("USD"), noAccount()}, 0}
136  BEAST_EXPECT (
137  lines[1u][sfHighLimit.fieldName] ==
138  alice["USD"](1000).value().getJson(JsonOptions::none));
139  BEAST_EXPECT (
140  lines[1u][sfLowLimit.fieldName] ==
141  USD(0).value().getJson(JsonOptions::none));
142 
143  if (! BEAST_EXPECT (result[jss::accepted].isMember(jss::offers)))
144  return;
145  auto offers = result[jss::accepted][jss::offers];
146  if (! BEAST_EXPECT (offers.isArray() && offers.size() == 1))
147  return;
148 
149  BEAST_EXPECT (
150  offers[0u][jss::Account] == alice.human());
151  BEAST_EXPECT (
152  offers[0u][sfTakerGets.fieldName] ==
153  XRP(1000).value().getJson(JsonOptions::none));
154  BEAST_EXPECT (
155  offers[0u][sfTakerPays.fieldName] ==
156  USD(1).value().getJson(JsonOptions::none));
157 
158 
159  // current ledger entry
160  if (! BEAST_EXPECT (result[jss::current].isMember(jss::ripple_lines)))
161  return;
162  lines = result[jss::current][jss::ripple_lines];
163  if (! BEAST_EXPECT (lines.isArray() && lines.size() == 2))
164  return;
165 
166  BEAST_EXPECT (
167  lines[0u][sfBalance.fieldName] ==
168  (STAmount{Issue{to_currency("CNY"), noAccount()}, -50}
169  .value().getJson(JsonOptions::none)));
170  BEAST_EXPECT (
171  lines[0u][sfHighLimit.fieldName] ==
172  alice["CNY"](1000).value().getJson(JsonOptions::none));
173  BEAST_EXPECT (
174  lines[0u][sfLowLimit.fieldName] ==
175  gw["CNY"](0).value().getJson(JsonOptions::none));
176 
177  BEAST_EXPECT (
178  lines[1u][sfBalance.fieldName] ==
179  (STAmount{Issue{to_currency("USD"), noAccount()}, -50}
180  .value().getJson(JsonOptions::none)));
181  BEAST_EXPECT (
182  lines[1u][sfHighLimit.fieldName] ==
183  alice["USD"](1000).value().getJson(JsonOptions::none));
184  BEAST_EXPECT (
185  lines[1u][sfLowLimit.fieldName] ==
186  gw["USD"](0).value().getJson(JsonOptions::none));
187 
188  if (! BEAST_EXPECT (result[jss::current].isMember(jss::offers)))
189  return;
190  offers = result[jss::current][jss::offers];
191  // 1 additional offer in current, (2 total)
192  if (! BEAST_EXPECT (offers.isArray() && offers.size() == 2))
193  return;
194 
195  BEAST_EXPECT (
196  offers[1u] == result[jss::accepted][jss::offers][0u]);
197  BEAST_EXPECT (
198  offers[0u][jss::Account] == alice.human());
199  BEAST_EXPECT (
200  offers[0u][sfTakerGets.fieldName] ==
201  XRP(1000).value().getJson(JsonOptions::none));
202  BEAST_EXPECT (
203  offers[0u][sfTakerPays.fieldName] ==
204  CNY(2).value().getJson(JsonOptions::none));
205  }
206 
207 public:
208  void run () override
209  {
210  testBadInput ();
211  testBasic ();
212  }
213 };
214 
215 BEAST_DEFINE_TESTSUITE(OwnerInfo,app,ripple);
216 
217 } // ripple
218 
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:109
ripple::SField::fieldName
const std::string fieldName
Definition: SField.h:136
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:426
ripple::OwnerInfo_test
Definition: OwnerInfo_test.cpp:28
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::sfHighLimit
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
Definition: SField.h:429
ripple::OwnerInfo_test::testBadInput
void testBadInput()
Definition: OwnerInfo_test.cpp:31
ripple::sfLowLimit
const SF_Amount sfLowLimit(access, STI_AMOUNT, 6, "LowLimit")
Definition: SField.h:428
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
ripple::JsonOptions::none
@ none
ripple::STAmount
Definition: STAmount.h:42
ripple::test::jtx::offers
owner_count< ltOFFER > offers
Match the number of offers in the account's owner directory.
Definition: owners.h:94
ripple::OwnerInfo_test::run
void run() override
Definition: OwnerInfo_test.cpp:208
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:272
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::sfBalance
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
Definition: SField.h:424
ripple::STAmount::value
STAmount const & value() const noexcept
Definition: STAmount.h:179
ripple::OwnerInfo_test::testBasic
void testBasic()
Definition: OwnerInfo_test.cpp:82
ripple::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:427
Json::Value
Represents a JSON value.
Definition: json_value.h:141