Example #1
0
        public async Task DeviceNotFoundExceptionReturnsDeviceDisabledStatus()
        {
            var contextMock      = Substitute.For <IPipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => throw new DeviceNotFoundException());

            ConnectionStatus?              status              = null;
            ConnectionStatusChangeReason?  statusChangeReason  = null;
            ConnectionStatusChangesHandler statusChangeHandler = (s, r) =>
            {
                status             = s;
                statusChangeReason = r;
            };

            contextMock.Get <ConnectionStatusChangesHandler>().Returns(statusChangeHandler);

            var cancellationToken = new CancellationToken();
            var testee            = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            await((Func <Task>)(() => testee.OpenAsync(cancellationToken))).ExpectedAsync <DeviceNotFoundException>().ConfigureAwait(false);

            Assert.AreEqual(ConnectionStatus.Disconnected, status);
            Assert.AreEqual(ConnectionStatusChangeReason.Device_Disabled, statusChangeReason);
        }
Example #2
0
        public async Task CreateFromEnvironmentTest(
            Option <UpstreamProtocol> upstreamProtocol,
            Option <IWebProxy> webProxy,
            string productInfo)
        {
            // Arrange
            ITransportSettings receivedTransportSettings = null;

            var sdkModuleClient = new Mock <ISdkModuleClient>();

            var sdkModuleClientProvider = new Mock <ISdkModuleClientProvider>();

            sdkModuleClientProvider.Setup(s => s.GetSdkModuleClient(It.IsAny <ITransportSettings>()))
            .Callback <ITransportSettings>(t => receivedTransportSettings = t)
            .ReturnsAsync(sdkModuleClient.Object);

            bool     closeOnIdleTimeout            = false;
            TimeSpan idleTimeout                   = TimeSpan.FromMinutes(5);
            ConnectionStatusChangesHandler handler = (status, reason) => { };

            // Act
            var moduleClientProvider = new ModuleClientProvider(
                sdkModuleClientProvider.Object,
                upstreamProtocol,
                webProxy,
                productInfo,
                closeOnIdleTimeout,
                idleTimeout,
                false);
            IModuleClient moduleClient = await moduleClientProvider.Create(handler);

            // Assert
            Assert.NotNull(moduleClient);
            sdkModuleClientProvider.Verify(s => s.GetSdkModuleClient(It.IsAny <ITransportSettings>()), Times.Once);

            sdkModuleClient.Verify(s => s.SetProductInfo(productInfo), Times.Once);

            Assert.NotNull(receivedTransportSettings);
            UpstreamProtocol up = upstreamProtocol.GetOrElse(UpstreamProtocol.Amqp);

            Assert.Equal(up, moduleClient.UpstreamProtocol);
            switch (up)
            {
            case UpstreamProtocol.Amqp:
            case UpstreamProtocol.AmqpWs:
                var amqpTransportSettings = receivedTransportSettings as AmqpTransportSettings;
                Assert.NotNull(amqpTransportSettings);
                webProxy.ForEach(w => Assert.Equal(w, amqpTransportSettings.Proxy));
                break;

            case UpstreamProtocol.Mqtt:
            case UpstreamProtocol.MqttWs:
                var mqttTransportSettings = receivedTransportSettings as MqttTransportSettings;
                Assert.NotNull(mqttTransportSettings);
                webProxy.ForEach(w => Assert.Equal(w, mqttTransportSettings.Proxy));
                break;
            }

            sdkModuleClient.Verify(s => s.OpenAsync(), Times.Once);
        }
Example #3
0
        public void CreateFromEnvironment_NullProductInfo_ShouldThrow()
        {
            // Arrange
            ITransportSettings receivedTransportSettings = null;

            var sdkModuleClient = new Mock <ISdkModuleClient>();

            var sdkModuleClientProvider = new Mock <ISdkModuleClientProvider>();

            sdkModuleClientProvider.Setup(s => s.GetSdkModuleClient(It.IsAny <ITransportSettings>()))
            .Callback <ITransportSettings>(t => receivedTransportSettings = t)
            .ReturnsAsync(sdkModuleClient.Object);

            bool     closeOnIdleTimeout            = false;
            TimeSpan idleTimeout                   = TimeSpan.FromMinutes(5);
            ConnectionStatusChangesHandler handler = (status, reason) => { };

            // Assert
            Assert.Throws <ArgumentNullException>(() => new ModuleClientProvider(
                                                      sdkModuleClientProvider.Object,
                                                      Option.None <UpstreamProtocol>(),
                                                      Option.None <IWebProxy>(),
                                                      null,
                                                      closeOnIdleTimeout,
                                                      idleTimeout,
                                                      false));
        }
Example #4
0
 public MainPage()
 {
     this.InitializeComponent();
     ViewModel             = new MainViewModel();
     ConnStatusDelegate    = OnConnectionChanged;
     ViewModel.DeviceIdStr = $"UNIQUE ID: {deviceId}";
 }
        public async Task Twin_ClientSetsReportedPropertyWithoutDesiredPropertyCallback(Client.TransportType transportType)
        {
            // arrange

            TestDevice testDevice = await TestDevice.GetTestDeviceAsync(_devicePrefix).ConfigureAwait(false);

            using var deviceClient = DeviceClient.CreateFromConnectionString(testDevice.ConnectionString, transportType);

            await Twin_DeviceSetsReportedPropertyAndGetsItBackAsync(deviceClient).ConfigureAwait(false);

            int connectionStatusChangeCount = 0;
            ConnectionStatusChangesHandler connectionStatusChangesHandler = (ConnectionStatus status, ConnectionStatusChangeReason reason) =>
            {
                Interlocked.Increment(ref connectionStatusChangeCount);
            };

            string propName  = Guid.NewGuid().ToString();
            string propValue = Guid.NewGuid().ToString();

            s_log.WriteLine($"{nameof(Twin_ServiceSetsDesiredPropertyAndDeviceReceivesEventAsync)}: name={propName}, value={propValue}");

            // act
            await RegistryManagerUpdateDesiredPropertyAsync(testDevice.Id, propName, propValue).ConfigureAwait(false);

            await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);

            // assert
            Assert.AreEqual(0, connectionStatusChangeCount, "AMQP should not be disconnected.");
        }
