rippled
Loading...
Searching...
No Matches
ServerInfo_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2016 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 <xrpld/app/misc/NetworkOPs.h>
22#include <xrpld/core/ConfigSections.h>
23#include <xrpl/beast/unit_test.h>
24#include <xrpl/protocol/jss.h>
25
26#include <boost/format.hpp>
27
28namespace ripple {
29
30namespace test {
31
32namespace validator_data {
33static auto const public_key =
34 "nHBt9fsb4849WmZiCds4r5TXyBeQjqnH5kzPtqgMAQMgi39YZRPa";
35
36static auto const token =
37 "eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n"
38 "QzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2IiwibWFuaWZl\n"
39 "c3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncxL3ZDeE\n"
40 "hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4U0tG\n"
41 "bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUzZQU2\n"
42 "hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZeXd1\n"
43 "NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZWRGdj\n"
44 "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==\n";
45} // namespace validator_data
46
48{
49public:
52 {
53 auto p = std::make_unique<Config>();
54 boost::format toLoad(R"rippleConfig(
55[validator_token]
56%1%
57
58[validators]
59%2%
60
61[port_grpc]
62ip = 0.0.0.0
63port = 50051
64
65[port_admin]
66ip = 0.0.0.0
67port = 50052
68protocol = wss2
69admin = 127.0.0.1
70)rippleConfig");
71
72 p->loadFromString(boost::str(
74
76
77 return p;
78 }
79
80 void
82 {
83 testcase("server_info");
84
85 using namespace test::jtx;
86
87 {
88 Env env(*this);
89 auto const serverinfo = env.rpc("server_info");
90 BEAST_EXPECT(serverinfo.isMember(jss::result));
91 auto const& result = serverinfo[jss::result];
92 BEAST_EXPECT(!result.isMember(jss::error));
93 BEAST_EXPECT(result[jss::status] == "success");
94 BEAST_EXPECT(result.isMember(jss::info));
95 auto const& info = result[jss::info];
96 BEAST_EXPECT(info.isMember(jss::build_version));
97 // Git info is not guaranteed to be present
98 if (info.isMember(jss::git))
99 {
100 auto const& git = info[jss::git];
101 BEAST_EXPECT(
102 git.isMember(jss::hash) || git.isMember(jss::branch));
103 BEAST_EXPECT(
104 !git.isMember(jss::hash) ||
105 (git[jss::hash].isString() &&
106 git[jss::hash].asString().size() == 40));
107 BEAST_EXPECT(
108 !git.isMember(jss::branch) ||
109 (git[jss::branch].isString() &&
110 git[jss::branch].asString().size() != 0));
111 }
112 }
113
114 {
115 Env env(*this);
116
117 // Call NetworkOPs directly and set the admin flag to false.
118 auto const result =
119 env.app().getOPs().getServerInfo(true, false, 0);
120 // Expect that the admin ports are not included in the result.
121 auto const& ports = result[jss::ports];
122 BEAST_EXPECT(ports.isArray() && ports.size() == 0);
123 // Expect that git info is absent
124 BEAST_EXPECT(!result.isMember(jss::git));
125 }
126
127 {
128 Env env(*this, makeValidatorConfig());
129 auto const& config = env.app().config();
130
131 auto const rpc_port = config["port_rpc"].get<unsigned int>("port");
132 auto const grpc_port =
133 config[SECTION_PORT_GRPC].get<unsigned int>("port");
134 auto const ws_port = config["port_ws"].get<unsigned int>("port");
135 BEAST_EXPECT(grpc_port);
136 BEAST_EXPECT(rpc_port);
137 BEAST_EXPECT(ws_port);
138
139 auto const result = env.rpc("server_info");
140 BEAST_EXPECT(!result[jss::result].isMember(jss::error));
141 BEAST_EXPECT(result[jss::result][jss::status] == "success");
142 BEAST_EXPECT(result[jss::result].isMember(jss::info));
143 BEAST_EXPECT(
144 result[jss::result][jss::info][jss::pubkey_validator] ==
146
147 auto const& ports = result[jss::result][jss::info][jss::ports];
148 BEAST_EXPECT(ports.isArray() && ports.size() == 3);
149 for (auto const& port : ports)
150 {
151 auto const& proto = port[jss::protocol];
152 BEAST_EXPECT(proto.isArray());
153 auto const p = port[jss::port].asUInt();
154 BEAST_EXPECT(p == rpc_port || p == ws_port || p == grpc_port);
155 if (p == grpc_port)
156 {
157 BEAST_EXPECT(proto.size() == 1);
158 BEAST_EXPECT(proto[0u].asString() == "grpc");
159 }
160 if (p == rpc_port)
161 {
162 BEAST_EXPECT(proto.size() == 2);
163 BEAST_EXPECT(proto[0u].asString() == "http");
164 BEAST_EXPECT(proto[1u].asString() == "ws2");
165 }
166 if (p == ws_port)
167 {
168 BEAST_EXPECT(proto.size() == 1);
169 BEAST_EXPECT(proto[0u].asString() == "ws");
170 }
171 }
172 }
173 }
174
175 void
177 {
178 testcase("server_definitions");
179
180 using namespace test::jtx;
181
182 {
183 Env env(*this);
184 auto const result = env.rpc("server_definitions");
185 BEAST_EXPECT(!result[jss::result].isMember(jss::error));
186 BEAST_EXPECT(result[jss::result][jss::status] == "success");
187 BEAST_EXPECT(result[jss::result].isMember(jss::FIELDS));
188 BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES));
189 BEAST_EXPECT(
190 result[jss::result].isMember(jss::TRANSACTION_RESULTS));
191 BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_TYPES));
192 BEAST_EXPECT(result[jss::result].isMember(jss::TYPES));
193 BEAST_EXPECT(result[jss::result].isMember(jss::hash));
194
195 // test a random element of each result
196 // (testing the whole output would be difficult to maintain)
197
198 {
199 auto const firstField = result[jss::result][jss::FIELDS][0u];
200 BEAST_EXPECT(firstField[0u].asString() == "Generic");
201 BEAST_EXPECT(
202 firstField[1][jss::isSerialized].asBool() == false);
203 BEAST_EXPECT(
204 firstField[1][jss::isSigningField].asBool() == false);
205 BEAST_EXPECT(firstField[1][jss::isVLEncoded].asBool() == false);
206 BEAST_EXPECT(firstField[1][jss::nth].asUInt() == 0);
207 BEAST_EXPECT(firstField[1][jss::type].asString() == "Unknown");
208 }
209
210 BEAST_EXPECT(
211 result[jss::result][jss::LEDGER_ENTRY_TYPES]["AccountRoot"]
212 .asUInt() == 97);
213 BEAST_EXPECT(
214 result[jss::result][jss::TRANSACTION_RESULTS]["tecDIR_FULL"]
215 .asUInt() == 121);
216 BEAST_EXPECT(
217 result[jss::result][jss::TRANSACTION_TYPES]["Payment"]
218 .asUInt() == 0);
219 BEAST_EXPECT(
220 result[jss::result][jss::TYPES]["AccountID"].asUInt() == 8);
221
222 // check exception SFields
223 {
224 auto const fieldExists = [&](std::string name) {
225 for (auto& field : result[jss::result][jss::FIELDS])
226 {
227 if (field[0u].asString() == name)
228 {
229 return true;
230 }
231 }
232 return false;
233 };
234 BEAST_EXPECT(fieldExists("Generic"));
235 BEAST_EXPECT(fieldExists("Invalid"));
236 BEAST_EXPECT(fieldExists("ObjectEndMarker"));
237 BEAST_EXPECT(fieldExists("ArrayEndMarker"));
238 BEAST_EXPECT(fieldExists("taker_gets_funded"));
239 BEAST_EXPECT(fieldExists("taker_pays_funded"));
240 BEAST_EXPECT(fieldExists("hash"));
241 BEAST_EXPECT(fieldExists("index"));
242 }
243
244 // test that base_uint types are replaced with "Hash" prefix
245 {
246 auto const types = result[jss::result][jss::TYPES];
247 BEAST_EXPECT(types["Hash128"].asUInt() == 4);
248 BEAST_EXPECT(types["Hash160"].asUInt() == 17);
249 BEAST_EXPECT(types["Hash192"].asUInt() == 21);
250 BEAST_EXPECT(types["Hash256"].asUInt() == 5);
251 BEAST_EXPECT(types["Hash384"].asUInt() == 22);
252 BEAST_EXPECT(types["Hash512"].asUInt() == 23);
253 }
254 }
255
256 // test providing the same hash
257 {
258 Env env(*this);
259 auto const firstResult = env.rpc("server_definitions");
260 auto const hash = firstResult[jss::result][jss::hash].asString();
261 auto const hashParam =
262 std::string("{ ") + "\"hash\": \"" + hash + "\"}";
263
264 auto const result =
265 env.rpc("json", "server_definitions", hashParam);
266 BEAST_EXPECT(!result[jss::result].isMember(jss::error));
267 BEAST_EXPECT(result[jss::result][jss::status] == "success");
268 BEAST_EXPECT(!result[jss::result].isMember(jss::FIELDS));
269 BEAST_EXPECT(
270 !result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES));
271 BEAST_EXPECT(
272 !result[jss::result].isMember(jss::TRANSACTION_RESULTS));
273 BEAST_EXPECT(!result[jss::result].isMember(jss::TRANSACTION_TYPES));
274 BEAST_EXPECT(!result[jss::result].isMember(jss::TYPES));
275 BEAST_EXPECT(result[jss::result].isMember(jss::hash));
276 }
277
278 // test providing a different hash
279 {
280 Env env(*this);
281 std::string const hash =
282 "54296160385A27154BFA70A239DD8E8FD4CC2DB7BA32D970BA3A5B132CF749"
283 "D1";
284 auto const hashParam =
285 std::string("{ ") + "\"hash\": \"" + hash + "\"}";
286
287 auto const result =
288 env.rpc("json", "server_definitions", hashParam);
289 BEAST_EXPECT(!result[jss::result].isMember(jss::error));
290 BEAST_EXPECT(result[jss::result][jss::status] == "success");
291 BEAST_EXPECT(result[jss::result].isMember(jss::FIELDS));
292 BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES));
293 BEAST_EXPECT(
294 result[jss::result].isMember(jss::TRANSACTION_RESULTS));
295 BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_TYPES));
296 BEAST_EXPECT(result[jss::result].isMember(jss::TYPES));
297 BEAST_EXPECT(result[jss::result].isMember(jss::hash));
298 }
299 }
300
301 void
302 run() override
303 {
306 }
307};
308
309BEAST_DEFINE_TESTSUITE(ServerInfo, app, ripple);
310
311} // namespace test
312} // namespace ripple
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
A testsuite class.
Definition: suite.h:53
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:153
virtual Config & config()=0
virtual NetworkOPs & getOPs()=0
virtual Json::Value getServerInfo(bool human, bool admin, bool counters)=0
void run() override
Runs the suite.
static std::unique_ptr< Config > makeValidatorConfig()
A transaction testing environment.
Definition: Env.h:117
Application & app()
Definition: Env.h:255
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:764
void setupConfigForUnitTests(Config &config)
initializes a config object for use with jtx::Env
Definition: envconfig.cpp:31
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26