public async Task SendMessageWithNoFeedbackTest()
        {
            // Arrange
            var productInfoStore = Mock.Of <IProductInfoStore>();
            var modelIdStore     = Mock.Of <IModelIdStore>();
            var identity         = Mock.Of <IIdentity>(i => i.Id == "d1");
            var deviceListener   = new Mock <IDeviceListener>();

            deviceListener.Setup(d => d.ProcessMessageFeedbackAsync(It.IsAny <string>(), It.IsAny <FeedbackStatus>()))
            .Returns(Task.CompletedTask);
            AmqpMessage receivedAmqpMessage = null;
            var         connectionHandler   = Mock.Of <IConnectionHandler>(c => c.GetDeviceListener() == Task.FromResult(deviceListener.Object));
            var         amqpAuthenticator   = new Mock <IAmqpAuthenticator>();

            amqpAuthenticator.Setup(c => c.AuthenticateAsync("d1")).ReturnsAsync(true);
            Mock <ICbsNode> cbsNodeMock    = amqpAuthenticator.As <ICbsNode>();
            ICbsNode        cbsNode        = cbsNodeMock.Object;
            var             amqpConnection = Mock.Of <IAmqpConnection>(
                c =>
                c.FindExtension <IConnectionHandler>() == connectionHandler &&
                c.FindExtension <ICbsNode>() == cbsNode);
            var amqpSession      = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var amqpLinkSettings = new AmqpLinkSettings();
            var sendingLink      = Mock.Of <ISendingAmqpLink>(l => l.Session == amqpSession && !l.IsReceiver && l.Settings == amqpLinkSettings && l.State == AmqpObjectState.Opened);

            Mock.Get(sendingLink).Setup(s => s.SendMessageAsync(It.IsAny <AmqpMessage>(), It.IsAny <ArraySegment <byte> >(), It.IsAny <ArraySegment <byte> >(), It.IsAny <TimeSpan>()))
            .Callback <AmqpMessage, ArraySegment <byte>, ArraySegment <byte>, TimeSpan>((m, d, t, ts) => { receivedAmqpMessage = m; })
            .Returns(Task.CompletedTask);

            var requestUri     = new Uri("amqps://foo.bar/devices/d1");
            var boundVariables = new Dictionary <string, string> {
                { "deviceid", "d1" }
            };
            var messageConverter = new AmqpMessageConverter();

            var      sendingLinkHandler = new TestSendingLinkHandler(identity, sendingLink, requestUri, boundVariables, connectionHandler, messageConverter, QualityOfService.AtMostOnce, productInfoStore, modelIdStore);
            var      body    = new byte[] { 0, 1, 2, 3 };
            IMessage message = new EdgeMessage.Builder(body).Build();

            // Act
            await sendingLinkHandler.OpenAsync(TimeSpan.FromSeconds(5));

            await sendingLinkHandler.SendMessage(message);

            // Assert
            Assert.NotNull(receivedAmqpMessage);
            Assert.Equal(body, receivedAmqpMessage.GetPayloadBytes());
            Assert.Equal((byte)SenderSettleMode.Settled, amqpLinkSettings.SndSettleMode);
            Assert.Equal((byte)ReceiverSettleMode.First, amqpLinkSettings.RcvSettleMode);
        }
        /// <summary>
        /// Creates a new <see cref="EventDataBatch"/>.
        /// </summary>
        /// <param name="maxSizeInBytes">The maximum size allowed for the batch</param>
        /// <param name="partitionKey">Partition key associate with the batch</param>
        public EventDataBatch(long maxSizeInBytes, string partitionKey = null)
        {
            PartitionKey  = partitionKey;
            maxSize       = Math.Min(maxSizeInBytes, MaxSizeLimit);
            eventDataList = new List <EventData>();

            // Reserve for wrapper message.
            using (var batchMessage = AmqpMessage.Create())
            {
                batchMessage.MessageFormat = AmqpConstants.AmqpBatchedMessageFormat;
                AmqpMessageConverter.UpdateAmqpMessagePartitionKey(batchMessage, partitionKey);
                currentSize = batchMessage.SerializedMessageSize;
            }
        }
        private long GetEventSizeForBatch(EventData eventData)
        {
            // Create AMQP message here. We will use the same message while sending to save compute time.
            AmqpMessage amqpMessage = AmqpMessageConverter.EventDataToAmqpMessage(eventData);

            AmqpMessageConverter.UpdateAmqpMessagePartitionKey(amqpMessage, PartitionKey);
            eventData.AmqpMessage = amqpMessage;

            // Calculate overhead depending on the message size.
            // Overhead is smaller for messages smaller than 256 bytes.
            long overhead = eventData.AmqpMessage.SerializedMessageSize < 256 ? 5 : 8;

            return(eventData.AmqpMessage.SerializedMessageSize + overhead);
        }
