xrpld
Loading...
Searching...
No Matches
traffic_attribution_test.cpp
1#include <test/jtx/Env.h>
2#include <test/jtx/envconfig.h>
3#include <test/overlay/CapturePeer.h>
4
5#include <xrpld/overlay/Cluster.h>
6#include <xrpld/overlay/detail/TrafficCount.h>
7
8#include <xrpl/beast/unit_test/suite.h>
9#include <xrpl/json/JsonPropertyStream.h>
10#include <xrpl/protocol/KeyType.h>
11#include <xrpl/protocol/PublicKey.h>
12#include <xrpl/protocol/SecretKey.h>
13
14#include <xrpl.pb.h>
15
16#include <cstddef>
17#include <cstdint>
18#include <memory>
19#include <string>
20
21namespace xrpl::test {
22
23using namespace jtx;
24
35{
36 // The assertions compare deltas, so any size works. A size other than 1
37 // keeps a byte count from passing as a message count.
38 static constexpr std::size_t kFrameSize = 37;
39
47
56 static Counts
57 read(Env& env)
58 {
59 JsonPropertyStream stream;
60 env.app().getOverlay().writeOne(stream);
61
62 // `TrafficCount::toString` names the categories, so a renamed counter
63 // cannot leave this lookup silently matching nothing.
66
67 Counts counts;
68 for (auto const& entry : stream.top()["peers"]["traffic"])
69 {
70 auto const name = entry["category"].asString();
71 auto const messages = std::stoull(entry["messages_in"].asString());
72 auto const bytes = std::stoull(entry["bytes_in"].asString());
73
74 if (name == clusterName)
75 {
76 counts.clusterMessages = messages;
77 counts.clusterBytes = bytes;
78 }
79 else if (name == unknownName)
80 {
81 counts.unknownMessages = messages;
82 counts.unknownBytes = bytes;
83 }
84 }
85 return counts;
86 }
87
88 void
90 {
91 testcase("inbound cluster attribution");
92
93 Env env{*this, envconfig()};
94
95 // The outsider takes a fresh random key, which no `[cluster_nodes]`
96 // entry names. `cluster()` reads the cluster map on every message, so
97 // the member's key can be registered either side of its peer.
98 auto const outsider = makeCapturePeer(env);
99 PublicKey const memberKey = randomKeyPair(KeyType::Ed25519).first;
100 BEAST_EXPECT(env.app().getCluster().update(memberKey, "test-member"));
101 auto const member = makeCapturePeer(env, memberKey);
102
103 auto const message = std::make_shared<protocol::TMCluster>();
104 auto const before = read(env);
105
106 // Any peer can send this type, so a sender outside the cluster is
107 // counted as unknown, leaving the cluster counter to mean traffic
108 // between configured members.
109 outsider->onMessageBegin(protocol::mtCLUSTER, message, kFrameSize, kFrameSize, false);
110 auto const afterOutsider = read(env);
111 BEAST_EXPECT(afterOutsider.unknownMessages == before.unknownMessages + 1);
112 BEAST_EXPECT(afterOutsider.unknownBytes == before.unknownBytes + kFrameSize);
113 BEAST_EXPECT(afterOutsider.clusterMessages == before.clusterMessages);
114 BEAST_EXPECT(afterOutsider.clusterBytes == before.clusterBytes);
115
116 // The same frame from a configured member is counted as cluster
117 // traffic.
118 member->onMessageBegin(protocol::mtCLUSTER, message, kFrameSize, kFrameSize, false);
119 auto const afterMember = read(env);
120 BEAST_EXPECT(afterMember.clusterMessages == afterOutsider.clusterMessages + 1);
121 BEAST_EXPECT(afterMember.clusterBytes == afterOutsider.clusterBytes + kFrameSize);
122 BEAST_EXPECT(afterMember.unknownMessages == afterOutsider.unknownMessages);
123 BEAST_EXPECT(afterMember.unknownBytes == afterOutsider.unknownBytes);
124 }
125
126public:
127 void
128 run() override
129 {
131 }
132};
133
134BEAST_DEFINE_TESTSUITE(traffic_attribution, overlay, xrpl);
135
136} // namespace xrpl::test
void writeOne(PropertyStream &stream)
Write only this Source to the stream.
A testsuite class.
Definition suite.h:52
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:155
std::string asString() const
Returns the unquoted string value.
bool update(PublicKey const &identity, std::string name, std::uint32_t loadFee=0, NetClock::time_point reportTime=NetClock::time_point{})
Store information about the state of a cluster node.
Definition Cluster.cpp:58
A PropertyStream::Sink which produces a json::Value of type ValueType::Object.
A public key.
Definition PublicKey.h:53
virtual Cluster & getCluster()=0
virtual Overlay & getOverlay()=0
static std::string toString(Category cat)
A transaction testing environment.
Definition Env.h:161
Application & app()
Definition Env.h:300
Covers the traffic attribution in PeerImp::onMessageBegin.
static Counts read(Env &env)
Reads the cluster and unknown counters the way an operator reads them, through the overlay's property...
T make_shared(T... args)
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:38
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
std::shared_ptr< PeerType > makeCapturePeer(jtx::Env &env, std::optional< PublicKey > key=std::nullopt, HttpRequestType request={})
Build an active CapturePeer and register it with the overlay.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
T stoull(T... args)