diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Configuration.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Configuration.cs index c31d995f3f42..25ada820b9af 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Configuration.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Configuration.cs @@ -32,7 +32,7 @@ internal static class Configuration /// /// Gets the namespace used for testing. /// - private static string ServiceNamespace { get { throw new NotImplementedException(); } } + private static string ServiceNamespace { get { throw new NotImplementedException(); } } /// /// Gets the user name used for testing. diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Microsoft.WindowsAzure.ServiceLayer.UnitTests.csproj b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Microsoft.WindowsAzure.ServiceLayer.UnitTests.csproj index fb66e2c1df03..36ee264b446b 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Microsoft.WindowsAzure.ServiceLayer.UnitTests.csproj +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/Microsoft.WindowsAzure.ServiceLayer.UnitTests.csproj @@ -115,10 +115,14 @@ + + + + diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/ContentTests.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/ContentTests.cs new file mode 100644 index 000000000000..cb22569ae4ea --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/ContentTests.cs @@ -0,0 +1,273 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.WindowsAzure.ServiceLayer.Http; +using Windows.Storage.Streams; +using Xunit; + +namespace Microsoft.WindowsAzure.ServiceLayer.UnitTests.ServiceBusTests +{ + /// + /// Tests for the Content class. + /// + public sealed class ContentTests + { + /// + /// Creates a memory content from the given text. + /// + /// Content text. + /// Memory-initialized content with the given text. + private static HttpContent CreateMemoryContent(string text) + { + return HttpContent.CreateFromText(text, "text/plain"); + } + + /// + /// Creates a memory content from the given bytes. + /// + /// Content data. + /// Memory-initialized content with the given bytes. + private static HttpContent CreateMemoryContent(params byte[] bytes) + { + return HttpContent.CreateFromByteArray(bytes); + } + + /// + /// Creates a stream content from the array of bytes. + /// + /// Content bytes. + /// Stream-initialized content with the given bytes. + private static HttpContent CreateStreamContent(params byte[] bytes) + { + MemoryStream stream = new MemoryStream(bytes); + return HttpContent.CreateFromStream(stream.AsInputStream()); + } + + /// + /// Creates a stream content from the given string. + /// + /// Content string. + /// Stream-initialized text content. + private static HttpContent CreateStreamContent(string text) + { + byte[] bytes = Encoding.UTF8.GetBytes(text); + MemoryStream stream = new MemoryStream(bytes); + return HttpContent.CreateFromStream(stream.AsInputStream()); + } + + + /// + /// Tests passing invalid arguments into content's constructors. + /// + [Fact] + public void InvalidArgs() + { + Assert.Throws(() => HttpContent.CreateFromText(null, "text/plain")); + Assert.Throws(() => HttpContent.CreateFromText("test", null)); + Assert.Throws(() => HttpContent.CreateFromByteArray(null)); + Assert.Throws(() => HttpContent.CreateFromStream(null)); + + HttpContent content = HttpContent.CreateFromText("this is a test.", "text/plain"); + Assert.Throws(() => content.CopyToAsync(null)); + } + + /// + /// Tests reading text content as a string. + /// + [Fact] + public void ReadTextAsString() + { + string originalContent = Guid.NewGuid().ToString(); + HttpContent content = CreateMemoryContent(originalContent); + + // Must be able to read multiple times + for (int i = 0; i < 2; i++) + { + string readContent = content.ReadAsStringAsync().AsTask().Result; + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + } + } + + /// + /// Tests reading text content as a bytes array. + /// + [Fact] + public void ReadTextAsBytes() + { + string originalContent = Guid.NewGuid().ToString(); + HttpContent content = HttpContent.CreateFromText(originalContent, "text/plain"); + + // Must be able to read multiple times. + for (int i = 0; i < 2; i++) + { + List bytes = new List(content.ReadAsByteArrayAsync().AsTask().Result); + + string readContent = Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count); + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + } + } + + /// + /// Tests reading text content as a bytes stream. + /// + [Fact] + public void ReadTextAsStream() + { + string originalContent = Guid.NewGuid().ToString(); + HttpContent content = HttpContent.CreateFromText(originalContent, "text/plain"); + + // Must be able to read multiple times. + for (int i = 0; i < 2; i++) + { + Stream stream = content.ReadAsStreamAsync().AsTask().Result.AsStreamForRead(); + using (StreamReader reader = new StreamReader(stream)) + { + string readContent = reader.ReadToEnd(); + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + } + } + } + + /// + /// Tests buffering memory content (which is a no-op operation). + /// + [Fact] + public void BufferMemoryContent() + { + string originalContent = Guid.NewGuid().ToString(); + HttpContent content = CreateMemoryContent(originalContent); + + content.CopyToBufferAsync().AsTask().Wait(); + + // Must be able to read as many times as we want. + for (int i = 0; i < 2; i++) + { + string readContent = content.ReadAsStringAsync().AsTask().Result; + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + } + } + + /// + /// Tests copying memory content into a stream. + /// + [Fact] + public void CopyMemoryContent() + { + byte[] originalContent = new byte[] { 1, 2, 3, 4, }; + HttpContent content = CreateMemoryContent(originalContent); + + // Memory content allows multiple reads. + for (int i = 0; i < 2; i++) + { + using (MemoryStream stream = new MemoryStream()) + { + content.CopyToAsync(stream.AsOutputStream()).AsTask().Wait(); + stream.Flush(); + byte[] readContent = stream.ToArray(); + + Assert.Equal(originalContent, readContent); + } + } + } + + /// + /// Tests reading stream content as a string. + /// + [Fact] + public void ReadStreamAsText() + { + string originalContent = Guid.NewGuid().ToString(); + HttpContent content = CreateStreamContent(originalContent); + + // Reading the first time should be OK. + string readContent = content.ReadAsStringAsync().AsTask().Result; + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + + // Reading again: there should be nothing left in the stream. + readContent = content.ReadAsStringAsync().AsTask().Result; + Assert.Equal(readContent, string.Empty, StringComparer.Ordinal); + } + + /// + /// Tests reading stream as a bytes array. + /// + [Fact] + public void ReadStreamAsBytes() + { + byte[] originalBytes = new byte[] { 1, 2, 3, 4, }; + HttpContent content = CreateStreamContent(originalBytes); + List readBytes = new List(content.ReadAsByteArrayAsync().AsTask().Result); + + Assert.Equal(originalBytes, readBytes); + + // Reading again: there should be nothing left in the stream. + readBytes = new List(content.ReadAsByteArrayAsync().AsTask().Result); + Assert.Equal(readBytes.Count, 0); + } + + /// + /// Tests buffering stream content. + /// + [Fact] + public void BufferStreamContent() + { + byte[] originalBytes = new byte[] { 1, 2, 3, 4, }; + HttpContent content = CreateStreamContent(originalBytes); + + // Reading multiple times should work after buffering. + content.CopyToBufferAsync().AsTask().Wait(); + + for (int i = 0; i < 2; i++) + { + List readBytes = new List( + content.ReadAsByteArrayAsync().AsTask().Result); + Assert.Equal(originalBytes, readBytes); + } + } + + /// + /// Tests copying stream content into a stream. + /// + [Fact] + public void CopyStreamContent() + { + byte[] originalContent = new byte[] { 1, 2, 3, 4, }; + HttpContent content = CreateStreamContent(originalContent); + + using (MemoryStream stream = new MemoryStream()) + { + content.CopyToAsync(stream.AsOutputStream()).AsTask().Wait(); + stream.Flush(); + byte[] readContent = stream.ToArray(); + Assert.Equal(originalContent, readContent); + } + + // Reading for the second time should + using (MemoryStream stream = new MemoryStream()) + { + content.CopyToAsync(stream.AsOutputStream()).AsTask().Wait(); + stream.Flush(); + byte[] readContent = stream.ToArray(); + Assert.Equal(readContent.Length, 0); + } + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageHelper.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageHelper.cs new file mode 100644 index 000000000000..f3622bc9ab78 --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageHelper.cs @@ -0,0 +1,61 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.WindowsAzure.ServiceLayer.Http; + +namespace Microsoft.WindowsAzure.ServiceLayer.ServiceBus +{ + /// + /// Helper class for dealing with messages. + /// + internal static class MessageHelper + { + /// + /// Creates a brokered message with the text content. + /// + /// Message text. + /// Brokered message. + internal static BrokeredMessageSettings CreateMessage(string messageText, string contentType = "text/plain") + { + return BrokeredMessageSettings.CreateFromText(messageText, contentType); + } + + /// + /// Creates a brokered message with the binary content. + /// + /// Message content. + /// Brokered message. + internal static BrokeredMessageSettings CreateMessage(byte[] bytes) + { + return BrokeredMessageSettings.CreateFromByteArray(bytes); + } + + /// + /// Creates a brokered message with the binary content. + /// + /// Message content. + /// Brokered message. + internal static BrokeredMessageSettings CreateMessage(Stream stream) + { + return BrokeredMessageSettings.CreateFromStream(stream.AsInputStream()); + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagePropertiesTests.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagePropertiesTests.cs index aa5fa407ce26..4f8c5c45968e 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagePropertiesTests.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagePropertiesTests.cs @@ -36,8 +36,8 @@ public sealed class MessagePropertiesTests public void MessageProperties() { string queueName = UsesUniqueQueueAttribute.QueueName; - DateTimeOffset originalDateTime = DateTimeOffset.Now; - BrokeredMessageSettings messageSettings = BrokeredMessageSettings.CreateFromText("text/plain", "This is a test."); + DateTimeOffset originalDateTime = DateTimeOffset.UtcNow; + BrokeredMessageSettings messageSettings = MessageHelper.CreateMessage("This is a test."); messageSettings.Properties.Add("StringProperty", "Test"); messageSettings.Properties.Add("BoolPropertyTrue", true); @@ -81,7 +81,7 @@ public void MessageProperties() public void InvalidPropertyType() { string queueName = UsesUniqueQueueAttribute.QueueName; - BrokeredMessageSettings messageSettings = BrokeredMessageSettings.CreateFromText("text/plain", "This is a test."); + BrokeredMessageSettings messageSettings = MessageHelper.CreateMessage("This is a test."); messageSettings.Properties.Add("TestProperty", new int[] { 1, 2, 3}); Assert.Throws(() => Configuration.ServiceBus.SendMessageAsync(queueName, messageSettings)); diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageSettingsTests.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageSettingsTests.cs index 6a7fd8fcb14c..909c4c7c2ea2 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageSettingsTests.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessageSettingsTests.cs @@ -19,64 +19,13 @@ public sealed class MessageSettingsTests /// Tests specifying null arguments in constructors. /// [Fact] - public void NullArgumentsInConstructors() + public void InvalidArgumentsInMethods() { - Assert.Throws(() => BrokeredMessageSettings.CreateFromBytes((byte[])null)); - Assert.Throws(() => BrokeredMessageSettings.CreateFromText(null, "This is a test.")); - Assert.Throws(() => BrokeredMessageSettings.CreateFromText("text/plain", (string)null)); - Assert.Throws(() => BrokeredMessageSettings.CreateFromStream((IInputStream)null)); - } - - /// - /// Tests specifying null arguments in methods of a brokered message. - /// - [Fact] - public void NullArgumentsInMethods() - { - BrokeredMessageSettings message = BrokeredMessageSettings.CreateFromText("text/plain", "This is a test."); - Assert.Throws(() => message.CopyContentToAsync(null)); - } - - /// - /// Tests reading a message as a string. - /// - [Fact] - public void ReadAsString() - { - string originalBody = "This is only a test!"; - BrokeredMessageSettings message = BrokeredMessageSettings.CreateFromText("text/plain", originalBody); - - // Do it twice to make sure the position in the stream is restored after each read. - for (int i = 0; i < 2; i++) - { - string newBody = message.ReadContentAsStringAsync().AsTask().Result; - Assert.Equal(originalBody, newBody, StringComparer.Ordinal); - } - } - - /// - /// Tests reading content of the message into a stream. - /// - [Fact] - public void ReadIntoStream() - { - Byte[] bytes = new byte[] { 1, 2, 3 }; - BrokeredMessageSettings message = BrokeredMessageSettings.CreateFromBytes(bytes); - - // Do it twice to make sure the position in the stream is restored after each read. - for (int i = 0; i < 2; i++) - { - using (MemoryStream stream = new MemoryStream()) - { - message.CopyContentToAsync(stream.AsOutputStream()).AsTask().Wait(); - stream.Flush(); - stream.Position = 0; - - BinaryReader reader = new BinaryReader(stream); - byte[] readBytes = reader.ReadBytes(bytes.Length + 1); - Assert.Equal(bytes, readBytes); - } - } + Assert.Throws(() => new BrokeredMessageSettings(null)); + Assert.Throws(() => BrokeredMessageSettings.CreateFromText(null)); + Assert.Throws(() => BrokeredMessageSettings.CreateFromText("Test", null)); + Assert.Throws(() => BrokeredMessageSettings.CreateFromByteArray(null)); + Assert.Throws(() => BrokeredMessageSettings.CreateFromStream(null)); } } } diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagingTestsBase.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagingTestsBase.cs new file mode 100644 index 000000000000..9fee31a534c1 --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/MessagingTestsBase.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.WindowsAzure.ServiceLayer; +using Microsoft.WindowsAzure.ServiceLayer.ServiceBus; +using Xunit; + +namespace Microsoft.WindowsAzure.ServiceLayer.UnitTests.ServiceBusTests +{ + /// + /// Base class for messaging tests. All tests in this class assume single + /// storage with support for the following operations: send, get, peek, + /// lock, unock, and delete. + /// + public abstract class MessagingTestsBase + { + /// + /// Sends a message, + /// + /// Message to send. + protected abstract void SendMessage(BrokeredMessageSettings settings); + + /// + /// Gets a message from the queue. + /// + /// First queued message. + protected abstract BrokeredMessageInfo GetMessage(TimeSpan lockSpan); + + /// + /// Peeks a message from the queue. + /// + /// First queued message. + protected abstract BrokeredMessageInfo PeekMessage(TimeSpan lockSpan); + + /// + /// Unlocks previously locked message. + /// + /// Sequence number of the locked message. + /// Lock token of the locked message. + protected abstract void UnlockMessage(long sequenceNumber, string lockToken); + + /// + /// Deletes previously locked message. + /// + /// Sequence number of the locked message. + /// Lock token of the locked message. + protected abstract void DeleteMessage(long sequenceNumber, string lockToken); + + /// + /// Tests setting and reading a property. + /// + /// Property type. + /// Property value. + /// Method for setting the value. + /// Method for getting the value. + /// Comparer for values. + protected void TestSetProperty( + T value, + Action setValue, + Func getValue, + IEqualityComparer comparer = null) + { + if (comparer == null) + { + comparer = EqualityComparer.Default; + } + + // Create a message. + BrokeredMessageSettings settings = MessageHelper.CreateMessage(Guid.NewGuid().ToString()); + + // Set the requested property. + setValue(settings, value); + + // Send the message to the queue. + SendMessage(settings); + + // Get the message and compare properties. + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + T newValue = getValue(message); + Assert.Equal(value, newValue, comparer); + } + + /// + /// Verifies preserving content type. + /// + [Fact] + public void PreserveContentType() + { + string[] contentTypes = new string[] { "text/plain", "text/xml", }; + + foreach (string contentType in contentTypes) + { + BrokeredMessageSettings settings = MessageHelper.CreateMessage(Guid.NewGuid().ToString(), contentType); + SendMessage(settings); + + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + Assert.Equal(message.ContentType, contentType, StringComparer.Ordinal); + } + } + + /// + /// Tests preserving content text. + /// + [Fact] + public void PreservingContentText() + { + string originalContent = Guid.NewGuid().ToString(); + BrokeredMessageSettings settings = MessageHelper.CreateMessage(originalContent); + SendMessage(settings); + + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + string readContent = message.ReadContentAsStringAsync().AsTask().Result; + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + } + + /// + /// Tests peeking a message. + /// + [Fact] + public void PeekingMessage() + { + string originalContent = Guid.NewGuid().ToString(); + BrokeredMessageSettings settings = MessageHelper.CreateMessage(originalContent); + SendMessage(settings); + + BrokeredMessageInfo message = PeekMessage(TimeSpan.FromSeconds(10)); + string readContent = message.ReadContentAsStringAsync().AsTask().Result; + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + + // Delete message. This will fail if the message is not there. + DeleteMessage(message.SequenceNumber, message.LockToken); + } + + /// + /// Tests peeking a message from an empty queue. + /// + [Fact] + public void PeekingMessageFromEmptyQueue() + { + Assert.Throws(() => PeekMessage(TimeSpan.FromSeconds(10))); + } + + /// + /// Tests getting a message. + /// + [Fact] + public void GettingMessage() + { + string originalContent = Guid.NewGuid().ToString(); + BrokeredMessageSettings settings = MessageHelper.CreateMessage(originalContent); + SendMessage(settings); + + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + string readContent = message.ReadContentAsStringAsync().AsTask().Result; + Assert.Equal(originalContent, readContent, StringComparer.Ordinal); + + // Make sure nothing's left. + Assert.Throws(() => PeekMessage(TimeSpan.FromSeconds(10))); + } + + /// + /// Tests getting a message from an empty queue. + /// + [Fact] + public void GettingMessageFromEmptyQueue() + { + Assert.Throws(() => GetMessage(TimeSpan.FromSeconds(10))); + } + + /// + /// Tests deleting a message. + /// + [Fact] + public void DeletingMessage() + { + BrokeredMessageSettings settings = MessageHelper.CreateMessage("This is a test."); + SendMessage(settings); + + BrokeredMessageInfo message = PeekMessage(TimeSpan.FromSeconds(10)); + DeleteMessage(message.SequenceNumber, message.LockToken); + + Assert.Throws(() => PeekMessage(TimeSpan.FromSeconds(10))); + } + + /// + /// Tests specifying invalid arguments for DeleteMessage call. + /// + [Fact] + public void InvalidArgsInDeleteMessage() + { + Assert.Throws(() => DeleteMessage(0, null)); + } + + /// + /// Tests unlocking a message. + /// + [Fact] + public void UnlockingMessage() + { + BrokeredMessageSettings settings = MessageHelper.CreateMessage("This is a test."); + SendMessage(settings); + + BrokeredMessageInfo message = PeekMessage(TimeSpan.FromSeconds(10)); + UnlockMessage(message.SequenceNumber, message.LockToken); + message = GetMessage(TimeSpan.FromSeconds(10)); + Assert.Throws(() => PeekMessage(TimeSpan.FromSeconds(10))); + } + + /// + /// Tests specifying invalid arguments for UnlockMessage call. + /// + [Fact] + public void InvalidArgsInUnlockMessage() + { + Assert.Throws(() => UnlockMessage(0, null)); + } + + /// + /// Tests setting/getting message's CorrelationId property. + /// + [Fact] + public void SetCorrelationId() + { + TestSetProperty( + "correlationId", + (message, value) => { message.CorrelationId = value; }, + (message) => message.CorrelationId, + StringComparer.Ordinal); + } + + /// + /// Tests setting/getting message's Label property. + /// + [Fact] + public void SetLabel() + { + TestSetProperty( + "TestLabel", + (message, value) => { message.Label = value; }, + (message) => message.Label, + StringComparer.Ordinal); + } + + /// + /// Tests setting/getting MessaqgeId property. + /// + [Fact] + public void SetMessageId() + { + TestSetProperty( + "TestMessageId", + (message, value) => { message.MessageId = value; }, + (message) => message.MessageId, + StringComparer.Ordinal); + } + + /// + /// Tests setting ReplyTo property. + /// + [Fact] + public void SetReplyTo() + { + TestSetProperty( + "testReplyTo", + (message, value) => { message.ReplyTo = value; }, + (message) => message.ReplyTo, + StringComparer.Ordinal); + } + + /// + /// Tests setting ReplyToSessionId property. + /// + [Fact] + public void SetReplyToSessionId() + { + TestSetProperty( + "testReplyToSessionId", + (message, value) => { message.ReplyToSessionId = value; }, + (message) => message.ReplyToSessionId, + StringComparer.Ordinal); + } + + /// + /// Tests setting SessionId property. + /// + [Fact] + public void SetSessionId() + { + TestSetProperty( + "testSessionId", + (message, value) => { message.SessionId = value; }, + (message) => message.SessionId, + StringComparer.Ordinal); + } + + /// + /// Tests setting TimeToLive property. + /// + [Fact] + public void SetTimeToLive() + { + TestSetProperty( + TimeSpan.FromDays(2), + (message, value) => { message.TimeToLive = value; }, + (message) => message.TimeToLive.Value); + } + + /// + /// Tests setting To property. + /// + [Fact] + public void SetTo() + { + TestSetProperty( + "testTo", + (message, value) => { message.To = value; }, + (message) => message.To, + StringComparer.Ordinal); + } + + /// + /// Tests sending and receiving an array of bytes. + /// + [Fact] + public void PreserveBytes() + { + byte[] originalBytes = new byte[] { 1, 2, 3, 4, }; + BrokeredMessageSettings settings = MessageHelper.CreateMessage(originalBytes); + SendMessage(settings); + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + + List readBytes = new List(message.ReadContentAsBytesAsync().AsTask().Result); + Assert.Equal(originalBytes, readBytes); + } + + /// + /// Tests sending and receiving a stream. + /// + [Fact] + public void PreserveStream() + { + byte[] originalBytes = new byte[] { 5, 4, 3, 2, 1, }; + using (MemoryStream stream = new MemoryStream(originalBytes)) + { + BrokeredMessageSettings settings = MessageHelper.CreateMessage(stream); + SendMessage(settings); + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + + using (Stream readStream = message.ReadContentAsStreamAsync().AsTask().Result.AsStreamForRead()) + { + byte[] readBytes = new byte[originalBytes.Length]; + int cnt = readStream.Read(readBytes, 0, originalBytes.Length); + Assert.Equal(cnt, readBytes.Length); + Assert.Equal(originalBytes, readBytes); + + cnt = readStream.Read(readBytes, 0, 1); + Assert.Equal(cnt, 0); + } + } + } + + /// + /// Tests sending/receiving an empty string in the message content. + /// + [Fact] + public void EmptyStringContent() + { + BrokeredMessageSettings settings = MessageHelper.CreateMessage(string.Empty); + SendMessage(settings); + + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + string readText = message.ReadContentAsStringAsync().AsTask().Result; + Assert.Equal(readText.Length, 0); + } + + /// + /// Tests sending/receiving an empty bytes array. + /// + [Fact] + public void EmptyArrayContent() + { + byte[] originalBytes = new byte[0]; + BrokeredMessageSettings settings = MessageHelper.CreateMessage(originalBytes); + SendMessage(settings); + + BrokeredMessageInfo message = GetMessage(TimeSpan.FromSeconds(10)); + List readBytes = new List(message.ReadContentAsBytesAsync().AsTask().Result); + Assert.Equal(originalBytes, readBytes); + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/QueueMessagingTests.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/QueueMessagingTests.cs index 1a27cad30ee2..f35f62b57006 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/QueueMessagingTests.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/QueueMessagingTests.cs @@ -27,133 +27,74 @@ namespace Microsoft.WindowsAzure.ServiceLayer.UnitTests.ServiceBusTests /// /// Runtime tests for queues. /// - public sealed class QueueMessagingTests + public sealed class QueueMessagingTests: MessagingTestsBase, IUseFixture { + private string _queueName; // Shared queue. + /// - /// Tests setting and reading a property. + /// Sends a message to the queue. /// - /// Property type. - /// Property value. - /// Method for setting the value. - /// Method for getting the value. - /// Comparer for values. - private void TestSetProperty( - T value, - Action setValue, - Func getValue, - IEqualityComparer comparer = null) + /// Message to send. + protected override void SendMessage(BrokeredMessageSettings settings) { - if (comparer == null) - { - comparer = EqualityComparer.Default; - } - - // Create a message. - string messageText = Guid.NewGuid().ToString(); - BrokeredMessageSettings messageSettings = BrokeredMessageSettings.CreateFromText("text/plain", messageText); - - // Set the requested property. - setValue(messageSettings, value); - - // Send the message to the queue. - string queueName = UsesUniqueQueueAttribute.QueueName; - Configuration.ServiceBus.SendMessageAsync(queueName, messageSettings).AsTask().Wait(); - BrokeredMessageInfo message = Configuration.ServiceBus.GetQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result; - T newValue = getValue(message); - - Assert.Equal(value, newValue, comparer); + Configuration.ServiceBus.SendMessageAsync(_queueName, settings).AsTask().Wait(); } - /// - /// Tests getting a message from the queue. + /// Gets the first message in the queue. /// - [Fact] - [UsesUniqueQueue] - public void PeekMessage() + /// Lock interval. + /// Message. + protected override BrokeredMessageInfo GetMessage(TimeSpan lockSpan) { - string queueName = UsesUniqueQueueAttribute.QueueName; - string text = Guid.NewGuid().ToString(); - BrokeredMessageSettings messageSettings = BrokeredMessageSettings.CreateFromText("text/plain", text); - - BrokeredMessageInfo message = Configuration.ServiceBus.SendMessageAsync(queueName, messageSettings) - .AsTask() - .ContinueWith((t) => Configuration.ServiceBus.PeekQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result, TaskContinuationOptions.OnlyOnRanToCompletion) - .Result; - - string newText = message.ReadContentAsStringAsync().AsTask().Result; - - Assert.Equal(text, newText, StringComparer.Ordinal); - - // Make sure the message is still there. - QueueInfo info = Configuration.ServiceBus.GetQueueAsync(queueName).AsTask().Result; - Assert.Equal(info.MessageCount, 1); + return Configuration.ServiceBus.GetQueueMessageAsync(_queueName, lockSpan).AsTask().Result; } /// - /// Tests getting a message from the queue. + /// Peeks the first message in the queue. /// - [Fact] - [UsesUniqueQueue] - public void GetMessage() + /// Lock interval. + /// Message. + protected override BrokeredMessageInfo PeekMessage(TimeSpan lockSpan) { - string queueName = UsesUniqueQueueAttribute.QueueName; - string text = Guid.NewGuid().ToString(); - BrokeredMessageSettings messageSettings = BrokeredMessageSettings.CreateFromText("text/html", text); - - BrokeredMessageInfo message = Configuration.ServiceBus.SendMessageAsync(queueName, messageSettings) - .AsTask() - .ContinueWith((t) => Configuration.ServiceBus.GetQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result, TaskContinuationOptions.OnlyOnRanToCompletion) - .Result; - string newText = message.ReadContentAsStringAsync().AsTask().Result; - - Assert.Equal(newText, text, StringComparer.Ordinal); - - // Make sure the message disappeared. - QueueInfo info = Configuration.ServiceBus.GetQueueAsync(queueName).AsTask().Result; - Assert.Equal(info.MessageCount, 0); + return Configuration.ServiceBus.PeekQueueMessageAsync(_queueName, lockSpan).AsTask().Result; } /// - /// Tests getting a message from an empty queue. + /// Unlocks given message. /// - [Fact] - [UsesUniqueQueue] - public void GetMessageFromEmptyQueue() + /// Sequence number of the locked message. + /// Lock token of the locked message. + protected override void UnlockMessage(long sequenceNumber, string lockToken) { - string queueName = UsesUniqueQueueAttribute.QueueName; - - Assert.Throws(() => Configuration.ServiceBus.GetQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Wait()); + Configuration.ServiceBus.UnlockQueueMessageAsync(_queueName, sequenceNumber, lockToken).AsTask().Wait(); } /// - /// Tests deleting a message from the queue. + /// Deletes previously locked message. /// - [Fact] - [UsesUniqueQueue] - public void DeleteMessage() + /// Sequence number of the locked message. + /// Lock token of the locked message. + protected override void DeleteMessage(long sequenceNumber, string lockToken) { - string queueName = UsesUniqueQueueAttribute.QueueName; - - BrokeredMessageSettings messageSettings = BrokeredMessageSettings.CreateFromText("text/plain", "This is only a test."); - Configuration.ServiceBus.SendMessageAsync(queueName, messageSettings).AsTask().Wait(); - BrokeredMessageInfo message = Configuration.ServiceBus.PeekQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result; - Configuration.ServiceBus.DeleteQueueMessageAsync(queueName, message.SequenceNumber, message.LockToken).AsTask().Wait(); + Configuration.ServiceBus.DeleteQueueMessageAsync(_queueName, sequenceNumber, lockToken).AsTask().Wait(); + } - QueueInfo info = Configuration.ServiceBus.GetQueueAsync(queueName).AsTask().Result; - Assert.Equal(info.MessageCount, 0); + // Assigns a fixture to the class. + void IUseFixture.SetFixture(UniqueQueueFixture data) + { + _queueName = data.QueueName; } /// - /// Tests peeking a message from a non-existing queue. + /// Tests specifying invalid arguments in SendMessage call. /// [Fact] - [UsesUniqueQueue] - public void PeekMessageFromEmptyQueue() + public void InvalidArgsInSendMessage() { - string queueName = UsesUniqueQueueAttribute.QueueName; - BrokeredMessageInfo message = Configuration.ServiceBus.PeekQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result; - Assert.Null(message); + BrokeredMessageSettings message = MessageHelper.CreateMessage("This is a test."); + Assert.Throws(() => Configuration.ServiceBus.SendMessageAsync(null, message)); + Assert.Throws(() => Configuration.ServiceBus.SendMessageAsync(_queueName, null)); } /// @@ -177,189 +118,5 @@ public void PeekMessageFromNonExistingQueue() Assert.Throws(() => Configuration.ServiceBus.PeekQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Wait()); } - - /// - /// Tests null reference exceptions in queue methods. - /// - [Fact] - public void NullArgsInQueueMessages() - { - BrokeredMessageSettings validMessageSettings = BrokeredMessageSettings.CreateFromText("test/plain", "This is a test"); - Assert.Throws(() => Configuration.ServiceBus.SendMessageAsync(null, validMessageSettings)); - Assert.Throws(() => Configuration.ServiceBus.SendMessageAsync("somename", null)); - Assert.Throws(() => Configuration.ServiceBus.GetQueueMessageAsync(null, TimeSpan.FromSeconds(10))); - Assert.Throws(() => Configuration.ServiceBus.PeekQueueMessageAsync(null, TimeSpan.FromSeconds(10))); - Assert.Throws(() => Configuration.ServiceBus.UnlockQueueMessageAsync(null, 0, "test")); - Assert.Throws(() => Configuration.ServiceBus.UnlockQueueMessageAsync("test", 0, null)); - Assert.Throws(() => Configuration.ServiceBus.DeleteQueueMessageAsync(null, 0, "test")); - Assert.Throws(() => Configuration.ServiceBus.DeleteQueueMessageAsync("test", 0, null)); - } - - /// - /// Tests setting/getting message's CorrelationId property. - /// - [Fact] - [UsesUniqueQueue] - public void SetCorrelationId() - { - TestSetProperty( - "correlationId", - (message, value) => { message.CorrelationId = value; }, - (message) => message.CorrelationId, - StringComparer.Ordinal); - } - - /// - /// Tests setting/getting message's Label property. - /// - [Fact] - [UsesUniqueQueue] - public void SetLabel() - { - TestSetProperty( - "TestLabel", - (message, value) => { message.Label = value; }, - (message) => message.Label, - StringComparer.Ordinal); - } - - /// - /// Tests setting/getting MessaqgeId property. - /// - [Fact] - [UsesUniqueQueue] - public void SetMessageId() - { - TestSetProperty( - "TestMessageId", - (message, value) => { message.MessageId = value; }, - (message) => message.MessageId, - StringComparer.Ordinal); - } - - /// - /// Tests setting ReplyTo property. - /// - [Fact] - [UsesUniqueQueue] - public void SetReplyTo() - { - TestSetProperty( - "testReplyTo", - (message, value) => { message.ReplyTo = value; }, - (message) => message.ReplyTo, - StringComparer.Ordinal); - } - - /// - /// Tests setting ReplyToSessionId property. - /// - [Fact] - [UsesUniqueQueue] - public void SetReplyToSessionId() - { - TestSetProperty( - "testReplyToSessionId", - (message, value) => { message.ReplyToSessionId = value; }, - (message) => message.ReplyToSessionId, - StringComparer.Ordinal); - } - - /// - /// Tests setting SessionId property. - /// - [Fact] - [UsesUniqueQueue] - public void SetSessionId() - { - TestSetProperty( - "testSessionId", - (message, value) => { message.SessionId = value; }, - (message) => message.SessionId, - StringComparer.Ordinal); - } - - /// - /// Tests setting TimeToLive property. - /// - [Fact] - [UsesUniqueQueue] - public void SetTimeToLive() - { - TestSetProperty( - TimeSpan.FromDays(2), - (message, value) => { message.TimeToLive = value; }, - (message) => message.TimeToLive.Value); - } - - /// - /// Tests setting To property. - /// - [Fact] - [UsesUniqueQueue] - public void SetTo() - { - TestSetProperty( - "testTo", - (message, value) => { message.To = value; }, - (message) => message.To, - StringComparer.Ordinal); - } - - /// - /// Tests sending and receiving an array of bytes. - /// - [Fact] - [UsesUniqueQueue] - public void SendBytes() - { - string queueName = UsesUniqueQueueAttribute.QueueName; - byte[] bytes = new byte[] { 1, 2, 3, }; - BrokeredMessageSettings settings = BrokeredMessageSettings.CreateFromBytes(bytes); - Configuration.ServiceBus.SendMessageAsync(queueName, settings).AsTask().Wait(); - - BrokeredMessageInfo message = Configuration.ServiceBus.GetQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result; - - // Do that twice to make sure stream positions are preserved. - for (int i = 0; i < 2; i++) - { - List newBytes = new List(message.ReadContentAsBytesAsync().AsTask().Result); - Assert.Equal(bytes, newBytes.ToArray()); - } - } - - /// - /// Tests sending a stream of bytes. - /// - [Fact(Skip="Doesn't work with .Net libraries; disabling for now.")] - [UsesUniqueQueue] - public void SendStream() - { - string queueName = UsesUniqueQueueAttribute.QueueName; - byte[] inBytes = new byte[] { 1, 2, 3, 4, }; - - using (MemoryStream inStream = new MemoryStream()) - { - inStream.Write(inBytes, 0, inBytes.Length); - inStream.Flush(); - inStream.Position = 0; - - BrokeredMessageSettings settings = BrokeredMessageSettings.CreateFromStream(inStream.AsInputStream()); - Configuration.ServiceBus.SendMessageAsync(queueName, settings).AsTask().Wait(); - } - - BrokeredMessageInfo message = Configuration.ServiceBus.GetQueueMessageAsync(queueName, TimeSpan.FromSeconds(10)).AsTask().Result; - - for (int i = 0; i < 2; i++) - { - using (Stream stream = message.ReadContentAsStreamAsync().AsTask().Result.AsStreamForRead()) - { - byte[] outBytes = new byte[4]; - int cnt = stream.Read(outBytes, 0, 4); - Assert.Equal(cnt, 4); - Assert.Equal(inBytes, outBytes); - } - } - } } } diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/SubscriptionMessagingTests.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/SubscriptionMessagingTests.cs index 7b84af4f6d3d..d04a7a6c67f3 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/SubscriptionMessagingTests.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/SubscriptionMessagingTests.cs @@ -1,4 +1,19 @@ -using System; +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,7 +26,7 @@ namespace Microsoft.WindowsAzure.ServiceLayer.UnitTests.ServiceBusTests /// /// Unit tests for topic/subscription messaging. /// - public sealed class SubscriptionMessagingTests: IUseFixture + public sealed class SubscriptionMessagingTests: MessagingTestsBase, IUseFixture { UniqueSubscriptionFixture _subscription; // Unique topic/subscription fixture. @@ -40,24 +55,61 @@ private IServiceBusService ServiceBus } /// - /// Assigns fixture to the class. + /// Sends a message to the subscription. /// - /// Fixture. - void IUseFixture.SetFixture(UniqueSubscriptionFixture data) + /// Message settings. + protected override void SendMessage(BrokeredMessageSettings settings) { - _subscription = data; + Configuration.ServiceBus.SendMessageAsync(TopicName, settings).AsTask().Wait(); } /// - /// Sends a text message with the given text to the topic. + /// Gets the first message in the subscription. /// - /// Message text. - /// Message settings. - BrokeredMessageSettings SendTextMessage(string messageText) + /// Locking interval. + /// Message. + protected override BrokeredMessageInfo GetMessage(TimeSpan lockSpan) { - BrokeredMessageSettings message = BrokeredMessageSettings.CreateFromText("text/plain", messageText); - ServiceBus.SendMessageAsync(TopicName, message).AsTask().Wait(); - return message; + return Configuration.ServiceBus.GetSubscriptionMessageAsync(TopicName, SubscriptionName, lockSpan).AsTask().Result; + } + + /// + /// Peeks the first message in the subscription. + /// + /// Lock interval. + /// Message or null, if none. + protected override BrokeredMessageInfo PeekMessage(TimeSpan lockSpan) + { + return Configuration.ServiceBus.PeekSubscriptionMessageAsync(TopicName, SubscriptionName, lockSpan).AsTask().Result; + } + + /// + /// Unlocks previously locked message in the subscription. + /// + /// Sequence number of the locked message. + /// Lock token of the message. + protected override void UnlockMessage(long sequenceNumber, string lockToken) + { + Configuration.ServiceBus.UnlockSubscriptionMessageAsync(TopicName, SubscriptionName, sequenceNumber, lockToken).AsTask().Wait(); + } + + /// + /// Deletes previously locked subscription message. + /// + /// Sequence number of the previously locked message. + /// Lock token of the message. + protected override void DeleteMessage(long sequenceNumber, string lockToken) + { + Configuration.ServiceBus.DeleteSubscriptionMessageAsync(TopicName, SubscriptionName, sequenceNumber, lockToken).AsTask().Wait(); + } + + /// + /// Assigns fixture to the class. + /// + /// Fixture. + void IUseFixture.SetFixture(UniqueSubscriptionFixture data) + { + _subscription = data; } /// @@ -79,57 +131,23 @@ public void NullArgs() } /// - /// Tests getting a message from subscription (destructive reading). - /// - [Fact] - public void GetMessage() - { - string messageText = Guid.NewGuid().ToString(); - SendTextMessage(messageText); - - BrokeredMessageInfo message = ServiceBus.GetSubscriptionMessageAsync(TopicName, SubscriptionName, TimeSpan.FromSeconds(10)).AsTask().Result; - Assert.Equal(message.ReadContentAsStringAsync().AsTask().Result, messageText, StringComparer.Ordinal); - - // Reading the message should've removed it from the subscription. - Assert.Throws(() => ServiceBus.GetSubscriptionMessageAsync(TopicName, SubscriptionName, TimeSpan.FromSeconds(10)).AsTask().Wait()); - } - - /// - /// Tests peeking a message. + /// Tests getting a message from a non-existing topic. /// [Fact] - public void PeekMessage() + public void GettingMessageFromNonExistingTopic() { - string messageText = Guid.NewGuid().ToString(); - SendTextMessage(messageText); - - // Peeking is a non-destructive operation; should work two times in a row. - for (int i = 0; i < 2; i++) - { - BrokeredMessageInfo message = ServiceBus.PeekSubscriptionMessageAsync(TopicName, SubscriptionName, TimeSpan.FromSeconds(10)).AsTask().Result; - Assert.Equal(messageText, message.ReadContentAsStringAsync().AsTask().Result, StringComparer.Ordinal); - - // Unlock the message. - ServiceBus.UnlockSubscriptionMessageAsync(TopicName, SubscriptionName, message.SequenceNumber, message.LockToken).AsTask().Wait(); - } - - // Remove the message. - ServiceBus.GetSubscriptionMessageAsync(TopicName, SubscriptionName, TimeSpan.FromSeconds(0)).AsTask().Wait(); + Assert.Throws( + () => Configuration.ServiceBus.GetSubscriptionMessageAsync(Configuration.GetUniqueTopicName(), SubscriptionName, TimeSpan.FromSeconds(10)).AsTask().Wait()); } /// - /// Tests locking and deleting a message. + /// Tests getting a message from a non-existing subscription. /// [Fact] - public void DeleteMessage() + public void GettingMessageFromNonExistingSubscription() { - string messageText = Guid.NewGuid().ToString(); - SendTextMessage(messageText); - - BrokeredMessageInfo message = ServiceBus.PeekSubscriptionMessageAsync(TopicName, SubscriptionName, TimeSpan.FromSeconds(10)).AsTask().Result; - ServiceBus.DeleteSubscriptionMessageAsync(TopicName, SubscriptionName, message.SequenceNumber, message.LockToken).AsTask().Wait(); - - Assert.Throws(() => ServiceBus.GetSubscriptionMessageAsync(TopicName, SubscriptionName, TimeSpan.FromSeconds(10)).AsTask().Wait()); + Assert.Throws( + () => Configuration.ServiceBus.GetSubscriptionMessageAsync(TopicName, Configuration.GetUniqueSubscriptionName(), TimeSpan.FromSeconds(10)).AsTask().Wait()); } } } diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/UniqueQueueFixture.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/UniqueQueueFixture.cs new file mode 100644 index 000000000000..8b282e421bb6 --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer.UnitTests/ServiceBusTests/UniqueQueueFixture.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.WindowsAzure.ServiceLayer.UnitTests.ServiceBusTests +{ + /// + /// A fixture for generating unique queue for a group of tests. + /// + public class UniqueQueueFixture: IDisposable + { + public string QueueName { get; private set; } + + /// + /// Initializes the fixture by creating a queue with the unique name. + /// + public UniqueQueueFixture() + { + QueueName = Configuration.GetUniqueQueueName(); + Configuration.ServiceBus.CreateQueueAsync(QueueName).AsTask().Wait(); + } + + /// + /// Disposes the fixture by removing the queue. + /// + void IDisposable.Dispose() + { + Configuration.ServiceBus.DeleteQueueAsync(QueueName).AsTask().Wait(); + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Constants.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Constants.cs index 6841aeabba97..9f83948cb3e5 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Constants.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Constants.cs @@ -53,9 +53,9 @@ internal static class Constants internal const string SerializationContentType = "application/xml"; internal const string BodyContentType = "application/atom+xml"; - internal const string MessageContentType = "application/atom+xml"; + internal const string DefaultMessageContentType = "text/plain"; internal const string WrapAuthenticationContentType = "application/x-www-form-urlencoded"; - + internal const string BrokerPropertiesHeader = "BrokerProperties"; // Header name for broker properties. internal const int CompatibilityLevel = 20; // Compatibility level for rules. diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/HttpContent.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/HttpContent.cs new file mode 100644 index 000000000000..8af047318405 --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/HttpContent.cs @@ -0,0 +1,194 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.Storage.Streams; + +using NetHttpContent = System.Net.Http.HttpContent; + +namespace Microsoft.WindowsAzure.ServiceLayer.Http +{ + /// + /// A data container for brokered messages, HTTP requests and responses. + /// + /// + /// The class represents a container for HTTP content, which is used in + /// body of an HTTP request. The class provides multiple methods for + /// reading stored data, however, unless the content is buffered into + /// memory, the data can be read only once. If you plan to read data more + /// than once, you should load content's data into memory by calling + /// CopyInfoBufferAsync. + public sealed class HttpContent + { + private IHttpContent _rawContent; // Container with data. + + /// + /// Gets content type. + /// + public string ContentType { get; private set; } + + /// + /// Creates a content from the given string. + /// + /// String content. + /// HTTP content type. + /// Content object. + public static HttpContent CreateFromText(string text, string contentType) + { + if (text == null) + { + throw new ArgumentNullException("text"); + } + if (contentType == null) + { + throw new ArgumentNullException("contentType"); + } + + return new HttpContent( + new MemoryContent(text), + contentType); + } + + /// + /// Creates a content from binary data specified in the array. + /// + /// Binary data. + /// Content object. + public static HttpContent CreateFromByteArray(byte[] bytes) + { + if (bytes == null) + { + throw new ArgumentNullException("bytes"); + } + + return new HttpContent(new MemoryContent(bytes)); + } + + /// + /// Creates a content from binary data specified in the stream. + /// + /// Binary data. + /// Content object. + public static HttpContent CreateFromStream(IInputStream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + return new HttpContent(new StreamContent(stream.AsStreamForRead())); + } + + /// + /// Initializes the content. + /// + /// Content container. + /// Content type. + private HttpContent(IHttpContent rawContent, string contentType = null) + { + _rawContent = rawContent; + ContentType = contentType; + } + + /// + /// Reads content as a string. + /// + /// Content string. + public IAsyncOperation ReadAsStringAsync() + { + return _rawContent + .ReadAsStringAsync() + .AsAsyncOperation(); + } + + /// + /// Reads content as a byte array. + /// + /// Content bytes. + public IAsyncOperation> ReadAsByteArrayAsync() + { + //TODO: this mehtod returns IEnumerable instead of byte[] because + // winmd does not accept arrays as return values. Check this with the + // latest version and make this method consistent with + // CreateFromByteArray method. + return _rawContent + .ReadAsBytesAsync() + .ContinueWith>(t => t.Result, TaskContinuationOptions.OnlyOnRanToCompletion) + .AsAsyncOperation(); + } + + /// + /// Reads content as a stream of bytes. + /// + /// Content bytes. + public IAsyncOperation ReadAsStreamAsync() + { + return _rawContent + .ReadAsStreamAsync() + .ContinueWith(t => t.Result.AsInputStream(), TaskContinuationOptions.OnlyOnRanToCompletion) + .AsAsyncOperation(); + } + + /// + /// Copies content into the given stream. + /// + /// Target stream. + /// Result of the operation. + public IAsyncAction CopyToAsync(IOutputStream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + return _rawContent + .CopyToAsync(stream.AsStreamForWrite()) + .AsAsyncAction(); + } + + /// + /// Copies content into an internal buffer allowing multiple read + /// operations. + /// + /// Result of the operation. + public IAsyncAction CopyToBufferAsync() + { + return _rawContent.BufferContentAsync() + .ContinueWith(t => { _rawContent = t.Result; }, TaskContinuationOptions.OnlyOnRanToCompletion) + .AsAsyncAction(); + } + + /// + /// Submits content data into the given request. + /// + /// Target request. + internal void SubmitTo(HttpRequestMessage request) + { + NetHttpContent content = new System.Net.Http.StreamContent( + _rawContent.ReadAsStreamAsync().Result); + + if (!string.IsNullOrEmpty(ContentType)) + { + content.Headers.Add("Content-Type", ContentType); + } + request.Content = content; + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/IHttpContent.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/IHttpContent.cs new file mode 100644 index 000000000000..8f0d9c40c193 --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/IHttpContent.cs @@ -0,0 +1,65 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.WindowsAzure.ServiceLayer.Http +{ + /// + /// Content interface. The interface is used to hide details on physical + /// storage mechanism. + /// + internal interface IHttpContent + { + /// + /// Reads content as a string. + /// + /// Content string. + Task ReadAsStringAsync(); + + /// + /// Reads content as an array of bytes. + /// + /// Content bytes. + Task ReadAsBytesAsync(); + + /// + /// Reads content as a stream. + /// + /// Content bytes. + Task ReadAsStreamAsync(); + + /// + /// Copies content into the given stream. + /// + /// Target stream. + /// Result of the operation. + Task CopyToAsync(Stream stream); + + /// + /// Buffers content into memory. + /// + /// Buffered content. + /// Buffering content allows multiple reading operations from + /// the same content. Without buffering, data from stream-based content + /// can be read only once. + Task BufferContentAsync(); + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/MemoryContent.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/MemoryContent.cs new file mode 100644 index 000000000000..82a935bd352c --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/MemoryContent.cs @@ -0,0 +1,109 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.WindowsAzure.ServiceLayer.Http +{ + /// + /// A content whose data is stored in memory. + /// + internal class MemoryContent: IHttpContent + { + private byte[] _bytes; // Memory content. + + /// + /// Initializes content with the text. + /// + /// Content text. + internal MemoryContent(string text) + { + Debug.Assert(text != null); + _bytes = Encoding.UTF8.GetBytes(text); + } + + /// + /// Initializes content with the array of bytes. + /// + /// Content bytes. + internal MemoryContent(byte[] bytes) + { + Debug.Assert(bytes != null); + _bytes = bytes; + } + + /// + /// Reads content as a string. + /// + /// Content string. + Task IHttpContent.ReadAsStringAsync() + { + using (MemoryStream stream = new MemoryStream(_bytes)) + { + StreamReader reader = new StreamReader(stream); + return reader.ReadToEndAsync(); + } + } + + /// + /// Reads content as a bytes array. + /// + /// Content bytes. + Task IHttpContent.ReadAsBytesAsync() + { + TaskCompletionSource completion = new TaskCompletionSource(); + completion.SetResult(_bytes); + return completion.Task; + } + + /// + /// Reads content as a stream. + /// + /// Content bytes in a stream. + Task IHttpContent.ReadAsStreamAsync() + { + TaskCompletionSource completion = new TaskCompletionSource(); + completion.SetResult(new MemoryStream(_bytes)); + return completion.Task; + } + + /// + /// Copies content into the given stream. + /// + /// Destination stream. + /// Result of the operation. + Task IHttpContent.CopyToAsync(Stream stream) + { + return stream.WriteAsync(_bytes, 0, _bytes.Length); + } + + /// + /// Buffers content into memory. + /// + /// Buffered content. + Task IHttpContent.BufferContentAsync() + { + TaskCompletionSource completion = new TaskCompletionSource(); + completion.SetResult(this); + return completion.Task; + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/StreamContent.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/StreamContent.cs new file mode 100644 index 000000000000..ec02a1738fff --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/StreamContent.cs @@ -0,0 +1,106 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.WindowsAzure.ServiceLayer.Http +{ + /// + /// Stream-based content. + /// + internal class StreamContent: IHttpContent + { + private Stream _stream; // Data stream. + + /// + /// Initializes the content with the stream data. + /// + /// Content stream. + internal StreamContent(Stream stream) + { + Debug.Assert(stream != null); + _stream = stream; + } + + /// + /// Reads content as a string. + /// + /// Content string. + Task IHttpContent.ReadAsStringAsync() + { + StreamReader reader = new StreamReader(_stream); + return reader.ReadToEndAsync(); + } + + /// + /// Reads content as a bytes array. + /// + /// Content bytes. + Task IHttpContent.ReadAsBytesAsync() + { + MemoryStream buffer = new MemoryStream(); + return _stream + .CopyToAsync(buffer) + .ContinueWith(t => buffer.ToArray(), TaskContinuationOptions.OnlyOnRanToCompletion); + } + + /// + /// Reads content as a stream of bytes. + /// + /// Content bytes. + Task IHttpContent.ReadAsStreamAsync() + { + TaskCompletionSource completion = new TaskCompletionSource(); + completion.SetResult(_stream); + return completion.Task; + } + + /// + /// Copies content into the given stream. + /// + /// Destination stream. + /// Result of the operation. + Task IHttpContent.CopyToAsync(Stream stream) + { + return _stream.CopyToAsync(stream); + } + + /// + /// Buffers content into memory making all its read operations + /// reusable. + /// + /// Buffered content. + Task IHttpContent.BufferContentAsync() + { + MemoryStream buffer = new MemoryStream(); + + return _stream + .CopyToAsync(buffer) + .ContinueWith(t => + { + buffer.Flush(); + byte[] bytes = buffer.ToArray(); + buffer.Dispose(); + return new MemoryContent(bytes) as IHttpContent; + }, TaskContinuationOptions.OnlyOnRanToCompletion); + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Microsoft.WindowsAzure.ServiceLayer.csproj b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Microsoft.WindowsAzure.ServiceLayer.csproj index 9b78a2f7f42e..880172b39917 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Microsoft.WindowsAzure.ServiceLayer.csproj +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Microsoft.WindowsAzure.ServiceLayer.csproj @@ -105,6 +105,10 @@ true + + + + @@ -115,6 +119,7 @@ + diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/BrokeredMessageSettings.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/BrokeredMessageSettings.cs index c4d1e9ac3998..b9f719741331 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/BrokeredMessageSettings.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/BrokeredMessageSettings.cs @@ -16,13 +16,16 @@ using System; using System.Collections.Generic; using System.IO; -using System.Net.Http; using System.Text; using System.Threading.Tasks; +using Microsoft.WindowsAzure.ServiceLayer.Http; using Windows.Foundation; using Windows.Foundation.Metadata; using Windows.Storage.Streams; +using NetHttpContent = System.Net.Http.HttpContent; +using NetHttpRequestMessage = System.Net.Http.HttpRequestMessage; + namespace Microsoft.WindowsAzure.ServiceLayer.ServiceBus { /// @@ -30,17 +33,13 @@ namespace Microsoft.WindowsAzure.ServiceLayer.ServiceBus /// public sealed class BrokeredMessageSettings { - private HttpContent _content; // Body content. private BrokerProperties _brokerProperties; // Message's broker properties. private CustomPropertiesDictionary _customProperties; // Custom properties of the message. /// - /// Gets the content type of the message. + /// Message content. /// - public string ContentType - { - get { return _content.Headers.ContentType.ToString(); } - } + public HttpContent Content { get; private set; } /// /// Gets or sets the identifier of the correlation. @@ -133,99 +132,66 @@ public string To } /// - /// Constructor for a message consisting of text. - /// - /// Text of the message. - private BrokeredMessageSettings(string contentType, string messageText) - { - if (contentType == null) - { - throw new ArgumentNullException("contentType"); - } - if (messageText == null) - { - throw new ArgumentNullException("messageText"); - } - - _content = new StringContent(messageText, Encoding.UTF8, contentType); - _brokerProperties = new BrokerProperties(); - _customProperties = new CustomPropertiesDictionary(); - } - - /// - /// Constructor for a message consisting of bytes. + /// Constructor. /// - /// Content type. - /// Content of the message. - private BrokeredMessageSettings(byte[] messageBytes) + /// Message content. + public BrokeredMessageSettings(HttpContent content) { - if (messageBytes == null) + if (content == null) { - throw new ArgumentNullException("messageBytes"); + throw new ArgumentNullException("content"); } - _content = new ByteArrayContent(messageBytes); - _brokerProperties = new BrokerProperties(); - _customProperties = new CustomPropertiesDictionary(); - } - - /// - /// Constructor for a message with the content specified in the stream. - /// - /// Content type. - /// Stream with the content. - private BrokeredMessageSettings(IInputStream stream) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - _content = new StreamContent(stream.AsStreamForRead()); + Content = content; _brokerProperties = new BrokerProperties(); _customProperties = new CustomPropertiesDictionary(); } /// /// Creates a message from the given text. This method exists only - /// becase JavaScript cannot work with multiple constructors with + /// because JavaScript cannot work with multiple constructors with /// identical number of parameters. /// - /// Content type. /// Message text. + /// Content type. /// Message settings. - public static BrokeredMessageSettings CreateFromText(string contentType, string messageText) + public static BrokeredMessageSettings CreateFromText(string messageText, string contentType = Constants.DefaultMessageContentType) { if (messageText == null) { throw new ArgumentNullException("messageText"); } + if (contentType == null) + { + throw new ArgumentNullException("contentType"); + } - return new BrokeredMessageSettings(contentType: contentType, messageText: messageText); + HttpContent content = HttpContent.CreateFromText(messageText, contentType); + return new BrokeredMessageSettings(content); } /// - /// Creates a message object from the array of bytes. This method - /// simply instantiates the object with the corresponding constructor; - /// it is defined only because JavaScript does not support multiple - /// constructors with the same number of parameters. + /// Creates a message from the array of bytes. This method exists only + /// because JavaScript cannot work with multiple constructors with + /// identical number of parameters. /// /// Array of bytes. /// Message settings. - public static BrokeredMessageSettings CreateFromBytes(byte[] messageBytes) + public static BrokeredMessageSettings CreateFromByteArray(byte[] messageBytes) { if (messageBytes == null) { throw new ArgumentNullException("messageBytes"); } - return new BrokeredMessageSettings(messageBytes); + HttpContent content = HttpContent.CreateFromByteArray(messageBytes); + return new BrokeredMessageSettings(content); } /// - /// Creates a message object from the given stream. This method - /// exists only because JavaScript does not support having multiple - /// constructors with the same number of parameters. + /// Creates a message from the given stream. The method exists only + /// because JavaScript cannot work with multiple constructors with + /// identical number of parameters. /// /// Stream with message data. /// Message settings. @@ -236,70 +202,20 @@ public static BrokeredMessageSettings CreateFromStream(IInputStream stream) throw new ArgumentNullException("stream"); } - return new BrokeredMessageSettings(stream); + HttpContent content = HttpContent.CreateFromStream(stream); + return new BrokeredMessageSettings(content); } - /// - /// Reads message's body as a string. This method is not thread-safe. - /// - /// Message body. - public IAsyncOperation ReadContentAsStringAsync() - { - return _content - .ReadAsStringAsync() - .AsAsyncOperation(); - } - - /// - /// Reads message's body as an array of bytes. - /// - /// Message body. - public IAsyncOperation> ReadContentAsBytesAsync() - { - return _content - .ReadAsByteArrayAsync() - .ContinueWith(t => (IEnumerable)t.Result, TaskContinuationOptions.OnlyOnRanToCompletion) - .AsAsyncOperation(); - } - - /// - /// Gets stream with the content of the message. - /// - /// Stream with the content. - public IAsyncOperation ReadContentAsStreamAsync() - { - return _content - .ReadAsStreamAsync() - .ContinueWith(t => t.Result.AsInputStream(), TaskContinuationOptions.OnlyOnRanToCompletion) - .AsAsyncOperation(); - } - - /// - /// Copies content of the body to the given stream. - /// - /// Target stream. - /// Result of the operation. - public IAsyncAction CopyContentToAsync(IOutputStream stream) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - return _content - .CopyToAsync(stream.AsStreamForWrite()) - .AsAsyncAction(); - } /// /// Submits content to the given request. /// /// Target request. - internal void SubmitTo(HttpRequestMessage request) + internal void SubmitTo(NetHttpRequestMessage request) { _brokerProperties.SubmitTo(request); _customProperties.SubmitTo(request); - request.Content = _content; + Content.SubmitTo(request); } } } diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/MessageHelper.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/MessageHelper.cs new file mode 100644 index 000000000000..f6738ea47576 --- /dev/null +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/MessageHelper.cs @@ -0,0 +1,42 @@ +// +// Copyright 2012 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.WindowsAzure.ServiceLayer.Http; + +namespace Microsoft.WindowsAzure.ServiceLayer.ServiceBus +{ + /// + /// Helper class for dealing with messages. + /// + internal static class MessageHelper + { + /// + /// Creates a brokered message with the text content. + /// + /// Message text. + /// Brokered message. + internal static BrokeredMessageSettings CreateTextMessage(string messageText) + { + HttpContent content = HttpContent.CreateFromText(messageText, "text/plain"); + BrokeredMessageSettings message = new BrokeredMessageSettings(content); + return message; + } + } +} diff --git a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/ServiceBusRestProxy.cs b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/ServiceBusRestProxy.cs index 773b5313578d..a4e7caa6661f 100644 --- a/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/ServiceBusRestProxy.cs +++ b/microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/ServiceBus/ServiceBusRestProxy.cs @@ -102,8 +102,6 @@ IAsyncOperation> IServiceBusService.ListQueuesAsync(int f ServiceConfig.GetQueuesContainerUri(), firstItem, count, InitQueue); - - throw new NotImplementedException(); } /// @@ -622,7 +620,7 @@ IAsyncOperation IServiceBusService.PeekQueueMessageAsync(st Uri uri = ServiceConfig.GetUnlockedMessageUri(queueName, lockInterval); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri); - return SendAsync(request) + return SendAsync(request, CheckNoContent) .ContinueWith((t) => BrokeredMessageInfo.CreateFromPeekResponse(t.Result), TaskContinuationOptions.OnlyOnRanToCompletion) .AsAsyncOperation(); }