示例#4
0
        void Convert_SB_message_to_Amqp_message_and_back()
        {
            var messageBody     = Encoding.UTF8.GetBytes("hello");
            var messageId       = Guid.NewGuid().ToString();
            var partitionKey    = Guid.NewGuid().ToString();
            var viaPartitionKey = Guid.NewGuid().ToString();
            var sessionId       = Guid.NewGuid().ToString();
            var correlationId   = Guid.NewGuid().ToString();
            var label           = Guid.NewGuid().ToString();
            var to               = Guid.NewGuid().ToString();
            var contentType      = Guid.NewGuid().ToString();
            var replyTo          = Guid.NewGuid().ToString();
            var replyToSessionId = Guid.NewGuid().ToString();
            var publisher        = Guid.NewGuid().ToString();
            var timeToLive       = TimeSpan.FromDays(5);

            var sbMessage = new Message(messageBody)
            {
                MessageId       = messageId,
                PartitionKey    = partitionKey,
                ViaPartitionKey = viaPartitionKey,
                SessionId       = sessionId,
                CorrelationId   = correlationId,
                Label           = label,
                To               = to,
                ContentType      = contentType,
                ReplyTo          = replyTo,
                ReplyToSessionId = replyToSessionId,
                TimeToLive       = timeToLive
            };

            sbMessage.UserProperties.Add("UserProperty", "SomeUserProperty");

            var amqpMessage        = AmqpMessageConverter.SBMessageToAmqpMessage(sbMessage);
            var convertedSbMessage = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);

            Assert.Equal("SomeUserProperty", convertedSbMessage.UserProperties["UserProperty"]);
            Assert.Equal(messageBody, convertedSbMessage.Body);
            Assert.Equal(messageId, convertedSbMessage.MessageId);
            Assert.Equal(partitionKey, convertedSbMessage.PartitionKey);
            Assert.Equal(viaPartitionKey, convertedSbMessage.ViaPartitionKey);
            Assert.Equal(sessionId, convertedSbMessage.SessionId);
            Assert.Equal(correlationId, convertedSbMessage.CorrelationId);
            Assert.Equal(label, convertedSbMessage.Label);
            Assert.Equal(to, convertedSbMessage.To);
            Assert.Equal(contentType, convertedSbMessage.ContentType);
            Assert.Equal(replyTo, convertedSbMessage.ReplyTo);
            Assert.Equal(replyToSessionId, convertedSbMessage.ReplyToSessionId);
            Assert.Equal(timeToLive, convertedSbMessage.TimeToLive);
        }
        public void CreateEventFromMessagePopulatesTheBody()
        {
            var body = new byte[] { 0x11, 0x22, 0x33 };

            using var bodyStream = new MemoryStream(body, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Body.ToArray(), Is.EqualTo(body), "The body contents should match.");
        }
        public void ConvertAmqpMessageToSBMessage()
        {
            var messageBody = Encoding.UTF8.GetBytes("message1");

            var data = new Data();

            data.Value = messageBody;
            var amqpMessage = AmqpMessage.Create(data);

            var sbMessage = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);
            ReadOnlyMemory <byte> sbBody = sbMessage.Body;

            Assert.AreEqual(messageBody, sbBody.ToArray());
        }
        public async Task SendLargeMessageThrowsTest()
        {
            // Arrange
            bool disposeMessageCalled = true;
            var  identity             = Mock.Of <IIdentity>(i => i.Id == "d1");
            var  amqpAuth             = new AmqpAuthentication(true, Option.Some(Mock.Of <IClientCredentials>(c => c.Identity == identity)));

            var deviceListener = Mock.Of <IDeviceListener>();

            Mock.Get(deviceListener).Setup(d => d.ProcessDeviceMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >()))
            .Returns(Task.CompletedTask);

            var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetAmqpAuthentication() == Task.FromResult(amqpAuth) && c.GetDeviceListener() == Task.FromResult(deviceListener));
            var amqpConnection    = Mock.Of <IAmqpConnection>(c => c.FindExtension <IConnectionHandler>() == connectionHandler);
            var amqpSession       = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var amqpLink          = Mock.Of <IReceivingAmqpLink>(l => l.Session == amqpSession && l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened);

            Action <AmqpMessage> onMessageCallback = null;

            Mock.Get(amqpLink).Setup(l => l.RegisterMessageListener(It.IsAny <Action <AmqpMessage> >())).Callback <Action <AmqpMessage> >(a => onMessageCallback = a);
            Mock.Get(amqpLink).SetupGet(l => l.Settings).Returns(new AmqpLinkSettings());
            Mock.Get(amqpLink).Setup(l => l.SafeAddClosed(It.IsAny <EventHandler>()));
            Mock.Get(amqpLink).Setup(l => l.DisposeMessage(It.IsAny <AmqpMessage>(), It.IsAny <Outcome>(), It.IsAny <bool>(), It.IsAny <bool>()))
            .Callback(() => disposeMessageCalled = true);

            var requestUri     = new Uri("amqps://foo.bar/devices/d1/messages/events");
            var boundVariables = new Dictionary <string, string> {
                { "deviceid", "d1" }
            };
            var messageConverter = new AmqpMessageConverter();

            using (AmqpMessage amqpMessage = AmqpMessage.Create(new MemoryStream(new byte[800000]), false))
            {
                amqpMessage.ApplicationProperties.Map["LargeProp"] = new int[600000];
                ILinkHandler linkHandler = new EventsLinkHandler(amqpLink, requestUri, boundVariables, messageConverter);

                // Act
                await linkHandler.OpenAsync(TimeSpan.FromSeconds(30));

                // Assert
                Assert.NotNull(onMessageCallback);

                // Act
                onMessageCallback.Invoke(amqpMessage);

                // Assert
                await WaitAndAssert(() => disposeMessageCalled, TimeSpan.FromSeconds(5));
            }
        }
        async Task <long> OnScheduleMessageAsync(Message message)
        {
            // TODO: Ensure System.Transactions.Transaction.Current is null. Transactions are not supported by 1.0.0 version of dotnet core.
            using (AmqpMessage amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(message))
            {
                var request = AmqpRequestMessage.CreateRequest(
                    ManagementConstants.Operations.ScheduleMessageOperation,
                    this.OperationTimeout,
                    null);

                ArraySegment <byte>[] payload = amqpMessage.GetPayload();
                BufferListStream      buffer  = new BufferListStream(payload);
                ArraySegment <byte>   value   = buffer.ReadBytes((int)buffer.Length);

                var entry = new AmqpMap();
                {
                    entry[ManagementConstants.Properties.Message]   = value;
                    entry[ManagementConstants.Properties.MessageId] = message.MessageId;

                    if (!string.IsNullOrWhiteSpace(message.SessionId))
                    {
                        entry[ManagementConstants.Properties.SessionId] = message.SessionId;
                    }

                    if (!string.IsNullOrWhiteSpace(message.PartitionKey))
                    {
                        entry[ManagementConstants.Properties.PartitionKey] = message.PartitionKey;
                    }
                }

                request.Map[ManagementConstants.Properties.Messages] = new List <AmqpMap> {
                    entry
                };

                IEnumerable <long> sequenceNumbers = null;
                var response = await this.ExecuteRequestResponseAsync(request).ConfigureAwait(false);

                if (response.StatusCode == AmqpResponseStatusCode.OK)
                {
                    sequenceNumbers = response.GetValue <long[]>(ManagementConstants.Properties.SequenceNumbers);
                }
                else
                {
                    response.ToMessagingContractException();
                }

                return(sequenceNumbers?.FirstOrDefault() ?? 0);
            }
        }