Example #6
0
        public async Task FailingInitClosesModuleClient()
        {
            // Arrange
            ConnectionStatusChangesHandler connectionStatusChangesHandler = (status, reason) => { };
            DesiredPropertyUpdateCallback  desiredPropertyUpdateCallback  = (properties, context) => Task.CompletedTask;

            var milestone = new SemaphoreSlim(0, 1);

            var moduleClient = new Mock <IModuleClient>();

            moduleClient.Setup(m => m.SetDefaultMethodHandlerAsync(It.IsAny <MethodCallback>())).Callback(() => milestone.Release()).Throws <TimeoutException>();

            var moduleClientProvider = new Mock <IModuleClientProvider>();

            moduleClientProvider.Setup(m => m.Create(connectionStatusChangesHandler)).ReturnsAsync(moduleClient.Object);

            var  requestManager      = new Mock <IRequestManager>();
            bool enableSubscriptions = true;

            // Act
            var moduleConnection = new ModuleConnection(moduleClientProvider.Object, requestManager.Object, connectionStatusChangesHandler, desiredPropertyUpdateCallback, enableSubscriptions);
            await milestone.WaitAsync(TimeSpan.FromSeconds(10));

            await Task.Delay(TimeSpan.FromSeconds(0.5)); // the milestone is hit a bit earlier than the exception, so wait a tiny bit

            // Assert
            moduleClient.Verify(m => m.CloseAsync(), Times.Once);
        }
        public async Task DeviceNotFoundExceptionReturnsDeviceDisabledStatus()
        {
            // arrange
            var contextMock      = Substitute.For <PipelineContext>();
            var innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t => throw new DeviceNotFoundException());

            ConnectionStatus?              status              = null;
            ConnectionStatusChangeReason?  statusChangeReason  = null;
            ConnectionStatusChangesHandler statusChangeHandler = (s, r) =>
            {
                status             = s;
                statusChangeReason = r;
            };

            contextMock.ConnectionStatusChangesHandler = statusChangeHandler;

            var sut = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // act
            await((Func <Task>)(() => sut
                                .OpenAsync(CancellationToken.None)))
            .ExpectedAsync <DeviceNotFoundException>()
            .ConfigureAwait(false);

            // assert
            status.Should().Be(ConnectionStatus.Disconnected);
            statusChangeReason.Should().Be(ConnectionStatusChangeReason.Device_Disabled);
        }
Example #8
0
 public static Task <IModuleClient> Create(
     Option <string> connectionString,
     Option <UpstreamProtocol> upstreamProtocol,
     ConnectionStatusChangesHandler statusChangedHandler,
     Func <ModuleClient, Task> initialize,
     Option <string> productInfo) =>
 Create(upstreamProtocol, initialize, t => CreateAndOpenDeviceClient(t, connectionString, statusChangedHandler, productInfo));
Example #9
0
        public async Task CreateFromEnvironment_NoRuntimeInfoProvider(
            Option <UpstreamProtocol> upstreamProtocol,
            Option <IWebProxy> webProxy,
            string productInfo)
        {
            // Arrange
            ITransportSettings receivedTransportSettings = null;

            var sdkModuleClient = new Mock <ISdkModuleClient>();

            var sdkModuleClientProvider = new Mock <ISdkModuleClientProvider>();

            sdkModuleClientProvider.Setup(s => s.GetSdkModuleClient(It.IsAny <ITransportSettings>()))
            .Callback <ITransportSettings>(t => receivedTransportSettings = t)
            .ReturnsAsync(sdkModuleClient.Object);

            bool     closeOnIdleTimeout            = false;
            TimeSpan idleTimeout                   = TimeSpan.FromMinutes(5);
            ConnectionStatusChangesHandler handler = (status, reason) => { };

            // Act
            var moduleClientProvider = new ModuleClientProvider(
                sdkModuleClientProvider.Object,
                Option.None <Task <IRuntimeInfoProvider> >(),
                upstreamProtocol,
                webProxy,
                productInfo,
                closeOnIdleTimeout,
                idleTimeout,
                false);
            IModuleClient moduleClient = await moduleClientProvider.Create(handler);

            // Write product info explicitly
            sdkModuleClient.Verify(s => s.SetProductInfo(productInfo), Times.Once);
        }
