Exemplo n.º 1
0
        public static async Task SendSendBatchMessagesAndVerifyAsync(DeviceClient deviceClient, string deviceId)
        {
            var messagesToBeSent = new Dictionary <Client.Message, Tuple <string, string> >();

            try
            {
                var props = new List <Tuple <string, string> >();
                for (int i = 0; i < MessageBatchCount; i++)
                {
                    (Client.Message testMessage, string payload, string p1Value) = ComposeD2cTestMessage();
                    messagesToBeSent.Add(testMessage, Tuple.Create(payload, p1Value));
                }

                await deviceClient.SendEventBatchAsync(messagesToBeSent.Keys.ToList()).ConfigureAwait(false);

                foreach (KeyValuePair <Client.Message, Tuple <string, string> > messageEntry in messagesToBeSent)
                {
                    Client.Message         message = messageEntry.Key;
                    Tuple <string, string> prop    = messageEntry.Value;

                    bool isReceived = EventHubTestListener.VerifyIfMessageIsReceived(deviceId, message, prop.Item1, prop.Item2);
                    Assert.IsTrue(isReceived, "Message is not received.");
                }
            }
            finally
            {
                foreach (KeyValuePair <Client.Message, Tuple <string, string> > messageEntry in messagesToBeSent)
                {
                    Client.Message message = messageEntry.Key;
                    message.Dispose();
                }
            }
        }
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    _message.Dispose();
                }

                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.

                disposedValue = true;
            }
        }
        public static async Task SendBatchMessagesAsync(DeviceClient deviceClient, string deviceId, MsTestLogger logger)
        {
            var messagesToBeSent = new Dictionary <Client.Message, Tuple <string, string> >();

            try
            {
                var props = new List <Tuple <string, string> >();
                for (int i = 0; i < MessageBatchCount; i++)
                {
                    (Client.Message testMessage, string payload, string p1Value) = ComposeD2cTestMessage(logger);
                    messagesToBeSent.Add(testMessage, Tuple.Create(payload, p1Value));
                }

                await deviceClient.SendEventBatchAsync(messagesToBeSent.Keys.ToList()).ConfigureAwait(false);
            }
            finally
            {
                foreach (KeyValuePair <Client.Message, Tuple <string, string> > messageEntry in messagesToBeSent)
                {
                    Client.Message message = messageEntry.Key;
                    message.Dispose();
                }
            }
        }
Exemplo n.º 4
0
        public static async Task VerifyReceivedC2DMessageAsync(Client.TransportType transport, DeviceClient dc, string deviceId, Message message, string payload, MsTestLogger logger)
        {
            string receivedMessageDestination = $"/devices/{deviceId}/messages/deviceBound";

            var  sw       = new Stopwatch();
            bool received = false;

            sw.Start();

            while (!received && sw.ElapsedMilliseconds < FaultInjection.RecoveryTimeMilliseconds)
            {
                Client.Message receivedMessage = null;

                try
                {
                    logger.Trace($"Receiving messages for device {deviceId}.");

                    if (transport == Client.TransportType.Http1)
                    {
                        // timeout on HTTP is not supported
                        receivedMessage = await dc.ReceiveAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        receivedMessage = await dc.ReceiveAsync(s_oneMinute).ConfigureAwait(false);
                    }

                    if (receivedMessage == null)
                    {
                        Assert.Fail($"No message is received for device {deviceId} in {s_oneMinute}.");
                    }

                    try
                    {
                        // always complete message
                        await dc.CompleteAsync(receivedMessage).ConfigureAwait(false);
                    }
                    catch (Exception)
                    {
                        // ignore exception from CompleteAsync
                    }

                    Assert.AreEqual(receivedMessage.MessageId, message.MessageId, "Recieved message Id is not what was sent by service");
                    Assert.AreEqual(receivedMessage.UserId, message.UserId, "Recieved user Id is not what was sent by service");
                    Assert.AreEqual(receivedMessage.To, receivedMessageDestination, "Recieved message destination is not what was sent by service");

                    string messageData = Encoding.ASCII.GetString(receivedMessage.GetBytes());
                    logger.Trace($"{nameof(VerifyReceivedC2DMessageAsync)}: Received message: for {deviceId}: {messageData}");
                    if (Equals(payload, messageData))
                    {
                        Assert.AreEqual(1, receivedMessage.Properties.Count, $"The count of received properties did not match for device {deviceId}");
                        System.Collections.Generic.KeyValuePair <string, string> prop = receivedMessage.Properties.Single();
                        string propertyKey = "property1";
                        Assert.AreEqual(propertyKey, prop.Key, $"The key \"property1\" did not match for device {deviceId}");
                        Assert.AreEqual(message.Properties[propertyKey], prop.Value, $"The value of \"property1\" did not match for device {deviceId}");
                        received = true;
                    }
                }
                finally
                {
                    receivedMessage?.Dispose();
                }
            }

            sw.Stop();
            Assert.IsTrue(received, $"No message received for device {deviceId} with payload={payload} in {FaultInjection.RecoveryTimeMilliseconds}.");
        }