示例#9
0
        void Convert_SB_message_to_Amqp_message_and_back()
        {
            var messageBody      = Encoding.UTF8.GetBytes("hello");
            var messageId        = Guid.NewGuid().ToString();
            var partitionKey     = Guid.NewGuid().ToString();
            var sessionId        = Guid.NewGuid().ToString();
            var correlationId    = Guid.NewGuid().ToString();
            var label            = Guid.NewGuid().ToString();
            var to               = Guid.NewGuid().ToString();
            var contentType      = Guid.NewGuid().ToString();
            var replyTo          = Guid.NewGuid().ToString();
            var replyToSessionId = Guid.NewGuid().ToString();
            var publisher        = Guid.NewGuid().ToString();
            var deadLetterSource = Guid.NewGuid().ToString();

            var sbMessage = new Message(messageBody)
            {
                MessageId        = messageId,
                PartitionKey     = partitionKey,
                SessionId        = sessionId,
                CorrelationId    = correlationId,
                Label            = label,
                To               = to,
                ContentType      = contentType,
                ReplyTo          = replyTo,
                ReplyToSessionId = replyToSessionId,
                Publisher        = publisher,
                DeadLetterSource = deadLetterSource,
            };

            sbMessage.UserProperties.Add("UserProperty", "SomeUserProperty");

            var amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(sbMessage);
            var convertedBrokeredMessage = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);

            Assert.Equal("SomeUserProperty", convertedBrokeredMessage.UserProperties["UserProperty"]);
            Assert.Equal(messageBody, convertedBrokeredMessage.Body);
            Assert.Equal(messageId, convertedBrokeredMessage.MessageId);
            Assert.Equal(partitionKey, convertedBrokeredMessage.PartitionKey);
            Assert.Equal(sessionId, convertedBrokeredMessage.SessionId);
            Assert.Equal(correlationId, convertedBrokeredMessage.CorrelationId);
            Assert.Equal(label, convertedBrokeredMessage.Label);
            Assert.Equal(to, convertedBrokeredMessage.To);
            Assert.Equal(contentType, convertedBrokeredMessage.ContentType);
            Assert.Equal(replyTo, convertedBrokeredMessage.ReplyTo);
            Assert.Equal(replyToSessionId, convertedBrokeredMessage.ReplyToSessionId);
            Assert.Equal(publisher, convertedBrokeredMessage.Publisher);
            Assert.Equal(deadLetterSource, convertedBrokeredMessage.DeadLetterSource);
        }
示例#10
0
        public void FromMessageTest()
        {
            // Arrange
            byte[] bytes           = { 1, 2, 3, 4 };
            string messageId       = Guid.NewGuid().ToString();
            string correlationId   = Guid.NewGuid().ToString();
            string contentType     = "UTF-8";
            string contentEncoding = "application/json";

            var systemProperties = new Dictionary <string, string>
            {
                [SystemProperties.MessageId]        = messageId,
                [SystemProperties.MsgCorrelationId] = correlationId,
                [SystemProperties.ContentType]      = contentType,
                [SystemProperties.ContentEncoding]  = contentEncoding,
            };

            var properties = new Dictionary <string, string>
            {
                ["Prop1"] = "Value1",
                ["Prop2"] = "Value2"
            };

            byte[] GetMessageBody(AmqpMessage sourceMessage)
            {
                using (var ms = new MemoryStream())
                {
                    sourceMessage.BodyStream.CopyTo(ms);
                    return(ms.ToArray());
                }
            }

            var message          = new EdgeMessage(bytes, properties, systemProperties);
            var messageConverter = new AmqpMessageConverter();

            // Act
            using (AmqpMessage amqpMessage = messageConverter.FromMessage(message))
            {
                // Assert
                Assert.NotNull(amqpMessage);
                Assert.Equal(bytes, GetMessageBody(amqpMessage));
                Assert.Equal(messageId, amqpMessage.Properties.MessageId.ToString());
                Assert.Equal(correlationId, amqpMessage.Properties.CorrelationId.ToString());
                Assert.Equal(contentEncoding, amqpMessage.Properties.ContentEncoding.ToString());
                Assert.Equal(contentType, amqpMessage.Properties.ContentType.ToString());
                Assert.Equal("Value1", amqpMessage.ApplicationProperties.Map["Prop1"].ToString());
                Assert.Equal("Value2", amqpMessage.ApplicationProperties.Map["Prop2"].ToString());
            }
        }
