diff --git a/include/up-cpp/communication/Publisher.h b/include/up-cpp/communication/Publisher.h index ef83932e4..1b3011075 100644 --- a/include/up-cpp/communication/Publisher.h +++ b/include/up-cpp/communication/Publisher.h @@ -44,7 +44,7 @@ struct Publisher { /// @param ttl How long published messages will be valid from the time /// publish() is called. Publisher(std::shared_ptr transport, - const v1::UUri& topic, v1::UPayloadFormat format, + v1::UUri&& topic, v1::UPayloadFormat format, std::optional priority = {}, std::optional ttl = {}); diff --git a/src/communication/Publisher.cpp b/src/communication/Publisher.cpp index 25a0c8c1e..46759d4dc 100644 --- a/src/communication/Publisher.cpp +++ b/src/communication/Publisher.cpp @@ -10,3 +10,29 @@ // SPDX-License-Identifier: Apache-2.0 #include "up-cpp/communication/Publisher.h" + +#include + +namespace uprotocol::communication { +using namespace uprotocol::datamodel::builder; + +Publisher::Publisher(std::shared_ptr transport, + v1::UUri&& topic, v1::UPayloadFormat format, + std::optional priority, + std::optional ttl) + : transport_(std::move(transport)), + publish_builder_(UMessageBuilder::publish(std::move(topic))) { + publish_builder_.withPayloadFormat(format).withPriority( + priority.value_or(v1::UPriority::UPRIORITY_CS1)); + + if (ttl.has_value()) { + publish_builder_.withTtl(ttl.value()); + } +} + +v1::UStatus Publisher::publish(datamodel::builder::Payload&& payload) const { + auto message = publish_builder_.build(std::move(payload)); + return transport_->send(std::move(message)); +} + +} // namespace uprotocol::communication \ No newline at end of file diff --git a/test/coverage/communication/PublisherTest.cpp b/test/coverage/communication/PublisherTest.cpp index b146d984b..9171ce611 100644 --- a/test/coverage/communication/PublisherTest.cpp +++ b/test/coverage/communication/PublisherTest.cpp @@ -11,30 +11,155 @@ #include #include +#include +#include +#include #include "UTransportMock.h" +#include "spdlog/spdlog.h" +#include "up-cpp/communication/Publisher.h" +#include "up-cpp/datamodel/builder/UMessage.h" +#include "up-cpp/datamodel/validator/UMessage.h" +#include "up-cpp/transport/UTransport.h" +using namespace uprotocol::communication; +using namespace uprotocol::datamodel::builder; +using namespace uprotocol::v1; +using ::testing::_; +using ::testing::Return; namespace { +using namespace uprotocol::datamodel::builder; -class TestFixture : public testing::Test { +class TestPublisher : public testing::Test { protected: // Run once per TEST_F. // Used to set up clean environments per test. - void SetUp() override {} + void SetUp() override { + source_.set_authority_name("10.0.0.1"); + source_.set_ue_id(0x00011101); + source_.set_ue_version_major(0xF1); + source_.set_resource_id(0x0); + + topic_.set_authority_name("10.0.0.1"); + topic_.set_ue_id(0x00011101); + topic_.set_ue_version_major(0xF8); + topic_.set_resource_id(0x8101); + transportMock_ = + std::make_shared(source_); + + format_ = UPayloadFormat::UPAYLOAD_FORMAT_TEXT; + priority_ = UPriority::UPRIORITY_CS2; + ttl_ = std::chrono::milliseconds(1000); + } + void TearDown() override {} // Run once per execution of the test application. // Used for setup of all tests. Has access to this instance. - TestFixture() = default; - ~TestFixture() = default; + TestPublisher() = default; + ~TestPublisher() = default; // Run once per execution of the test application. // Used only for global setup outside of tests. static void SetUpTestSuite() {} static void TearDownTestSuite() {} + + std::shared_ptr transportMock_; + UUri source_; + UUri topic_; + UPayloadFormat format_; + std::optional priority_; + std::optional ttl_; }; -// TODO replace -TEST_F(TestFixture, SomeTestName) {} +TEST_F(TestPublisher, PublisherSuccess) { + std::string testPayloadStr = "test_payload"; + Publisher publisher(transportMock_, std::move(topic_), format_, priority_, + ttl_); + + uprotocol::v1::UStatus retval; + retval.set_code(uprotocol::v1::UCode::OK); + transportMock_->send_status_ = retval; + + Payload testPayload(testPayloadStr, format_); + auto status = publisher.publish(std::move(testPayload)); + + EXPECT_EQ(status.code(), retval.code()); + + auto [valid, reason] = + uprotocol::datamodel::validator::message::isValidPublish( + transportMock_->message_); + EXPECT_EQ(valid, true); + spdlog::info("RCDBG-1 ttl[{}]", + transportMock_->message_.attributes().ttl()); + spdlog::info( + "RCDBG-1 priority[{}]", + static_cast(transportMock_->message_.attributes().priority())); +} + +TEST_F(TestPublisher, PublishFailure) { + std::string testPayloadStr = "test_payload"; + Publisher publisher(transportMock_, std::move(topic_), format_, priority_, + ttl_); + + uprotocol::v1::UStatus retval; + retval.set_code(uprotocol::v1::UCode::DATA_LOSS); + transportMock_->send_status_ = retval; + + Payload testPayload(testPayloadStr, format_); + auto status = publisher.publish(std::move(testPayload)); + + EXPECT_EQ(status.code(), retval.code()); + spdlog::info("RCDBG-2 ttl[{}]", + transportMock_->message_.attributes().ttl()); + spdlog::info( + "RCDBG-2 priority[{}]", + static_cast(transportMock_->message_.attributes().priority())); +} + +TEST_F(TestPublisher, PublishSuccessWithoutTTL) { + std::string testPayloadStr = "test_payload"; + Publisher publisher(transportMock_, std::move(topic_), format_, priority_); + + uprotocol::v1::UStatus retval; + retval.set_code(uprotocol::v1::UCode::OK); + transportMock_->send_status_ = retval; + + Payload testPayload(testPayloadStr, format_); + auto status = publisher.publish(std::move(testPayload)); + + EXPECT_EQ(status.code(), retval.code()); + + auto [valid, reason] = + uprotocol::datamodel::validator::message::isValidPublish( + transportMock_->message_); + EXPECT_EQ(valid, true); + + EXPECT_EQ(transportMock_->message_.attributes().ttl(), 0); +} + +TEST_F(TestPublisher, PublishSuccessWithoutPriority) { + std::string testPayloadStr = "test_payload"; + priority_.reset(); + Publisher publisher(transportMock_, std::move(topic_), format_, priority_, + ttl_); + + uprotocol::v1::UStatus retval; + retval.set_code(uprotocol::v1::UCode::OK); + transportMock_->send_status_ = retval; + + Payload testPayload(testPayloadStr, format_); + auto status = publisher.publish(std::move(testPayload)); + + EXPECT_EQ(status.code(), retval.code()); + + auto [valid, reason] = + uprotocol::datamodel::validator::message::isValidPublish( + transportMock_->message_); + EXPECT_EQ(valid, true); + + EXPECT_EQ(transportMock_->message_.attributes().priority(), + UPriority::UPRIORITY_CS1); +} } // namespace