xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
tests
libxrpl
resource
Logic.cpp
1
#include <xrpl/resource/detail/Logic.h>
2
3
#include <xrpl/basics/Log.h>
4
#include <xrpl/basics/chrono.h>
5
#include <xrpl/basics/random.h>
6
#include <xrpl/beast/insight/NullCollector.h>
7
#include <xrpl/beast/net/IPAddressV4.h>
8
#include <xrpl/beast/utility/Journal.h>
9
#include <xrpl/resource/Charge.h>
10
#include <xrpl/resource/Consumer.h>
11
#include <xrpl/resource/Disposition.h>
12
#include <xrpl/resource/Gossip.h>
13
#include <xrpl/resource/detail/Tuning.h>
14
15
#include <boost/utility/base_from_member.hpp>
16
17
#include <gtest/gtest.h>
18
#include <helpers/TestSink.h>
19
20
#include <
algorithm
>
21
#include <
chrono
>
22
#include <
cstdint
>
23
#include <
ranges
>
24
#include <
string
>
25
#include <
utility
>
26
27
namespace
xrpl::resource
{
28
29
class
ResourceManagerTest
:
public
::testing::Test
30
{
31
protected
:
32
beast::Journal
const
j_
{
TestSink::instance
()};
33
34
class
TestLogic
:
private
boost::base_from_member<TestStopwatch>,
public
Logic
35
{
36
private
:
37
using
ClockType
= boost::base_from_member<TestStopwatch>;
38
39
public
:
40
explicit
TestLogic
(
beast::Journal
journal)
41
:
Logic
(
beast
::insight::NullCollector::make(), member, journal)
42
{
43
}
44
45
void
46
advance
()
47
{
48
++member;
49
}
50
51
TestStopwatch
&
52
clock
()
53
{
54
return
member;
55
}
56
};
57
58
//--------------------------------------------------------------------------
59
60
static
Gossip
61
makeGossip
()
62
{
63
Gossip
gossip;
64
std::uint8_t
const
v(10 +
randInt
(9));
65
std::uint8_t
const
n(10 +
randInt
(9));
66
gossip.
items
.reserve(n);
67
for
(
std::uint8_t
i = 0; i < n; ++i)
68
{
69
Gossip::Item
item;
70
item.
balance
= 100 +
randInt
(499);
71
beast::ip::AddressV4::bytes_type
const
d = {{
72
192,
73
0,
74
2,
75
static_cast<
std::uint8_t
>
(v + i),
76
}};
77
item.
address
=
beast::ip::Endpoint
{
beast::ip::AddressV4
{d}};
78
gossip.
items
.push_back(std::move(item));
79
}
80
return
gossip;
81
}
82
};
83
84
TEST_F
(
ResourceManagerTest
, limited_warn_drop)
85
{
86
TestLogic logic{j_};
87
88
Charge
const
fee{
kDropThreshold
+ 1};
89
beast::ip::Endpoint
const
addr{
beast::ip::Endpoint::fromString
(
"192.0.2.2"
)};
90
91
{
92
Consumer
c{logic.newInboundEndpoint(addr)};
93
94
// Create load until we get a warning
95
auto
n = 10000;
96
auto
warned =
false
;
97
98
while
(--n >= 0)
99
{
100
if
(c.
charge
(fee) ==
Disposition::Warn
)
101
{
102
warned =
true
;
103
break
;
104
}
105
logic.advance();
106
}
107
108
ASSERT_TRUE(warned) <<
"Loop count exceeded without warning"
;
109
110
// Create load until we get dropped
111
bool
dropped =
false
;
112
while
(--n >= 0)
113
{
114
if
(c.
charge
(fee) ==
Disposition::Drop
)
115
{
116
dropped =
true
;
117
// Disconnect abusive Consumer
118
EXPECT_TRUE(c.
disconnect
(j_));
119
break
;
120
}
121
logic.advance();
122
}
123
124
ASSERT_TRUE(dropped) <<
"Loop count exceeded without dropping"
;
125
}
126
127
// Make sure the consumer is on the blacklist for a while.
128
{
129
Consumer
const
c{logic.newInboundEndpoint(addr)};
130
logic.periodicActivity();
131
EXPECT_EQ(c.
disposition
(),
Disposition::Drop
) <<
"Dropped consumer not put on blacklist"
;
132
}
133
134
// Makes sure the Consumer is eventually removed from blacklist
135
bool
readmitted =
false
;
136
{
137
using namespace
std::chrono_literals;
138
// Give Consumer time to become readmitted. Should never
139
// exceed expiration time.
140
auto
n =
kSecondsUntilExpiration
+ 1s;
141
while
(--n > 0s)
142
{
143
logic.advance();
144
logic.periodicActivity();
145
Consumer
const
c{logic.newInboundEndpoint(addr)};
146
if
(c.
disposition
() !=
Disposition::Drop
)
147
{
148
readmitted =
true
;
149
break
;
150
}
151
}
152
}
153
EXPECT_TRUE(readmitted) <<
"Dropped Consumer left on blacklist too long"
;
154
}
155
156
TEST_F
(
ResourceManagerTest
, unlimited_warn_drop)
157
{
158
TestLogic logic{j_};
159
160
Charge
const
fee{
kDropThreshold
+ 1};
161
beast::ip::Endpoint
const
addr{
beast::ip::Endpoint::fromString
(
"192.0.2.2"
)};
162
Consumer
c{logic.newUnlimitedEndpoint(addr)};
163
164
// Create load until we get a warning
165
int
n = 10000;
166
bool
warned =
false
;
167
168
while
(--n >= 0)
169
{
170
if
(c.
charge
(fee) ==
Disposition::Warn
)
171
{
172
warned =
true
;
173
break
;
174
}
175
logic.advance();
176
}
177
178
EXPECT_FALSE(warned) <<
"Should loop forever with no warning"
;
179
}
180
181
TEST_F
(
ResourceManagerTest
, charges)
182
{
183
static
constexpr
auto
kDecayTicks = 128uz;
184
185
TestLogic logic{j_};
186
187
{
188
beast::ip::Endpoint
const
address{
beast::ip::Endpoint::fromString
(
"192.0.2.1"
)};
189
Consumer
c{logic.newInboundEndpoint(address)};
190
Charge
const
fee{1000};
191
JLOG(j_.info()) <<
"Charging "
<< c.
toString
() <<
" "
<< fee <<
" per second"
;
192
c.
charge
(fee);
193
for
(
auto
tick = 0uz; tick < kDecayTicks; ++tick)
194
{
195
JLOG(j_.info()) <<
"Time= "
<< logic.clock().now().time_since_epoch().count()
196
<<
", Balance = "
<< c.
balance
();
197
logic.advance();
198
}
199
}
200
201
{
202
beast::ip::Endpoint
const
address{
beast::ip::Endpoint::fromString
(
"192.0.2.2"
)};
203
Consumer
c{logic.newInboundEndpoint(address)};
204
Charge
const
fee{1000};
205
JLOG(j_.info()) <<
"Charging "
<< c.
toString
() <<
" "
<< fee <<
" per second"
;
206
for
(
auto
tick = 0uz; tick < kDecayTicks; ++tick)
207
{
208
c.
charge
(fee);
209
JLOG(j_.info()) <<
"Time= "
<< logic.clock().now().time_since_epoch().count()
210
<<
", Balance = "
<< c.
balance
();
211
logic.advance();
212
}
213
}
214
}
215
216
TEST_F
(
ResourceManagerTest
, imports)
217
{
218
TestLogic logic{j_};
219
220
static
constexpr
auto
kGossipSources = 5uz;
221
std::ranges::for_each
(std::views::iota(0uz, kGossipSources), [&](
auto
const
i) {
222
logic.importConsumers(
std::to_string
(i), makeGossip());
223
});
224
}
225
226
TEST_F
(
ResourceManagerTest
,
import
)
227
{
228
TestLogic logic{j_};
229
230
Gossip
g;
231
Gossip::Item
item;
232
item.
balance
= 100;
233
beast::ip::AddressV4::bytes_type
const
d = {{
234
192,
235
0,
236
2,
237
1,
238
}};
239
item.
address
=
beast::ip::Endpoint
{
beast::ip::AddressV4
{d}};
240
g.
items
.push_back(std::move(item));
241
242
logic.importConsumers(
"g"
, g);
243
}
244
245
}
// namespace xrpl::resource
algorithm
chrono
beast::Journal
A generic endpoint for log messages.
Definition
Journal.h:44
beast::ip::Endpoint
A version-independent IP address and port combination.
Definition
IPEndpoint.h:24
beast::ip::Endpoint::fromString
static Endpoint fromString(std::string const &s)
Definition
IPEndpoint.cpp:42
xrpl::TestSink::instance
static TestSink & instance()
Definition
TestSink.h:12
xrpl::resource::Charge
A consumption charge.
Definition
Charge.h:13
xrpl::resource::Consumer
An endpoint that consumes resources.
Definition
Consumer.h:20
xrpl::resource::Consumer::disconnect
bool disconnect(beast::Journal const &j)
Returns true if the consumer should be disconnected.
Definition
Consumer.cpp:107
xrpl::resource::Consumer::balance
int balance()
Returns the credit balance representing consumption.
Definition
Consumer.cpp:119
xrpl::resource::Consumer::toString
std::string toString() const
Return a human readable string uniquely identifying this consumer.
Definition
Consumer.cpp:61
xrpl::resource::Consumer::charge
Disposition charge(Charge const &fee, std::string const &context={})
Apply a load charge to the consumer.
Definition
Consumer.cpp:89
xrpl::resource::Consumer::disposition
Disposition disposition() const
Returns the current disposition of this consumer.
Definition
Consumer.cpp:79
xrpl::resource::Logic::Logic
Logic(beast::insight::Collector::Ptr const &collector, ClockType &clock, beast::Journal journal)
Definition
resource/detail/Logic.h:79
xrpl::resource::ResourceManagerTest::TestLogic::clock
TestStopwatch & clock()
Definition
Logic.cpp:52
xrpl::resource::ResourceManagerTest::TestLogic::ClockType
boost::base_from_member< TestStopwatch > ClockType
Definition
Logic.cpp:37
xrpl::resource::ResourceManagerTest::TestLogic::advance
void advance()
Definition
Logic.cpp:46
xrpl::resource::ResourceManagerTest::TestLogic::TestLogic
TestLogic(beast::Journal journal)
Definition
Logic.cpp:40
xrpl::resource::ResourceManagerTest
Definition
Logic.cpp:30
xrpl::resource::ResourceManagerTest::j_
beast::Journal const j_
Definition
Logic.cpp:32
xrpl::resource::ResourceManagerTest::makeGossip
static Gossip makeGossip()
Definition
Logic.cpp:61
cstdint
std::ranges::for_each
T for_each(T... args)
std::uint8_t
beast::ip::AddressV4
boost::asio::ip::address_v4 AddressV4
Definition
IPAddressV4.h:7
beast
Definition
base_uint.h:697
xrpl::resource
Definition
ServiceRegistry.h:21
xrpl::resource::kSecondsUntilExpiration
static constexpr std::chrono::seconds kSecondsUntilExpiration
Definition
include/xrpl/resource/detail/Tuning.h:24
xrpl::resource::Disposition::Drop
@ Drop
Definition
Disposition.h:24
xrpl::resource::Disposition::Warn
@ Warn
Consumer should be disconnected for excess consumption.
Definition
Disposition.h:18
xrpl::resource::kDropThreshold
static constexpr auto kDropThreshold
Definition
include/xrpl/resource/detail/Tuning.h:15
xrpl::resource::TEST_F
TEST_F(ResourceManagerTest, limited_warn_drop)
Definition
Logic.cpp:84
xrpl::TestStopwatch
beast::ManualClock< std::chrono::steady_clock > TestStopwatch
A manual Stopwatch for unit tests.
Definition
chrono.h:95
xrpl::randInt
Integral randInt()
Definition
include/xrpl/basics/random.h:142
ranges
string
xrpl::resource::Gossip::Item
Describes a single consumer.
Definition
Gossip.h:20
xrpl::resource::Gossip::Item::address
beast::ip::Endpoint address
Definition
Gossip.h:24
xrpl::resource::Gossip::Item::balance
int balance
Definition
Gossip.h:23
xrpl::resource::Gossip
Data format for exchanging consumption information across peers.
Definition
Gossip.h:13
xrpl::resource::Gossip::items
std::vector< Item > items
Definition
Gossip.h:27
std::to_string
T to_string(T... args)
utility
Generated by
1.17.0