77#include " my_custom/bar_1_0.hpp"
88#include " tracking_memory_resource.hpp"
99#include " transport/msg_sessions_mock.hpp"
10+ #include " transport/transfer_id_map_mock.hpp"
1011#include " transport/transport_gtest_helpers.hpp"
1112#include " transport/transport_mock.hpp"
1213#include " verification_utilities.hpp"
1718#include < libcyphal/presentation/publisher.hpp>
1819#include < libcyphal/transport/errors.hpp>
1920#include < libcyphal/transport/msg_sessions.hpp>
21+ #include < libcyphal/transport/transfer_id_map.hpp>
2022#include < libcyphal/transport/types.hpp>
2123#include < libcyphal/types.hpp>
2224
@@ -176,7 +178,7 @@ TEST_F(TestPublisher, publish)
176178 EXPECT_CALL (msg_tx_session_mock, send (_, _)) //
177179 .WillOnce (Invoke ([now = now ()](const auto & metadata, const auto ) {
178180 //
179- EXPECT_THAT (metadata.base .transfer_id , 1 );
181+ EXPECT_THAT (metadata.base .transfer_id , 0 );
180182 EXPECT_THAT (metadata.base .priority , Priority::Exceptional);
181183 EXPECT_THAT (metadata.deadline , now + 200ms);
182184 return cetl::nullopt ;
@@ -189,7 +191,7 @@ TEST_F(TestPublisher, publish)
189191 EXPECT_CALL (msg_tx_session_mock, send (_, _)) //
190192 .WillOnce (Invoke ([now = now ()](const auto & metadata, const auto ) {
191193 //
192- EXPECT_THAT (metadata.base .transfer_id , 2 );
194+ EXPECT_THAT (metadata.base .transfer_id , 1 );
193195 EXPECT_THAT (metadata.base .priority , Priority::Fast);
194196 EXPECT_THAT (metadata.deadline , now + 100ms);
195197 return cetl::nullopt ;
@@ -283,7 +285,7 @@ TEST_F(TestPublisher, publishRawData)
283285 EXPECT_CALL (msg_tx_session_mock, send (_, _)) //
284286 .WillOnce (Invoke ([now = now ()](const auto & metadata, const auto frags) {
285287 //
286- EXPECT_THAT (metadata.base .transfer_id , 1 );
288+ EXPECT_THAT (metadata.base .transfer_id , 0 );
287289 EXPECT_THAT (metadata.base .priority , Priority::Nominal);
288290 EXPECT_THAT (metadata.deadline , now + 200ms);
289291 EXPECT_THAT (frags.size (), 1 );
@@ -303,6 +305,103 @@ TEST_F(TestPublisher, publishRawData)
303305 scheduler_.spinFor (10s);
304306}
305307
308+ TEST_F (TestPublisher, multiple_publishers_with_transfer_id_map)
309+ {
310+ using Message = uavcan::node::Heartbeat_1_0;
311+ using SessionSpec = ITransferIdMap::SessionSpec;
312+
313+ StrictMock<TransferIdMapMock> transfer_id_map_mock;
314+
315+ Presentation presentation{mr_, scheduler_, transport_mock_};
316+ presentation.setTransferIdMap (&transfer_id_map_mock);
317+
318+ EXPECT_CALL (transport_mock_, getLocalNodeId ()) //
319+ .WillOnce (Return (cetl::nullopt ));
320+
321+ StrictMock<MessageTxSessionMock> msg7_tx_session_mock;
322+ constexpr MessageTxParams tx7_params{7 };
323+ cetl::optional<Publisher<Message>> publisher7;
324+ {
325+ EXPECT_CALL (msg7_tx_session_mock, getParams ()).WillOnce (Return (tx7_params));
326+
327+ EXPECT_CALL (transport_mock_, makeMessageTxSession (MessageTxParamsEq (tx7_params))) //
328+ .WillOnce (Invoke ([&](const auto &) { //
329+ return libcyphal::detail::makeUniquePtr<UniquePtrMsgTxSpec>(mr_, msg7_tx_session_mock);
330+ }));
331+
332+ auto maybe_pub7 = presentation.makePublisher <Message>(tx7_params.subject_id );
333+ ASSERT_THAT (maybe_pub7, VariantWith<Publisher<Message>>(_));
334+
335+ publisher7.emplace (cetl::get<Publisher<Message>>(std::move (maybe_pub7)));
336+ }
337+
338+ constexpr NodeId local_node_id = 0x13 ;
339+ EXPECT_CALL (transport_mock_, getLocalNodeId ()) //
340+ .WillRepeatedly (Return (cetl::optional<NodeId>{NodeId{local_node_id}}));
341+
342+ StrictMock<MessageTxSessionMock> msg9_tx_session_mock;
343+ constexpr MessageTxParams tx9_params{9 };
344+ cetl::optional<Publisher<Message>> publisher9;
345+ {
346+ EXPECT_CALL (msg9_tx_session_mock, getParams ()).WillOnce (Return (tx9_params));
347+
348+ EXPECT_CALL (transport_mock_, makeMessageTxSession (MessageTxParamsEq (tx9_params))) //
349+ .WillOnce (Invoke ([&](const auto &) { //
350+ return libcyphal::detail::makeUniquePtr<UniquePtrMsgTxSpec>(mr_, msg9_tx_session_mock);
351+ }));
352+
353+ EXPECT_CALL (transfer_id_map_mock, getIdFor (SessionSpec{tx9_params.subject_id , local_node_id}))
354+ .WillOnce (Return (90 ));
355+
356+ auto maybe_pub9 = presentation.makePublisher <Message>(tx9_params.subject_id );
357+ ASSERT_THAT (maybe_pub9, VariantWith<Publisher<Message>>(_));
358+
359+ publisher9.emplace (cetl::get<Publisher<Message>>(std::move (maybe_pub9)));
360+ }
361+
362+ scheduler_.scheduleAt (1s, [&](const auto &) {
363+ //
364+ EXPECT_CALL (msg7_tx_session_mock, send (_, _)) //
365+ .WillOnce (Invoke ([now = now ()](const auto & metadata, const auto ) {
366+ //
367+ EXPECT_THAT (metadata.base .transfer_id , 0 );
368+ return cetl::nullopt ;
369+ }));
370+
371+ EXPECT_THAT (publisher7->publish (now () + 200ms, Message{&mr_}), Eq (cetl::nullopt ));
372+ });
373+ scheduler_.scheduleAt (2s, [&](const auto &) {
374+ //
375+ EXPECT_CALL (msg9_tx_session_mock, send (_, _)) //
376+ .WillOnce (Invoke ([now = now ()](const auto & metadata, const auto ) {
377+ //
378+ EXPECT_THAT (metadata.base .transfer_id , 90 );
379+ return cetl::nullopt ;
380+ }));
381+
382+ EXPECT_THAT (publisher9->publish (now () + 200ms, Message{&mr_}), Eq (cetl::nullopt ));
383+ });
384+ scheduler_.scheduleAt (8s, [&](const auto &) {
385+ //
386+ EXPECT_CALL (transfer_id_map_mock, setIdFor (SessionSpec{tx9_params.subject_id , local_node_id}, 90 + 1 )) //
387+ .WillOnce (Return ());
388+
389+ publisher9.reset ();
390+ testing::Mock::VerifyAndClearExpectations (&msg9_tx_session_mock);
391+ EXPECT_CALL (msg9_tx_session_mock, deinit ()).Times (1 );
392+ });
393+ scheduler_.scheduleAt (9s, [&](const auto &) {
394+ //
395+ EXPECT_CALL (transfer_id_map_mock, setIdFor (SessionSpec{tx7_params.subject_id , local_node_id}, 1 )) //
396+ .WillOnce (Return ());
397+
398+ publisher7.reset ();
399+ testing::Mock::VerifyAndClearExpectations (&msg7_tx_session_mock);
400+ EXPECT_CALL (msg7_tx_session_mock, deinit ()).Times (1 );
401+ });
402+ scheduler_.spinFor (10s);
403+ }
404+
306405// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
307406
308407} // namespace
0 commit comments