示例#11
0
        public void ConvertSBMessageToAmqpMessageAndBack()
        {
            var messageBody     = Encoding.UTF8.GetBytes("hello");
            var messageId       = Guid.NewGuid().ToString();
            var partitionKey    = Guid.NewGuid().ToString();
            var viaPartitionKey = Guid.NewGuid().ToString();
            var sessionId       = partitionKey;
            var correlationId   = Guid.NewGuid().ToString();
            var label           = Guid.NewGuid().ToString();
            var to               = Guid.NewGuid().ToString();
            var contentType      = Guid.NewGuid().ToString();
            var replyTo          = Guid.NewGuid().ToString();
            var replyToSessionId = Guid.NewGuid().ToString();
            var timeToLive       = TimeSpan.FromDays(5);

            var sbMessage = new ServiceBusMessage(messageBody)
            {
                MessageId               = messageId,
                PartitionKey            = partitionKey,
                TransactionPartitionKey = viaPartitionKey,
                SessionId               = sessionId,
                CorrelationId           = correlationId,
                Subject          = label,
                To               = to,
                ContentType      = contentType,
                ReplyTo          = replyTo,
                ReplyToSessionId = replyToSessionId,
                TimeToLive       = timeToLive,
            };

            sbMessage.ApplicationProperties.Add("UserProperty", "SomeUserProperty");

            var amqpMessage        = AmqpMessageConverter.SBMessageToAmqpMessage(sbMessage);
            var convertedSbMessage = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);

            Assert.AreEqual("SomeUserProperty", convertedSbMessage.ApplicationProperties["UserProperty"]);
            Assert.AreEqual(messageBody, convertedSbMessage.Body.ToArray());
            Assert.AreEqual(messageId, convertedSbMessage.MessageId);
            Assert.AreEqual(partitionKey, convertedSbMessage.PartitionKey);
            Assert.AreEqual(viaPartitionKey, convertedSbMessage.TransactionPartitionKey);
            Assert.AreEqual(sessionId, convertedSbMessage.SessionId);
            Assert.AreEqual(correlationId, convertedSbMessage.CorrelationId);
            Assert.AreEqual(label, convertedSbMessage.Subject);
            Assert.AreEqual(to, convertedSbMessage.To);
            Assert.AreEqual(contentType, convertedSbMessage.ContentType);
            Assert.AreEqual(replyTo, convertedSbMessage.ReplyTo);
            Assert.AreEqual(replyToSessionId, convertedSbMessage.ReplyToSessionId);
            Assert.AreEqual(timeToLive, convertedSbMessage.TimeToLive);
        }
示例#12
0
        protected virtual async Task <IList <Message> > OnReceiveAsync(int maxMessageCount, TimeSpan serverWaitTime)
        {
            ReceivingAmqpLink receiveLink = null;

            try
            {
                TimeoutHelper timeoutHelper = new TimeoutHelper(serverWaitTime, true);
                receiveLink = await this.ReceiveLinkManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

                IEnumerable <AmqpMessage> amqpMessages = null;
                bool hasMessages = await Task.Factory.FromAsync(
                    (c, s) => receiveLink.BeginReceiveRemoteMessages(maxMessageCount, DefaultBatchFlushInterval, timeoutHelper.RemainingTime(), c, s),
                    a => receiveLink.EndReceiveMessages(a, out amqpMessages),
                    this).ConfigureAwait(false);

                if (receiveLink.TerminalException != null)
                {
                    throw receiveLink.TerminalException;
                }

                if (hasMessages && amqpMessages != null)
                {
                    IList <Message> brokeredMessages = null;
                    foreach (var amqpMessage in amqpMessages)
                    {
                        if (brokeredMessages == null)
                        {
                            brokeredMessages = new List <Message>();
                        }

                        if (this.ReceiveMode == ReceiveMode.ReceiveAndDelete)
                        {
                            receiveLink.DisposeDelivery(amqpMessage, true, AmqpConstants.AcceptedOutcome);
                        }

                        Message message = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);
                        brokeredMessages.Add(message);
                    }

                    return(brokeredMessages);
                }

                return(null);
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception, receiveLink?.GetTrackingId());
            }
        }
示例#13
0
        public void CreateMessageFromEventProperlySetsThePartitionKeyAnnotation(string partitionKey)
        {
            var body      = new byte[] { 0x11, 0x22, 0x33 };
            var eventData = new EventData(body);
            var converter = new AmqpMessageConverter();

            using var message = converter.CreateMessageFromEvent(eventData, partitionKey);
            Assert.That(message, Is.Not.Null, "The AMQP message should have been created.");
            Assert.That(message.MessageAnnotations.Map.TryGetValue(AmqpAnnotation.PartitionKey, out object annotationPartionKey), Is.EqualTo(!String.IsNullOrEmpty(partitionKey)), "The partition key annotation was not correctly set.");

            if (!String.IsNullOrEmpty(partitionKey))
            {
                Assert.That(annotationPartionKey, Is.EqualTo(partitionKey), "The partition key annotation should match.");
            }
        }