Example #10
0
        private async Task ModuleClient_Gives_ConnectionStatus_DeviceDisabled_Base(
            Client.TransportType protocol, Func <RegistryManager, string, Task> registryManagerOperation)
        {
            AmqpTransportSettings amqpTransportSettings = new AmqpTransportSettings(protocol);

            ITransportSettings[] transportSettings = new ITransportSettings[] { amqpTransportSettings };

            TestModule testModule = await TestModule.GetTestModuleAsync(DevicePrefix + $"_{Guid.NewGuid()}", ModulePrefix).ConfigureAwait(false);

            ConnectionStatus?            status             = null;
            ConnectionStatusChangeReason?statusChangeReason = null;
            int deviceDisabledReceivedCount = 0;
            ConnectionStatusChangesHandler statusChangeHandler = (s, r) =>
            {
                if (r == ConnectionStatusChangeReason.Device_Disabled)
                {
                    status             = s;
                    statusChangeReason = r;
                    deviceDisabledReceivedCount++;
                }
            };

            using (ModuleClient moduleClient = ModuleClient.CreateFromConnectionString(testModule.ConnectionString, transportSettings))
            {
                moduleClient.SetConnectionStatusChangesHandler(statusChangeHandler);
                _log.WriteLine($"Created {nameof(DeviceClient)} ID={TestLogging.IdOf(moduleClient)}");

                Console.WriteLine("ModuleClient OpenAsync.");
                await moduleClient.OpenAsync().ConfigureAwait(false);

                // Receiving the module twin should succeed right now.
                Console.WriteLine("ModuleClient GetTwinAsync.");
                var twin = await moduleClient.GetTwinAsync().ConfigureAwait(false);

                Assert.IsNotNull(twin);

                // Delete/disable the device in IoT Hub.
                using (RegistryManager registryManager = RegistryManager.CreateFromConnectionString(Configuration.IoTHub.ConnectionString))
                {
                    await registryManagerOperation(registryManager, testModule.DeviceId).ConfigureAwait(false);
                }

                // Artificial sleep waiting for the connection status change handler to get triggered.
                int sleepCount = 50;
                for (int i = 0; i < sleepCount; i++)
                {
                    await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);

                    if (deviceDisabledReceivedCount == 1)
                    {
                        break;
                    }
                }

                Assert.AreEqual(1, deviceDisabledReceivedCount);
                Assert.AreEqual(ConnectionStatus.Disconnected, status);
                Assert.AreEqual(ConnectionStatusChangeReason.Device_Disabled, statusChangeReason);
            }
        }
Example #11
0
        public async Task <IModuleClient> Create(ConnectionStatusChangesHandler statusChangedHandler)
        {
            ISdkModuleClient sdkModuleClient = await this.CreateSdkModuleClientWithRetry(statusChangedHandler);

            IModuleClient moduleClient = new ModuleClient(sdkModuleClient, this.idleTimeout, this.closeOnIdleTimeout);

            return(moduleClient);
        }
Example #12
0
 static async Task OpenAsync(ConnectionStatusChangesHandler statusChangedHandler, Client.ModuleClient deviceClient)
 {
     // note: it's important to set the status-changed handler and
     // timeout value *before* we open a connection to the hub
     deviceClient.OperationTimeoutInMilliseconds = DeviceClientTimeout;
     deviceClient.SetConnectionStatusChangesHandler(statusChangedHandler);
     await deviceClient.OpenAsync();
 }
 /// <summary>
 /// Registers a new delegate for the connection status changed callback. If a delegate is already associated,
 /// it will be replaced with the new delegate.
 /// </summary>
 public void SetConnectionStatusChangesHandler(ConnectionStatusChangesHandler statusChangesHandler)
 {
     if (_iotHubClient == null)
     {
         _edgeHubClient.SetConnectionStatusChangesHandler(statusChangesHandler);
         return;
     }
     _iotHubClient.SetConnectionStatusChangesHandler(statusChangesHandler);
 }
Example #14
0
        public RetryDelegatingHandler(IPipelineContext context, IDelegatingHandler innerHandler)
            : base(context, innerHandler)
        {
            IRetryPolicy defaultRetryStrategy = new ExponentialBackoff(
                retryCount: RetryMaxCount,
                minBackoff: TimeSpan.FromMilliseconds(100),
                maxBackoff: TimeSpan.FromSeconds(10),
                deltaBackoff: TimeSpan.FromMilliseconds(100));

            _internalRetryPolicy       = new RetryPolicy(new TransientErrorStrategy(), new RetryStrategyAdapter(defaultRetryStrategy));
            _onConnectionStatusChanged = context.Get <ConnectionStatusChangesHandler>();

            Logging.Associate(this, _internalRetryPolicy, nameof(SetRetryPolicy));
        }
Example #15
0
        static async Task <Client.ModuleClient> CreateAndOpenDeviceClient(TransportType transport,
                                                                          Option <string> connectionString,
                                                                          ConnectionStatusChangesHandler statusChangedHandler,
                                                                          Option <string> productInfo)
        {
            Events.AttemptingConnectionWithTransport(transport);
            Client.ModuleClient deviceClient = await connectionString.Map(cs => Task.FromResult(Client.ModuleClient.CreateFromConnectionString(cs, transport)))
                                               .GetOrElse(() => Client.ModuleClient.CreateFromEnvironmentAsync(transport));

            productInfo.ForEach(p => deviceClient.ProductInfo = p);
            await OpenAsync(statusChangedHandler, deviceClient);

            Events.ConnectedWithTransport(transport);
            return(deviceClient);
        }
        public async Task Initialize(ConnectionStatusChangesHandler connectionStatusHander, MessageHandler messageCallback, DesiredPropertyUpdateCallback twinCallback, MethodCallback methodCallback, object context, CancellationToken ct)
        {
            if (deviceClient == null)
            {
                return;
            }
            deviceClient.SetConnectionStatusChangesHandler(connectionStatusHander);
            await deviceClient.SetDesiredPropertyUpdateCallbackAsync(twinCallback, context);

            await deviceClient.SetMethodDefaultHandlerAsync(methodCallback, context);

            this.messageCallback   = messageCallback;
            this.callbackContext   = context;
            this.cancellationToken = ct;
            ReceiveC2DMessages();
        }
