Skip to content

Commit e9768fe

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

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

test/blackbox/common/BlackboxTestsKeys.cpp

Lines changed: 140 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,136 @@ 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+
std::atomic<uint32_t> key_only_payload_count{ 0 };
325+
};
326+
327+
// Force using UDP transport
328+
auto udp_transport = std::make_shared<UDPv4TransportDescriptor>();
329+
330+
PubSubWriter<TestTypeSupport> writer(TEST_TOPIC_NAME);
331+
PubSubReader<TestTypeSupport> reader(TEST_TOPIC_NAME);
332+
333+
// Set custom reader locator so we can send hand-crafted data to a known location
334+
Locator_t reader_locator;
335+
ASSERT_TRUE(IPLocator::setIPv4(reader_locator, "127.0.0.1"));
336+
reader_locator.port = 7000;
337+
reader.add_to_unicast_locator_list("127.0.0.1", 7000);
338+
339+
reader.disable_builtin_transport().
340+
add_user_transport_to_pparams(udp_transport).
341+
init();
342+
ASSERT_TRUE(reader.isInitialized());
343+
344+
writer.disable_builtin_transport().
345+
add_user_transport_to_pparams(udp_transport).
346+
init();
347+
ASSERT_TRUE(writer.isInitialized());
348+
349+
// Wait for discovery.
350+
writer.wait_discovery();
351+
reader.wait_discovery();
352+
353+
auto data = default_keyedhelloworld_data_generator(2);
354+
reader.startReception(data);
355+
// Send data
356+
writer.send(data);
357+
EXPECT_TRUE(data.empty());
358+
reader.block_for_all();
359+
360+
// Check that compute_key was not called with a key-only payload
361+
auto ts = std::dynamic_pointer_cast<TestTypeSupport>(reader.get_type_support());
362+
ASSERT_TRUE(ts != nullptr);
363+
EXPECT_EQ(ts->key_only_payload_count.load(), 0u);
364+
365+
struct KeyOnlyPayloadPacket
366+
{
367+
std::array<char, 4> rtps_id{ {'R', 'T', 'P', 'S'} };
368+
std::array<uint8_t, 2> protocol_version{ {2, 3} };
369+
std::array<uint8_t, 2> vendor_id{ {0x01, 0x0F} };
370+
GuidPrefix_t sender_prefix{};
371+
372+
struct DataSubMsg
373+
{
374+
struct Header
375+
{
376+
uint8_t submessage_id = 0x15;
377+
#if FASTDDS_IS_BIG_ENDIAN_TARGET
378+
uint8_t flags = 0x08;
379+
#else
380+
uint8_t flags = 0x09;
381+
#endif // FASTDDS_IS_BIG_ENDIAN_TARGET
382+
uint16_t octets_to_next_header = 28;
383+
uint16_t extra_flags = 0;
384+
uint16_t octets_to_inline_qos = 16;
385+
EntityId_t reader_id{};
386+
EntityId_t writer_id{};
387+
SequenceNumber_t sn{ 3 };
388+
};
389+
390+
struct SerializedData
391+
{
392+
uint16_t encapsulation;
393+
uint16_t encapsulation_opts;
394+
uint8_t data[4] = {0x01, 0x00, 0x00, 0x00};
395+
};
396+
397+
Header header;
398+
SerializedData payload;
399+
}
400+
data;
401+
};
402+
403+
UDPMessageSender fake_msg_sender;
404+
405+
// Send hand-crafted data
406+
{
407+
auto writer_guid = writer.datawriter_guid();
408+
409+
KeyOnlyPayloadPacket key_only_packet{};
410+
key_only_packet.sender_prefix = writer_guid.guidPrefix;
411+
key_only_packet.data.header.writer_id = writer_guid.entityId;
412+
key_only_packet.data.header.reader_id = reader.datareader_guid().entityId;
413+
key_only_packet.data.payload.encapsulation = CDR_LE;
414+
415+
CDRMessage_t msg(0);
416+
uint32_t msg_len = static_cast<uint32_t>(sizeof(key_only_packet));
417+
msg.init(reinterpret_cast<octet*>(&key_only_packet), msg_len);
418+
msg.length = msg_len;
419+
msg.pos = msg_len;
420+
fake_msg_sender.send(msg, reader_locator);
421+
}
422+
423+
// Wait for key-only compute key to be called
424+
while (ts->key_only_payload_count.load() <= 0)
425+
{
426+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
427+
}
428+
}
429+
290430
/* Uncomment when DDS API supports NO_WRITERS_ALIVE
291431
TEST(KeyedTopic, WriteSamplesBestEffort)
292432
{

0 commit comments

Comments
 (0)