Exemple #1
0
        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.");
        }
Exemple #2
0
        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());
            }
        }
Exemple #3
0
        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);
            }
        }
Exemple #4
0
        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>());
        }
Exemple #8
0
        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>());
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        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>());
        }
Exemple #11
0
        /// <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);
            }
        }
Exemple #12
0
        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);
        }
Exemple #13
0
        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");
            }
        }