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