Skip to content

Commit 45ffd29

Browse files
committed
Refs #22901. Add BB test.
Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
1 parent 01d6e5a commit 45ffd29

1 file changed

Lines changed: 148 additions & 0 deletions

File tree

test/blackbox/common/BlackboxTestsKeys.cpp

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,22 @@
1414

1515
#include "BlackboxTests.hpp"
1616

17+
#include <atomic>
18+
#include <memory>
19+
20+
#include <fastdds/dds/core/policy/ParameterTypes.hpp>
21+
#include <fastdds/dds/topic/TypeSupport.hpp>
1722
#include <fastdds/rtps/common/CDRMessage_t.hpp>
23+
#include <fastdds/rtps/common/InstanceHandle.hpp>
24+
#include <fastdds/rtps/common/SerializedPayload.hpp>
1825
#include <fastdds/rtps/transport/test_UDPv4TransportDescriptor.hpp>
1926

27+
#include "../types/HelloWorldPubSubTypes.hpp"
28+
#include "../types/KeyedHelloWorldPubSubTypes.hpp"
2029
#include "../utils/filter_helpers.hpp"
2130
#include "PubSubReader.hpp"
2231
#include "PubSubWriter.hpp"
32+
#include "UDPMessageSender.hpp"
2333

2434
TEST(KeyedTopic, RegistrationNonKeyedFail)
2535
{
@@ -287,6 +297,144 @@ TEST(KeyedTopic, DataWriterAlwaysSendTheSerializedKeyViaInlineQoS)
287297
EXPECT_TRUE(writer_sends_pid_key_hash);
288298
}
289299

300+
// Check that compute_key is called with a key-only payload when KEY_HASH is not present
301+
TEST(KeyedTopic, key_only_payload)
302+
{
303+
using namespace eprosima::fastdds::dds;
304+
using namespace eprosima::fastdds::rtps;
305+
306+
struct TestTypeSupport : public KeyedHelloWorldPubSubType
307+
{
308+
typedef KeyedHelloWorldPubSubType::type type;
309+
310+
bool compute_key(
311+
eprosima::fastdds::rtps::SerializedPayload_t& payload,
312+
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
313+
bool force_md5 = false) override
314+
{
315+
if (payload.is_serialized_key)
316+
{
317+
// Count the number of times compute_key is called with a key-only payload
318+
key_only_payload_count++;
319+
}
320+
321+
return KeyedHelloWorldPubSubType::compute_key(payload, ihandle, force_md5);
322+
}
323+
324+
bool compute_key(
325+
const void* const data,
326+
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
327+
bool force_md5 = false) override
328+
{
329+
return KeyedHelloWorldPubSubType::compute_key(data, ihandle, force_md5);
330+
}
331+
332+
std::atomic<uint32_t> key_only_payload_count{ 0 };
333+
};
334+
335+
// Force using UDP transport
336+
auto udp_transport = std::make_shared<UDPv4TransportDescriptor>();
337+
338+
PubSubWriter<TestTypeSupport> writer(TEST_TOPIC_NAME);
339+
PubSubReader<TestTypeSupport> reader(TEST_TOPIC_NAME);
340+
341+
// Set custom reader locator so we can send hand-crafted data to a known location
342+
Locator_t reader_locator;
343+
ASSERT_TRUE(IPLocator::setIPv4(reader_locator, "127.0.0.1"));
344+
reader_locator.port = 7000;
345+
reader.add_to_unicast_locator_list("127.0.0.1", 7000);
346+
347+
reader.disable_builtin_transport().
348+
add_user_transport_to_pparams(udp_transport).
349+
init();
350+
ASSERT_TRUE(reader.isInitialized());
351+
352+
writer.disable_builtin_transport().
353+
add_user_transport_to_pparams(udp_transport).
354+
init();
355+
ASSERT_TRUE(writer.isInitialized());
356+
357+
// Wait for discovery.
358+
writer.wait_discovery();
359+
reader.wait_discovery();
360+
361+
auto data = default_keyedhelloworld_data_generator(2);
362+
reader.startReception(data);
363+
// Send data
364+
writer.send(data);
365+
EXPECT_TRUE(data.empty());
366+
reader.block_for_all();
367+
368+
// Check that compute_key was not called with a key-only payload
369+
auto ts = std::dynamic_pointer_cast<TestTypeSupport>(reader.get_type_support());
370+
ASSERT_TRUE(ts != nullptr);
371+
EXPECT_EQ(ts->key_only_payload_count.load(), 0u);
372+
373+
struct KeyOnlyPayloadPacket
374+
{
375+
std::array<char, 4> rtps_id{ {'R', 'T', 'P', 'S'} };
376+
std::array<uint8_t, 2> protocol_version{ {2, 3} };
377+
std::array<uint8_t, 2> vendor_id{ {0x01, 0x0F} };
378+
GuidPrefix_t sender_prefix{};
379+
380+
struct DataSubMsg
381+
{
382+
struct Header
383+
{
384+
uint8_t submessage_id = 0x15;
385+
#if FASTDDS_IS_BIG_ENDIAN_TARGET
386+
uint8_t flags = 0x08;
387+
#else
388+
uint8_t flags = 0x09;
389+
#endif // FASTDDS_IS_BIG_ENDIAN_TARGET
390+
uint16_t octets_to_next_header = 28;
391+
uint16_t extra_flags = 0;
392+
uint16_t octets_to_inline_qos = 16;
393+
EntityId_t reader_id{};
394+
EntityId_t writer_id{};
395+
SequenceNumber_t sn{ 3 };
396+
};
397+
398+
struct SerializedData
399+
{
400+
uint16_t encapsulation;
401+
uint16_t encapsulation_opts;
402+
uint8_t data[4] = {0x01, 0x00, 0x00, 0x00};
403+
};
404+
405+
Header header;
406+
SerializedData payload;
407+
}
408+
data;
409+
};
410+
411+
UDPMessageSender fake_msg_sender;
412+
413+
// Send hand-crafted data
414+
{
415+
auto writer_guid = writer.datawriter_guid();
416+
417+
KeyOnlyPayloadPacket key_only_packet{};
418+
key_only_packet.sender_prefix = writer_guid.guidPrefix;
419+
key_only_packet.data.header.writer_id = writer_guid.entityId;
420+
key_only_packet.data.header.reader_id = reader.datareader_guid().entityId;
421+
key_only_packet.data.payload.encapsulation = CDR_LE;
422+
423+
CDRMessage_t msg(0);
424+
uint32_t msg_len = static_cast<uint32_t>(sizeof(key_only_packet));
425+
msg.init(reinterpret_cast<octet*>(&key_only_packet), msg_len);
426+
msg.length = msg_len;
427+
msg.pos = msg_len;
428+
fake_msg_sender.send(msg, reader_locator);
429+
}
430+
431+
// Wait for key-only compute key to be called
432+
while (ts->key_only_payload_count.load() <= 0)
433+
{
434+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
435+
}
436+
}
437+
290438
/* Uncomment when DDS API supports NO_WRITERS_ALIVE
291439
TEST(KeyedTopic, WriteSamplesBestEffort)
292440
{

0 commit comments

Comments
 (0)