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); }
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); }
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)); }
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."); }
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); }
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));
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); }
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); } }
public async Task <IModuleClient> Create(ConnectionStatusChangesHandler statusChangedHandler) { ISdkModuleClient sdkModuleClient = await this.CreateSdkModuleClientWithRetry(statusChangedHandler); IModuleClient moduleClient = new ModuleClient(sdkModuleClient, this.idleTimeout, this.closeOnIdleTimeout); return(moduleClient); }
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); }
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)); }
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(); }
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); }
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); }
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); }
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); });
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); }
public void SetConnectionStatusChangedHandler(ConnectionStatusChangesHandler handler) { this.connectionStatusChangedHandler = handler; this.underlyingClient.SetConnectionStatusChangedHandler(this.InternalConnectionStatusChangedHandler); }
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); }
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); }
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); }
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); } }
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); }