rippled
Loading...
Searching...
No Matches
TMGetObjectByHash_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/Env.h>
3
4#include <xrpld/overlay/Message.h>
5#include <xrpld/overlay/detail/OverlayImpl.h>
6#include <xrpld/overlay/detail/PeerImp.h>
7#include <xrpld/overlay/detail/Tuning.h>
8#include <xrpld/peerfinder/detail/SlotImp.h>
9
10#include <xrpl/basics/make_SSLContext.h>
11#include <xrpl/beast/unit_test.h>
12#include <xrpl/nodestore/NodeObject.h>
13#include <xrpl/protocol/digest.h>
14#include <xrpl/protocol/messages.h>
15
16namespace xrpl {
17namespace test {
18
19using namespace jtx;
20
29{
30 using middle_type = boost::beast::tcp_stream;
31 using stream_type = boost::beast::ssl_stream<middle_type>;
32 using socket_type = boost::asio::ip::tcp::socket;
37 class PeerTest : public PeerImp
38 {
39 public:
41 Application& app,
43 http_request_type&& request,
44 PublicKey const& publicKey,
46 Resource::Consumer consumer,
48 OverlayImpl& overlay)
49 : PeerImp(
50 app,
51 id_++,
52 slot,
53 std::move(request),
54 publicKey,
56 consumer,
57 std::move(stream_ptr),
58 overlay)
59 {
60 }
61
62 ~PeerTest() = default;
63
64 void
65 run() override
66 {
67 }
68
69 void
70 send(std::shared_ptr<Message> const& m) override
71 {
73 }
74
77 {
78 return lastSentMessage_;
79 }
80
81 static void
83 {
84 id_ = 0;
85 }
86
87 private:
88 inline static Peer::id_t id_ = 0;
90 };
91
94
97 {
98 auto& overlay = dynamic_cast<OverlayImpl&>(env.app().overlay());
99 boost::beast::http::request<boost::beast::http::dynamic_body> request;
100 auto stream_ptr = std::make_unique<stream_type>(
102
104 boost::asio::ip::make_address("172.1.1.1"), 51235);
105 beast::IP::Endpoint remote(
106 boost::asio::ip::make_address("172.1.1.2"), 51235);
107
109 auto consumer = overlay.resourceManager().newInboundEndpoint(remote);
110 auto [slot, _] = overlay.peerFinder().new_inbound_slot(local, remote);
111
112 auto peer = std::make_shared<PeerTest>(
113 env.app(),
114 slot,
115 std::move(request),
116 key,
118 consumer,
119 std::move(stream_ptr),
120 overlay);
121
122 overlay.add_active(peer);
123 return peer;
124 }
125
127 createRequest(size_t const numObjects, Env& env)
128 {
129 // Store objects in the NodeStore that will be found during the query
130 auto& nodeStore = env.app().getNodeStore();
131
132 // Create and store objects
134 hashes.reserve(numObjects);
135 for (int i = 0; i < numObjects; ++i)
136 {
137 uint256 hash(xrpl::sha512Half(i));
138 hashes.push_back(hash);
139
140 Blob data(100, static_cast<unsigned char>(i % 256));
141 nodeStore.store(
142 hotLEDGER,
143 std::move(data),
144 hash,
145 nodeStore.earliestLedgerSeq());
146 }
147
148 // Create a request with more objects than hardMaxReplyNodes
150 request->set_type(protocol::TMGetObjectByHash_ObjectType_otLEDGER);
151 request->set_query(true);
152
153 for (int i = 0; i < numObjects; ++i)
154 {
155 auto object = request->add_objects();
156 object->set_hash(hashes[i].data(), hashes[i].size());
157 object->set_ledgerseq(i);
158 }
159 return request;
160 }
161
166 void
167 testReplyLimit(size_t const numObjects, int const expectedReplySize)
168 {
169 testcase("Reply Limit");
170
171 Env env(*this);
173
174 auto peer = createPeer(env);
175
176 auto request = createRequest(numObjects, env);
177 // Call the onMessage handler
178 peer->onMessage(request);
179
180 // Verify that a reply was sent
181 auto sentMessage = peer->getLastSentMessage();
182 BEAST_EXPECT(sentMessage != nullptr);
183
184 // Parse the reply message
185 auto const& buffer =
186 sentMessage->getBuffer(compression::Compressed::Off);
187
188 BEAST_EXPECT(buffer.size() > 6);
189 // Skip the message header (6 bytes: 4 for size, 2 for type)
190 protocol::TMGetObjectByHash reply;
191 BEAST_EXPECT(
192 reply.ParseFromArray(buffer.data() + 6, buffer.size() - 6) == true);
193
194 // Verify the reply is limited to expectedReplySize
195 BEAST_EXPECT(reply.objects_size() == expectedReplySize);
196 }
197
198 void
199 run() override
200 {
201 int const limit = static_cast<int>(Tuning::hardMaxReplyNodes);
202 testReplyLimit(limit + 1, limit);
203 testReplyLimit(limit, limit);
204 testReplyLimit(limit - 1, limit - 1);
205 }
206};
207
208BEAST_DEFINE_TESTSUITE(TMGetObjectByHash, overlay, xrpl);
209
210} // namespace test
211} // namespace xrpl
A version-independent IP address and port combination.
Definition IPEndpoint.h:19
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
virtual NodeStore::Database & getNodeStore()=0
virtual boost::asio::io_context & getIOContext()=0
virtual Overlay & overlay()=0
This class manages established peer-to-peer connections, handles message exchange,...
Definition PeerImp.h:99
std::shared_ptr< PeerFinder::Slot > const & slot()
Definition PeerImp.h:332
A public key.
Definition PublicKey.h:43
An endpoint that consumes resources.
Definition Consumer.h:17
Test peer that captures sent messages for verification.
std::shared_ptr< Message > getLastSentMessage() const
void send(std::shared_ptr< Message > const &m) override
PeerTest(Application &app, std::shared_ptr< PeerFinder::Slot > const &slot, http_request_type &&request, PublicKey const &publicKey, ProtocolVersion protocol, Resource::Consumer consumer, std::unique_ptr< TMGetObjectByHash_test::stream_type > &&stream_ptr, OverlayImpl &overlay)
Test for TMGetObjectByHash reply size limiting.
std::shared_ptr< protocol::TMGetObjectByHash > createRequest(size_t const numObjects, Env &env)
boost::beast::ssl_stream< middle_type > stream_type
void testReplyLimit(size_t const numObjects, int const expectedReplySize)
Test that reply is limited to hardMaxReplyNodes when more objects are requested than the limit allows...
std::shared_ptr< PeerTest > createPeer(jtx::Env &env)
boost::asio::ip::tcp::socket socket_type
A transaction testing environment.
Definition Env.h:102
Application & app()
Definition Env.h:244
T is_same_v
STL namespace.
@ hardMaxReplyNodes
The hard cap on the number of ledger entries in a single reply.
auto const data
General field definitions, or fields used in multiple transaction namespaces.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:205
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:14
std::shared_ptr< boost::asio::ssl::context > make_SSLContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
@ hotLEDGER
Definition NodeObject.h:15
T push_back(T... args)
T reserve(T... args)