rippled
Loading...
Searching...
No Matches
Logic_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 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/unit_test/SuiteJournal.h>
21
22#include <xrpl/basics/chrono.h>
23#include <xrpl/basics/random.h>
24#include <xrpl/beast/unit_test.h>
25#include <xrpl/resource/Consumer.h>
26#include <xrpl/resource/detail/Entry.h>
27#include <xrpl/resource/detail/Logic.h>
28
29#include <boost/utility/base_from_member.hpp>
30
31#include <functional>
32
33namespace ripple {
34namespace Resource {
35
37{
38public:
39 class TestLogic : private boost::base_from_member<TestStopwatch>,
40 public Logic
41
42 {
43 private:
44 using clock_type = boost::base_from_member<TestStopwatch>;
45
46 public:
47 explicit TestLogic(beast::Journal journal)
48 : Logic(beast::insight::NullCollector::New(), member, journal)
49 {
50 }
51
52 void
54 {
55 ++member;
56 }
57
60 {
61 return member;
62 }
63 };
64
65 //--------------------------------------------------------------------------
66
67 void
69 {
70 std::uint8_t const v(10 + rand_int(9));
71 std::uint8_t const n(10 + rand_int(9));
72 gossip.items.reserve(n);
73 for (std::uint8_t i = 0; i < n; ++i)
74 {
75 Gossip::Item item;
76 item.balance = 100 + rand_int(499);
77 beast::IP::AddressV4::bytes_type d = {
78 {192, 0, 2, static_cast<std::uint8_t>(v + i)}};
80 gossip.items.push_back(item);
81 }
82 }
83
84 //--------------------------------------------------------------------------
85
86 void
87 testDrop(beast::Journal j, bool limited)
88 {
89 if (limited)
90 testcase("Limited warn/drop");
91 else
92 testcase("Unlimited warn/drop");
93
94 TestLogic logic(j);
95
96 Charge const fee(dropThreshold + 1);
97 beast::IP::Endpoint const addr(
99
101 ? std::bind(
102 &TestLogic::newInboundEndpoint, &logic, std::placeholders::_1)
103 : std::bind(
105 &logic,
106 std::placeholders::_1);
107
108 {
109 Consumer c(ep(addr));
110
111 // Create load until we get a warning
112 int n = 10000;
113
114 while (--n >= 0)
115 {
116 if (n == 0)
117 {
118 if (limited)
119 fail("Loop count exceeded without warning");
120 else
121 pass();
122 return;
123 }
124
125 if (c.charge(fee) == warn)
126 {
127 if (limited)
128 pass();
129 else
130 fail("Should loop forever with no warning");
131 break;
132 }
133 ++logic.clock();
134 }
135
136 // Create load until we get dropped
137 while (--n >= 0)
138 {
139 if (n == 0)
140 {
141 if (limited)
142 fail("Loop count exceeded without dropping");
143 else
144 pass();
145 return;
146 }
147
148 if (c.charge(fee) == drop)
149 {
150 // Disconnect abusive Consumer
151 BEAST_EXPECT(c.disconnect(j) == limited);
152 break;
153 }
154 ++logic.clock();
155 }
156 }
157
158 // Make sure the consumer is on the blacklist for a while.
159 {
160 Consumer c(logic.newInboundEndpoint(addr));
161 logic.periodicActivity();
162 if (c.disposition() != drop)
163 {
164 if (limited)
165 fail("Dropped consumer not put on blacklist");
166 else
167 pass();
168 return;
169 }
170 }
171
172 // Makes sure the Consumer is eventually removed from blacklist
173 bool readmitted = false;
174 {
175 using namespace std::chrono_literals;
176 // Give Consumer time to become readmitted. Should never
177 // exceed expiration time.
178 auto n = secondsUntilExpiration + 1s;
179 while (--n > 0s)
180 {
181 ++logic.clock();
182 logic.periodicActivity();
183 Consumer c(logic.newInboundEndpoint(addr));
184 if (c.disposition() != drop)
185 {
186 readmitted = true;
187 break;
188 }
189 }
190 }
191 if (readmitted == false)
192 {
193 fail("Dropped Consumer left on blacklist too long");
194 return;
195 }
196 pass();
197 }
198
199 void
201 {
202 testcase("Imports");
203
204 TestLogic logic(j);
205
206 Gossip g[5];
207
208 for (int i = 0; i < 5; ++i)
209 createGossip(g[i]);
210
211 for (int i = 0; i < 5; ++i)
212 logic.importConsumers(std::to_string(i), g[i]);
213
214 pass();
215 }
216
217 void
219 {
220 testcase("Import");
221
222 TestLogic logic(j);
223
224 Gossip g;
225 Gossip::Item item;
226 item.balance = 100;
227 beast::IP::AddressV4::bytes_type d = {{192, 0, 2, 1}};
229 g.items.push_back(item);
230
231 logic.importConsumers("g", g);
232
233 pass();
234 }
235
236 void
238 {
239 testcase("Charge");
240
241 TestLogic logic(j);
242
243 {
244 beast::IP::Endpoint address(
246 Consumer c(logic.newInboundEndpoint(address));
247 Charge fee(1000);
248 JLOG(j.info()) << "Charging " << c.to_string() << " " << fee
249 << " per second";
250 c.charge(fee);
251 for (int i = 0; i < 128; ++i)
252 {
253 JLOG(j.info()) << "Time= "
254 << logic.clock().now().time_since_epoch().count()
255 << ", Balance = " << c.balance();
256 logic.advance();
257 }
258 }
259
260 {
261 beast::IP::Endpoint address(
263 Consumer c(logic.newInboundEndpoint(address));
264 Charge fee(1000);
265 JLOG(j.info()) << "Charging " << c.to_string() << " " << fee
266 << " per second";
267 for (int i = 0; i < 128; ++i)
268 {
269 c.charge(fee);
270 JLOG(j.info()) << "Time= "
271 << logic.clock().now().time_since_epoch().count()
272 << ", Balance = " << c.balance();
273 logic.advance();
274 }
275 }
276
277 pass();
278 }
279
280 void
281 run() override
282 {
283 using namespace beast::severities;
284 test::SuiteJournal journal("ResourceManager_test", *this);
285
286 testDrop(journal, true);
287 testDrop(journal, false);
288 testCharges(journal);
289 testImports(journal);
290 testImport(journal);
291 }
292};
293
294BEAST_DEFINE_TESTSUITE(ResourceManager, resource, ripple);
295
296} // namespace Resource
297} // namespace ripple
T bind(T... args)
A version-independent IP address and port combination.
Definition: IPEndpoint.h:39
static Endpoint from_string(std::string const &s)
Definition: IPEndpoint.cpp:59
A generic endpoint for log messages.
Definition: Journal.h:60
Stream info() const
Definition: Journal.h:334
time_point now() const override
Returns the current time.
Definition: manual_clock.h:55
A testsuite class.
Definition: suite.h:55
void pass()
Record a successful test condition.
Definition: suite.h:511
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:155
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition: suite.h:533
A consumption charge.
Definition: Charge.h:31
An endpoint that consumes resources.
Definition: Consumer.h:35
int balance()
Returns the credit balance representing consumption.
Definition: Consumer.cpp:137
std::string to_string() const
Return a human readable string uniquely identifying this consumer.
Definition: Consumer.cpp:78
bool disconnect(beast::Journal const &j)
Returns true if the consumer should be disconnected.
Definition: Consumer.cpp:124
Disposition charge(Charge const &fee, std::string const &context={})
Apply a load charge to the consumer.
Definition: Consumer.cpp:106
Disposition disposition() const
Returns the current disposition of this consumer.
Definition: Consumer.cpp:96
Consumer newInboundEndpoint(beast::IP::Endpoint const &address)
void importConsumers(std::string const &origin, Gossip const &gossip)
Consumer newUnlimitedEndpoint(beast::IP::Endpoint const &address)
Create endpoint that should not have resource limits applied.
boost::base_from_member< TestStopwatch > clock_type
Definition: Logic_test.cpp:44
void testDrop(beast::Journal j, bool limited)
Definition: Logic_test.cpp:87
void run() override
Runs the suite.
Definition: Logic_test.cpp:281
void testCharges(beast::Journal j)
Definition: Logic_test.cpp:237
void testImports(beast::Journal j)
Definition: Logic_test.cpp:200
Set the fee on a JTx.
Definition: fee.h:37
boost::asio::ip::address_v4 AddressV4
Definition: IPAddressV4.h:36
A namespace for easy access to logging severity values.
Definition: Journal.h:30
@ warn
Consumer should be disconnected for excess consumption.
Definition: Disposition.h:33
std::chrono::seconds constexpr secondsUntilExpiration
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
Describes a single consumer.
Definition: Gossip.h:35
beast::IP::Endpoint address
Definition: Gossip.h:39
Data format for exchanging consumption information across peers.
Definition: Gossip.h:30
std::vector< Item > items
Definition: Gossip.h:42
T to_string(T... args)