示例#14
0
        public void CreateMessageFromEventPopulatesTheBody()
        {
            var body      = new byte[] { 0x11, 0x22, 0x33 };
            var eventData = new EventData(body);
            var converter = new AmqpMessageConverter();

            using var message = converter.CreateMessageFromEvent(eventData);
            Assert.That(message, Is.Not.Null, "The AMQP message should have been created.");
            Assert.That(message.DataBody, Is.Not.Null, "The AMQP message should a body.");

            var messageData = message.DataBody.ToList();

            Assert.That(messageData.Count, Is.EqualTo(1), "The AMQP message should a single data body.");
            Assert.That(messageData[0].Value, Is.EqualTo(eventData.Body.ToArray()), "The AMQP message data should match the event body.");
        }
示例#15
0
        public async Task SendMessageTest()
        {
            // Arrange
            var feedbackStatus = FeedbackStatus.Abandon;
            var deviceListener = new Mock <IDeviceListener>();

            deviceListener.Setup(d => d.ProcessMessageFeedbackAsync(It.IsAny <string>(), It.IsAny <FeedbackStatus>()))
            .Callback <string, FeedbackStatus>((m, s) => feedbackStatus = s)
            .Returns(Task.CompletedTask);
            AmqpMessage receivedAmqpMessage = null;
            var         connectionHandler   = Mock.Of <IConnectionHandler>(c => c.GetDeviceListener() == Task.FromResult(deviceListener.Object) &&
                                                                           c.GetAmqpAuthentication() == Task.FromResult(new AmqpAuthentication(true, Option.Some(Mock.Of <IClientCredentials>()))));
            var amqpConnection = Mock.Of <IAmqpConnection>(c => c.FindExtension <IConnectionHandler>() == connectionHandler);
            var amqpSession    = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var sendingLink    = Mock.Of <ISendingAmqpLink>(l => l.Session == amqpSession && !l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened);

            Mock.Get(sendingLink).Setup(s => s.SendMessageNoWait(It.IsAny <AmqpMessage>(), It.IsAny <ArraySegment <byte> >(), It.IsAny <ArraySegment <byte> >()))
            .Callback <AmqpMessage, ArraySegment <byte>, ArraySegment <byte> >((m, d, t) => { receivedAmqpMessage = m; });

            var requestUri     = new Uri("amqps://foo.bar/devices/d1");
            var boundVariables = new Dictionary <string, string> {
                { "deviceid", "d1" }
            };
            var messageConverter = new AmqpMessageConverter();

            var      sendingLinkHandler = new DeviceBoundLinkHandler(sendingLink, requestUri, boundVariables, messageConverter);
            var      body          = new byte[] { 0, 1, 2, 3 };
            IMessage message       = new EdgeMessage.Builder(body).Build();
            var      deliveryState = new Mock <DeliveryState>(new AmqpSymbol(""), AmqpConstants.AcceptedOutcome.DescriptorCode);
            var      delivery      = Mock.Of <Delivery>(d => d.State == deliveryState.Object &&
                                                        d.DeliveryTag == new ArraySegment <byte>(Guid.NewGuid().ToByteArray()));

            // Act
            await sendingLinkHandler.OpenAsync(TimeSpan.FromSeconds(5));

            await sendingLinkHandler.SendMessage(message);

            // Assert
            Assert.NotNull(receivedAmqpMessage);
            Assert.Equal(body, receivedAmqpMessage.GetPayloadBytes());

            // Act
            sendingLinkHandler.DispositionListener(delivery);
            await Task.Delay(TimeSpan.FromSeconds(5));

            // Assert
            Assert.Equal(feedbackStatus, FeedbackStatus.Complete);
        }
        public async Task SendBatchCreatesTheAmqpMessageFromTheBatch(string partitonKey)
        {
            var messageFactory      = default(Func <AmqpMessage>);
            var expectedMaximumSize = 512;
            var options             = new CreateBatchOptions {
                PartitionKey = partitonKey
            };
            var retryPolicy = new BasicRetryPolicy(new RetryOptions {
                TryTimeout = TimeSpan.FromSeconds(17)
            });

            var producer = new Mock <AmqpProducer>("aHub", null, Mock.Of <AmqpConnectionScope>(), new AmqpMessageConverter(), retryPolicy)
            {
                CallBase = true
            };

            producer
            .Protected()
            .Setup <Task <SendingAmqpLink> >("CreateLinkAndEnsureProducerStateAsync",
                                             ItExpr.IsAny <string>(),
                                             ItExpr.IsAny <TimeSpan>(),
                                             ItExpr.IsAny <CancellationToken>())
            .Callback(() => SetMaximumMessageSize(producer.Object, expectedMaximumSize))
            .Returns(Task.FromResult(new SendingAmqpLink(new AmqpLinkSettings())));

            producer
            .Protected()
            .Setup <Task>("SendAsync",
                          ItExpr.IsAny <Func <AmqpMessage> >(),
                          ItExpr.IsAny <string>(),
                          ItExpr.IsAny <CancellationToken>())
            .Callback <Func <AmqpMessage>, string, CancellationToken>((factory, key, token) => messageFactory = factory)
            .Returns(Task.CompletedTask);

            using TransportEventBatch transportBatch = await producer.Object.CreateBatchAsync(options, default);

            using var batch = new EventDataBatch(transportBatch, options);
            batch.TryAdd(new EventData(new byte[] { 0x15 }));

            await producer.Object.SendAsync(batch, CancellationToken.None);

            Assert.That(messageFactory, Is.Not.Null, "The batch message factory should have been set.");

            using var batchMessage   = new AmqpMessageConverter().CreateBatchFromMessages(batch.AsEnumerable <AmqpMessage>(), partitonKey);
            using var factoryMessage = messageFactory();

            Assert.That(factoryMessage.SerializedMessageSize, Is.EqualTo(batchMessage.SerializedMessageSize), "The serialized size of the messages should match.");
        }
        public void CreateEventFromMessageAllowsAnEmptyMessageWithProperties()
        {
            var propertyValue = 1;

            var message = AmqpMessage.Create();

            message.ApplicationProperties.Map.Add("Test", propertyValue);
            message.MessageAnnotations.Map.Add(AmqpProperty.Offset, propertyValue.ToString());

            var eventData = new AmqpMessageConverter().CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Properties.Count, Is.EqualTo(message.ApplicationProperties.Map.Count()), "There should have been properties present.");
            Assert.That(eventData.Properties.First().Value, Is.EqualTo(propertyValue), "The application property should have been populated.");
            Assert.That(eventData.Offset, Is.EqualTo(propertyValue), "The offset should have been populated.");
        }
