diff --git a/sdk/storage/azqueue/assets.json b/sdk/storage/azqueue/assets.json index 3f6b541dbce6..3b1cfb256fa1 100644 --- a/sdk/storage/azqueue/assets.json +++ b/sdk/storage/azqueue/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/storage/azqueue", - "Tag": "go/storage/azqueue_d0cbfd994e" + "Tag": "go/storage/azqueue_250a75f53b" } diff --git a/sdk/storage/azqueue/internal/base/clients.go b/sdk/storage/azqueue/internal/base/clients.go index bcc37cc9b106..a979ac5444d5 100644 --- a/sdk/storage/azqueue/internal/base/clients.go +++ b/sdk/storage/azqueue/internal/base/clients.go @@ -39,7 +39,7 @@ func NewServiceClient(queueURL string, pipeline runtime.Pipeline, sharedKey *exp func NewQueueClient(queueURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *CompositeClient[generated.QueueClient, generated.MessagesClient] { return &CompositeClient[generated.QueueClient, generated.MessagesClient]{ innerT: generated.NewQueueClient(queueURL, pipeline), - innerU: generated.NewMessagesClient(queueURL, pipeline), + innerU: generated.NewMessagesClient(runtime.JoinPaths(queueURL, "messages"), pipeline), sharedKey: sharedKey, } } diff --git a/sdk/storage/azqueue/internal/testcommon/common.go b/sdk/storage/azqueue/internal/testcommon/common.go index 625a21ae4c86..e38db6fd2f25 100644 --- a/sdk/storage/azqueue/internal/testcommon/common.go +++ b/sdk/storage/azqueue/internal/testcommon/common.go @@ -24,7 +24,8 @@ import ( ) const ( - QueuePrefix = "goq" + QueuePrefix = "goq" + QueueDefaultData = "this is some default data" ) func GenerateQueueName(testName string) string { diff --git a/sdk/storage/azqueue/models.go b/sdk/storage/azqueue/models.go index 008b4d204285..6d50c7b289a8 100644 --- a/sdk/storage/azqueue/models.go +++ b/sdk/storage/azqueue/models.go @@ -248,10 +248,6 @@ type GetAccessPolicyOptions struct { } func (o *GetAccessPolicyOptions) format() *generated.QueueClientGetAccessPolicyOptions { - if o == nil { - return nil - } - return nil } @@ -314,7 +310,15 @@ func (o *GetQueuePropertiesOptions) format() *generated.QueueClientGetProperties // EnqueueMessageOptions contains the optional parameters for the QueueClient.EnqueueMessage method. type EnqueueMessageOptions struct { - TimeToLive *int32 + // Specifies the time-to-live interval for the message, in seconds. + // The time-to-live may be any positive number or -1 for infinity. + // If this parameter is omitted, the default time-to-live is 7 days. + TimeToLive *int32 + // If not specified, the default value is 0. + // Specifies the new visibility timeout value, in seconds, relative to server time. + // The value must be larger than or equal to 0, and cannot be larger than 7 days. + // The visibility timeout of a message cannot be set to a value later than the expiry time. + // VisibilityTimeout should be set to a value smaller than the time-to-live value. VisibilityTimeout *int32 } @@ -329,8 +333,13 @@ func (o *EnqueueMessageOptions) format() *generated.MessagesClientEnqueueOptions // --------------------------------------------------------------------------------------------------------------------- -// DequeueMessageOptions contains the optional parameters for the QueueClient.EnqueueMessage method. +// DequeueMessageOptions contains the optional parameters for the QueueClient.DequeueMessage method. type DequeueMessageOptions struct { + // If not specified, the default value is 0. Specifies the new visibility timeout value, + // in seconds, relative to server time. The value must be larger than or equal to 0, and cannot be + // larger than 7 days. The visibility timeout of a message cannot be + // set to a value later than the expiry time. VisibilityTimeout + // should be set to a value smaller than the time-to-live value. VisibilityTimeout *int32 } @@ -348,7 +357,16 @@ func (o *DequeueMessageOptions) format() *generated.MessagesClientDequeueOptions // DequeueMessagesOptions contains the optional parameters for the QueueClient.DequeueMessages method. type DequeueMessagesOptions struct { - NumberOfMessages *int32 + // Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, + // up to a maximum of 32. If fewer messages are visible, the visible messages are returned. + // By default, a single message is retrieved from the queue with this operation. + NumberOfMessages *int32 + // If not specified, the default value is 30. Specifies the + // new visibility timeout value, in seconds, relative to server time. + // The value must be larger than or equal to 1, and cannot be + // larger than 7 days. The visibility timeout of a message cannot be + // set to a value later than the expiry time. VisibilityTimeout + // should be set to a value smaller than the time-to-live value. VisibilityTimeout *int32 } @@ -369,10 +387,13 @@ type UpdateMessageOptions struct { } func (o *UpdateMessageOptions) format() *generated.MessageIDClientUpdateOptions { + defaultVT := to.Ptr(int32(0)) if o == nil { - return nil + return &generated.MessageIDClientUpdateOptions{Visibilitytimeout: defaultVT} + } + if o.VisibilityTimeout == nil { + o.VisibilityTimeout = defaultVT } - return &generated.MessageIDClientUpdateOptions{Visibilitytimeout: o.VisibilityTimeout} } @@ -398,10 +419,6 @@ type PeekMessageOptions struct { func (o *PeekMessageOptions) format() *generated.MessagesClientPeekOptions { numberOfMessages := int32(1) - if o == nil { - return &generated.MessagesClientPeekOptions{NumberOfMessages: &numberOfMessages} - } - return &generated.MessagesClientPeekOptions{NumberOfMessages: &numberOfMessages} } diff --git a/sdk/storage/azqueue/queue_client.go b/sdk/storage/azqueue/queue_client.go index 62dff06c4a4b..315b54e8364f 100644 --- a/sdk/storage/azqueue/queue_client.go +++ b/sdk/storage/azqueue/queue_client.go @@ -32,6 +32,10 @@ func (q *QueueClient) messagesClient() *generated.MessagesClient { return messages } +func (q *QueueClient) getMessageIDURL(messageID string) string { + return runtime.JoinPaths(q.queueClient().Endpoint(), "messages", messageID) +} + func (q *QueueClient) sharedKey() *SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.QueueClient, generated.MessagesClient])(q)) } @@ -171,8 +175,7 @@ func (q *QueueClient) DequeueMessage(ctx context.Context, o *DequeueMessageOptio func (q *QueueClient) UpdateMessage(ctx context.Context, messageID string, popReceipt string, content string, o *UpdateMessageOptions) (UpdateMessageResponse, error) { opts := o.format() message := generated.QueueMessage{MessageText: &content} - messageURL := runtime.JoinPaths(q.queueClient().Endpoint(), messageID) - messageClient := generated.NewMessageIDClient(messageURL, q.queueClient().Pipeline()) + messageClient := generated.NewMessageIDClient(q.getMessageIDURL(messageID), q.queueClient().Pipeline()) resp, err := messageClient.Update(ctx, popReceipt, message, opts) return resp, err } @@ -181,8 +184,7 @@ func (q *QueueClient) UpdateMessage(ctx context.Context, messageID string, popRe // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-message2. func (q *QueueClient) DeleteMessage(ctx context.Context, messageID string, popReceipt string, o *DeleteMessageOptions) (DeleteMessageResponse, error) { opts := o.format() - messageURL := runtime.JoinPaths(q.queueClient().Endpoint(), messageID) - messageClient := generated.NewMessageIDClient(messageURL, q.queueClient().Pipeline()) + messageClient := generated.NewMessageIDClient(q.getMessageIDURL(messageID), q.queueClient().Pipeline()) resp, err := messageClient.Delete(ctx, popReceipt, opts) return resp, err } diff --git a/sdk/storage/azqueue/queue_client_test.go b/sdk/storage/azqueue/queue_client_test.go index b6b8b03b0683..e5ae2477b354 100644 --- a/sdk/storage/azqueue/queue_client_test.go +++ b/sdk/storage/azqueue/queue_client_test.go @@ -8,11 +8,16 @@ package azqueue_test import ( "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/internal/shared" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/internal/testcommon" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/queueerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/sas" "github.com/stretchr/testify/require" + "os" "strconv" "time" ) @@ -32,6 +37,50 @@ func (s *RecordedTestSuite) TestQueueCreateQueue() { _require.NotZero(resp) } +func (s *UnrecordedTestSuite) TestQueueClientFromConnectionString() { + _require := require.New(s.T()) + testName := s.T().Name() + + accountName, _ := testcommon.GetAccountInfo(testcommon.TestAccountDefault) + connectionString := testcommon.GetConnectionString(testcommon.TestAccountDefault) + + parsedConnStr, err := shared.ParseConnectionString(connectionString) + _require.Nil(err) + _require.Equal(parsedConnStr.ServiceURL, "https://"+accountName+".queue.core.windows.net/") + + queueName := testcommon.GenerateQueueName(testName) + + sharedKeyCred, err := azqueue.NewSharedKeyCredential(parsedConnStr.AccountName, parsedConnStr.AccountKey) + _require.Nil(err) + + qClient, err := azqueue.NewQueueClientWithSharedKeyCredential( + runtime.JoinPaths(parsedConnStr.ServiceURL, queueName), sharedKeyCred, nil) + _require.Nil(err) + + _, err = qClient.Create(context.Background(), nil) + _require.Nil(err) +} + +func (s *UnrecordedTestSuite) TestQueueClientFromConnectionString1() { + _require := require.New(s.T()) + testName := s.T().Name() + + accountName, _ := testcommon.GetAccountInfo(testcommon.TestAccountDefault) + connectionString := testcommon.GetConnectionString(testcommon.TestAccountDefault) + + parsedConnStr, err := shared.ParseConnectionString(connectionString) + _require.Nil(err) + _require.Equal(parsedConnStr.ServiceURL, "https://"+accountName+".queue.core.windows.net/") + + queueName := testcommon.GenerateQueueName(testName) + + qClient, err := azqueue.NewQueueClientFromConnectionString(connectionString, queueName, nil) + _require.Nil(err) + + _, err = qClient.Create(context.Background(), nil) + _require.Nil(err) +} + func (s *RecordedTestSuite) TestQueueCreateQueueWithMetadata() { _require := require.New(s.T()) svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) @@ -87,6 +136,26 @@ func (s *RecordedTestSuite) TestQueueSetMetadata() { _require.Nil(err) } +func (s *RecordedTestSuite) TestQueueSetMetadataNilOptions() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + _, err = queueClient.SetMetadata(context.Background(), nil) + _require.Nil(err) + + _, err = queueClient.GetProperties(context.Background(), nil) + _require.Nil(err) +} + func (s *RecordedTestSuite) TestQueueSetEmptyACL() { _require := require.New(s.T()) svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) @@ -105,6 +174,23 @@ func (s *RecordedTestSuite) TestQueueSetEmptyACL() { _require.Nil(err) } +func (s *RecordedTestSuite) TestQueueSetACLNil() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + _, err = queueClient.SetAccessPolicy(context.Background(), nil) + _require.Nil(err) +} + func (s *RecordedTestSuite) TestQueueSetEmptyACL2() { _require := require.New(s.T()) svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) @@ -486,9 +572,887 @@ func (s *RecordedTestSuite) TestQueueSetPermissionsSignedIdentifierTooLong() { testcommon.ValidateQueueErrorCode(_require, err, queueerror.InvalidXMLDocument) } -//TODO: TestPutMessage -//TODO: TestGetMessages -//TODO: TestPeekMessages -//TODO: TestDeleteMessage -//TODO: TestClearMessages -//TODO: TestUpdateMessage +func (s *RecordedTestSuite) TestEnqueueMessageBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + + } +} + +func (s *RecordedTestSuite) TestEnqueueMessageWithTimeToLive() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.EnqueueMessageOptions{TimeToLive: to.Ptr(int32(1))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, &opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestEnqueueMessageWithTimeToLiveExpired() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.EnqueueMessageOptions{TimeToLive: to.Ptr(int32(1))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, &opts) + _require.Nil(err) + + time.Sleep(time.Second * 2) + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(0, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestEnqueueMessageWithInfiniteTimeToLive() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.EnqueueMessageOptions{TimeToLive: to.Ptr(int32(-1))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, &opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestEnqueueMessageWithVisibilityTimeout() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.EnqueueMessageOptions{VisibilityTimeout: to.Ptr(int32(1))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, &opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestEnqueueMessageWithVisibilityTimeoutSmallerThanTTL() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.EnqueueMessageOptions{TimeToLive: to.Ptr(int32(2)), VisibilityTimeout: to.Ptr(int32(1))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, &opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestEnqueueMessageWithVisibilityTimeoutLargerThanTTL() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.EnqueueMessageOptions{TimeToLive: to.Ptr(int32(1)), VisibilityTimeout: to.Ptr(int32(2))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, &opts) + // cannot have visibility timeout be greater than ttl + testcommon.ValidateQueueErrorCode(_require, err, queueerror.InvalidQueryParameterValue) +} + +func (s *RecordedTestSuite) TestDequeueMessageBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // dequeue 4 messages + for i := 0; i < 4; i++ { + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(1, len(resp.QueueMessagesList)) + _require.NotNil(resp.QueueMessagesList[0].MessageID) + } + // should be 0 now + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Equal(0, len(resp.QueueMessagesList)) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestDequeueMessageWithVisibilityTimeout() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := azqueue.DequeueMessageOptions{VisibilityTimeout: to.Ptr(int32(1))} + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + + resp, err := queueClient.DequeueMessage(context.Background(), &opts) + _require.Nil(err) + _require.NotNil(resp.QueueMessagesList[0].TimeNextVisible) +} + +func (s *RecordedTestSuite) TestDequeueMessagesBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // dequeue 4 messages + opts := azqueue.DequeueMessagesOptions{NumberOfMessages: to.Ptr(int32(4))} + resp, err := queueClient.DequeueMessages(context.Background(), &opts) + _require.Nil(err) + _require.Equal(4, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestDequeueMessagesDefault() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // should dequeue only 1 message (since default num of messages is 1 when not specified) + resp, err := queueClient.DequeueMessages(context.Background(), nil) + _require.Nil(err) + _require.Equal(1, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestDequeueMessagesWithVisibilityTimeout() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // dequeue 4 messages + opts := azqueue.DequeueMessagesOptions{NumberOfMessages: to.Ptr(int32(4)), VisibilityTimeout: to.Ptr(int32(2))} + _, err = queueClient.DequeueMessages(context.Background(), &opts) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestDequeueMessagesWithNumMessagesLargerThan32() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 33 messages + for i := 0; i < 33; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + opts := azqueue.DequeueMessagesOptions{NumberOfMessages: to.Ptr(int32(33))} + _, err = queueClient.DequeueMessages(context.Background(), &opts) + // should fail + testcommon.ValidateQueueErrorCode(_require, err, queueerror.OutOfRangeQueryParameterValue) +} + +func (s *RecordedTestSuite) TestDequeueMessagesWithLeftovers() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 10 messages + for i := 0; i < 10; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // dequeue 5 messages + opts := azqueue.DequeueMessagesOptions{NumberOfMessages: to.Ptr(int32(5))} + resp, err := queueClient.DequeueMessages(context.Background(), &opts) + _require.Nil(err) + _require.Equal(*resp.QueueMessagesList[0].MessageText, testcommon.QueueDefaultData) + _require.Equal(5, len(resp.QueueMessagesList)) + + // dequeue other 5 messages + resp, err = queueClient.DequeueMessages(context.Background(), &opts) + _require.Nil(err) + _require.Equal(*resp.QueueMessagesList[0].MessageText, testcommon.QueueDefaultData) + _require.Equal(5, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestPeekMessageBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // peek 4 messages + for i := 0; i < 4; i++ { + resp, err := queueClient.PeekMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(1, len(resp.QueueMessagesList)) + _require.NotNil(resp.QueueMessagesList[0].MessageID) + _require.Equal(*resp.QueueMessagesList[0].MessageText, testcommon.QueueDefaultData) + } + + opts := azqueue.DequeueMessagesOptions{NumberOfMessages: to.Ptr(int32(4))} + // should all still be there + resp, err := queueClient.DequeueMessages(context.Background(), &opts) + _require.Equal(4, len(resp.QueueMessagesList)) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestPeekMessagesBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // dequeue 4 messages + opts := azqueue.PeekMessagesOptions{NumberOfMessages: to.Ptr(int32(4))} + resp, err := queueClient.PeekMessages(context.Background(), &opts) + _require.Nil(err) + _require.Equal(4, len(resp.QueueMessagesList)) + + opts1 := azqueue.DequeueMessagesOptions{NumberOfMessages: to.Ptr(int32(4))} + // should all still be there + resp1, err := queueClient.DequeueMessages(context.Background(), &opts1) + _require.Equal(4, len(resp1.QueueMessagesList)) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestPeekMessagesDefault() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // should peek only 1 message (since default num of messages is 1 when not specified) + resp, err := queueClient.PeekMessages(context.Background(), nil) + _require.Nil(err) + _require.Equal(1, len(resp.QueueMessagesList)) + _require.Equal(*resp.QueueMessagesList[0].MessageText, testcommon.QueueDefaultData) +} + +func (s *RecordedTestSuite) TestPeekMessagesWithNumMessagesLargerThan32() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 33 messages + for i := 0; i < 33; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + opts := azqueue.PeekMessagesOptions{NumberOfMessages: to.Ptr(int32(33))} + _, err = queueClient.PeekMessages(context.Background(), &opts) + // should fail + testcommon.ValidateQueueErrorCode(_require, err, queueerror.OutOfRangeQueryParameterValue) +} + +func (s *RecordedTestSuite) TestDeleteMessageBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + var popReceipts []string + var messageIDs []string + // enqueue 4 messages + for i := 0; i < 4; i++ { + resp, err := queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + popReceipts = append(popReceipts, *resp.QueueMessagesList[0].PopReceipt) + messageIDs = append(messageIDs, *resp.QueueMessagesList[0].MessageID) + } + + // delete 4 messages + for i := 0; i < 4; i++ { + opts := &azqueue.DeleteMessageOptions{} + _, err := queueClient.DeleteMessage(context.Background(), messageIDs[i], popReceipts[i], opts) + _require.Nil(err) + } + // should be 0 now + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Equal(0, len(resp.QueueMessagesList)) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestDeleteMessageNilOptions() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + var popReceipts []string + var messageIDs []string + // enqueue 4 messages + for i := 0; i < 4; i++ { + resp, err := queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + popReceipts = append(popReceipts, *resp.QueueMessagesList[0].PopReceipt) + messageIDs = append(messageIDs, *resp.QueueMessagesList[0].MessageID) + } + + // delete 4 messages + for i := 0; i < 4; i++ { + _, err := queueClient.DeleteMessage(context.Background(), messageIDs[i], popReceipts[i], nil) + _require.Nil(err) + } + // should be 0 now + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Equal(0, len(resp.QueueMessagesList)) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestDeleteMessageDoesNotExist() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + resp, err := queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + popReceipt := *resp.QueueMessagesList[0].PopReceipt + messageID := *resp.QueueMessagesList[0].MessageID + + opts := &azqueue.DeleteMessageOptions{} + _, err = queueClient.DeleteMessage(context.Background(), messageID, popReceipt, opts) + _require.Nil(err) + + // should fail since we already deleted it + _, err = queueClient.DeleteMessage(context.Background(), messageID, popReceipt, opts) + _require.NotNil(err) + testcommon.ValidateQueueErrorCode(_require, err, queueerror.MessageNotFound) +} + +func (s *RecordedTestSuite) TestClearMessagesBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // delete the queue's messages + opts := azqueue.ClearMessagesOptions{} + _, err = queueClient.ClearMessages(context.Background(), &opts) + _require.Nil(err) + + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(0, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestClearMessagesNilOptions() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // delete the queue's messages + _, err = queueClient.ClearMessages(context.Background(), nil) + _require.Nil(err) + + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(0, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestClearMessagesMoreThan32() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + // enqueue 33 messages + for i := 0; i < 33; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // delete the queue's messages + opts := azqueue.ClearMessagesOptions{} + _, err = queueClient.ClearMessages(context.Background(), &opts) + _require.Nil(err) + + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(0, len(resp.QueueMessagesList)) +} + +func (s *RecordedTestSuite) TestUpdateMessageBasic() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + resp, err := queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + popReceipt := *resp.QueueMessagesList[0].PopReceipt + messageID := *resp.QueueMessagesList[0].MessageID + + opts := &azqueue.UpdateMessageOptions{} + _, err = queueClient.UpdateMessage(context.Background(), messageID, popReceipt, "new content", opts) + _require.Nil(err) + + resp1, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + content := *resp1.QueueMessagesList[0].MessageText + _require.Equal("new content", content) +} + +func (s *RecordedTestSuite) TestUpdateMessageWithVisibilityTimeout() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + testName := s.T().Name() + queueName := testcommon.GenerateQueueName(testName) + queueClient := testcommon.GetQueueClient(queueName, svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + resp, err := queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + popReceipt := *resp.QueueMessagesList[0].PopReceipt + messageID := *resp.QueueMessagesList[0].MessageID + + opts := &azqueue.UpdateMessageOptions{VisibilityTimeout: to.Ptr(int32(1))} + _, err = queueClient.UpdateMessage(context.Background(), messageID, popReceipt, "new content", opts) + _require.Nil(err) + time.Sleep(time.Second * 2) + resp1, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + content := *resp1.QueueMessagesList[0].MessageText + _require.Equal("new content", content) +} + +// this test ensures that our sas related methods work properly +func (s *UnrecordedTestSuite) TestQueueSignatureValues() { + _require := require.New(s.T()) + testName := s.T().Name() + + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + + _require.Nil(err) + queueName := testcommon.GenerateQueueName(testName) + + permissions := sas.QueuePermissions{ + Read: true, + Add: true, + Update: true, + } + + expiry := time.Now().Add(time.Hour) + qsv := sas.QueueSignatureValues{ + Version: sas.Version, + Protocol: sas.ProtocolHTTPS, + StartTime: time.Time{}, + ExpiryTime: expiry, + Permissions: permissions.String(), + QueueName: queueName, + } + _, err = qsv.SignWithSharedKey(cred) + _require.Nil(err) +} + +func (s *UnrecordedTestSuite) TestQueueGetSASURL() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential(fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + queueClient := serviceClient.NewQueueClient(queueName) + + permissions := sas.QueuePermissions{ + Read: true, + Add: true, + } + start := time.Now().Add(-5 * time.Minute).UTC() + expiry := time.Now().Add(time.Hour) + + opts := azqueue.GetSASURLOptions{StartTime: &start} + sasUrl, err := queueClient.GetSASURL(permissions, expiry, &opts) + _require.Nil(err) + + queueClient2, err := azqueue.NewQueueClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + _, err = queueClient2.Create(context.Background(), &azqueue.CreateOptions{Metadata: testcommon.BasicMetadata}) + _require.NotNil(err) + testcommon.ValidateQueueErrorCode(_require, err, queueerror.AuthorizationFailure) +} + +func (s *UnrecordedTestSuite) TestQueueGetSASURL2() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential(fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + queueClient := serviceClient.NewQueueClient(queueName) + start := time.Now().Add(-5 * time.Minute).UTC() + opts := azqueue.GetSASURLOptions{StartTime: &start} + + sasUrlReadAdd, err := queueClient.GetSASURL(sas.QueuePermissions{Add: true}, time.Now().Add(time.Hour), &opts) + _require.Nil(err) + _, err = queueClient.Create(context.Background(), &azqueue.CreateOptions{Metadata: testcommon.BasicMetadata}) + _require.Nil(err) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + queueClient1, err := azqueue.NewQueueClientWithNoCredential(sasUrlReadAdd, nil) + _require.Nil(err) + + // queue metadata and properties can't be read or written with SAS auth + _, err = queueClient1.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateQueueErrorCode(_require, err, queueerror.AuthorizationPermissionMismatch) + + start = time.Now().Add(-5 * time.Minute).UTC() + opts = azqueue.GetSASURLOptions{StartTime: &start} + + // this should work now + sasUrlRCWL, err := queueClient.GetSASURL(sas.QueuePermissions{Add: true, + Read: true, Update: true, Process: true}, time.Now().Add(time.Hour), &opts) + _require.Nil(err) + + queueClient2, err := azqueue.NewQueueClientWithNoCredential(sasUrlRCWL, nil) + _require.Nil(err) + + // queues can't be created, deleted, or listed with service SAS auth + _, err = queueClient2.Create(context.Background(), nil) + _require.Error(err) + testcommon.ValidateQueueErrorCode(_require, err, queueerror.AuthorizationFailure) +} + +func (s *UnrecordedTestSuite) TestServiceSASEnqueueMessage() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential( + fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + queueClient := serviceClient.NewQueueClient(queueName) + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + permissions := sas.QueuePermissions{ + Read: true, + Add: true, + Update: true, + } + + expiry := time.Now().Add(time.Hour) + + sasUrl, err := queueClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + queueClient1, err := azqueue.NewQueueClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient1.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + + } +} + +func (s *UnrecordedTestSuite) TestServiceSASDequeueMessage() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential( + fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + queueClient := serviceClient.NewQueueClient(queueName) + _, err = queueClient.Create(context.Background(), nil) + _require.Nil(err) + + defer testcommon.DeleteQueue(context.Background(), _require, queueClient) + + permissions := sas.QueuePermissions{ + Read: true, + Add: true, + Update: true, + Process: true, + } + + expiry := time.Now().Add(time.Hour) + + sasUrl, err := queueClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + queueClient1, err := azqueue.NewQueueClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient1.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + + } + // dequeue 4 messages + for i := 0; i < 4; i++ { + resp, err := queueClient1.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(1, len(resp.QueueMessagesList)) + _require.NotNil(resp.QueueMessagesList[0].MessageID) + } + // should be 0 now + resp, err := queueClient1.DequeueMessage(context.Background(), nil) + _require.Equal(0, len(resp.QueueMessagesList)) + _require.Nil(err) +} diff --git a/sdk/storage/azqueue/service_client_test.go b/sdk/storage/azqueue/service_client_test.go index 6510ccc6d213..10e8c34fc4fa 100644 --- a/sdk/storage/azqueue/service_client_test.go +++ b/sdk/storage/azqueue/service_client_test.go @@ -8,14 +8,19 @@ package azqueue_test import ( "context" + "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/internal/shared" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/queueerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/sas" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "os" "testing" + "time" ) func Test(t *testing.T) { @@ -77,7 +82,18 @@ func (s *UnrecordedTestSuite) TestServiceClientFromConnectionString() { _require.NotZero(sProps) } -//TODO: TestGetSASUrl +func (s *UnrecordedTestSuite) TestServiceClientFromConnectionString1() { + _require := require.New(s.T()) + + connectionString := testcommon.GetConnectionString(testcommon.TestAccountDefault) + + svcClient, err := azqueue.NewServiceClientFromConnectionString(connectionString, nil) + _require.Nil(err) + + sProps, err := svcClient.GetServiceProperties(context.Background(), nil) + _require.Nil(err) + _require.NotZero(sProps) +} func (s *RecordedTestSuite) TestSetPropertiesLogging() { _require := require.New(s.T()) @@ -346,3 +362,312 @@ func (s *RecordedTestSuite) TestServiceListQueuesPagination() { // greater or equal since storage account might have more than the 3 queues created above _require.GreaterOrEqual(count, 3) } + +func (s *RecordedTestSuite) TestServiceListQueuesPaginationEmptyPrefix() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + queueClient1 := testcommon.CreateNewQueue(context.Background(), _require, testcommon.GenerateQueueName(testName)+"1", svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient1) + queueClient2 := testcommon.CreateNewQueue(context.Background(), _require, testcommon.GenerateQueueName(testName)+"2", svcClient) + defer testcommon.DeleteQueue(context.Background(), _require, queueClient2) + + count := 0 + pager := svcClient.NewListQueuesPager(nil) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + + for _, queue := range resp.Queues { + count++ + _require.NotNil(queue.Name) + } + if err != nil { + break + } + } + _require.GreaterOrEqual(count, 2) +} + +func (s *RecordedTestSuite) TestServiceListQueuesPaged() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.Nil(err) + const numQueues = 6 + maxResults := int32(2) + const pagedqueuesPrefix = "azqueuepaged" + + queues := make([]*azqueue.QueueClient, numQueues) + expectedResults := make(map[string]bool) + for i := 0; i < numQueues; i++ { + queueName := pagedqueuesPrefix + testcommon.GenerateQueueName(testName) + fmt.Sprintf("%d", i) + queueClient := testcommon.CreateNewQueue(context.Background(), _require, queueName, svcClient) + queues[i] = queueClient + expectedResults[queueName] = false + } + + defer func() { + for i := range queues { + testcommon.DeleteQueue(context.Background(), _require, queues[i]) + } + }() + + prefix := pagedqueuesPrefix + testcommon.QueuePrefix + listOptions := azqueue.ListQueuesOptions{MaxResults: &maxResults, Prefix: &prefix, Include: azqueue.ListQueuesInclude{Metadata: true}} + count := 0 + results := make([]azqueue.Queue, 0) + pager := svcClient.NewListQueuesPager(&listOptions) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + for _, ctnr := range resp.Queues { + _require.NotNil(ctnr.Name) + results = append(results, *ctnr) + count += 1 + } + } + + _require.Equal(count, numQueues) + _require.Equal(len(results), numQueues) + + // make sure each queue we see is expected + for _, q := range results { + _, ok := expectedResults[*q.Name] + _require.Equal(ok, true) + expectedResults[*q.Name] = true + } + + // make sure every expected queue was seen + for _, seen := range expectedResults { + _require.Equal(seen, true) + } +} + +// this test ensures that our sas related methods work properly +func (s *UnrecordedTestSuite) TestServiceSignatureValues() { + _require := require.New(s.T()) + + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Update: true, + Delete: true, + } + + expiry := time.Now().Add(time.Hour) + + qsv := sas.AccountSignatureValues{ + Version: sas.Version, + Protocol: sas.ProtocolHTTPS, + StartTime: time.Time{}, + ExpiryTime: expiry, + ResourceTypes: resources.String(), + Permissions: permissions.String(), + } + _, err = qsv.SignWithSharedKey(cred) + _require.Nil(err) +} + +func (s *UnrecordedTestSuite) TestSASServiceClient() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential(fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Update: true, + Delete: true, + } + + expiry := time.Now().Add(time.Hour) + + sasUrl, err := serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Nil(err) + + svcClient, err := azqueue.NewServiceClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + // create queue using SAS + _, err = svcClient.CreateQueue(context.Background(), queueName, nil) + _require.Nil(err) + + _, err = svcClient.DeleteQueue(context.Background(), queueName, nil) + _require.Nil(err) +} + +func (s *UnrecordedTestSuite) TestNoSharedKeyCredError() { + _require := require.New(s.T()) + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + + // Creating service client without credentials + serviceClient, err := azqueue.NewServiceClientWithNoCredential(fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), nil) + _require.Nil(err) + + // Adding SAS and options + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Update: true, + Delete: true, + } + start := time.Now().Add(-time.Hour) + expiry := start.Add(time.Hour) + opts := azqueue.GetSASURLOptions{StartTime: &start} + + // GetSASURL fails (with MissingSharedKeyCredential) because service client is created without credentials + _, err = serviceClient.GetSASURL(resources, permissions, expiry, &opts) + _require.Equal(err, queueerror.MissingSharedKeyCredential) + +} + +func (s *UnrecordedTestSuite) TestAccountSASEnqueueMessage() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential(fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Update: true, + Delete: true, + } + + expiry := time.Now().Add(time.Hour) + + sasUrl, err := serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Nil(err) + + svcClient, err := azqueue.NewServiceClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + // create queue using account SAS + _, err = svcClient.CreateQueue(context.Background(), queueName, nil) + _require.Nil(err) + + queueClient := svcClient.NewQueueClient(queueName) + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + + } + _, err = svcClient.DeleteQueue(context.Background(), queueName, nil) + _require.Nil(err) +} + +func (s *UnrecordedTestSuite) TestAccountSASDequeueMessage() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azqueue.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := azqueue.NewServiceClientWithSharedKeyCredential(fmt.Sprintf("https://%s.queue.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + queueName := testcommon.GenerateQueueName(testName) + + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Update: true, + Delete: true, + Process: true, + } + + expiry := time.Now().Add(time.Hour) + + sasUrl, err := serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Nil(err) + + svcClient, err := azqueue.NewServiceClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + // create queue using account SAS + _, err = svcClient.CreateQueue(context.Background(), queueName, nil) + _require.Nil(err) + + queueClient := svcClient.NewQueueClient(queueName) + // enqueue 4 messages + for i := 0; i < 4; i++ { + _, err = queueClient.EnqueueMessage(context.Background(), testcommon.QueueDefaultData, nil) + _require.Nil(err) + } + + // dequeue 4 messages + for i := 0; i < 4; i++ { + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Nil(err) + _require.Equal(1, len(resp.QueueMessagesList)) + _require.NotNil(resp.QueueMessagesList[0].MessageID) + } + // should be 0 now + resp, err := queueClient.DequeueMessage(context.Background(), nil) + _require.Equal(0, len(resp.QueueMessagesList)) + _require.Nil(err) + _, err = svcClient.DeleteQueue(context.Background(), queueName, nil) + _require.Nil(err) +}