rippled
Feature_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-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 <ripple/protocol/Feature.h>
22 #include <ripple/protocol/jss.h>
23 #include <ripple/app/misc/AmendmentTable.h>
24 
25 namespace ripple {
26 
27 class Feature_test : public beast::unit_test::suite
28 {
29  void
31  {
32  testcase ("No Params, None Enabled");
33 
34  using namespace test::jtx;
35  Env env {*this};
36 
37  auto jrr = env.rpc("feature") [jss::result];
38  if(! BEAST_EXPECT(jrr.isMember(jss::features)))
39  return;
40  for(auto const& feature : jrr[jss::features])
41  {
42  if(! BEAST_EXPECT(feature.isMember(jss::name)))
43  return;
44  //default config - so all should be disabled, not vetoed, and supported
45  BEAST_EXPECTS(! feature[jss::enabled].asBool(),
46  feature[jss::name].asString() + " enabled");
47  BEAST_EXPECTS(! feature[jss::vetoed].asBool(),
48  feature[jss::name].asString() + " vetoed");
49  BEAST_EXPECTS(feature[jss::supported].asBool(),
50  feature[jss::name].asString() + " supported");
51  }
52  }
53 
54  void
56  {
57  testcase ("Feature Param");
58 
59  using namespace test::jtx;
60  Env env {*this};
61 
62  auto jrr = env.rpc("feature", "MultiSignReserve") [jss::result];
63  BEAST_EXPECTS(jrr[jss::status] == jss::success, "status");
64  jrr.removeMember(jss::status);
65  BEAST_EXPECT(jrr.size() == 1);
66  auto feature = *(jrr.begin());
67 
68  BEAST_EXPECTS(feature[jss::name] == "MultiSignReserve", "name");
69  BEAST_EXPECTS(! feature[jss::enabled].asBool(), "enabled");
70  BEAST_EXPECTS(! feature[jss::vetoed].asBool(), "vetoed");
71  BEAST_EXPECTS(feature[jss::supported].asBool(), "supported");
72 
73  // feature names are case-sensitive - expect error here
74  jrr = env.rpc("feature", "multiSignReserve") [jss::result];
75  BEAST_EXPECT(jrr[jss::error] == "badFeature");
76  BEAST_EXPECT(jrr[jss::error_message] == "Feature unknown or invalid.");
77  }
78 
79  void
81  {
82  testcase ("Invalid Feature");
83 
84  using namespace test::jtx;
85  Env env {*this};
86 
87  auto jrr = env.rpc("feature", "AllTheThings") [jss::result];
88  BEAST_EXPECT(jrr[jss::error] == "badFeature");
89  BEAST_EXPECT(jrr[jss::error_message] == "Feature unknown or invalid.");
90  }
91 
92  void
94  {
95  testcase ("Feature Without Admin");
96 
97  using namespace test::jtx;
98  Env env {*this, envconfig([](std::unique_ptr<Config> cfg) {
99  (*cfg)["port_rpc"].set("admin","");
100  (*cfg)["port_ws"].set("admin","");
101  return cfg;
102  })};
103 
104  auto jrr = env.rpc("feature") [jss::result];
105  // The current HTTP/S ServerHandler returns an HTTP 403 error code here
106  // rather than a noPermission JSON error. The JSONRPCClient just eats that
107  // error and returns an null result.
108  BEAST_EXPECT(jrr.isNull());
109  }
110 
111  void
113  {
114  testcase ("No Params, Some Enabled");
115 
116  using namespace test::jtx;
117  Env env {*this,
119 
120  auto jrr = env.rpc("feature") [jss::result];
121  if(! BEAST_EXPECT(jrr.isMember(jss::features)))
122  return;
123  for(auto it = jrr[jss::features].begin();
124  it != jrr[jss::features].end(); ++it)
125  {
126  uint256 id;
127  id.SetHexExact(it.key().asString().c_str());
128  if(! BEAST_EXPECT((*it).isMember(jss::name)))
129  return;
130  bool expectEnabled = env.app().getAmendmentTable().isEnabled(id);
131  bool expectSupported = env.app().getAmendmentTable().isSupported(id);
132  BEAST_EXPECTS((*it)[jss::enabled].asBool() == expectEnabled,
133  (*it)[jss::name].asString() + " enabled");
134  BEAST_EXPECTS(! (*it)[jss::vetoed].asBool(),
135  (*it)[jss::name].asString() + " vetoed");
136  BEAST_EXPECTS((*it)[jss::supported].asBool() == expectSupported,
137  (*it)[jss::name].asString() + " supported");
138  }
139  }
140 
141  void
143  {
144  testcase ("With Majorities");
145 
146  using namespace test::jtx;
147  Env env {*this, envconfig(validator, "")};
148 
149  auto jrr = env.rpc("feature") [jss::result];
150  if(! BEAST_EXPECT(jrr.isMember(jss::features)))
151  return;
152 
153  // at this point, there are no majorities so no fields related to
154  // amendment voting
155  for(auto const& feature : jrr[jss::features])
156  {
157  if(! BEAST_EXPECT(feature.isMember(jss::name)))
158  return;
159  BEAST_EXPECTS(! feature.isMember(jss::majority),
160  feature[jss::name].asString() + " majority");
161  BEAST_EXPECTS(! feature.isMember(jss::count),
162  feature[jss::name].asString() + " count");
163  BEAST_EXPECTS(! feature.isMember(jss::threshold),
164  feature[jss::name].asString() + " threshold");
165  BEAST_EXPECTS(! feature.isMember(jss::validations),
166  feature[jss::name].asString() + " validations");
167  BEAST_EXPECTS(! feature.isMember(jss::vote),
168  feature[jss::name].asString() + " vote");
169  }
170 
171  auto majorities = getMajorityAmendments (*env.closed());
172  if(! BEAST_EXPECT(majorities.empty()))
173  return;
174 
175  // close ledgers until the amendments show up.
176  for (auto i = 0; i <= 256; ++i)
177  {
178  env.close();
179  majorities = getMajorityAmendments (*env.closed());
180  if (! majorities.empty())
181  break;
182  }
183 
184  // There should be at least 5 amendments. Don't do exact comparison
185  // to avoid maintenance as more amendments are added in the future.
186  BEAST_EXPECT(majorities.size() >= 5);
187 
188  jrr = env.rpc("feature") [jss::result];
189  if(! BEAST_EXPECT(jrr.isMember(jss::features)))
190  return;
191  for(auto const& feature : jrr[jss::features])
192  {
193  if(! BEAST_EXPECT(feature.isMember(jss::name)))
194  return;
195  BEAST_EXPECTS(feature.isMember(jss::majority),
196  feature[jss::name].asString() + " majority");
197  BEAST_EXPECTS(feature.isMember(jss::count),
198  feature[jss::name].asString() + " count");
199  BEAST_EXPECTS(feature.isMember(jss::threshold),
200  feature[jss::name].asString() + " threshold");
201  BEAST_EXPECTS(feature.isMember(jss::validations),
202  feature[jss::name].asString() + " validations");
203  BEAST_EXPECTS(feature.isMember(jss::vote),
204  feature[jss::name].asString() + " vote");
205  BEAST_EXPECT(feature[jss::vote] == 256);
206  BEAST_EXPECT(feature[jss::majority] == 2740);
207  }
208 
209  }
210 
211  void
213  {
214  testcase ("Veto");
215 
216  using namespace test::jtx;
217  Env env {*this,
219 
220  auto jrr = env.rpc("feature", "MultiSignReserve") [jss::result];
221  if(! BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"))
222  return;
223  jrr.removeMember(jss::status);
224  if(! BEAST_EXPECT(jrr.size() == 1))
225  return;
226  auto feature = *(jrr.begin());
227  BEAST_EXPECTS(feature[jss::name] == "MultiSignReserve", "name");
228  BEAST_EXPECTS(! feature[jss::vetoed].asBool(), "vetoed");
229 
230  jrr = env.rpc("feature", "MultiSignReserve", "reject") [jss::result];
231  if(! BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"))
232  return;
233  jrr.removeMember(jss::status);
234  if(! BEAST_EXPECT(jrr.size() == 1))
235  return;
236  feature = *(jrr.begin());
237  BEAST_EXPECTS(feature[jss::name] == "MultiSignReserve", "name");
238  BEAST_EXPECTS(feature[jss::vetoed].asBool(), "vetoed");
239 
240  jrr = env.rpc("feature", "MultiSignReserve", "accept") [jss::result];
241  if(! BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"))
242  return;
243  jrr.removeMember(jss::status);
244  if(! BEAST_EXPECT(jrr.size() == 1))
245  return;
246  feature = *(jrr.begin());
247  BEAST_EXPECTS(feature[jss::name] == "MultiSignReserve", "name");
248  BEAST_EXPECTS(! feature[jss::vetoed].asBool(), "vetoed");
249 
250  // anything other than accept or reject is an error
251  jrr = env.rpc("feature", "MultiSignReserve", "maybe");
252  BEAST_EXPECT(jrr[jss::error] == "invalidParams");
253  BEAST_EXPECT(jrr[jss::error_message] == "Invalid parameters.");
254  }
255 
256 public:
257 
258  void run() override
259  {
260  testNoParams();
263  testNonAdmin();
264  testSomeEnabled();
266  testVeto();
267  }
268 };
269 
270 BEAST_DEFINE_TESTSUITE(Feature,rpc,ripple);
271 
272 } // ripple
ripple::getMajorityAmendments
majorityAmendments_t getMajorityAmendments(ReadView const &view)
Definition: View.cpp:530
ripple::Feature_test::testSingleFeature
void testSingleFeature()
Definition: Feature_test.cpp:55
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::Feature_test::testVeto
void testVeto()
Definition: Feature_test.cpp:212
ripple::featureDepositPreauth
const uint256 featureDepositPreauth
Definition: Feature.cpp:169
ripple::Feature_test::run
void run() override
Definition: Feature_test.cpp:258
ripple::featureDepositAuth
const uint256 featureDepositAuth
Definition: Feature.cpp:164
ripple::featureMultiSignReserve
const uint256 featureMultiSignReserve
Definition: Feature.cpp:172
ripple::base_uint< 256 >
ripple::Feature_test::testSomeEnabled
void testSomeEnabled()
Definition: Feature_test.cpp:112
ripple::Feature_test
Definition: Feature_test.cpp:27
ripple::base_uint::SetHexExact
bool SetHexExact(const char *psz)
Parse a hex string into a base_uint The string must contain exactly bytes * 2 hex characters and must...
Definition: base_uint.h:327
ripple::Feature_test::testWithMajorities
void testWithMajorities()
Definition: Feature_test.cpp:142
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::FeatureBitset
Definition: Feature.h:153
ripple::Feature_test::testNoParams
void testNoParams()
Definition: Feature_test.cpp:30
ripple::Feature_test::testNonAdmin
void testNonAdmin()
Definition: Feature_test.cpp:93
ripple::Feature_test::testInvalidFeature
void testInvalidFeature()
Definition: Feature_test.cpp:80
std::unique_ptr
STL class.