示例#18
0
        public void PeekedMessageShouldNotIncrementDeliveryCount()
        {
            var messageBody = Encoding.UTF8.GetBytes("message1");

            var amqpValue = new AmqpValue();

            amqpValue.Value = new ArraySegment <byte>(messageBody);
            var amqpMessage = AmqpMessage.Create(amqpValue);

            amqpMessage.Header.DeliveryCount = 2;

            var sbMessage = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage, isPeeked: true);

            sbMessage.SequenceNumber = 1L;

            Assert.AreEqual(2, sbMessage.DeliveryCount);
        }
示例#19
0
        void When_message_is_received_should_have_delivery_count_increased()
        {
            var messageBody = Encoding.UTF8.GetBytes("message1");

            var amqpValue = new AmqpValue();

            amqpValue.Value = new ArraySegment <byte>(messageBody);
            var amqpMessage = AmqpMessage.Create(amqpValue);

            amqpMessage.Header.DeliveryCount = 2;

            var sbMessage = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage, isPeeked: false);

            sbMessage.SystemProperties.SequenceNumber = 1L;

            Assert.Equal(3, sbMessage.SystemProperties.DeliveryCount);
        }
示例#20
0
        public void CreateMessageFromEventPopulatesSimpleApplicationProperties()
        {
            var propertyValues = new object[]
            {
                (byte)0x22,
                (sbyte)0x11,
                (Int16)5,
                (Int32)27,
                (Int64)1122334,
                (UInt16)12,
                (UInt32)24,
                (UInt64)9955,
                (Single)4.3,
                (Double)3.4,
                (Decimal)7.893,
                Guid.NewGuid(),
                DateTime.Parse("2015-10-27T12:00:00Z"),
                true,
                'x',
                "hello"
            };

            var eventData = new EventData(new byte[] { 0x11, 0x22, 0x33 })
            {
                Properties = propertyValues.ToDictionary(value => $"{ value.GetType().Name }Property", value => value)
            };

            using var message = new AmqpMessageConverter().CreateMessageFromEvent(eventData);

            Assert.That(message, Is.Not.Null, "The AMQP message should have been created.");
            Assert.That(message.DataBody, Is.Not.Null, "The AMQP message should a body.");
            Assert.That(message.ApplicationProperties, Is.Not.Null, "The AMQP message should have a set of application properties.");

            // The collection comparisons built into the test assertions do not recognize
            // the property sets as equivalent, but a manual inspection proves the properties exist
            // in both.

            foreach (var property in eventData.Properties.Keys)
            {
                var containsValue = message.ApplicationProperties.Map.TryGetValue(property, out object value);

                Assert.That(containsValue, Is.True, $"The message properties did not contain: [{ property }]");
                Assert.That(value, Is.EqualTo(eventData.Properties[property]), $"The property value did not match for: [{ property }]");
            }
        }
示例#21
0
        public void CreateBatchFromEventsWithOneMessagePopulatesEnvelopeProperties(string partitionKey)
        {
            var eventData = new EventData(new byte[] { 0x11, 0x22, 0x33 });
            var converter = new AmqpMessageConverter();

            using var message = converter.CreateBatchFromEvents(new[] { eventData }, partitionKey);
            Assert.That(message, Is.Not.Null, "The batch envelope should have been created.");
            Assert.That(message.Batchable, Is.True, "The batch envelope should be set to batchable.");
            Assert.That(message.MessageFormat, Is.EqualTo(AmqpConstants.AmqpBatchedMessageFormat), "The batch envelope should have a batchable format.");
            Assert.That(message.DataBody, Is.Not.Null, "The batch envelope should a body.");
            Assert.That(message.DataBody.ToList().Count, Is.EqualTo(1), "The batch envelope should contain a single event in the body.");
            Assert.That(message.MessageAnnotations.Map.TryGetValue(AmqpAnnotation.PartitionKey, out string partitionKeyAnnotation), Is.EqualTo(!String.IsNullOrEmpty(partitionKey)), "There should be an annotation if a partition key was present.");

            if (!String.IsNullOrEmpty(partitionKey))
            {
                Assert.That(partitionKeyAnnotation, Is.EqualTo(partitionKey), "The partition key annotation should match.");
            }
        }
        public void AnEventCanBeTranslatedToItself()
        {
            var sourceEvent = new EventData(new byte[] { 0x11, 0x22, 0x33 })
            {
                Properties = new Dictionary <string, object> {
                    { "Test", 1234 }
                }
            };

            var converter = new AmqpMessageConverter();

            using var message = converter.CreateMessageFromEvent(sourceEvent);
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(message, Is.Not.Null, "The AMQP message should have been created.");
            Assert.That(eventData, Is.Not.Null, "The translated event should have been created.");
            Assert.That(eventData.IsEquivalentTo(sourceEvent), "The translated event should match the source event.");
        }
