@@ -3476,6 +3476,96 @@ TEST(DDSStatus, entire_history_acked_volatile_unknown_pointer)
3476
3476
}
3477
3477
}
3478
3478
3479
+ /* ¡
3480
+ * Regression Test for 22648: on_unacknowledged_sample_removed callback is called when writer with keep all
3481
+ * history is used, when the history was full but before max_blocking_time a sample was acknowledged, as is_acked was
3482
+ * checked before the waiting time, and is not re-checked. This should not happen.
3483
+ */
3484
+ TEST (DDSStatus, reliable_keep_all_unack_sample_removed_call)
3485
+ {
3486
+ auto test_transport = std::make_shared<test_UDPv4TransportDescriptor>();
3487
+ test_transport->drop_data_messages_filter_ = [](eprosima::fastdds::rtps::CDRMessage_t& msg) -> bool
3488
+ {
3489
+ static std::vector<std::pair<eprosima::fastdds::rtps::SequenceNumber_t,
3490
+ std::chrono::steady_clock::time_point>> delayed_messages;
3491
+
3492
+ uint32_t old_pos = msg.pos ;
3493
+
3494
+ // Parse writer ID and sequence number
3495
+ msg.pos += 2 ; // flags
3496
+ msg.pos += 2 ; // inline QoS
3497
+ msg.pos += 4 ; // reader ID
3498
+ auto writerID = eprosima::fastdds::helpers::cdr_parse_entity_id ((char *)&msg.buffer [msg.pos ]);
3499
+ msg.pos += 4 ;
3500
+ eprosima::fastdds::rtps::SequenceNumber_t sn;
3501
+ sn.high = (int32_t )eprosima::fastdds::helpers::cdr_parse_u32 ((char *)&msg.buffer [msg.pos ]);
3502
+ msg.pos += 4 ;
3503
+ sn.low = eprosima::fastdds::helpers::cdr_parse_u32 ((char *)&msg.buffer [msg.pos ]);
3504
+
3505
+ // Restore buffer position
3506
+ msg.pos = old_pos;
3507
+
3508
+ // Delay logic for user endpoints only
3509
+ if ((writerID.value [3 ] & 0xC0 ) == 0 ) // only user endpoints
3510
+ {
3511
+ auto now = std::chrono::steady_clock::now ();
3512
+ auto it = std::find_if (delayed_messages.begin (), delayed_messages.end (),
3513
+ [&sn](const auto & pair)
3514
+ {
3515
+ return pair.first == sn;
3516
+ });
3517
+
3518
+ if (it == delayed_messages.end ())
3519
+ {
3520
+ // If the sequence number is encountered for the first time, start the delay
3521
+ delayed_messages.emplace_back (sn, now + std::chrono::milliseconds (750 )); // Add delay
3522
+ return true ; // Start dropping this message
3523
+ }
3524
+ else if (now < it->second )
3525
+ {
3526
+ // If the delay period has not elapsed, keep dropping the message
3527
+ return true ;
3528
+ }
3529
+ else
3530
+ {
3531
+ // Once the delay has elapsed, allow the message to proceed
3532
+ delayed_messages.erase (it);
3533
+ }
3534
+ }
3535
+ return false ; // Allow message to proceed
3536
+ };
3537
+
3538
+ PubSubWriter<HelloWorldPubSubType> writer (TEST_TOPIC_NAME);
3539
+ PubSubReader<HelloWorldPubSubType> reader (TEST_TOPIC_NAME);
3540
+
3541
+ writer.reliability (eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, eprosima::fastdds::dds::Duration_t (200 , 0 ))
3542
+ .history_kind (eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS)
3543
+ .resource_limits_max_instances (1 )
3544
+ .resource_limits_max_samples (1 )
3545
+ .resource_limits_max_samples_per_instance (1 )
3546
+ .disable_builtin_transport ()
3547
+ .add_user_transport_to_pparams (test_transport)
3548
+ .init ();
3549
+ ASSERT_TRUE (writer.isInitialized ());
3550
+
3551
+ reader.reliability (eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS)
3552
+ .init ();
3553
+ ASSERT_TRUE (reader.isInitialized ());
3554
+
3555
+ // Wait for discovery
3556
+ writer.wait_discovery ();
3557
+ reader.wait_discovery ();
3558
+
3559
+ auto data = default_helloworld_data_generator (2 );
3560
+
3561
+ for (auto sample : data)
3562
+ {
3563
+ writer.send_sample (sample);
3564
+ }
3565
+
3566
+ EXPECT_EQ (writer.times_unack_sample_removed (), 0u );
3567
+ }
3568
+
3479
3569
/* !
3480
3570
* Test that checks with a writer of each type that having the same listener attached, the notified writer in the
3481
3571
* callback is the corresponding writer that has removed a sample unacknowledged.
0 commit comments