Example #17
0
        public ModuleConnection(
            IModuleClientProvider moduleClientProvider,
            IRequestManager requestManager,
            ConnectionStatusChangesHandler connectionStatusChangesHandler,
            DesiredPropertyUpdateCallback desiredPropertyUpdateCallback,
            bool enableSubscriptions)
        {
            this.moduleClientProvider           = Preconditions.CheckNotNull(moduleClientProvider, nameof(moduleClientProvider));
            this.requestManager                 = Preconditions.CheckNotNull(requestManager, nameof(requestManager));
            this.connectionStatusChangesHandler = Preconditions.CheckNotNull(connectionStatusChangesHandler, nameof(connectionStatusChangesHandler));
            this.desiredPropertyUpdateCallback  = Preconditions.CheckNotNull(desiredPropertyUpdateCallback, nameof(desiredPropertyUpdateCallback));
            this.enableSubscriptions            = enableSubscriptions;

            // Run initialize module client to create the module client. But we don't need to wait for the result.
            // The subsequent calls will automatically wait because of the lock
            Task.Run(this.InitModuleClient);
        }
Example #18
0
        async Task <ISdkModuleClient> CreateSdkModuleClientWithRetry(ConnectionStatusChangesHandler statusChangedHandler)
        {
            try
            {
                ISdkModuleClient moduleClient = await ExecuteWithRetry(
                    () => this.CreateSdkModuleClient(statusChangedHandler),
                    Events.RetryingDeviceClientConnection);

                Events.DeviceClientCreated();
                return(moduleClient);
            }
            catch (Exception e)
            {
                Events.DeviceClientSetupFailed(e);
                Environment.Exit(1);
                return(null);
            }
        }
        public async Task Initialize(ConnectionStatusChangesHandler connectionStatusHander, MessageHandler messageCallback, DesiredPropertyUpdateCallback twinCallback, MethodCallback methodCallback, object context, CancellationToken ct)
        {
            var option = new ClientOptions
            {
                ModelId = ModuleClientConnector.PnPModelId
            };

            moduleClient = await ModuleClient.CreateFromEnvironmentAsync(envSettings, options : option);

            Console.WriteLine($"Connected to Edge Hub as Plug and Play Model Id={ModuleClientConnector.PnPModelId}");

            await moduleClient.OpenAsync();

            moduleClient.SetConnectionStatusChangesHandler(connectionStatusHander);
            await moduleClient.SetInputMessageHandlerAsync(this.msgInputName, messageCallback, context);

            await moduleClient.SetDesiredPropertyUpdateCallbackAsync(twinCallback, context);

            await moduleClient.SetMethodDefaultHandlerAsync(methodCallback, context);
        }
Example #20
0
        static async Task <Client.ModuleClient> CreateAndOpenDeviceClient(
            UpstreamProtocol upstreamProtocol,
            Option <string> connectionString,
            ConnectionStatusChangesHandler statusChangedHandler,
            Option <IWebProxy> proxy,
            Option <string> productInfo)
        {
            ITransportSettings settings = GetTransportSettings(upstreamProtocol, proxy);

            Events.AttemptingConnectionWithTransport(settings.GetTransportType());
            Client.ModuleClient deviceClient = await connectionString
                                               .Map(cs => Task.FromResult(Client.ModuleClient.CreateFromConnectionString(cs, new[] { settings })))
                                               .GetOrElse(() => Client.ModuleClient.CreateFromEnvironmentAsync(new[] { settings }));

            productInfo.ForEach(p => deviceClient.ProductInfo = p);
            await OpenAsync(statusChangedHandler, deviceClient);

            Events.ConnectedWithTransport(settings.GetTransportType());
            return(deviceClient);
        }
Example #21
0
        Task <ISdkModuleClient> CreateSdkModuleClient(ConnectionStatusChangesHandler statusChangedHandler)
        => this.upstreamProtocol
        .Map(u => this.CreateAndOpenSdkModuleClient(u, statusChangedHandler))
        .GetOrElse(
            async() =>
        {
            // The device SDK doesn't appear to be falling back to WebSocket from TCP,
            // so we'll do it explicitly until we can get the SDK sorted out.
            Try <ISdkModuleClient> result = await Fallback.ExecuteAsync(
                () => this.CreateAndOpenSdkModuleClient(UpstreamProtocol.Amqp, statusChangedHandler),
                () => this.CreateAndOpenSdkModuleClient(UpstreamProtocol.AmqpWs, statusChangedHandler));

            if (!result.Success)
            {
                Events.DeviceConnectionError(result.Exception);
                ExceptionDispatchInfo.Capture(result.Exception).Throw();
            }

            return(result.Value);
        });
Example #22
0
        public async Task CreateAndInitTest()
        {
            // Arrange
            ConnectionStatusChangesHandler connectionStatusChangesHandler = (status, reason) => { };
            DesiredPropertyUpdateCallback  desiredPropertyUpdateCallback  = (properties, context) => Task.CompletedTask;

            var moduleClient = new Mock <IModuleClient>();

            moduleClient.Setup(m => m.IsActive).Returns(true);
            var moduleClientProvider = new Mock <IModuleClientProvider>();

            moduleClientProvider.Setup(m => m.Create(connectionStatusChangesHandler))
            .ReturnsAsync(moduleClient.Object);

            var  requestManager      = new Mock <IRequestManager>();
            bool enableSubscriptions = true;

            // Act
            var moduleConnection = new ModuleConnection(moduleClientProvider.Object, requestManager.Object, connectionStatusChangesHandler, desiredPropertyUpdateCallback, enableSubscriptions);
            await Task.Delay(TimeSpan.FromSeconds(5));

            Option <IModuleClient> resultModuleClientOption = moduleConnection.GetModuleClient();

            // Assert
            Assert.True(resultModuleClientOption.HasValue);
            Assert.Equal(moduleClient.Object, resultModuleClientOption.OrDefault());
            moduleClientProvider.Verify(m => m.Create(connectionStatusChangesHandler), Times.Once);
            moduleClient.Verify(m => m.SetDefaultMethodHandlerAsync(It.IsAny <MethodCallback>()), Times.Once);
            moduleClient.Verify(m => m.SetDesiredPropertyUpdateCallbackAsync(desiredPropertyUpdateCallback), Times.Once);

            // Act
            IModuleClient resultModuleClient = await moduleConnection.GetOrCreateModuleClient();

            // Assert
            Assert.NotNull(resultModuleClient);
            Assert.Equal(moduleClient.Object, resultModuleClient);
            moduleClientProvider.Verify(m => m.Create(connectionStatusChangesHandler), Times.Once);
            moduleClient.Verify(m => m.SetDefaultMethodHandlerAsync(It.IsAny <MethodCallback>()), Times.Once);
            moduleClient.Verify(m => m.SetDesiredPropertyUpdateCallbackAsync(desiredPropertyUpdateCallback), Times.Once);
        }