示例#23
0
        long GetEventSizeForBatch(EventData eventData)
        {
            // Create AMQP message here. We will use the same message while sending to save compute time.
            var amqpMessage = AmqpMessageConverter.EventDataToAmqpMessage(eventData);

            AmqpMessageConverter.UpdateAmqpMessagePartitionKey(amqpMessage, this.PartitionKey);
            eventData.AmqpMessage = amqpMessage;

            // Calculate overhead depending on the message size.
            if (eventData.AmqpMessage.SerializedMessageSize < 256)
            {
                // Overhead is smaller for messages smaller than 256 bytes.
                return(eventData.AmqpMessage.SerializedMessageSize + 5);
            }
            else
            {
                return(eventData.AmqpMessage.SerializedMessageSize + 8);
            }
        }
        void UpdateEventDataHeaderAndPropertiesReceiveCorrelationIdAndCopyItsValueToEventData()
        {
            // Arrange
            // the following simulates a message's round trip from client to broker to client
            var message = AmqpMessage.Create(new MemoryStream(new byte[12]), true);

            AddSection(message, SectionFlag.Properties);
            // serialize - send the message on client side
            ArraySegment <byte>[] buffers = ReadMessagePayLoad(message, 71);

            // Act
            var eventData = AmqpMessageConverter.AmqpMessageToEventData(message);

            // Assert
            Assert.NotNull(eventData);
            Assert.NotNull(eventData.SystemProperties);
            Assert.NotNull(eventData.SystemProperties[Properties.CorrelationIdName]);
            Assert.Equal("42", eventData.SystemProperties[Properties.CorrelationIdName].ToString());
        }
示例#25
0
        public async Task ReceiveMessageTest()
        {
            // Arrange
            var deviceListener    = new Mock <IDeviceListener>();
            var connectionHandler = Mock.Of <IConnectionHandler>(c => c.GetDeviceListener() == Task.FromResult(deviceListener.Object));
            var amqpAuthenticator = new Mock <IAmqpAuthenticator>();

            amqpAuthenticator.Setup(c => c.AuthenticateAsync("d1")).ReturnsAsync(true);
            Mock <ICbsNode> cbsNodeMock    = amqpAuthenticator.As <ICbsNode>();
            ICbsNode        cbsNode        = cbsNodeMock.Object;
            var             amqpConnection = Mock.Of <IAmqpConnection>(
                c =>
                c.FindExtension <IConnectionHandler>() == connectionHandler &&
                c.FindExtension <ICbsNode>() == cbsNode);
            var amqpSession   = Mock.Of <IAmqpSession>(s => s.Connection == amqpConnection);
            var receivingLink = Mock.Of <IReceivingAmqpLink>(l => l.Session == amqpSession && l.IsReceiver && l.Settings == new AmqpLinkSettings() && l.State == AmqpObjectState.Opened);

            var requestUri     = new Uri("amqps://foo.bar/devices/d1");
            var boundVariables = new Dictionary <string, string> {
                { "deviceid", "d1" }
            };
            var         messageConverter = new AmqpMessageConverter();
            var         body             = new byte[] { 0, 1, 2, 3 };
            AmqpMessage message          = AmqpMessage.Create(new Data {
                Value = new ArraySegment <byte>(body)
            });
            var identity         = Mock.Of <IIdentity>(i => i.Id == "d1");
            var productInfoStore = Mock.Of <IProductInfoStore>();
            var modelIdStore     = Mock.Of <IModelIdStore>();

            // Act
            var receivingLinkHandler = new TestReceivingLinkHandler(identity, receivingLink, requestUri, boundVariables, connectionHandler, messageConverter, productInfoStore, modelIdStore);
            await receivingLinkHandler.OpenAsync(Constants.DefaultTimeout);

            await receivingLinkHandler.ProcessMessageAsync(message);

            // Assert
            await Task.Delay(TimeSpan.FromSeconds(3));

            Assert.Equal(1, receivingLinkHandler.ReceivedMessages.Count);
            Assert.Equal(body, receivingLinkHandler.ReceivedMessages[0].GetPayloadBytes());
        }
