rippled
Loading...
Searching...
No Matches
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
20#include <test/jtx.h>
21
22#include <xrpl/beast/unit_test.h>
23#include <xrpl/protocol/AccountID.h>
24#include <xrpl/protocol/STAmount.h>
25#include <xrpl/protocol/jss.h>
26
27namespace ripple {
28
30{
31 void
33 {
34 testcase("Bad input to owner_info");
35
36 using namespace test::jtx;
37 Env env{*this};
38
39 auto const alice = Account{"alice"};
40 env.fund(XRP(10000), alice);
41 env.close();
42
43 { // missing account field
44 auto const result =
45 env.rpc("json", "owner_info", "{}")[jss::result];
46 BEAST_EXPECT(result[jss::error] == "invalidParams");
47 BEAST_EXPECT(
48 result[jss::error_message] == "Missing field 'account'.");
49 }
50
51 { // ask for empty account
52 Json::Value params;
53 params[jss::account] = "";
54 auto const result =
55 env.rpc("json", "owner_info", to_string(params))[jss::result];
56 if (BEAST_EXPECT(
57 result.isMember(jss::accepted) &&
58 result.isMember(jss::current)))
59 {
60 BEAST_EXPECT(
61 result[jss::accepted][jss::error] == "actMalformed");
62 BEAST_EXPECT(
63 result[jss::accepted][jss::error_message] ==
64 "Account malformed.");
65 BEAST_EXPECT(
66 result[jss::current][jss::error] == "actMalformed");
67 BEAST_EXPECT(
68 result[jss::current][jss::error_message] ==
69 "Account malformed.");
70 }
71 }
72
73 { // ask for nonexistent account
74 // this seems like it should be an error, but current impl
75 // (deprecated) does not return an error, just empty fields.
76 Json::Value params;
77 params[jss::account] = Account{"bob"}.human();
78 auto const result =
79 env.rpc("json", "owner_info", to_string(params))[jss::result];
80 BEAST_EXPECT(result[jss::accepted] == Json::objectValue);
81 BEAST_EXPECT(result[jss::current] == Json::objectValue);
82 BEAST_EXPECT(result[jss::status] == "success");
83 }
84 }
85
86 void
88 {
89 testcase("Basic request for owner_info");
90
91 using namespace test::jtx;
92 Env env{*this};
93
94 auto const alice = Account{"alice"};
95 auto const gw = Account{"gateway"};
96 env.fund(XRP(10000), alice, gw);
97 env.close();
98 auto const USD = gw["USD"];
99 auto const CNY = gw["CNY"];
100 env(trust(alice, USD(1000)));
101 env(trust(alice, CNY(1000)));
102 env(offer(alice, USD(1), XRP(1000)));
103 env.close();
104
105 env(pay(gw, alice, USD(50)));
106 env(pay(gw, alice, CNY(50)));
107 env(offer(alice, CNY(2), XRP(1000)));
108
109 Json::Value params;
110 params[jss::account] = alice.human();
111 auto const result =
112 env.rpc("json", "owner_info", to_string(params))[jss::result];
113 if (!BEAST_EXPECT(
114 result.isMember(jss::accepted) &&
115 result.isMember(jss::current)))
116 {
117 return;
118 }
119
120 // accepted ledger entry
121 if (!BEAST_EXPECT(result[jss::accepted].isMember(jss::ripple_lines)))
122 return;
123 auto lines = result[jss::accepted][jss::ripple_lines];
124 if (!BEAST_EXPECT(lines.isArray() && lines.size() == 2))
125 return;
126
127 BEAST_EXPECT(
128 lines[0u][sfBalance.fieldName] ==
129 (STAmount{Issue{to_currency("CNY"), noAccount()}, 0}
130 .value()
132 BEAST_EXPECT(
133 lines[0u][sfHighLimit.fieldName] ==
134 alice["CNY"](1000).value().getJson(JsonOptions::none));
135 BEAST_EXPECT(
136 lines[0u][sfLowLimit.fieldName] ==
137 gw["CNY"](0).value().getJson(JsonOptions::none));
138
139 BEAST_EXPECT(
140 lines[1u][sfBalance.fieldName] ==
141 (STAmount{Issue{to_currency("USD"), noAccount()}, 0}
142 .value()
144 BEAST_EXPECT(
145 lines[1u][sfHighLimit.fieldName] ==
146 alice["USD"](1000).value().getJson(JsonOptions::none));
147 BEAST_EXPECT(
148 lines[1u][sfLowLimit.fieldName] ==
149 USD(0).value().getJson(JsonOptions::none));
150
151 if (!BEAST_EXPECT(result[jss::accepted].isMember(jss::offers)))
152 return;
153 auto offers = result[jss::accepted][jss::offers];
154 if (!BEAST_EXPECT(offers.isArray() && offers.size() == 1))
155 return;
156
157 BEAST_EXPECT(offers[0u][jss::Account] == alice.human());
158 BEAST_EXPECT(
159 offers[0u][sfTakerGets.fieldName] ==
160 XRP(1000).value().getJson(JsonOptions::none));
161 BEAST_EXPECT(
162 offers[0u][sfTakerPays.fieldName] ==
163 USD(1).value().getJson(JsonOptions::none));
164
165 // current ledger entry
166 if (!BEAST_EXPECT(result[jss::current].isMember(jss::ripple_lines)))
167 return;
168 lines = result[jss::current][jss::ripple_lines];
169 if (!BEAST_EXPECT(lines.isArray() && lines.size() == 2))
170 return;
171
172 BEAST_EXPECT(
173 lines[0u][sfBalance.fieldName] ==
174 (STAmount{Issue{to_currency("CNY"), noAccount()}, -50}
175 .value()
176 .getJson(JsonOptions::none)));
177 BEAST_EXPECT(
178 lines[0u][sfHighLimit.fieldName] ==
179 alice["CNY"](1000).value().getJson(JsonOptions::none));
180 BEAST_EXPECT(
181 lines[0u][sfLowLimit.fieldName] ==
182 gw["CNY"](0).value().getJson(JsonOptions::none));
183
184 BEAST_EXPECT(
185 lines[1u][sfBalance.fieldName] ==
186 (STAmount{Issue{to_currency("USD"), noAccount()}, -50}
187 .value()
188 .getJson(JsonOptions::none)));
189 BEAST_EXPECT(
190 lines[1u][sfHighLimit.fieldName] ==
191 alice["USD"](1000).value().getJson(JsonOptions::none));
192 BEAST_EXPECT(
193 lines[1u][sfLowLimit.fieldName] ==
194 gw["USD"](0).value().getJson(JsonOptions::none));
195
196 if (!BEAST_EXPECT(result[jss::current].isMember(jss::offers)))
197 return;
198 offers = result[jss::current][jss::offers];
199 // 1 additional offer in current, (2 total)
200 if (!BEAST_EXPECT(offers.isArray() && offers.size() == 2))
201 return;
202
203 BEAST_EXPECT(offers[1u] == result[jss::accepted][jss::offers][0u]);
204 BEAST_EXPECT(offers[0u][jss::Account] == alice.human());
205 BEAST_EXPECT(
206 offers[0u][sfTakerGets.fieldName] ==
207 XRP(1000).value().getJson(JsonOptions::none));
208 BEAST_EXPECT(
209 offers[0u][sfTakerPays.fieldName] ==
210 CNY(2).value().getJson(JsonOptions::none));
211 }
212
213public:
214 void
215 run() override
216 {
217 testBadInput();
218 testBasic();
219 }
220};
221
222BEAST_DEFINE_TESTSUITE(OwnerInfo, app, ripple);
223
224} // namespace ripple
Represents a JSON value.
Definition: json_value.h:149
A testsuite class.
Definition: suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:155
void run() override
Runs the suite.
STAmount const & value() const noexcept
Definition: STAmount.h:594
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
owner_count< ltOFFER > offers
Match the number of offers in the account's owner directory.
Definition: owners.h:92
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:25
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.