Example #23
0
 public void SetConnectionStatusChangedHandler(ConnectionStatusChangesHandler handler)
 {
     this.connectionStatusChangedHandler = handler;
     this.underlyingClient.SetConnectionStatusChangedHandler(this.InternalConnectionStatusChangedHandler);
 }
Example #24
0
        async Task <ISdkModuleClient> CreateAndOpenSdkModuleClient(UpstreamProtocol upstreamProtocol, ConnectionStatusChangesHandler statusChangedHandler)
        {
            ITransportSettings settings = GetTransportSettings(upstreamProtocol, this.proxy);

            Events.AttemptingConnectionWithTransport(settings.GetTransportType());

            ISdkModuleClient moduleClient = await this.connectionString
                                            .Map(cs => Task.FromResult(this.sdkModuleClientProvider.GetSdkModuleClient(cs, settings)))
                                            .GetOrElse(this.sdkModuleClientProvider.GetSdkModuleClient(settings));

            moduleClient.SetProductInfo(this.productInfo);

            // note: it's important to set the status-changed handler and
            // timeout value *before* we open a connection to the hub
            moduleClient.SetOperationTimeoutInMilliseconds(ModuleClientTimeoutMilliseconds);
            moduleClient.SetConnectionStatusChangesHandler(statusChangedHandler);
            await moduleClient.OpenAsync();

            Events.ConnectedWithTransport(settings.GetTransportType());
            return(moduleClient);
        }
        public async Task UpdateDeviceConnectionTest()
        {
            int receivedConnectedStatusCount = 0;
            ConnectionStatusChangesHandler connectionStatusChangesHandler = null;
            string hostname = "dummy.azure-devices.net";
            string deviceId = "device1";

            ITokenCredentials GetClientCredentials(TimeSpan tokenExpiryDuration)
            {
                string token    = TokenHelper.CreateSasToken(hostname, DateTime.UtcNow.AddSeconds(tokenExpiryDuration.TotalSeconds));
                var    identity = new DeviceIdentity(hostname, deviceId);

                return(new TokenCredentials(identity, token, string.Empty, Option.None <string>(), Option.None <string>(), false));
            }

            IDeviceProxy GetMockDeviceProxy()
            {
                var deviceProxyMock1 = new Mock <IDeviceProxy>();

                deviceProxyMock1.SetupGet(dp => dp.IsActive).Returns(true);
                deviceProxyMock1.Setup(dp => dp.CloseAsync(It.IsAny <Exception>()))
                .Callback(() => deviceProxyMock1.SetupGet(dp => dp.IsActive).Returns(false))
                .Returns(Task.CompletedTask);
                return(deviceProxyMock1.Object);
            }

            IClient GetMockedDeviceClient()
            {
                var deviceClient = new Mock <IClient>();

                deviceClient.SetupGet(dc => dc.IsActive).Returns(true);
                deviceClient.Setup(dc => dc.CloseAsync())
                .Callback(() => deviceClient.SetupGet(dc => dc.IsActive).Returns(false))
                .Returns(Task.FromResult(true));

                deviceClient.Setup(dc => dc.SetConnectionStatusChangedHandler(It.IsAny <ConnectionStatusChangesHandler>()))
                .Callback <ConnectionStatusChangesHandler>(c => connectionStatusChangesHandler = c);

                deviceClient.Setup(dc => dc.OpenAsync())
                .Callback(
                    () =>
                {
                    int currentCount = receivedConnectedStatusCount;
                    Assert.NotNull(connectionStatusChangesHandler);
                    connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
                    Assert.Equal(receivedConnectedStatusCount, currentCount);
                })
                .Returns(Task.CompletedTask);
                return(deviceClient.Object);
            }

            ITokenProvider tokenProvider        = null;
            var            deviceClientProvider = new Mock <IClientProvider>();

            deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <ITokenProvider>(), It.IsAny <ITransportSettings[]>(), Option.None <string>()))
            .Callback <IIdentity, ITokenProvider, ITransportSettings[], Option <string> >((s, a, t, m) => tokenProvider = a)
            .Returns(GetMockedDeviceClient);

            var metadataStore = new Mock <IMetadataStore>();

            metadataStore.Setup(m => m.GetMetadata(It.IsAny <string>())).ReturnsAsync(new ConnectionMetadata("dummyValue"));
            var messageConverterProvider = Mock.Of <IMessageConverterProvider>();

            var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>();

            deviceScopeIdentitiesCache.Setup(d => d.GetAuthChain(It.Is <string>(i => i == deviceId))).ReturnsAsync(Option.Some(deviceId));

            var credentialsCache = Mock.Of <ICredentialsCache>();
            ICloudConnectionProvider cloudConnectionProvider = new CloudConnectionProvider(
                messageConverterProvider,
                1,
                deviceClientProvider.Object,
                Option.None <UpstreamProtocol>(),
                TokenProvider,
                deviceScopeIdentitiesCache.Object,
                credentialsCache,
                Mock.Of <IIdentity>(i => i.Id == $"{deviceId}/$edgeHub"),
                TimeSpan.FromMinutes(60),
                true,
                TimeSpan.FromSeconds(20),
                false,
                Option.None <IWebProxy>(),
                metadataStore.Object,
                scopeAuthenticationOnly: true,
                trackDeviceState: true,
                true);

            cloudConnectionProvider.BindEdgeHub(Mock.Of <IEdgeHub>());
            var deviceConnectivityManager        = Mock.Of <IDeviceConnectivityManager>();
            IConnectionManager connectionManager = new ConnectionManager(cloudConnectionProvider, Mock.Of <ICredentialsCache>(), new IdentityProvider(hostname), deviceConnectivityManager);

            ITokenCredentials clientCredentials1 = GetClientCredentials(TimeSpan.FromSeconds(10));
            Try <ICloudProxy> cloudProxyTry1     = await connectionManager.CreateCloudConnectionAsync(clientCredentials1);

            Assert.True(cloudProxyTry1.Success);

            IDeviceProxy deviceProxy1 = GetMockDeviceProxy();
            await connectionManager.AddDeviceConnection(clientCredentials1.Identity, deviceProxy1);

            await Task.Delay(TimeSpan.FromSeconds(10));

            Assert.NotNull(tokenProvider);
            Task <string> tokenGetter = tokenProvider.GetTokenAsync(Option.None <TimeSpan>());

            Assert.False(tokenGetter.IsCompleted);

            ITokenCredentials clientCredentials2 = GetClientCredentials(TimeSpan.FromMinutes(2));
            Try <ICloudProxy> cloudProxyTry2     = await connectionManager.CreateCloudConnectionAsync(clientCredentials2);

            Assert.True(cloudProxyTry2.Success);

            IDeviceProxy deviceProxy2 = GetMockDeviceProxy();
            await connectionManager.AddDeviceConnection(clientCredentials2.Identity, deviceProxy2);

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

            Assert.False(tokenGetter.IsCompleted);

            ITokenCredentials clientCredentials3 = GetClientCredentials(TimeSpan.FromMinutes(10));
            Try <ICloudProxy> cloudProxyTry3     = await connectionManager.CreateCloudConnectionAsync(clientCredentials3);

            Assert.True(cloudProxyTry3.Success);

            IDeviceProxy deviceProxy3 = GetMockDeviceProxy();
            await connectionManager.AddDeviceConnection(clientCredentials3.Identity, deviceProxy3);

            await Task.Delay(TimeSpan.FromSeconds(23));

            Assert.True(tokenGetter.IsCompleted);
            Assert.Equal(tokenGetter.Result, clientCredentials3.Token);
        }
