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#include <xrpl/basics/chrono.h>
22#include <xrpl/basics/random.h>
23#include <xrpl/beast/unit_test.h>
24#include <xrpl/resource/Consumer.h>
25#include <xrpl/resource/detail/Entry.h>
26#include <xrpl/resource/detail/Logic.h>
27
28#include <boost/utility/base_from_member.hpp>
29
30#include <functional>
31
32namespace ripple {
33namespace Resource {
34
36{
37public:
38 class TestLogic : private boost::base_from_member<TestStopwatch>,
39 public Logic
40
41 {
42 private:
43 using clock_type = boost::base_from_member<TestStopwatch>;
44
45 public:
46 explicit TestLogic(beast::Journal journal)
47 : Logic(beast::insight::NullCollector::New(), member, journal)
48 {
49 }
50
51 void
53 {
54 ++member;
55 }
56
59 {
60 return member;
61 }
62 };
63
64 //--------------------------------------------------------------------------
65
66 void
68 {
69 std::uint8_t const v(10 + rand_int(9));
70 std::uint8_t const n(10 + rand_int(9));
71 gossip.items.reserve(n);
72 for (std::uint8_t i = 0; i < n; ++i)
73 {
74 Gossip::Item item;
75 item.balance = 100 + rand_int(499);
76 beast::IP::AddressV4::bytes_type d = {
77 {192, 0, 2, static_cast<std::uint8_t>(v + i)}};
79 gossip.items.push_back(item);
80 }
81 }
82
83 //--------------------------------------------------------------------------
84
85 void
86 testDrop(beast::Journal j, bool limited)
87 {
88 if (limited)
89 testcase("Limited warn/drop");
90 else
91 testcase("Unlimited warn/drop");
92
93 TestLogic logic(j);
94
95 Charge const fee(dropThreshold + 1);
96 beast::IP::Endpoint const addr(
98
100 ? std::bind(
101 &TestLogic::newInboundEndpoint, &logic, std::placeholders::_1)
102 : std::bind(
104 &logic,
105 std::placeholders::_1);
106
107 {
108 Consumer c(ep(addr));
109
110 // Create load until we get a warning
111 int n = 10000;
112
113 while (--n >= 0)
114 {
115 if (n == 0)
116 {
117 if (limited)
118 fail("Loop count exceeded without warning");
119 else
120 pass();
121 return;
122 }
123
124 if (c.charge(fee) == warn)
125 {
126 if (limited)
127 pass();
128 else
129 fail("Should loop forever with no warning");
130 break;
131 }
132 ++logic.clock();
133 }
134
135 // Create load until we get dropped
136 while (--n >= 0)
137 {
138 if (n == 0)
139 {
140 if (limited)
141 fail("Loop count exceeded without dropping");
142 else
143 pass();
144 return;
145 }
146
147 if (c.charge(fee) == drop)
148 {
149 // Disconnect abusive Consumer
150 BEAST_EXPECT(c.disconnect(j) == limited);
151 break;
152 }
153 ++logic.clock();
154 }
155 }
156
157 // Make sure the consumer is on the blacklist for a while.
158 {
159 Consumer c(logic.newInboundEndpoint(addr));
160 logic.periodicActivity();
161 if (c.disposition() != drop)
162 {
163 if (limited)
164 fail("Dropped consumer not put on blacklist");
165 else
166 pass();
167 return;
168 }
169 }
170
171 // Makes sure the Consumer is eventually removed from blacklist
172 bool readmitted = false;
173 {
174 using namespace std::chrono_literals;
175 // Give Consumer time to become readmitted. Should never
176 // exceed expiration time.
177 auto n = secondsUntilExpiration + 1s;
178 while (--n > 0s)
179 {
180 ++logic.clock();
181 logic.periodicActivity();
182 Consumer c(logic.newInboundEndpoint(addr));
183 if (c.disposition() != drop)
184 {
185 readmitted = true;
186 break;
187 }
188 }
189 }
190 if (readmitted == false)
191 {
192 fail("Dropped Consumer left on blacklist too long");
193 return;
194 }
195 pass();
196 }
197
198 void
200 {
201 testcase("Imports");
202
203 TestLogic logic(j);
204
205 Gossip g[5];
206
207 for (int i = 0; i < 5; ++i)
208 createGossip(g[i]);
209
210 for (int i = 0; i < 5; ++i)
211 logic.importConsumers(std::to_string(i), g[i]);
212
213 pass();
214 }
215
216 void
218 {
219 testcase("Import");
220
221 TestLogic logic(j);
222
223 Gossip g;
224 Gossip::Item item;
225 item.balance = 100;
226 beast::IP::AddressV4::bytes_type d = {{192, 0, 2, 1}};
228 g.items.push_back(item);
229
230 logic.importConsumers("g", g);
231
232 pass();
233 }
234
235 void
237 {
238 testcase("Charge");
239
240 TestLogic logic(j);
241
242 {
243 beast::IP::Endpoint address(
245 Consumer c(logic.newInboundEndpoint(address));
246 Charge fee(1000);
247 JLOG(j.info()) << "Charging " << c.to_string() << " " << fee
248 << " per second";
249 c.charge(fee);
250 for (int i = 0; i < 128; ++i)
251 {
252 JLOG(j.info()) << "Time= "
253 << logic.clock().now().time_since_epoch().count()
254 << ", Balance = " << c.balance();
255 logic.advance();
256 }
257 }
258
259 {
260 beast::IP::Endpoint address(
262 Consumer c(logic.newInboundEndpoint(address));
263 Charge fee(1000);
264 JLOG(j.info()) << "Charging " << c.to_string() << " " << fee
265 << " per second";
266 for (int i = 0; i < 128; ++i)
267 {
268 c.charge(fee);
269 JLOG(j.info()) << "Time= "
270 << logic.clock().now().time_since_epoch().count()
271 << ", Balance = " << c.balance();
272 logic.advance();
273 }
274 }
275
276 pass();
277 }
278
279 void
280 run() override
281 {
282 using namespace beast::severities;
283 test::SuiteJournal journal("ResourceManager_test", *this);
284
285 testDrop(journal, true);
286 testDrop(journal, false);
287 testCharges(journal);
288 testImports(journal);
289 testImport(journal);
290 }
291};
292
293BEAST_DEFINE_TESTSUITE(ResourceManager, resource, ripple);
294
295} // namespace Resource
296} // 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:43
void testDrop(beast::Journal j, bool limited)
Definition: Logic_test.cpp:86
void run() override
Runs the suite.
Definition: Logic_test.cpp:280
void testCharges(beast::Journal j)
Definition: Logic_test.cpp:236
void testImports(beast::Journal j)
Definition: Logic_test.cpp:199
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)