Beispiel #1
0
        public void CloneDoesNotForceAllocationOfUnpopulatedSections()
        {
            var firstBody = new List <object> {
                1, 2, 3
            };
            var secondBody = new List <object> {
                4, 5, 6
            };
            var body   = AmqpMessageBody.FromSequence(new[] { firstBody, secondBody });
            var source = new AmqpAnnotatedMessage(body);
            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.TryGetSequence(out var sourceBody), Is.True, "The source should have a sequence body.");
            Assert.That(clone.Body.TryGetSequence(out var cloneBody), Is.True, "The clone should have a sequence body.");
            Assert.That(cloneBody, Is.EquivalentTo(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.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.Footer), Is.False, "The footer should 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.");
            Assert.That(clone.HasSection(AmqpMessageSection.ApplicationProperties), Is.False, "The application properties should not be populated.");
        }
Beispiel #2
0
        public async Task CanSendSequenceSection(IEnumerable <IList <object> > sequence)
        {
            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.FromSequence(sequence);

                await sender.SendMessageAsync(msg);

                var receiver = client.CreateReceiver(scope.QueueName);
                var received = await receiver.ReceiveMessageAsync();

                received.GetRawAmqpMessage().Body.TryGetSequence(out IEnumerable <IList <object> > receivedData);
                var outerEnum = receivedData.GetEnumerator();
                foreach (IList <object> seq in sequence)
                {
                    outerEnum.MoveNext();
                    var innerEnum = outerEnum.Current.GetEnumerator();
                    foreach (object elem in seq)
                    {
                        innerEnum.MoveNext();
                        Assert.AreEqual(elem, innerEnum.Current);
                    }
                }

                Assert.That(
                    () => received.Body,
                    Throws.InstanceOf <NotSupportedException>());
            }
        }
Beispiel #3
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 Convert_SequenceBodyMessage_Throws()
        {
            ServiceBusReceivedMessage message = ServiceBusModelFactory.ServiceBusReceivedMessage();

            message.GetRawAmqpMessage().Body = AmqpMessageBody.FromSequence(new IList <object>[] { new object[] { "sequence" } });

            MessageToStringConverter converter = new MessageToStringConverter();

            Assert.That(
                () => converter.Convert(message),
                Throws.InstanceOf <NotSupportedException>());
        }
Beispiel #5
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>());
        }
Beispiel #6
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>());
        }
Beispiel #7
0
        public void CanCreateSequenceBody()
        {
            var sequence = new List <object>[] { new List <object> {
                                                     1, "two"
                                                 }, new List <object> {
                                                     3, "four"
                                                 } };
            var body = AmqpMessageBody.FromSequence(sequence);

            Assert.AreEqual(AmqpMessageBodyType.Sequence, body.BodyType);
            Assert.IsTrue(body.TryGetSequence(out var outSequence));
            var outList = outSequence.ToList();

            Assert.AreEqual(1, outList[0][0]);
            Assert.AreEqual("two", outList[0][1]);
            Assert.AreEqual(3, outList[1][0]);
            Assert.AreEqual("four", outList[1][1]);

            Assert.IsFalse(body.TryGetData(out var data));
            Assert.IsNull(data);

            Assert.IsFalse(body.TryGetValue(out var value));
            Assert.IsNull(value);
        }
Beispiel #8
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);
            }
        }
Beispiel #9
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);
        }