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