Example #26
0
        public async Task UpdateDeviceConnectionTest()
        {
            int receivedConnectedStatusCount = 0;
            ConnectionStatusChangesHandler connectionStatusChangesHandler = null;
            string hostname = "dummy.azure-devices.net";
            string deviceId = "device1";

            IClientCredentials GetClientCredentials(TimeSpan tokenExpiryDuration)
            {
                string token    = TokenHelper.CreateSasToken(hostname, DateTime.UtcNow.AddSeconds(tokenExpiryDuration.TotalSeconds));
                var    identity = new DeviceIdentity(hostname, deviceId);

                return(new TokenCredentials(identity, token, string.Empty));
            }

            IDeviceProxy GetMockDeviceProxy()
            {
                var deviceProxyMock1 = new Mock <IDeviceProxy>();

                deviceProxyMock1.SetupGet(dp => dp.IsActive).Returns(true);
                deviceProxyMock1.Setup(dp => dp.CloseAsync(It.IsAny <Exception>()))
                .Callback(() => deviceProxyMock1.SetupGet(dp => dp.IsActive).Returns(false))
                .Returns(Task.CompletedTask);
                return(deviceProxyMock1.Object);
            }

            IClient GetMockedDeviceClient()
            {
                var deviceClient = new Mock <IClient>();

                deviceClient.SetupGet(dc => dc.IsActive).Returns(true);
                deviceClient.Setup(dc => dc.CloseAsync())
                .Callback(() => deviceClient.SetupGet(dc => dc.IsActive).Returns(false))
                .Returns(Task.FromResult(true));

                deviceClient.Setup(dc => dc.SetConnectionStatusChangedHandler(It.IsAny <ConnectionStatusChangesHandler>()))
                .Callback <ConnectionStatusChangesHandler>(c => connectionStatusChangesHandler = c);

                deviceClient.Setup(dc => dc.OpenAsync())
                .Callback(() =>
                {
                    int currentCount = receivedConnectedStatusCount;
                    Assert.NotNull(connectionStatusChangesHandler);
                    connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
                    Assert.Equal(receivedConnectedStatusCount, currentCount);
                })
                .Returns(Task.CompletedTask);
                return(deviceClient.Object);
            }

            IAuthenticationMethod authenticationMethod = null;
            var deviceClientProvider = new Mock <IClientProvider>();

            deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <IAuthenticationMethod>(), It.IsAny <ITransportSettings[]>()))
            .Callback <IIdentity, IAuthenticationMethod, ITransportSettings[]>((s, a, t) => authenticationMethod = a)
            .Returns(() => GetMockedDeviceClient());

            var messageConverterProvider = Mock.Of <IMessageConverterProvider>();

            ICloudConnectionProvider cloudConnectionProvider = new CloudConnectionProvider(messageConverterProvider, 1, deviceClientProvider.Object, Option.None <UpstreamProtocol>(), TokenProvider, DeviceScopeIdentitiesCache, TimeSpan.FromMinutes(60), true);

            cloudConnectionProvider.BindEdgeHub(Mock.Of <IEdgeHub>());
            var credentialsCache = Mock.Of <ICredentialsCache>();
            IConnectionManager connectionManager = new ConnectionManager(cloudConnectionProvider, credentialsCache, deviceId, "$edgeHub");

            IClientCredentials clientCredentials1 = GetClientCredentials(TimeSpan.FromSeconds(10));
            Try <ICloudProxy>  cloudProxyTry1     = await connectionManager.CreateCloudConnectionAsync(clientCredentials1);

            Assert.True(cloudProxyTry1.Success);

            IDeviceProxy deviceProxy1 = GetMockDeviceProxy();
            await connectionManager.AddDeviceConnection(clientCredentials1.Identity, deviceProxy1);

            await Task.Delay(TimeSpan.FromSeconds(10));

            Assert.NotNull(authenticationMethod);
            var deviceTokenRefresher = authenticationMethod as DeviceAuthenticationWithTokenRefresh;

            Assert.NotNull(deviceTokenRefresher);
            Task <string> tokenGetter = deviceTokenRefresher.GetTokenAsync(hostname);

            Assert.False(tokenGetter.IsCompleted);

            IClientCredentials clientCredentials2 = GetClientCredentials(TimeSpan.FromMinutes(2));
            Try <ICloudProxy>  cloudProxyTry2     = await connectionManager.CreateCloudConnectionAsync(clientCredentials2);

            Assert.True(cloudProxyTry2.Success);

            IDeviceProxy deviceProxy2 = GetMockDeviceProxy();
            await connectionManager.AddDeviceConnection(clientCredentials2.Identity, deviceProxy2);

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

            Assert.False(tokenGetter.IsCompleted);

            IClientCredentials clientCredentials3 = GetClientCredentials(TimeSpan.FromMinutes(10));
            Try <ICloudProxy>  cloudProxyTry3     = await connectionManager.CreateCloudConnectionAsync(clientCredentials3);

            Assert.True(cloudProxyTry3.Success);

            IDeviceProxy deviceProxy3 = GetMockDeviceProxy();
            await connectionManager.AddDeviceConnection(clientCredentials3.Identity, deviceProxy3);

            await Task.Delay(TimeSpan.FromSeconds(23));

            Assert.True(tokenGetter.IsCompleted);
            Assert.Equal(tokenGetter.Result, (clientCredentials3 as ITokenCredentials)?.Token);
        }
