@@ -403,6 +403,76 @@ TEST_F(RosBag2PlayTestFixture, recorded_messages_are_played_for_all_topics)
403403 ElementsAre (40 .0f , 2 .0f , 0 .0f )))));
404404}
405405
406+ TEST_F (RosBag2PlayTestFixture, can_play_messages_with_queue_size_equal_one)
407+ {
408+ const auto msg = get_messages_basic_types ()[0 ];
409+ auto topic_types = std::vector<rosbag2_storage::TopicMetadata>{
410+ {1u , " topic1" , " test_msgs/msg/BasicTypes" , " " , {}, " " },
411+ {2u , " topic2" , " test_msgs/msg/BasicTypes" , " " , {}, " " },
412+ };
413+
414+ std::vector<std::vector<std::shared_ptr<rosbag2_storage::SerializedBagMessage>>> messages_list{};
415+ msg->int32_value = 0 ;
416+ messages_list.emplace_back (std::vector<std::shared_ptr<rosbag2_storage::SerializedBagMessage>>{
417+ (msg->int32_value ++, serialize_test_message (" topic1" , 1 , msg)),
418+ (msg->int32_value ++, serialize_test_message (" topic2" , 2 , msg)),
419+ (msg->int32_value ++, serialize_test_message (" topic1" , 5 , msg)),
420+ (msg->int32_value ++, serialize_test_message (" topic2" , 6 , msg)),
421+ (msg->int32_value ++, serialize_test_message (" topic1" , 9 , msg)),
422+ (msg->int32_value ++, serialize_test_message (" topic2" , 10 , msg))
423+ });
424+
425+ std::vector<rosbag2_transport::Player::reader_storage_options_pair_t > bags{};
426+ std::size_t total_messages = 0u ;
427+ for (const auto & curr_bag_messages : messages_list) {
428+ auto prepared_mock_reader = std::make_unique<MockSequentialReader>();
429+ total_messages += curr_bag_messages.size ();
430+ prepared_mock_reader->prepare (curr_bag_messages, topic_types);
431+ bags.emplace_back (
432+ std::make_unique<rosbag2_cpp::Reader>(std::move (prepared_mock_reader)), storage_options_);
433+ }
434+ ASSERT_GT (total_messages, 0u );
435+ // Note: For the sake of the test, the read_ahead_queue_size is set to 1
436+ // to test the corner case of having the smallest possible queue size.
437+ // This means that only one message will be prefetched from the readers at a time.
438+ // This is to make sure that the player can handle this case correctly.
439+ // In a real scenario, a larger queue size is recommended to improve performance.
440+ play_options_.read_ahead_queue_size = 1 ;
441+ const rosbag2_transport::MessageOrder message_order = play_options_.message_order ;
442+
443+ auto player = std::make_shared<rosbag2_transport::Player>(std::move (bags), play_options_);
444+ std::size_t num_played_messages = 0u ;
445+ rcutils_time_point_value_t last_timestamp = 0 ;
446+ const auto get_timestamp =
447+ [message_order](std::shared_ptr<rosbag2_storage::SerializedBagMessage> msg) {
448+ switch (message_order) {
449+ case rosbag2_transport::MessageOrder::RECEIVED_TIMESTAMP:
450+ return msg->recv_timestamp ;
451+ case rosbag2_transport::MessageOrder::SENT_TIMESTAMP:
452+ return msg->send_timestamp ;
453+ default :
454+ throw std::runtime_error (" unknown rosbag2_transport::MessageOrder value" );
455+ }
456+ };
457+ const auto callback = [&](std::shared_ptr<rosbag2_storage::SerializedBagMessage> playing_msg) {
458+ // Make sure messages are played in order
459+ num_played_messages++;
460+ const auto timestamp = get_timestamp (playing_msg);
461+ using MessageT = typename decltype (msg)::element_type;
462+ const auto deserialized_msg = deserialize_test_message<MessageT>(playing_msg);
463+ // The int32_value was set in an increasing order when creating the messages
464+ EXPECT_EQ (deserialized_msg->int32_value , num_played_messages) << " , timestamp = " <<
465+ RCUTILS_NS_TO_MS (timestamp) << " , topic_name = `" << playing_msg->topic_name << " `\n " ;
466+ EXPECT_LE (last_timestamp, timestamp);
467+ last_timestamp = timestamp;
468+ };
469+ player->add_on_play_message_pre_callback (callback);
470+ player->play ();
471+ ASSERT_TRUE (player->wait_for_playback_to_start (10s));
472+ ASSERT_TRUE (player->wait_for_playback_to_finish (10s));
473+ EXPECT_EQ (total_messages, num_played_messages);
474+ }
475+
406476TEST_F (RosBag2PlayTestFixture, can_play_when_one_bag_has_fewer_messages_than_other_bags)
407477{
408478 auto msg = get_messages_basic_types ()[0 ];
0 commit comments