From b8013185d07a52e44a341b85b3a15ba6274c3676 Mon Sep 17 00:00:00 2001 From: JinmingHu Date: Fri, 27 Aug 2021 12:46:51 +0800 Subject: [PATCH] Storage Queue API review feedback (#2801) * fix * sample * CL * service version * fix * ACL --- sdk/storage/azure-storage-queues/CHANGELOG.md | 1 - .../azure-storage-queues/CMakeLists.txt | 2 + .../queues/protocol/queue_rest_client.hpp | 178 +++++++++++++++--- .../inc/azure/storage/queues/queue_client.hpp | 16 +- .../azure/storage/queues/queue_options.hpp | 54 +++++- .../sample/queue_encode_message.cpp | 35 ++++ .../sample/queue_getting_started.cpp | 24 ++- .../azure-storage-queues/src/queue_client.cpp | 23 +-- .../src/queue_options.cpp | 11 ++ .../src/queue_service_client.cpp | 6 +- .../test/ut/queue_client_messages_test.cpp | 34 ++-- .../test/ut/queue_client_test.cpp | 51 +++-- .../test/ut/queue_sas_test.cpp | 2 +- 13 files changed, 328 insertions(+), 109 deletions(-) create mode 100644 sdk/storage/azure-storage-queues/sample/queue_encode_message.cpp create mode 100644 sdk/storage/azure-storage-queues/src/queue_options.cpp diff --git a/sdk/storage/azure-storage-queues/CHANGELOG.md b/sdk/storage/azure-storage-queues/CHANGELOG.md index 20d1e4127..37c5dfc43 100644 --- a/sdk/storage/azure-storage-queues/CHANGELOG.md +++ b/sdk/storage/azure-storage-queues/CHANGELOG.md @@ -14,7 +14,6 @@ - QueueClient::Create - QueueClient::CreateIfNotExists - QueueClient::Delete - - QueueClient::DeleteIfExists - QueueClient::GetProperties - QueueClient::SetMetadata - QueueClient::GetAccessPolicy diff --git a/sdk/storage/azure-storage-queues/CMakeLists.txt b/sdk/storage/azure-storage-queues/CMakeLists.txt index ce575b0dd..76fd22ee5 100644 --- a/sdk/storage/azure-storage-queues/CMakeLists.txt +++ b/sdk/storage/azure-storage-queues/CMakeLists.txt @@ -42,6 +42,7 @@ set( AZURE_STORAGE_QUEUE_SOURCE src/private/package_version.hpp src/queue_client.cpp + src/queue_options.cpp src/queue_responses.cpp src/queue_rest_client.cpp src/queue_sas_builder.cpp @@ -93,6 +94,7 @@ if(BUILD_STORAGE_SAMPLES) target_sources( azure-storage-sample PRIVATE + sample/queue_encode_message.cpp sample/queue_getting_started.cpp ) diff --git a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp index 6a853abd2..152e68788 100644 --- a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp +++ b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp @@ -53,6 +53,33 @@ namespace Azure { namespace Storage { namespace Queues { std::string m_value; }; // extensible enum GeoReplicationStatus + /** + * @brief A peeked message object stored in the queue. + */ + struct PeekedQueueMessage final + { + /** + * The content of the message. + */ + std::string MessageText; + /** + * A GUID value that identifies the message in the queue. + */ + std::string MessageId; + /** + * The time the message was inserted into the queue. + */ + Azure::DateTime InsertedOn; + /** + * The time that the message will expire and be automatically deleted from the queue. + */ + Azure::DateTime ExpiresOn; + /** + * The number of times the message has been dequeued. + */ + int64_t DequeueCount = 0; + }; // struct PeekedQueueMessage + /** * @brief A queue item from the result of * #Azure::Storage::Queues::QueueServiceClient::ListQueues. @@ -77,7 +104,7 @@ namespace Azure { namespace Storage { namespace Queues { /** * The content of the message. */ - std::string Body; + std::string MessageText; /** * A GUID value that identifies the message in the queue. */ @@ -91,13 +118,11 @@ namespace Azure { namespace Storage { namespace Queues { */ Azure::DateTime ExpiresOn; /** - * An opaque string that is required to delete or update a message. Empty if it's a peeked - * message. + * An opaque string that is required to delete or update a message. */ std::string PopReceipt; /** - * The time that the message will again become visible in the queue. Invalid if it's a peeked - * message. + * The time that the message will again become visible in the queue. */ Azure::DateTime NextVisibleOn; /** @@ -134,11 +159,11 @@ namespace Azure { namespace Storage { namespace Queues { /** * Date and time since when this policy is active. */ - Azure::DateTime StartsOn; + Azure::Nullable StartsOn; /** * Date and time the policy expires. */ - Azure::DateTime ExpiresOn; + Azure::Nullable ExpiresOn; /** * The permissions for this ACL policy. */ @@ -346,7 +371,7 @@ namespace Azure { namespace Storage { namespace Queues { /** * A vector of peeked messages. */ - std::vector Messages; + std::vector Messages; }; // struct PeekMessagesResult /** @@ -1740,7 +1765,7 @@ namespace Azure { namespace Storage { namespace Queues { struct EnqueueMessageOptions final { Azure::Nullable Timeout; - std::string Body; + std::string MessageText; Azure::Nullable VisibilityTimeout; Azure::Nullable TimeToLive; }; // struct EnqueueMessageOptions @@ -1993,7 +2018,7 @@ namespace Azure { namespace Storage { namespace Queues { struct UpdateMessageOptions final { - std::string Body; + std::string MessageText; Azure::Nullable Timeout; std::string PopReceipt; std::chrono::seconds VisibilityTimeout; @@ -2199,7 +2224,7 @@ namespace Azure { namespace Storage { namespace Queues { if (path.size() == 2 && path[0] == XmlTagName::k_QueueMessagesList && path[1] == XmlTagName::k_QueueMessage) { - ret.Messages.emplace_back(QueueMessageFromXml(reader)); + ret.Messages.emplace_back(PeekedQueueMessageFromXml(reader)); path.pop_back(); } } @@ -2322,6 +2347,93 @@ namespace Azure { namespace Storage { namespace Queues { return ret; } + static PeekedQueueMessage PeekedQueueMessageFromXml(_internal::XmlReader& reader) + { + PeekedQueueMessage ret; + enum class XmlTagName + { + k_MessageText, + k_MessageId, + k_InsertionTime, + k_ExpirationTime, + k_DequeueCount, + k_Unknown, + }; + std::vector path; + while (true) + { + auto node = reader.Read(); + if (node.Type == _internal::XmlNodeType::End) + { + break; + } + else if (node.Type == _internal::XmlNodeType::EndTag) + { + if (path.size() > 0) + { + path.pop_back(); + } + else + { + break; + } + } + else if (node.Type == _internal::XmlNodeType::StartTag) + { + if (node.Name == "MessageText") + { + path.emplace_back(XmlTagName::k_MessageText); + } + else if (node.Name == "MessageId") + { + path.emplace_back(XmlTagName::k_MessageId); + } + else if (node.Name == "InsertionTime") + { + path.emplace_back(XmlTagName::k_InsertionTime); + } + else if (node.Name == "ExpirationTime") + { + path.emplace_back(XmlTagName::k_ExpirationTime); + } + else if (node.Name == "DequeueCount") + { + path.emplace_back(XmlTagName::k_DequeueCount); + } + else + { + path.emplace_back(XmlTagName::k_Unknown); + } + } + else if (node.Type == _internal::XmlNodeType::Text) + { + if (path.size() == 1 && path[0] == XmlTagName::k_MessageText) + { + ret.MessageText = node.Value; + } + else if (path.size() == 1 && path[0] == XmlTagName::k_MessageId) + { + ret.MessageId = node.Value; + } + else if (path.size() == 1 && path[0] == XmlTagName::k_InsertionTime) + { + ret.InsertedOn + = Azure::DateTime::Parse(node.Value, Azure::DateTime::DateFormat::Rfc1123); + } + else if (path.size() == 1 && path[0] == XmlTagName::k_ExpirationTime) + { + ret.ExpiresOn + = Azure::DateTime::Parse(node.Value, Azure::DateTime::DateFormat::Rfc1123); + } + else if (path.size() == 1 && path[0] == XmlTagName::k_DequeueCount) + { + ret.DequeueCount = std::stoll(node.Value); + } + } + } + return ret; + } + static QueueMessage QueueMessageFromXml(_internal::XmlReader& reader) { QueueMessage ret; @@ -2394,7 +2506,7 @@ namespace Azure { namespace Storage { namespace Queues { { if (path.size() == 1 && path[0] == XmlTagName::k_MessageText) { - ret.Body = node.Value; + ret.MessageText = node.Value; } else if (path.size() == 1 && path[0] == XmlTagName::k_MessageId) { @@ -2524,7 +2636,7 @@ namespace Azure { namespace Storage { namespace Queues { writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "QueueMessage"}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "MessageText"}); writer.Write( - _internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Body}); + _internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.MessageText}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); } @@ -2548,7 +2660,7 @@ namespace Azure { namespace Storage { namespace Queues { writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "QueueMessage"}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "MessageText"}); writer.Write( - _internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Body}); + _internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.MessageText}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); } @@ -2562,22 +2674,28 @@ namespace Azure { namespace Storage { namespace Queues { writer.Write(_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Id}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "AccessPolicy"}); - writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Start"}); - writer.Write(_internal::XmlNode{ - _internal::XmlNodeType::Text, - std::string(), - options.StartsOn.ToString( - Azure::DateTime::DateFormat::Rfc3339, - Azure::DateTime::TimeFractionFormat::AllDigits)}); - writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); - writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Expiry"}); - writer.Write(_internal::XmlNode{ - _internal::XmlNodeType::Text, - std::string(), - options.ExpiresOn.ToString( - Azure::DateTime::DateFormat::Rfc3339, - Azure::DateTime::TimeFractionFormat::AllDigits)}); - writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); + if (options.StartsOn.HasValue()) + { + writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Start"}); + writer.Write(_internal::XmlNode{ + _internal::XmlNodeType::Text, + std::string(), + options.StartsOn.Value().ToString( + Azure::DateTime::DateFormat::Rfc3339, + Azure::DateTime::TimeFractionFormat::AllDigits)}); + writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); + } + if (options.ExpiresOn.HasValue()) + { + writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Expiry"}); + writer.Write(_internal::XmlNode{ + _internal::XmlNodeType::Text, + std::string(), + options.ExpiresOn.Value().ToString( + Azure::DateTime::DateFormat::Rfc3339, + Azure::DateTime::TimeFractionFormat::AllDigits)}); + writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag}); + } writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Permission"}); writer.Write( _internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Permissions}); diff --git a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp index c745bf8b8..a8fb1367a 100644 --- a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp +++ b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp @@ -112,25 +112,15 @@ namespace Azure { namespace Storage { namespace Queues { const CreateQueueOptions& options = CreateQueueOptions(), const Azure::Core::Context& context = Azure::Core::Context()) const; - /** - * @brief Marks the specified queue for deletion. - * - * @param options Optional parameters to execute this function. - * @param context Context for cancelling long running operations. - * @return A DeleteQueueResult if successful. - */ - Azure::Response Delete( - const DeleteQueueOptions& options = DeleteQueueOptions(), - const Azure::Core::Context& context = Azure::Core::Context()) const; - /** * @brief Marks the specified queue for deletion if it exists. * * @param options Optional parameters to execute this function. * @param context Context for cancelling long running operations. - * @return A DeleteQueueResult if successful. + * @return DeleteQueueResult.Deleted will be true if successful, false if the queue doesn't + * exist. */ - Azure::Response DeleteIfExists( + Azure::Response Delete( const DeleteQueueOptions& options = DeleteQueueOptions(), const Azure::Core::Context& context = Azure::Core::Context()) const; diff --git a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp index 4fd36f450..6e268cb1d 100644 --- a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp +++ b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp @@ -17,6 +17,48 @@ namespace Azure { namespace Storage { namespace Queues { + /** + * @brief API version for Storage Queue service. + */ + class ServiceVersion final { + public: + /** + * @brief Construct a new Service Version object + * + * @param version The string version for Storage Queue Service. + */ + explicit ServiceVersion(std::string version) : m_version(std::move(version)) {} + + /** + * @brief Enable comparing between two versions. + * + * @param other Another service version to be compared. + */ + bool operator==(const ServiceVersion& other) const { return m_version == other.m_version; } + + /** + * @brief Enable comparing between two versions. + * + * @param other Another service version to be compared. + */ + bool operator!=(const ServiceVersion& other) const { return !(*this == other); } + + /** + * @brief Returns string representation. + * + */ + std::string const& ToString() const { return m_version; } + + /** + * @brief API version 2018-03-28. + * + */ + AZ_STORAGE_QUEUES_DLLEXPORT const static ServiceVersion V2018_03_28; + + private: + std::string m_version; + }; + struct QueueClientOptions final : Azure::Core::_internal::ClientOptions { /** @@ -31,7 +73,7 @@ namespace Azure { namespace Storage { namespace Queues { /** * API version used by this client. */ - std::string ApiVersion = _detail::ApiVersion; + ServiceVersion ApiVersion{_detail::ApiVersion}; }; /** @@ -132,11 +174,6 @@ namespace Azure { namespace Storage { namespace Queues { { }; - /** - * @brief A TTL value representing the queue message does not expire. - */ - constexpr static std::chrono::seconds MessageNeverExpires{-1}; - /** * Optional parameters for #Azure::Storage::Queues::QueueClient::EnqueueMessages. */ @@ -152,6 +189,11 @@ namespace Azure { namespace Storage { namespace Queues { * positive number, as well as MessageNeverExpires indicating that the message does not expire */ Azure::Nullable TimeToLive; + + /** + * @brief A TTL value representing the queue message does not expire. + */ + AZ_STORAGE_QUEUES_DLLEXPORT const static std::chrono::seconds MessageNeverExpires; }; /** diff --git a/sdk/storage/azure-storage-queues/sample/queue_encode_message.cpp b/sdk/storage/azure-storage-queues/sample/queue_encode_message.cpp new file mode 100644 index 000000000..ad16eb043 --- /dev/null +++ b/sdk/storage/azure-storage-queues/sample/queue_encode_message.cpp @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include +#include + +#include +#include + +#include "samples_common.hpp" + +SAMPLE(QueuesEncodeMessage, QueuesEncodeMessage) +void QueuesEncodeMessage() +{ + using namespace Azure::Storage::Queues; + std::string QueueName = "sample-queue"; + + auto queueClient = QueueClient::CreateFromConnectionString(GetConnectionString(), QueueName); + queueClient.CreateIfNotExists(); + + // Binary message cannot be enqueued directly, we encode the message with Base64. + std::vector binaryMessage{0x00, 0x01, 0x02, 0x03}; + std::string encodedMessage = Azure::Core::Convert::Base64Encode(binaryMessage); + queueClient.EnqueueMessage(encodedMessage); + + auto receiveMessagesResult = queueClient.ReceiveMessages().Value; + auto& receivedMessage = receiveMessagesResult.Messages[0]; + + std::cout << receivedMessage.MessageText << std::endl; + + // Sometimes messages are Base64 encoded. Some other queue clients automatically encode the + // message even it's in plaintext. We need to decode the message in that case. + auto decodedMessage = Azure::Core::Convert::Base64Decode(receivedMessage.MessageText); + assert(decodedMessage == binaryMessage); +} diff --git a/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp b/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp index 64746f6b2..0c2d70f90 100644 --- a/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp +++ b/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp @@ -20,6 +20,15 @@ void ProducerFunc() std::string msg = "Message " + std::to_string(i); queueClient.EnqueueMessage(msg); } + + for (int i = 5; i < 10; ++i) + { + std::string msg = "Message " + std::to_string(i); + EnqueueMessageOptions options; + options.TimeToLive = std::chrono::seconds(60 * 60 * 24); + options.VisibilityTimeout = std::chrono::seconds(1); + queueClient.EnqueueMessage(msg, options); + } } void ConsumerFunc() @@ -29,12 +38,12 @@ void ConsumerFunc() int counter = 0; while (counter < 5) { - auto msgResponse = queueClient.ReceiveMessages(); - if (!msgResponse.Value.Messages.empty()) + auto receiveMessagesResult = queueClient.ReceiveMessages().Value; + if (!receiveMessagesResult.Messages.empty()) { - auto& msg = msgResponse.Value.Messages[0]; + auto& msg = receiveMessagesResult.Messages[0]; - std::cout << msg.Body << std::endl; + std::cout << msg.MessageText << std::endl; ++counter; queueClient.DeleteMessage(msg.MessageId, msg.PopReceipt); @@ -52,10 +61,10 @@ void ConsumerFunc2() { ReceiveMessagesOptions receiveOptions; receiveOptions.MaxMessages = 3; - auto msgResponse = queueClient.ReceiveMessages(receiveOptions); - for (auto& msg : msgResponse.Value.Messages) + auto receiveMessagesResult = queueClient.ReceiveMessages(receiveOptions).Value; + for (auto& msg : receiveMessagesResult.Messages) { - std::cout << msg.Body << std::endl; + std::cout << msg.MessageText << std::endl; ++counter; auto updateResponse @@ -75,4 +84,5 @@ void QueuesGettingStarted() ProducerFunc(); ConsumerFunc(); + ConsumerFunc2(); } diff --git a/sdk/storage/azure-storage-queues/src/queue_client.cpp b/sdk/storage/azure-storage-queues/src/queue_client.cpp index 3a7cfa1af..0145a49b8 100644 --- a/sdk/storage/azure-storage-queues/src/queue_client.cpp +++ b/sdk/storage/azure-storage-queues/src/queue_client.cpp @@ -49,7 +49,7 @@ namespace Azure { namespace Storage { namespace Queues { m_queueUrl.GetHost(), newOptions.SecondaryHostForRetryReads)); perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>()); perOperationPolicies.emplace_back( - std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion)); + std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion.ToString())); m_pipeline = std::make_shared( newOptions, _internal::QueueServicePackageName, @@ -77,7 +77,7 @@ namespace Azure { namespace Storage { namespace Queues { credential, tokenContext)); } perOperationPolicies.emplace_back( - std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion)); + std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString())); m_pipeline = std::make_shared( options, _internal::QueueServicePackageName, @@ -95,7 +95,7 @@ namespace Azure { namespace Storage { namespace Queues { m_queueUrl.GetHost(), options.SecondaryHostForRetryReads)); perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>()); perOperationPolicies.emplace_back( - std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion)); + std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString())); m_pipeline = std::make_shared( options, _internal::QueueServicePackageName, @@ -139,18 +139,11 @@ namespace Azure { namespace Storage { namespace Queues { const Azure::Core::Context& context) const { (void)options; - _detail::QueueRestClient::Queue::DeleteQueueOptions protocolLayerOptions; - return _detail::QueueRestClient::Queue::Delete( - *m_pipeline, m_queueUrl, protocolLayerOptions, context); - } - - Azure::Response QueueClient::DeleteIfExists( - const DeleteQueueOptions& options, - const Azure::Core::Context& context) const - { try { - return Delete(options, context); + _detail::QueueRestClient::Queue::DeleteQueueOptions protocolLayerOptions; + return _detail::QueueRestClient::Queue::Delete( + *m_pipeline, m_queueUrl, protocolLayerOptions, context); } catch (StorageException& e) { @@ -216,7 +209,7 @@ namespace Azure { namespace Storage { namespace Queues { auto messagesUrl = m_queueUrl; messagesUrl.AppendPath("messages"); _detail::QueueRestClient::Queue::EnqueueMessageOptions protocolLayerOptions; - protocolLayerOptions.Body = std::move(messageText); + protocolLayerOptions.MessageText = std::move(messageText); protocolLayerOptions.TimeToLive = options.TimeToLive; protocolLayerOptions.VisibilityTimeout = options.VisibilityTimeout; return _detail::QueueRestClient::Queue::EnqueueMessage( @@ -262,7 +255,7 @@ namespace Azure { namespace Storage { namespace Queues { if (options.MessageText.HasValue()) { _detail::QueueRestClient::Queue::UpdateMessageOptions protocolLayerOptions; - protocolLayerOptions.Body = options.MessageText.Value(); + protocolLayerOptions.MessageText = options.MessageText.Value(); protocolLayerOptions.PopReceipt = popReceipt; protocolLayerOptions.VisibilityTimeout = visibilityTimeout; return _detail::QueueRestClient::Queue::UpdateMessage( diff --git a/sdk/storage/azure-storage-queues/src/queue_options.cpp b/sdk/storage/azure-storage-queues/src/queue_options.cpp new file mode 100644 index 000000000..e1054a15b --- /dev/null +++ b/sdk/storage/azure-storage-queues/src/queue_options.cpp @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include "azure/storage/queues/queue_options.hpp" + +namespace Azure { namespace Storage { namespace Queues { + + const ServiceVersion ServiceVersion::V2018_03_28(std::string("2018-03-28")); + const std::chrono::seconds EnqueueMessageOptions::MessageNeverExpires{-1}; + +}}} // namespace Azure::Storage::Queues diff --git a/sdk/storage/azure-storage-queues/src/queue_service_client.cpp b/sdk/storage/azure-storage-queues/src/queue_service_client.cpp index de98dfa50..ca3b25350 100644 --- a/sdk/storage/azure-storage-queues/src/queue_service_client.cpp +++ b/sdk/storage/azure-storage-queues/src/queue_service_client.cpp @@ -48,7 +48,7 @@ namespace Azure { namespace Storage { namespace Queues { m_serviceUrl.GetHost(), newOptions.SecondaryHostForRetryReads)); perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>()); perOperationPolicies.emplace_back( - std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion)); + std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion.ToString())); m_pipeline = std::make_shared( newOptions, _internal::QueueServicePackageName, @@ -76,7 +76,7 @@ namespace Azure { namespace Storage { namespace Queues { credential, tokenContext)); } perOperationPolicies.emplace_back( - std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion)); + std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString())); m_pipeline = std::make_shared( options, _internal::QueueServicePackageName, @@ -96,7 +96,7 @@ namespace Azure { namespace Storage { namespace Queues { m_serviceUrl.GetHost(), options.SecondaryHostForRetryReads)); perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>()); perOperationPolicies.emplace_back( - std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion)); + std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString())); m_pipeline = std::make_shared( options, _internal::QueueServicePackageName, diff --git a/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp b/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp index adef49ac9..1c5b50a51 100644 --- a/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp +++ b/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp @@ -24,7 +24,7 @@ namespace Azure { namespace Storage { namespace Test { auto peekedMessage = queueClient.PeekMessages().Value.Messages[0]; - EXPECT_EQ(peekedMessage.Body, message); + EXPECT_EQ(peekedMessage.MessageText, message); EXPECT_EQ(peekedMessage.MessageId, res.MessageId); EXPECT_EQ(peekedMessage.InsertedOn, res.InsertedOn); EXPECT_EQ(peekedMessage.ExpiresOn, res.ExpiresOn); @@ -51,7 +51,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_TRUE(queueClient.PeekMessages().Value.Messages.empty()); enqueueOptions = Queues::EnqueueMessageOptions(); - enqueueOptions.TimeToLive = Queues::MessageNeverExpires; + enqueueOptions.TimeToLive = Queues::EnqueueMessageOptions::MessageNeverExpires; res = queueClient.EnqueueMessage(message, enqueueOptions).Value; const Azure::DateTime neverExpireDateTime = Azure::DateTime::Parse( @@ -83,7 +83,7 @@ namespace Azure { namespace Storage { namespace Test { receiveOptions.VisibilityTimeout = std::chrono::seconds(1); auto receivedMessage = queueClient.ReceiveMessages(receiveOptions).Value.Messages[0]; - EXPECT_EQ(receivedMessage.Body, message); + EXPECT_EQ(receivedMessage.MessageText, message); EXPECT_EQ(receivedMessage.MessageId, res.MessageId); EXPECT_EQ(receivedMessage.InsertedOn, res.InsertedOn); EXPECT_EQ(receivedMessage.ExpiresOn, res.ExpiresOn); @@ -124,17 +124,17 @@ namespace Azure { namespace Storage { namespace Test { receivedMessages = queueClient.ReceiveMessages(receiveOptions).Value.Messages; EXPECT_EQ(receivedMessages.size(), static_cast(receiveOptions.MaxMessages.Value())); - EXPECT_EQ(receivedMessages[0].Body, message1); + EXPECT_EQ(receivedMessages[0].MessageText, message1); receivedMessages = queueClient.ReceiveMessages().Value.Messages; EXPECT_EQ(receivedMessages.size(), size_t(1)); - EXPECT_EQ(receivedMessages[0].Body, message2); + EXPECT_EQ(receivedMessages[0].MessageText, message2); receiveOptions.MaxMessages = 10; receivedMessages = queueClient.ReceiveMessages(receiveOptions).Value.Messages; EXPECT_EQ(receivedMessages.size(), size_t(2)); - EXPECT_EQ(receivedMessages[0].Body, message3); - EXPECT_EQ(receivedMessages[1].Body, message4); + EXPECT_EQ(receivedMessages[0].MessageText, message3); + EXPECT_EQ(receivedMessages[1].MessageText, message4); queueClient.Delete(); } @@ -152,13 +152,11 @@ namespace Azure { namespace Storage { namespace Test { auto peekedMessage = queueClient.PeekMessages().Value.Messages[0]; - EXPECT_EQ(peekedMessage.Body, message); + EXPECT_EQ(peekedMessage.MessageText, message); EXPECT_EQ(peekedMessage.MessageId, res.MessageId); EXPECT_EQ(peekedMessage.InsertedOn, res.InsertedOn); EXPECT_EQ(peekedMessage.ExpiresOn, res.ExpiresOn); EXPECT_EQ(peekedMessage.DequeueCount, 0); - EXPECT_TRUE(peekedMessage.PopReceipt.empty()); - EXPECT_EQ(peekedMessage.NextVisibleOn, Azure::DateTime()); queueClient.Delete(); } @@ -189,19 +187,19 @@ namespace Azure { namespace Storage { namespace Test { peekedMessages = queueClient.PeekMessages(peekOptions).Value.Messages; EXPECT_EQ(peekedMessages.size(), static_cast(peekOptions.MaxMessages.Value())); - EXPECT_EQ(peekedMessages[0].Body, message1); + EXPECT_EQ(peekedMessages[0].MessageText, message1); peekedMessages = queueClient.PeekMessages().Value.Messages; EXPECT_EQ(peekedMessages.size(), size_t(1)); - EXPECT_EQ(peekedMessages[0].Body, message1); + EXPECT_EQ(peekedMessages[0].MessageText, message1); peekOptions.MaxMessages = 10; peekedMessages = queueClient.PeekMessages(peekOptions).Value.Messages; EXPECT_EQ(peekedMessages.size(), size_t(4)); - EXPECT_EQ(peekedMessages[0].Body, message1); - EXPECT_EQ(peekedMessages[1].Body, message2); - EXPECT_EQ(peekedMessages[2].Body, message3); - EXPECT_EQ(peekedMessages[3].Body, message4); + EXPECT_EQ(peekedMessages[0].MessageText, message1); + EXPECT_EQ(peekedMessages[1].MessageText, message2); + EXPECT_EQ(peekedMessages[2].MessageText, message3); + EXPECT_EQ(peekedMessages[3].MessageText, message4); queueClient.Delete(); } @@ -222,7 +220,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_TRUE(IsValidTime(updateRes.NextVisibleOn)); auto peekedMessage = queueClient.PeekMessages().Value.Messages[0]; - EXPECT_EQ(peekedMessage.Body, message); + EXPECT_EQ(peekedMessage.MessageText, message); Queues::UpdateMessageOptions updateOptions; updateOptions.MessageText = updatedMessage; @@ -232,7 +230,7 @@ namespace Azure { namespace Storage { namespace Test { std::this_thread::sleep_for(std::chrono::milliseconds(1200)); peekedMessage = queueClient.PeekMessages().Value.Messages[0]; - EXPECT_EQ(peekedMessage.Body, updatedMessage); + EXPECT_EQ(peekedMessage.MessageText, updatedMessage); queueClient.Delete(); } diff --git a/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp b/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp index f9d7b3f81..234cd9e0b 100644 --- a/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp +++ b/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp @@ -10,7 +10,10 @@ namespace Azure { namespace Storage { namespace Queues { namespace Models { bool operator==(const SignedIdentifier& lhs, const SignedIdentifier& rhs) { - return lhs.Id == rhs.Id && lhs.StartsOn == rhs.StartsOn && lhs.ExpiresOn == rhs.ExpiresOn + return lhs.Id == rhs.Id && lhs.StartsOn.HasValue() == rhs.StartsOn.HasValue() + && (!lhs.StartsOn.HasValue() || lhs.StartsOn.Value() == rhs.StartsOn.Value()) + && lhs.ExpiresOn.HasValue() == rhs.ExpiresOn.HasValue() + && (!lhs.ExpiresOn.HasValue() || lhs.ExpiresOn.Value() == rhs.ExpiresOn.Value()) && lhs.Permissions == rhs.Permissions; } @@ -64,7 +67,7 @@ namespace Azure { namespace Storage { namespace Test { queueClient = Azure::Storage::Queues::QueueClient::CreateFromConnectionString( StandardStorageConnectionString(), LowercaseRandomString()); { - auto response = queueClient.DeleteIfExists(); + auto response = queueClient.Delete(); EXPECT_FALSE(response.Value.Deleted); } { @@ -80,7 +83,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(response.Value.Created); } { - auto response = queueClient.DeleteIfExists(); + auto response = queueClient.Delete(); EXPECT_TRUE(response.Value.Deleted); } } @@ -130,18 +133,36 @@ namespace Azure { namespace Storage { namespace Test { queueClient.Create(); std::vector signedIdentifiers; - Queues::Models::SignedIdentifier identifier; - identifier.Id = RandomString(64); - identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(1); - identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(1); - identifier.Permissions = "r"; - signedIdentifiers.emplace_back(identifier); - identifier.Id = RandomString(64); - identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(2); - identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(2); - /* cspell:disable-next-line */ - identifier.Permissions = "raup"; - signedIdentifiers.emplace_back(identifier); + { + Queues::Models::SignedIdentifier identifier; + identifier.Id = RandomString(64); + identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(1); + identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(1); + identifier.Permissions = "r"; + signedIdentifiers.emplace_back(identifier); + } + { + Queues::Models::SignedIdentifier identifier; + identifier.Id = RandomString(64); + identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(2); + identifier.ExpiresOn.Reset(); + /* cspell:disable-next-line */ + identifier.Permissions = "raup"; + signedIdentifiers.emplace_back(identifier); + } + { + Queues::Models::SignedIdentifier identifier; + identifier.Id = RandomString(64); + identifier.Permissions = "r"; + signedIdentifiers.emplace_back(identifier); + } + { + Queues::Models::SignedIdentifier identifier; + identifier.Id = RandomString(64); + identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(1); + identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(1); + signedIdentifiers.emplace_back(identifier); + } EXPECT_NO_THROW(queueClient.SetAccessPolicy(signedIdentifiers)); diff --git a/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp b/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp index 980a86e6c..29fce5f70 100644 --- a/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp +++ b/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp @@ -84,7 +84,7 @@ namespace Azure { namespace Storage { namespace Test { auto queueServiceClient = Queues::QueueServiceClient(queueServiceUrl + sas); const std::string newQueueName = LowercaseRandomString(); EXPECT_NO_THROW(queueServiceClient.CreateQueue(newQueueName)); - queueServiceClient0.GetQueueClient(newQueueName).DeleteIfExists(); + queueServiceClient0.GetQueueClient(newQueueName).Delete(); }; auto verifyQueueDelete = [&](const std::string& sas) {