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