Exemplo n.º 5
0
        async void Receive()
        {
            Message     message        = null;
            IByteBuffer messagePayload = null;

            try
            {
                while (true)
                {
                    message = await this.bridge.DeviceClient.ReceiveAsync(this.lifetimeCancellation.Token);

                    if (message == null)
                    {
                        this.messagingChannel.Close(null);
                        return;
                    }

                    if (this.bridge.Settings.MaxOutboundRetransmissionEnforced && message.DeliveryCount > this.bridge.Settings.MaxOutboundRetransmissionCount)
                    {
                        await this.RejectAsync(message.LockToken);

                        message.Dispose();
                        continue;
                    }

                    using (Stream payloadStream = message.GetBodyStream())
                    {
                        long streamLength = payloadStream.Length;
                        if (streamLength > int.MaxValue)
                        {
                            throw new InvalidOperationException($"Message size ({streamLength.ToString()} bytes) is too big to process.");
                        }

                        int length = (int)streamLength;
                        messagePayload = this.allocator.Buffer(length, length);
                        await messagePayload.WriteBytesAsync(payloadStream, length);

                        Contract.Assert(messagePayload.ReadableBytes == length);
                    }

                    var msg = new IotHubClientMessage(message, messagePayload);
                    msg.Properties[TemplateParameters.DeviceIdTemplateParam] = this.bridge.DeviceId;
                    string address;
                    if (!this.addressFormatter(msg, out address))
                    {
                        messagePayload.Release();
                        await this.RejectAsync(message.LockToken); // todo: fork await

                        message.Dispose();
                        continue;
                    }
                    msg.Address = address;

                    this.messagingChannel.Handle(msg, this);

                    message        = null; // ownership has been transferred to messagingChannel
                    messagePayload = null;
                }
            }
            catch (IotHubException ex)
            {
                this.messagingChannel.Close(ex.ToMessagingException());
            }
            catch (Exception ex)
            {
                this.messagingChannel.Close(ex);
            }
            finally
            {
                message?.Dispose();
                if (messagePayload != null)
                {
                    ReferenceCountUtil.SafeRelease(messagePayload);
                }
            }
        }
        private async Task ReuseAuthenticationMethod_MuxedDevices(Client.TransportType transport, int devicesCount)
        {
            IList <TestDevice>   testDevices   = new List <TestDevice>();
            IList <DeviceClient> deviceClients = new List <DeviceClient>();
            IList <AuthenticationWithTokenRefresh> authenticationMethods  = new List <AuthenticationWithTokenRefresh>();
            IList <AmqpConnectionStatusChange>     amqpConnectionStatuses = new List <AmqpConnectionStatusChange>();

            // Set up amqp transport settings to multiplex all device sessions over the same amqp connection.
            var amqpTransportSettings = new AmqpTransportSettings(transport)
            {
                AmqpConnectionPoolSettings = new AmqpConnectionPoolSettings
                {
                    Pooling     = true,
                    MaxPoolSize = 1,
                },
            };

            for (int i = 0; i < devicesCount; i++)
            {
                TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false);

#pragma warning disable CA2000 // Dispose objects before losing scope - the authentication method is disposed at the end of the test.
                var authenticationMethod = new DeviceAuthenticationSasToken(testDevice.ConnectionString, disposeWithClient: false);
#pragma warning restore CA2000 // Dispose objects before losing scope

                testDevices.Add(testDevice);
                authenticationMethods.Add(authenticationMethod);
            }

            // Initialize the client instances, set the connection status change handler and open the connection.
            for (int i = 0; i < devicesCount; i++)
            {
#pragma warning disable CA2000 // Dispose objects before losing scope - the client instance is disposed during the course of the test.
                DeviceClient deviceClient = DeviceClient.Create(testDevices[i].IoTHubHostName, authenticationMethods[i], new ITransportSettings[] { amqpTransportSettings });
#pragma warning restore CA2000 // Dispose objects before losing scope

                var amqpConnectionStatusChange = new AmqpConnectionStatusChange(testDevices[i].Id, Logger);
                deviceClient.SetConnectionStatusChangesHandler(amqpConnectionStatusChange.ConnectionStatusChangesHandler);
                amqpConnectionStatuses.Add(amqpConnectionStatusChange);

                await deviceClient.OpenAsync().ConfigureAwait(false);

                deviceClients.Add(deviceClient);
            }

            // Close and dispose client instance 1.
            // The closed client should report a status of "disabled" while the rest of them should be connected.
            // This is to ensure that disposal on one multiplexed device doesn't cause cascading failures
            // in the rest of the devices on the same tcp connection.

            await deviceClients[0].CloseAsync().ConfigureAwait(false);
            deviceClients[0].Dispose();

            amqpConnectionStatuses[0].LastConnectionStatus.Should().Be(ConnectionStatus.Disabled);

            Logger.Trace($"{nameof(ReuseAuthenticationMethod_MuxedDevices)}: Confirming the rest of the multiplexed devices are online and operational.");

            bool notRecovered = true;
            var  sw           = Stopwatch.StartNew();
            while (notRecovered && sw.Elapsed < MaxWaitTime)
            {
                notRecovered = false;
                for (int i = 1; i < devicesCount; i++)
                {
                    if (amqpConnectionStatuses[i].LastConnectionStatus != ConnectionStatus.Connected)
                    {
                        await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

                        notRecovered = true;
                        break;
                    }
                }
            }

            notRecovered.Should().BeFalse();

            // Send a message through the rest of the multiplexed client instances.
            var message = new Client.Message();
            for (int i = 1; i < devicesCount; i++)
            {
                await deviceClients[i].SendEventAsync(message).ConfigureAwait(false);
                Logger.Trace($"Test with client {i} completed.");
            }
            message.Dispose();

            // Close and dispose all of the client instances.
            for (int i = 1; i < devicesCount; i++)
            {
                await deviceClients[i].CloseAsync().ConfigureAwait(false);
                deviceClients[i].Dispose();
            }

            deviceClients.Clear();
            amqpConnectionStatuses.Clear();

            // Initialize the client instances by reusing the created authentication methods and open the connection.
            for (int i = 0; i < devicesCount; i++)
            {
#pragma warning disable CA2000 // Dispose objects before losing scope - the client instance is disposed at the end of the test.
                DeviceClient deviceClient = DeviceClient.Create(testDevices[i].IoTHubHostName, authenticationMethods[i], new ITransportSettings[] { amqpTransportSettings });
#pragma warning restore CA2000 // Dispose objects before losing scope

                var amqpConnectionStatusChange = new AmqpConnectionStatusChange(testDevices[i].Id, Logger);
                deviceClient.SetConnectionStatusChangesHandler(amqpConnectionStatusChange.ConnectionStatusChangesHandler);
                amqpConnectionStatuses.Add(amqpConnectionStatusChange);

                await deviceClient.OpenAsync().ConfigureAwait(false);

                deviceClients.Add(deviceClient);
            }

            // Ensure that all clients are connected successfully, and the close and dispose the instances.
            // Also dispose the authentication methods created.
            for (int i = 0; i < devicesCount; i++)
            {
                amqpConnectionStatuses[i].LastConnectionStatus.Should().Be(ConnectionStatus.Connected);

                await deviceClients[i].CloseAsync();
                deviceClients[i].Dispose();
                authenticationMethods[i].Dispose();

                amqpConnectionStatuses[i].LastConnectionStatus.Should().Be(ConnectionStatus.Disabled);
            }
        }