示例#26
0
        protected virtual async Task <IList <Message> > OnReceiveBySequenceNumberAsync(IEnumerable <long> sequenceNumbers)
        {
            List <Message> messages = new List <Message>();

            try
            {
                AmqpRequestMessage requestMessage = AmqpRequestMessage.CreateRequest(ManagementConstants.Operations.ReceiveBySequenceNumberOperation, this.OperationTimeout, null);
                requestMessage.Map[ManagementConstants.Properties.SequenceNumbers]    = sequenceNumbers.ToArray();
                requestMessage.Map[ManagementConstants.Properties.ReceiverSettleMode] = (uint)(this.ReceiveMode == ReceiveMode.ReceiveAndDelete ? 0 : 1);

                AmqpResponseMessage response = await this.ExecuteRequestResponseAsync(requestMessage).ConfigureAwait(false);

                if (response.StatusCode == AmqpResponseStatusCode.OK)
                {
                    IEnumerable <AmqpMap> amqpMapList = response.GetListValue <AmqpMap>(ManagementConstants.Properties.Messages);
                    foreach (AmqpMap entry in amqpMapList)
                    {
                        ArraySegment <byte> payload     = (ArraySegment <byte>)entry[ManagementConstants.Properties.Message];
                        AmqpMessage         amqpMessage = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(new[] { payload }), true);
                        Message             message     = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);
                        Guid lockToken;
                        if (entry.TryGetValue(ManagementConstants.Properties.LockToken, out lockToken))
                        {
                            message.SystemProperties.LockTokenGuid = lockToken;
                            this.requestResponseLockedMessages.AddOrUpdate(lockToken, message.SystemProperties.LockedUntilUtc);
                        }

                        messages.Add(message);
                    }
                }
                else
                {
                    throw response.ToMessagingContractException();
                }
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception);
            }

            return(messages);
        }
        public void  CreateEventFromMessageDoesNotIncludeUnknownApplicationPropertyType()
        {
            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var typeDescriptor    = (AmqpSymbol)"INVALID";
            var describedProperty = new DescribedType(typeDescriptor, 1234);

            message.ApplicationProperties.Map.Add(typeDescriptor.ToString(), describedProperty);

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Any(), Is.False, "The event should not have a set of application properties.");

            var containsValue = eventData.Properties.TryGetValue(typeDescriptor.ToString(), out var _);

            Assert.That(containsValue, Is.False, $"The event properties should not contain the described property.");
        }
示例#28
0
        public void CreateBatchFromMessagesWithMultipleEventsMessagePopulatesEnvelopeProperties(string partitionKey)
        {
            var converter = new AmqpMessageConverter();

            using var first  = converter.CreateMessageFromEvent(new EventData(new byte[] { 0x11, 0x22, 0x33 }));
            using var second = converter.CreateMessageFromEvent(new EventData(new byte[] { 0x44, 0x55, 0x66 }));
            var source = new[] { first, second };

            using var batchEnvelope = converter.CreateBatchFromMessages(source, partitionKey);
            Assert.That(batchEnvelope, Is.Not.Null, "The batch envelope should have been created.");
            Assert.That(batchEnvelope.Batchable, Is.True, "The batch envelope should be marked as batchable.");
            Assert.That(batchEnvelope.MessageFormat, Is.EqualTo(AmqpConstants.AmqpBatchedMessageFormat), "The batch envelope should be marked with a batchable format.");
            Assert.That(batchEnvelope.DataBody, Is.Not.Null, "The batch envelope should a body.");
            Assert.That(batchEnvelope.DataBody.ToList().Count, Is.EqualTo(source.Length), "The batch envelope should contain each batch event in the body.");
            Assert.That(batchEnvelope.MessageAnnotations.Map.TryGetValue(AmqpAnnotation.PartitionKey, out string partitionKeyAnnotation), Is.EqualTo(!String.IsNullOrEmpty(partitionKey)), "There should be an annotation if a partition key was present.");

            if (!String.IsNullOrEmpty(partitionKey))
            {
                Assert.That(partitionKeyAnnotation, Is.EqualTo(partitionKey), "The partition key annotation should match.");
            }
        }
示例#29
0
        public void ToMessageTest()
        {
            // Arrange
            IMessage receivedMessage;

            byte[] bytes         = { 1, 2, 3, 4 };
            string messageId     = Guid.NewGuid().ToString();
            string correlationId = Guid.NewGuid().ToString();

            using (AmqpMessage amqpMessage = AmqpMessage.Create(new Data {
                Value = new ArraySegment <byte>(bytes)
            }))
            {
                amqpMessage.Properties.MessageId       = messageId;
                amqpMessage.Properties.CorrelationId   = correlationId;
                amqpMessage.Properties.ContentType     = "application/json";
                amqpMessage.Properties.ContentEncoding = "UTF-8";

                amqpMessage.ApplicationProperties.Map["Prop1"] = "Value1";
                amqpMessage.ApplicationProperties.Map["Prop2"] = "Value2";

                var messageConverter = new AmqpMessageConverter();

                // Act
                receivedMessage = messageConverter.ToMessage(amqpMessage);
            }

            // Assert
            Assert.NotNull(receivedMessage);
            Assert.Equal(receivedMessage.Body, bytes);
            Assert.Equal(receivedMessage.SystemProperties.Count, 4);
            Assert.Equal(receivedMessage.Properties.Count, 2);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MessageId], messageId);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.MsgCorrelationId], correlationId);
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ContentType], "application/json");
            Assert.Equal(receivedMessage.SystemProperties[SystemProperties.ContentEncoding], "UTF-8");
            Assert.Equal(receivedMessage.Properties["Prop1"], "Value1");
            Assert.Equal(receivedMessage.Properties["Prop2"], "Value2");
        }
        public void  CreateEventFromMessagePopulatesAnArraySegmentApplicationPropertyType()
        {
            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var propertyKey   = "Test";
            var propertyValue = new byte[] { 0x11, 0x15, 0xF8, 0x20 };

            message.ApplicationProperties.Map.Add(propertyKey, new ArraySegment <byte>(propertyValue, 1, 2));

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Any(), Is.True, "The event should have a set of application properties.");

            var containsValue = eventData.Properties.TryGetValue(propertyKey, out var eventValue);

            Assert.That(containsValue, Is.True, $"The event properties should contain the property.");
            Assert.That(eventValue, Is.EquivalentTo(propertyValue.Skip(1).Take(2)));
        }