public void CloneAllocatesWhenSectionsArePopulated() { var body = AmqpMessageBody.FromValue("this is an awesome value!"); var source = new AmqpAnnotatedMessage(body); source.Footer.Add("footOne", "1111"); source.ApplicationProperties.Add("appProp", "1111"); var clone = source.Clone(); // Body Assert.That(ReferenceEquals(clone.Body, source.Body), Is.False, "The message body should not be the same instance."); Assert.That(source.Body.TryGetValue(out var sourceBody), Is.True, "The source should have a value body."); Assert.That(clone.Body.TryGetValue(out var cloneBody), Is.True, "The clone should have a value body."); Assert.That(cloneBody, Is.EqualTo(sourceBody), "The body data should match."); // Other sections Assert.That(clone.HasSection(AmqpMessageSection.Body), Is.True, "The body should be populated."); Assert.That(clone.HasSection(AmqpMessageSection.Footer), Is.True, "The footer should be populated."); Assert.That(clone.HasSection(AmqpMessageSection.ApplicationProperties), Is.True, "The application properties should be populated."); Assert.That(clone.HasSection(AmqpMessageSection.Header), Is.False, "The header should not be populated."); Assert.That(clone.HasSection(AmqpMessageSection.Properties), Is.False, "The properties should not be populated."); Assert.That(clone.HasSection(AmqpMessageSection.DeliveryAnnotations), Is.False, "The delivery annotations should not be populated."); Assert.That(clone.HasSection(AmqpMessageSection.MessageAnnotations), Is.False, "The message annotations should not be populated."); }
public async Task CanRoundTripAbsoluteExpiryCreationTime() { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var message = new ServiceBusMessage(); var amqpMessage = message.GetRawAmqpMessage(); // body amqpMessage.Body = AmqpMessageBody.FromValue("body"); // properties var expiry = DateTimeOffset.Now.AddDays(1); var creation = DateTimeOffset.Now.AddMinutes(1); amqpMessage.Properties.AbsoluteExpiryTime = expiry; amqpMessage.Properties.CreationTime = creation; var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var sender = client.CreateSender(scope.QueueName); var now = DateTimeOffset.UtcNow; await sender.SendMessageAsync(message); var receiver = client.CreateReceiver(scope.QueueName); var received = (await receiver.ReceiveMessageAsync()).GetRawAmqpMessage(); received.Body.TryGetValue(out var body); Assert.AreEqual("body", body); Assert.AreEqual(expiry.ToUnixTimeSeconds(), received.Properties.AbsoluteExpiryTime.Value.ToUnixTimeSeconds()); Assert.AreEqual(creation.ToUnixTimeSeconds(), received.Properties.CreationTime.Value.ToUnixTimeSeconds()); } }
public async Task CanSendValueSection(object value) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false)) { var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var sender = client.CreateSender(scope.QueueName); var msg = new ServiceBusMessage(); msg.GetRawAmqpMessage().Body = AmqpMessageBody.FromValue(value); await sender.SendMessageAsync(msg); var receiver = client.CreateReceiver(scope.QueueName); var received = await receiver.ReceiveMessageAsync(); received.GetRawAmqpMessage().Body.TryGetValue(out var receivedData); Assert.AreEqual(value, receivedData); Assert.That( () => received.Body, Throws.InstanceOf <NotSupportedException>()); var sendable = new ServiceBusMessage(received); sendable.GetRawAmqpMessage().Body.TryGetValue(out var sendData); Assert.AreEqual(value, sendData); } }
public void CannotUseCustomType() { Assert.That( () => AmqpMessageBody.FromValue(new Test()), Throws.InstanceOf <NotSupportedException>()); Assert.That( () => AmqpMessageBody.FromSequence(Enumerable.Repeat(new Test[] { new Test() }, 1)), Throws.InstanceOf <NotSupportedException>()); }
public void BodyIsDetectedByHasSection() { var message = new AmqpAnnotatedMessage(EmptyDataBody); message.Body = null; Assert.False(message.HasSection(AmqpMessageSection.Body)); message.Body = AmqpMessageBody.FromValue("this is a string value"); Assert.True(message.HasSection(AmqpMessageSection.Body)); }
public void Convert_ValueBodyMessage_String() { ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage(); message.GetRawAmqpMessage().Body = AmqpMessageBody.FromValue("value"); MessageToStringConverter converter = new MessageToStringConverter(); string result = converter.Convert(message); Assert.AreEqual("value", result); }
public void Convert_ValueBodyMessage_NonStringThrows() { ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage(); message.GetRawAmqpMessage().Body = AmqpMessageBody.FromValue(5); MessageToStringConverter converter = new MessageToStringConverter(); Assert.That( () => converter.Convert(message), Throws.InstanceOf <NotSupportedException>()); }
public void CannotCreateFromNullBody() { Assert.That( () => AmqpMessageBody.FromData(data: null), Throws.InstanceOf <ArgumentNullException>()); Assert.That( () => AmqpMessageBody.FromValue(value: null), Throws.InstanceOf <ArgumentNullException>()); Assert.That( () => AmqpMessageBody.FromSequence(sequence: null), Throws.InstanceOf <ArgumentNullException>()); }
public void CanCreateValueBody(object input) { var body = AmqpMessageBody.FromValue(input); Assert.AreEqual(AmqpMessageBodyType.Value, body.BodyType); Assert.IsTrue(body.TryGetValue(out var output)); Assert.AreEqual(input, output); Assert.IsFalse(body.TryGetData(out var data)); Assert.IsNull(data); Assert.IsFalse(body.TryGetSequence(out var sequence)); Assert.IsNull(sequence); }
public void GetEventBodyDoesNotAllowNonDataBodyTypes(AmqpMessageBodyType bodyType) { var body = bodyType switch { AmqpMessageBodyType.Sequence => AmqpMessageBody.FromSequence(new[] { new List <object> { 1, 2, 3 } }), AmqpMessageBodyType.Value => AmqpMessageBody.FromValue("This is a value"), _ => throw new ArgumentException($"Unsupported body type { bodyType }", nameof(bodyType)) }; var message = new AmqpAnnotatedMessage(body); Assert.That(() => message.GetEventBody(), Throws.InstanceOf <NotSupportedException>()); }
/// <summary> /// Creates a new message from the specified received message by copying the properties. /// </summary> /// <param name="receivedMessage">The received message to copy the data from.</param> public ServiceBusMessage(ServiceBusReceivedMessage receivedMessage) { Argument.AssertNotNull(receivedMessage, nameof(receivedMessage)); AmqpMessageBody body = null; if (receivedMessage.AmqpMessage.Body.TryGetData(out IEnumerable <ReadOnlyMemory <byte> > dataBody)) { body = AmqpMessageBody.FromData(MessageBody.FromReadOnlyMemorySegments(dataBody)); } else if (receivedMessage.AmqpMessage.Body.TryGetValue(out object valueBody)) { body = AmqpMessageBody.FromValue(valueBody); } else if (receivedMessage.AmqpMessage.Body.TryGetSequence(out IEnumerable <IList <object> > sequenceBody)) { body = AmqpMessageBody.FromSequence(sequenceBody); } else { throw new NotSupportedException($"{receivedMessage.AmqpMessage.Body.BodyType} is not a supported message body type."); } AmqpMessage = new AmqpAnnotatedMessage(body); // copy properties AmqpMessageProperties properties = AmqpMessage.Properties; AmqpMessageProperties receivedProperties = receivedMessage.AmqpMessage.Properties; properties.MessageId = receivedProperties.MessageId; properties.UserId = receivedProperties.UserId; properties.To = receivedProperties.To; properties.Subject = receivedProperties.Subject; properties.ReplyTo = receivedProperties.ReplyTo; properties.CorrelationId = receivedProperties.CorrelationId; properties.ContentType = receivedProperties.ContentType; properties.ContentEncoding = receivedProperties.ContentEncoding; properties.AbsoluteExpiryTime = receivedProperties.AbsoluteExpiryTime; properties.CreationTime = receivedProperties.CreationTime; properties.GroupId = receivedProperties.GroupId; properties.GroupSequence = receivedProperties.GroupSequence; properties.ReplyToGroupId = receivedProperties.ReplyToGroupId; // copy header except for delivery count which should be set to null AmqpMessageHeader header = AmqpMessage.Header; AmqpMessageHeader receivedHeader = receivedMessage.AmqpMessage.Header; header.DeliveryCount = null; header.Durable = receivedHeader.Durable; header.Priority = receivedHeader.Priority; header.TimeToLive = receivedHeader.TimeToLive; header.FirstAcquirer = receivedHeader.FirstAcquirer; // copy message annotations except for broker set ones foreach (KeyValuePair <string, object> kvp in receivedMessage.AmqpMessage.MessageAnnotations) { if (kvp.Key == AmqpMessageConstants.LockedUntilName || kvp.Key == AmqpMessageConstants.SequenceNumberName || kvp.Key == AmqpMessageConstants.DeadLetterSourceName || kvp.Key == AmqpMessageConstants.EnqueueSequenceNumberName || kvp.Key == AmqpMessageConstants.EnqueuedTimeUtcName || kvp.Key == AmqpMessageConstants.MessageStateName) { continue; } AmqpMessage.MessageAnnotations.Add(kvp.Key, kvp.Value); } // copy delivery annotations foreach (KeyValuePair <string, object> kvp in receivedMessage.AmqpMessage.DeliveryAnnotations) { AmqpMessage.DeliveryAnnotations.Add(kvp.Key, kvp.Value); } // copy footer foreach (KeyValuePair <string, object> kvp in receivedMessage.AmqpMessage.Footer) { AmqpMessage.Footer.Add(kvp.Key, kvp.Value); } // copy application properties except for broker set ones foreach (KeyValuePair <string, object> kvp in receivedMessage.AmqpMessage.ApplicationProperties) { if (kvp.Key == AmqpMessageConstants.DeadLetterReasonHeader || kvp.Key == AmqpMessageConstants.DeadLetterErrorDescriptionHeader) { continue; } AmqpMessage.ApplicationProperties.Add(kvp.Key, kvp.Value); } }
public static ServiceBusReceivedMessage AmqpMessageToSBMessage(AmqpMessage amqpMessage, bool isPeeked = false) { Argument.AssertNotNull(amqpMessage, nameof(amqpMessage)); AmqpAnnotatedMessage annotatedMessage; if ((amqpMessage.BodyType & SectionFlag.Data) != 0 && amqpMessage.DataBody != null) { annotatedMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromData(BodyMemory.FromAmqpData(amqpMessage.DataBody))); } else if ((amqpMessage.BodyType & SectionFlag.AmqpValue) != 0 && amqpMessage.ValueBody?.Value != null) { if (TryGetNetObjectFromAmqpObject(amqpMessage.ValueBody.Value, MappingType.MessageBody, out object netObject)) { annotatedMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromValue(netObject)); } else { throw new NotSupportedException(Resources.InvalidAmqpMessageValueBody.FormatForUser(amqpMessage.ValueBody.Value.GetType())); } } else if ((amqpMessage.BodyType & SectionFlag.AmqpSequence) != 0) { annotatedMessage = new AmqpAnnotatedMessage( AmqpMessageBody.FromSequence(amqpMessage.SequenceBody.Select(s => (IList <object>)s.List).ToList())); } // default to using an empty Data section if no data else { annotatedMessage = new AmqpAnnotatedMessage(new AmqpMessageBody(Enumerable.Empty <ReadOnlyMemory <byte> >())); } ServiceBusReceivedMessage sbMessage = new ServiceBusReceivedMessage(annotatedMessage); SectionFlag sections = amqpMessage.Sections; if ((sections & SectionFlag.Header) != 0) { if (amqpMessage.Header.Ttl != null) { annotatedMessage.Header.TimeToLive = TimeSpan.FromMilliseconds(amqpMessage.Header.Ttl.Value); } if (amqpMessage.Header.DeliveryCount != null) { annotatedMessage.Header.DeliveryCount = isPeeked ? (amqpMessage.Header.DeliveryCount.Value) : (amqpMessage.Header.DeliveryCount.Value + 1); } } if ((sections & SectionFlag.Properties) != 0) { if (amqpMessage.Properties.MessageId != null) { annotatedMessage.Properties.MessageId = new AmqpMessageId(amqpMessage.Properties.MessageId.ToString()); } if (amqpMessage.Properties.CorrelationId != null) { annotatedMessage.Properties.CorrelationId = new AmqpMessageId(amqpMessage.Properties.CorrelationId.ToString()); } if (amqpMessage.Properties.ContentType.Value != null) { annotatedMessage.Properties.ContentType = amqpMessage.Properties.ContentType.Value; } if (amqpMessage.Properties.Subject != null) { annotatedMessage.Properties.Subject = amqpMessage.Properties.Subject; } if (amqpMessage.Properties.To != null) { annotatedMessage.Properties.To = new AmqpAddress(amqpMessage.Properties.To.ToString()); } if (amqpMessage.Properties.ReplyTo != null) { annotatedMessage.Properties.ReplyTo = new AmqpAddress(amqpMessage.Properties.ReplyTo.ToString()); } if (amqpMessage.Properties.GroupId != null) { annotatedMessage.Properties.GroupId = amqpMessage.Properties.GroupId; } if (amqpMessage.Properties.ReplyToGroupId != null) { annotatedMessage.Properties.ReplyToGroupId = amqpMessage.Properties.ReplyToGroupId; } } // Do application properties before message annotations, because the application properties // can be updated by entries from message annotation. if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (var pair in amqpMessage.ApplicationProperties.Map) { if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.ApplicationProperties[pair.Key.ToString()] = netObject; } } } if ((sections & SectionFlag.MessageAnnotations) != 0) { foreach (var pair in amqpMessage.MessageAnnotations.Map) { var key = pair.Key.ToString(); switch (key) { case AmqpMessageConstants.EnqueuedTimeUtcName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueuedTimeUtcName] = pair.Value; break; case AmqpMessageConstants.ScheduledEnqueueTimeUtcName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.ScheduledEnqueueTimeUtcName] = pair.Value; break; case AmqpMessageConstants.SequenceNumberName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.SequenceNumberName] = pair.Value; break; case AmqpMessageConstants.EnqueueSequenceNumberName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.EnqueueSequenceNumberName] = pair.Value; break; case AmqpMessageConstants.LockedUntilName: DateTimeOffset lockedUntil = (DateTime)pair.Value >= DateTimeOffset.MaxValue.UtcDateTime ? DateTimeOffset.MaxValue : (DateTime)pair.Value; annotatedMessage.MessageAnnotations[AmqpMessageConstants.LockedUntilName] = lockedUntil.UtcDateTime; break; case AmqpMessageConstants.PartitionKeyName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionKeyName] = pair.Value; break; case AmqpMessageConstants.PartitionIdName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.PartitionIdName] = pair.Value; break; case AmqpMessageConstants.ViaPartitionKeyName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.ViaPartitionKeyName] = pair.Value; break; case AmqpMessageConstants.DeadLetterSourceName: annotatedMessage.MessageAnnotations[AmqpMessageConstants.DeadLetterSourceName] = pair.Value; break; default: if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out var netObject)) { annotatedMessage.MessageAnnotations[key] = netObject; } break; } } } if (amqpMessage.DeliveryTag.Count == GuidSizeInBytes) { Span <byte> guidBytes = stackalloc byte[GuidSizeInBytes]; amqpMessage.DeliveryTag.AsSpan().CopyTo(guidBytes); if (!MemoryMarshal.TryRead <Guid>(guidBytes, out var lockTokenGuid)) { lockTokenGuid = new Guid(guidBytes.ToArray()); } sbMessage.LockTokenGuid = lockTokenGuid; } amqpMessage.Dispose(); return(sbMessage); }
public async Task CanRoundTripAmqpProperties(bool enableSession) { await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: enableSession)) { var message = new ServiceBusMessage(); var amqpMessage = message.GetRawAmqpMessage(); // body amqpMessage.Body = AmqpMessageBody.FromValue("body"); // header amqpMessage.Header.TimeToLive = TimeSpan.FromSeconds(50); amqpMessage.Header.DeliveryCount = 3; amqpMessage.Header.Durable = true; amqpMessage.Header.FirstAcquirer = true; amqpMessage.Header.Priority = 1; // footer amqpMessage.Footer.Add("footerKey1", "footerVal1"); amqpMessage.Footer.Add("footerKey2", "footerVal2"); // properties amqpMessage.Properties.AbsoluteExpiryTime = DateTimeOffset.Now.AddDays(1); amqpMessage.Properties.ContentEncoding = "compress"; amqpMessage.Properties.ContentType = "application/json"; amqpMessage.Properties.CorrelationId = new AmqpMessageId("correlationId"); amqpMessage.Properties.CreationTime = DateTimeOffset.Now.AddDays(1); amqpMessage.Properties.GroupId = "groupId"; amqpMessage.Properties.GroupSequence = 5; amqpMessage.Properties.MessageId = new AmqpMessageId("messageId"); amqpMessage.Properties.ReplyTo = new AmqpAddress("replyTo"); amqpMessage.Properties.ReplyToGroupId = "replyToGroupId"; amqpMessage.Properties.Subject = "subject"; amqpMessage.Properties.To = new AmqpAddress("to"); amqpMessage.Properties.UserId = new byte[] { 1, 2, 3 }; // application properties amqpMessage.ApplicationProperties.Add("applicationKey1", "applicationVal1"); amqpMessage.ApplicationProperties.Add("applicationKey2", "applicationVal2"); // message annotations amqpMessage.MessageAnnotations.Add("messageAnnotationKey1", "messageAnnotationVal1"); amqpMessage.MessageAnnotations.Add("messageAnnotationKey2", "messageAnnotationVal2"); // delivery annotations amqpMessage.DeliveryAnnotations.Add("deliveryAnnotationKey1", "deliveryAnnotationVal1"); amqpMessage.DeliveryAnnotations.Add("deliveryAnnotationKey2", "deliveryAnnotationVal2"); var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString); var sender = client.CreateSender(scope.QueueName); var now = DateTimeOffset.UtcNow; await sender.SendMessageAsync(message); var receiver = enableSession ? await client.AcceptNextSessionAsync(scope.QueueName) : client.CreateReceiver(scope.QueueName); var received = (await receiver.ReceiveMessageAsync()).GetRawAmqpMessage(); received.Body.TryGetValue(out var body); Assert.AreEqual("body", body); Assert.AreEqual(TimeSpan.FromSeconds(50), received.Header.TimeToLive); // the broker will disregard the value set for delivery count Assert.AreEqual(1, received.Header.DeliveryCount); Assert.IsTrue(received.Header.Durable); Assert.IsTrue(received.Header.FirstAcquirer); Assert.AreEqual(1, received.Header.Priority); Assert.AreEqual("compress", received.Properties.ContentEncoding); Assert.AreEqual("application/json", received.Properties.ContentType); Assert.AreEqual(new AmqpMessageId("correlationId"), received.Properties.CorrelationId); Assert.AreEqual("groupId", received.Properties.GroupId); Assert.AreEqual(5, received.Properties.GroupSequence); Assert.AreEqual(new AmqpMessageId("messageId"), received.Properties.MessageId); Assert.AreEqual(new AmqpAddress("replyTo"), received.Properties.ReplyTo); Assert.AreEqual("replyToGroupId", received.Properties.ReplyToGroupId); Assert.AreEqual("subject", received.Properties.Subject); Assert.AreEqual(new AmqpAddress("to"), received.Properties.To); Assert.AreEqual(new byte[] { 1, 2, 3 }, received.Properties.UserId.Value.ToArray()); // since TTL was set these were overriden - provide some buffer since the Now time is Assert.That(received.Properties.CreationTime, Is.EqualTo(now).Within(TimeSpan.FromSeconds(1))); Assert.That(received.Properties.AbsoluteExpiryTime, Is.EqualTo(now.Add(TimeSpan.FromSeconds(50))).Within(TimeSpan.FromSeconds(1))); // application properties Assert.AreEqual(received.ApplicationProperties["applicationKey1"], "applicationVal1"); Assert.AreEqual(received.ApplicationProperties["applicationKey2"], "applicationVal2"); // message annotations Assert.AreEqual(received.MessageAnnotations["messageAnnotationKey1"], "messageAnnotationVal1"); Assert.AreEqual(received.MessageAnnotations["messageAnnotationKey2"], "messageAnnotationVal2"); // delivery annotations Assert.AreEqual(received.DeliveryAnnotations["deliveryAnnotationKey1"], "deliveryAnnotationVal1"); Assert.AreEqual(received.DeliveryAnnotations["deliveryAnnotationKey2"], "deliveryAnnotationVal2"); } }