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