Example #27
0
        public async Task CloudConnectionCallbackTest()
        {
            int receivedConnectedStatusCount = 0;
            ConnectionStatusChangesHandler connectionStatusChangesHandler = (_, __) => { };

            IClient GetMockedDeviceClient()
            {
                var deviceClient = new Mock <IClient>();

                deviceClient.SetupGet(dc => dc.IsActive).Returns(true);
                deviceClient.Setup(dc => dc.CloseAsync())
                .Callback(() => deviceClient.SetupGet(dc => dc.IsActive).Returns(false))
                .Returns(Task.FromResult(true));

                deviceClient.Setup(dc => dc.SetConnectionStatusChangedHandler(It.IsAny <ConnectionStatusChangesHandler>()))
                .Callback <ConnectionStatusChangesHandler>(c => connectionStatusChangesHandler = c);

                deviceClient.Setup(dc => dc.OpenAsync())
                .Callback(() =>
                {
                    int currentCount = receivedConnectedStatusCount;
                    Assert.NotNull(connectionStatusChangesHandler);
                    connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
                    Assert.Equal(receivedConnectedStatusCount, currentCount);
                })
                .Returns(Task.CompletedTask);
                return(deviceClient.Object);
            }

            var deviceClientProvider = new Mock <IClientProvider>();

            deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <IAuthenticationMethod>(), It.IsAny <ITransportSettings[]>()))
            .Returns(() => GetMockedDeviceClient());

            var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) };

            void ConnectionStatusHandler(string id, CloudConnectionStatus status)
            {
                if (status == CloudConnectionStatus.ConnectionEstablished)
                {
                    receivedConnectedStatusCount++;
                }
            }

            var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> {
                [typeof(TwinCollection)] = Mock.Of <IMessageConverter>()
            });
            var cloudConnection = new CloudConnection(ConnectionStatusHandler, transportSettings, messageConverterProvider, deviceClientProvider.Object, Mock.Of <ICloudListener>(), TokenProvider, DeviceScopeIdentitiesCache, TimeSpan.FromMinutes(60), true);

            IClientCredentials clientCredentialsWithExpiringToken1 = GetMockClientCredentialsWithToken();

            Assert.Equal(receivedConnectedStatusCount, 0);
            ICloudProxy cloudProxy1 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken1);

            Assert.True(cloudProxy1.IsActive);
            Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault());
            Assert.Equal(receivedConnectedStatusCount, 0);

            Assert.NotNull(connectionStatusChangesHandler);
            connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
            Assert.Equal(receivedConnectedStatusCount, 1);

            IClientCredentials clientCredentialsWithExpiringToken2 = GetMockClientCredentialsWithToken();
            ICloudProxy        cloudProxy2 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken2);

            Assert.True(cloudProxy2.IsActive);
            Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault());
            Assert.Equal(receivedConnectedStatusCount, 1);

            connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
            Assert.Equal(receivedConnectedStatusCount, 2);
        }
Example #28
0
        private async Task DeviceClient_Gives_ConnectionStatus_DeviceDisabled_Base(
            Client.TransportType protocol, Func <RegistryManager, string, Task> registryManagerOperation)
        {
            TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, DevicePrefix + $"_{Guid.NewGuid()}").ConfigureAwait(false);

            string deviceConnectionString = testDevice.ConnectionString;

            var    config   = new Configuration.IoTHub.ConnectionStringParser(deviceConnectionString);
            string deviceId = config.DeviceID;

            ConnectionStatus?            status             = null;
            ConnectionStatusChangeReason?statusChangeReason = null;
            int deviceDisabledReceivedCount = 0;

            using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(deviceConnectionString, protocol))
            {
                ConnectionStatusChangesHandler statusChangeHandler = (s, r) =>
                {
                    if (r == ConnectionStatusChangeReason.Device_Disabled)
                    {
                        status             = s;
                        statusChangeReason = r;
                        deviceDisabledReceivedCount++;
                    }
                };

                deviceClient.SetConnectionStatusChangesHandler(statusChangeHandler);
                Logger.Trace($"{nameof(DeviceClient_Gives_ConnectionStatus_DeviceDisabled_Base)}: Created {nameof(DeviceClient)} with device Id={testDevice.Id}");

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

                // Receiving the module twin should succeed right now.
                Logger.Trace($"{nameof(DeviceClient_Gives_ConnectionStatus_DeviceDisabled_Base)}: DeviceClient GetTwinAsync.");
                var twin = await deviceClient.GetTwinAsync().ConfigureAwait(false);

                Assert.IsNotNull(twin);

                // Delete/disable the device in IoT Hub. This should trigger the ConnectionStatusChangesHandler.
                using (RegistryManager registryManager = RegistryManager.CreateFromConnectionString(Configuration.IoTHub.ConnectionString))
                {
                    await registryManagerOperation(registryManager, deviceId).ConfigureAwait(false);
                }

                Logger.Trace($"{nameof(DeviceClient_Gives_ConnectionStatus_DeviceDisabled_Base)}: Completed RegistryManager operation.");

                // Artificial sleep waiting for the connection status change handler to get triggered.
                int sleepCount = 50;
                for (int i = 0; i < sleepCount; i++)
                {
                    await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);

                    if (deviceDisabledReceivedCount == 1)
                    {
                        break;
                    }
                }

                Logger.Trace($"{nameof(DeviceClient_Gives_ConnectionStatus_DeviceDisabled_Base)}: Asserting connection status change.");

                Assert.AreEqual(1, deviceDisabledReceivedCount);
                Assert.AreEqual(ConnectionStatus.Disconnected, status);
                Assert.AreEqual(ConnectionStatusChangeReason.Device_Disabled, statusChangeReason);
            }
        }
Example #29
0
 public void SetConnectionStatusChangedHandler(ConnectionStatusChangesHandler handler)
 {
 }
        public async Task CloudConnectionCallbackTest()
        {
            int receivedConnectedStatusCount = 0;
            ConnectionStatusChangesHandler connectionStatusChangesHandler = (_, __) => { };

            IClient GetMockedDeviceClient()
            {
                var deviceClient = new Mock <IClient>();

                deviceClient.SetupGet(dc => dc.IsActive).Returns(true);
                deviceClient.Setup(dc => dc.CloseAsync())
                .Callback(() => deviceClient.SetupGet(dc => dc.IsActive).Returns(false))
                .Returns(Task.FromResult(true));

                deviceClient.Setup(dc => dc.SetConnectionStatusChangedHandler(It.IsAny <ConnectionStatusChangesHandler>()))
                .Callback <ConnectionStatusChangesHandler>(c => connectionStatusChangesHandler = c);

                deviceClient.Setup(dc => dc.OpenAsync())
                .Callback(
                    () =>
                {
                    Assert.NotNull(connectionStatusChangesHandler);
                    connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
                })
                .Returns(Task.CompletedTask);
                return(deviceClient.Object);
            }

            var deviceClientProvider = new Mock <IClientProvider>();

            deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <ITokenProvider>(), It.IsAny <ITransportSettings[]>(), Option.None <string>()))
            .Returns(() => GetMockedDeviceClient());

            var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) };

            void ConnectionStatusHandler(string id, CloudConnectionStatus status)
            {
                if (status == CloudConnectionStatus.ConnectionEstablished)
                {
                    receivedConnectedStatusCount++;
                }
            }

            var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> {
                [typeof(TwinCollection)] = Mock.Of <IMessageConverter>()
            });
            ITokenCredentials          clientCredentialsWithExpiringToken1 = GetMockClientCredentialsWithToken();
            ClientTokenCloudConnection cloudConnection = await ClientTokenCloudConnection.Create(
                clientCredentialsWithExpiringToken1,
                ConnectionStatusHandler,
                transportSettings,
                messageConverterProvider,
                deviceClientProvider.Object,
                Mock.Of <ICloudListener>(),
                TimeSpan.FromMinutes(60),
                true,
                TimeSpan.FromSeconds(20),
                DummyProductInfo,
                Option.None <string>());

            Assert.Equal(1, receivedConnectedStatusCount);
            Option <ICloudProxy> cloudProxy1 = cloudConnection.CloudProxy;

            Assert.True(cloudProxy1.HasValue);
            Assert.True(cloudProxy1.OrDefault().IsActive);

            Assert.NotNull(connectionStatusChangesHandler);
            connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
            Assert.Equal(2, receivedConnectedStatusCount);

            ITokenCredentials clientCredentialsWithExpiringToken2 = GetMockClientCredentialsWithToken();
            ICloudProxy       cloudProxy2 = await cloudConnection.UpdateTokenAsync(clientCredentialsWithExpiringToken2);

            Assert.True(cloudProxy2.IsActive);
            Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault());
            Assert.Equal(2, receivedConnectedStatusCount);

            connectionStatusChangesHandler.Invoke(ConnectionStatus.Connected, ConnectionStatusChangeReason.Connection_Ok);
            Assert.Equal(3, receivedConnectedStatusCount);
        }