public async Task GetCloudConnectionForIdentityWithKeyTest() { IClientProvider clientProvider = GetMockDeviceClientProviderWithKey(); var tokenProvider = Mock.Of <ITokenProvider>(); var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); CloudConnection cloudConnection = await CloudConnection.Create( identity, (_, __) => { }, transportSettings, messageConverterProvider, clientProvider, Mock.Of <ICloudListener>(), tokenProvider, TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20), DummyProductInfo); Option <ICloudProxy> cloudProxy1 = cloudConnection.CloudProxy; Assert.True(cloudProxy1.HasValue); Assert.True(cloudProxy1.OrDefault().IsActive); }
public async Task UpdateInvalidIdentityWithTokenTest() { var deviceClientProvider = new Mock <IClientProvider>(); deviceClientProvider.SetupSequence(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <ITokenProvider>(), It.IsAny <ITransportSettings[]>())) .Returns(GetMockDeviceClient()) .Throws(new UnauthorizedException("Unauthorized")); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); ITokenCredentials identity1 = GetMockClientCredentialsWithToken(); ClientTokenCloudConnection cloudConnection = await ClientTokenCloudConnection.Create( identity1, (_, __) => { }, transportSettings, messageConverterProvider, deviceClientProvider.Object, Mock.Of <ICloudListener>(), TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20)); Option <ICloudProxy> cloudProxy1 = cloudConnection.CloudProxy; Assert.True(cloudProxy1.HasValue); Assert.True(cloudProxy1.OrDefault().IsActive); ITokenCredentials identity2 = GetMockClientCredentialsWithToken(); await Assert.ThrowsAsync <UnauthorizedException>(() => cloudConnection.UpdateTokenAsync(identity2)); Assert.True(cloudProxy1.OrDefault().IsActive); }
public async Task UpdateInvalidIdentityWithTokenTest() { var deviceClientProvider = new Mock <IClientProvider>(); deviceClientProvider.SetupSequence(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <IAuthenticationMethod>(), It.IsAny <ITransportSettings[]>())) .Returns(GetMockDeviceClient()) .Throws(new UnauthorizedException("Unauthorized")); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); var cloudConnection = new CloudConnection((_, __) => { }, transportSettings, messageConverterProvider, deviceClientProvider.Object, Mock.Of <ICloudListener>(), TokenProvider, DeviceScopeIdentitiesCache, TimeSpan.FromMinutes(60), true); IClientCredentials identity1 = GetMockClientCredentialsWithToken(); ICloudProxy cloudProxy1 = await cloudConnection.CreateOrUpdateAsync(identity1); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault()); IClientCredentials identity2 = GetMockClientCredentialsWithToken(); await Assert.ThrowsAsync <AggregateException>(() => cloudConnection.CreateOrUpdateAsync(identity2)); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault()); }
public void ThrowsWhenItDoesNotHaveTheRequestedProvider() { var provider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter>()); var fn = new Func <IMessageConverter <int> >(() => provider.Get <int>()); Assert.Throws <KeyNotFoundException>(fn); }
async Task <ICloudProxy> GetCloudProxyWithConnectionStringKey(string connectionStringConfigKey, IEdgeHub edgeHub) { const int ConnectionPoolSize = 10; string deviceConnectionString = await SecretsHelper.GetSecretFromConfigKey(connectionStringConfigKey); var converters = new MessageConverterProvider(new Dictionary <Type, IMessageConverter>() { { typeof(Client.Message), new DeviceClientMessageConverter() }, { typeof(Twin), new TwinMessageConverter() }, { typeof(TwinCollection), new TwinCollectionMessageConverter() } }); ICloudConnectionProvider cloudConnectionProvider = new CloudConnectionProvider(converters, ConnectionPoolSize, new ClientProvider(), Option.None <UpstreamProtocol>(), Mock.Of <ITokenProvider>(), Mock.Of <IDeviceScopeIdentitiesCache>(), TimeSpan.FromMinutes(60), true); cloudConnectionProvider.BindEdgeHub(edgeHub); var deviceIdentity = Mock.Of <IDeviceIdentity>(m => m.Id == ConnectionStringHelper.GetDeviceId(deviceConnectionString)); var clientCredentials = new SharedKeyCredentials(deviceIdentity, deviceConnectionString, string.Empty); Try <ICloudConnection> cloudConnection = await cloudConnectionProvider.Connect(clientCredentials, (_, __) => { }); Assert.True(cloudConnection.Success); Assert.True(cloudConnection.Value.IsActive); Assert.True(cloudConnection.Value.CloudProxy.HasValue); return(cloudConnection.Value.CloudProxy.OrDefault()); }
public async Task GetCloudConnectionForIdentityWithTokenTest() { IClientProvider clientProvider = GetMockDeviceClientProviderWithToken(); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); ITokenCredentials clientCredentials1 = GetMockClientCredentialsWithToken(); ClientTokenCloudConnection cloudConnection = await ClientTokenCloudConnection.Create( clientCredentials1, (_, __) => { }, transportSettings, messageConverterProvider, clientProvider, Mock.Of <ICloudListener>(), TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20)); Option <ICloudProxy> cloudProxy1 = cloudConnection.CloudProxy; Assert.True(cloudProxy1.HasValue); Assert.True(cloudProxy1.OrDefault().IsActive); ITokenCredentials clientCredentials2 = GetMockClientCredentialsWithToken(); ICloudProxy cloudProxy2 = await cloudConnection.UpdateTokenAsync(clientCredentials2); Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy2.IsActive); Assert.False(cloudProxy1.OrDefault().IsActive); Assert.NotEqual(cloudProxy1.OrDefault(), cloudProxy2); }
public async Task GetCloudConnectionThrowsTest() { 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.OpenAsync()).ThrowsAsync(new TimeoutException()); var deviceClientProvider = new Mock <IClientProvider>(); deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <ITokenProvider>(), It.IsAny <ITransportSettings[]>())) .Returns(deviceClient.Object); var tokenProvider = Mock.Of <ITokenProvider>(); var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); await Assert.ThrowsAsync <TimeoutException>( () => CloudConnection.Create( identity, (_, __) => { }, transportSettings, messageConverterProvider, deviceClientProvider.Object, Mock.Of <ICloudListener>(), tokenProvider, TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20), DummyProductInfo)); }
public async Task RefreshTokenTest() { string iothubHostName = "test.azure-devices.net"; string deviceId = "device1"; IClientCredentials GetClientCredentialsWithExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddSeconds(10)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty)); } IAuthenticationMethod authenticationMethod = null; IClientProvider clientProvider = GetMockDeviceClientProviderWithToken((s, a, t) => authenticationMethod = a); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var receivedStatus = CloudConnectionStatus.ConnectionEstablished; void ConnectionStatusHandler(string id, CloudConnectionStatus status) => receivedStatus = status; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter>()); var cloudConnection = new CloudConnection(ConnectionStatusHandler, transportSettings, messageConverterProvider, clientProvider); IClientCredentials clientCredentialsWithExpiringToken1 = GetClientCredentialsWithExpiringToken(); ICloudProxy cloudProxy1 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken1); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault()); Assert.NotNull(authenticationMethod); var deviceAuthenticationWithTokenRefresh = authenticationMethod as DeviceAuthenticationWithTokenRefresh; Assert.NotNull(deviceAuthenticationWithTokenRefresh); // Wait for the token to expire await Task.Delay(TimeSpan.FromSeconds(10)); Task <string> getTokenTask = deviceAuthenticationWithTokenRefresh.GetTokenAsync(iothubHostName); Assert.False(getTokenTask.IsCompleted); Assert.Equal(receivedStatus, CloudConnectionStatus.TokenNearExpiry); IClientCredentials clientCredentialsWithExpiringToken2 = GetClientCredentialsWithExpiringToken(); ICloudProxy cloudProxy2 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken2); // Wait for the task to complete await Task.Delay(TimeSpan.FromSeconds(10)); Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy2.IsActive); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudProxy2); Assert.True(getTokenTask.IsCompletedSuccessfully); Assert.Equal(getTokenTask.Result, (clientCredentialsWithExpiringToken2 as ITokenCredentials)?.Token); }
async Task <ICloudProxy> GetCloudProxyFromConnectionStringKey(string connectionStringConfigKey, IEdgeHub edgeHub) { const int ConnectionPoolSize = 10; string deviceConnectionString = await SecretsHelper.GetSecretFromConfigKey(connectionStringConfigKey); string deviceId = ConnectionStringHelper.GetDeviceId(deviceConnectionString); string iotHubHostName = ConnectionStringHelper.GetHostName(deviceConnectionString); string sasKey = ConnectionStringHelper.GetSharedAccessKey(deviceConnectionString); var converters = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Message), new DeviceClientMessageConverter() }, { typeof(Twin), new TwinMessageConverter() }, { typeof(TwinCollection), new TwinCollectionMessageConverter() } }); var credentialsCache = Mock.Of <ICredentialsCache>(); var metadataStore = new Mock <IMetadataStore>(); metadataStore.Setup(m => m.GetMetadata(It.IsAny <string>())).ReturnsAsync(new ConnectionMetadata("dummyValue")); ICloudConnectionProvider cloudConnectionProvider = new CloudConnectionProvider( converters, ConnectionPoolSize, new ClientProvider(Option.None <string>()), Option.None <UpstreamProtocol>(), Mock.Of <Util.ITokenProvider>(), Mock.Of <IDeviceScopeIdentitiesCache>(), credentialsCache, Mock.Of <IIdentity>(i => i.Id == $"{deviceId}/$edgeHub"), TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20), false, Option.None <IWebProxy>(), metadataStore.Object, true, true); cloudConnectionProvider.BindEdgeHub(edgeHub); var clientTokenProvider = new ClientTokenProvider(new SharedAccessKeySignatureProvider(sasKey), iotHubHostName, deviceId, TimeSpan.FromHours(1)); string token = await clientTokenProvider.GetTokenAsync(Option.None <TimeSpan>()); var deviceIdentity = new DeviceIdentity(iotHubHostName, deviceId); var clientCredentials = new TokenCredentials(deviceIdentity, token, string.Empty, Option.None <string>(), Option.None <string>(), false); Try <ICloudConnection> cloudConnection = await cloudConnectionProvider.Connect(clientCredentials, (_, __) => { }); Assert.True(cloudConnection.Success); Assert.True(cloudConnection.Value.IsActive); Assert.True(cloudConnection.Value.CloudProxy.HasValue); return(cloudConnection.Value.CloudProxy.OrDefault()); }
public void ProvidesAConverterForTheGivenType() { var expectedConverter = new TestMessageConverter(); var provider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(int), expectedConverter } }); IMessageConverter <int> actualConverter = provider.Get <int>(); Assert.Same(expectedConverter, actualConverter); }
public async Task InitializeAndGetCloudProxyTest() { string iothubHostName = "test.azure-devices.net"; string deviceId = "device1"; ITokenCredentials GetClientCredentialsWithNonExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddMinutes(10)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty, Option.None <string>(), Option.None <string>(), false)); } IClient client = GetMockDeviceClient(); var deviceClientProvider = new Mock <IClientProvider>(); deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <ITokenProvider>(), It.IsAny <ITransportSettings[]>(), Option.None <string>())) .Returns(() => client); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); ITokenCredentials clientCredentialsWithNonExpiringToken = GetClientCredentialsWithNonExpiringToken(); ClientTokenCloudConnection cloudConnection = await ClientTokenCloudConnection.Create( clientCredentialsWithNonExpiringToken, (_, __) => { }, transportSettings, messageConverterProvider, deviceClientProvider.Object, Mock.Of <ICloudListener>(), TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20), DummyProductInfo, Option.None <string>()); Option <ICloudProxy> cloudProxy = cloudConnection.CloudProxy; Assert.True(cloudProxy.HasValue); Assert.True(cloudProxy.OrDefault().IsActive); Mock.Get(client).Verify(c => c.OpenAsync(), Times.Once); }
static async Task GetCloudConnectionTest(Func <IClientCredentials> credentialsGenerator, IClientProvider clientProvider) { var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter>()); var cloudConnection = new CloudConnection((_, __) => { }, transportSettings, messageConverterProvider, clientProvider); IClientCredentials clientCredentials1 = credentialsGenerator(); ICloudProxy cloudProxy1 = await cloudConnection.CreateOrUpdateAsync(clientCredentials1); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault()); IClientCredentials clientCredentials2 = credentialsGenerator(); ICloudProxy cloudProxy2 = await cloudConnection.CreateOrUpdateAsync(clientCredentials2); Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy2.IsActive); Assert.False(cloudProxy1.IsActive); Assert.NotEqual(cloudProxy1, cloudProxy2); }
static async Task GetCloudConnectionTest(Func <IClientCredentials> credentialsGenerator, IClientProvider clientProvider) { var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); var cloudConnection = new CloudConnection((_, __) => { }, transportSettings, messageConverterProvider, clientProvider, Mock.Of <ICloudListener>(), TokenProvider, DeviceScopeIdentitiesCache, TimeSpan.FromMinutes(60), true); IClientCredentials clientCredentials1 = credentialsGenerator(); ICloudProxy cloudProxy1 = await cloudConnection.CreateOrUpdateAsync(clientCredentials1); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault()); IClientCredentials clientCredentials2 = credentialsGenerator(); ICloudProxy cloudProxy2 = await cloudConnection.CreateOrUpdateAsync(clientCredentials2); Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy2.IsActive); Assert.False(cloudProxy1.IsActive); Assert.NotEqual(cloudProxy1, cloudProxy2); }
public async Task InitializeAndGetCloudProxyTest() { string iothubHostName = "test.azure-devices.net"; string deviceId = "device1"; IClientCredentials GetClientCredentialsWithNonExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddMinutes(10)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty)); } IClient client = GetMockDeviceClient(); var deviceClientProvider = new Mock <IClientProvider>(); deviceClientProvider.Setup(dc => dc.Create(It.IsAny <IIdentity>(), It.IsAny <IAuthenticationMethod>(), It.IsAny <ITransportSettings[]>())) .Returns(() => client); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); var cloudConnection = new CloudConnection((_, __) => { }, transportSettings, messageConverterProvider, deviceClientProvider.Object, Mock.Of <ICloudListener>(), TokenProvider, DeviceScopeIdentitiesCache, TimeSpan.FromMinutes(60), true); IClientCredentials clientCredentialsWithExpiringToken2 = GetClientCredentialsWithNonExpiringToken(); ICloudProxy cloudProxy = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken2); // Wait for the task to complete await Task.Delay(TimeSpan.FromSeconds(10)); Assert.Equal(cloudProxy, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy.IsActive); Mock.Get(client).Verify(c => c.OpenAsync(), Times.Once); }
async Task <(IMessageConsumer, IMessageConsumer, NullBrokerConnector)> SetupEnvironment() { Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance; Routing.PerfCounter = NullRoutingPerfCounter.Instance; Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance; var defaultRetryStrategy = new FixedInterval(5, TimeSpan.FromSeconds(5)); var defaultRevivePeriod = TimeSpan.FromHours(1); var defaultTimeout = TimeSpan.FromSeconds(60); var endpointExecutorConfig = new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true); var cloudProxyDispatcher = new BrokeredCloudProxyDispatcher(); var cloudConnectionProvider = new BrokeredCloudConnectionProvider(cloudProxyDispatcher); var identityProvider = new IdentityProvider(iotHubName); var deviceConnectivityManager = new BrokeredDeviceConnectivityManager(cloudProxyDispatcher); var connectionManager = new ConnectionManager(cloudConnectionProvider, Mock.Of <ICredentialsCache>(), new IdentityProvider(iotHubName), deviceConnectivityManager); var routingMessageConverter = new RoutingMessageConverter(); var routeFactory = new EdgeRouteFactory(new EndpointFactory(connectionManager, routingMessageConverter, edgeDeviceId, 10, 10)); var routesList = new[] { routeFactory.Create("FROM /messages INTO $upstream") }; var endpoints = routesList.Select(r => r.Endpoint); var routerConfig = new RouterConfig(endpoints, routesList); var dbStoreProvider = new InMemoryDbStoreProvider(); var storeProvider = new StoreProvider(dbStoreProvider); var messageStore = new MessageStore(storeProvider, CheckpointStore.Create(storeProvider), TimeSpan.MaxValue, false, 1800); var endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(1, TimeSpan.FromMilliseconds(10)), messageStore); var router = await Router.CreateAsync(Guid.NewGuid().ToString(), iotHubName, routerConfig, endpointExecutorFactory); var messageConverterProvider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Twin), new TwinMessageConverter() }, { typeof(TwinCollection), new TwinCollectionMessageConverter() } }); var twinManager = TwinManager.CreateTwinManager(connectionManager, messageConverterProvider, Option.None <IStoreProvider>()); var invokeMethodHandler = Mock.Of <IInvokeMethodHandler>(); var subscriptionProcessor = new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager); var edgeHub = new RoutingEdgeHub(router, routingMessageConverter, connectionManager, twinManager, edgeDeviceId, edgeModuleName, invokeMethodHandler, subscriptionProcessor, Mock.Of <IDeviceScopeIdentitiesCache>()); var brokerConnector = new NullBrokerConnector(cloudProxyDispatcher); cloudProxyDispatcher.SetConnector(brokerConnector); cloudProxyDispatcher.BindEdgeHub(edgeHub); var connectionProvider = new ConnectionProvider(connectionManager, edgeHub, TimeSpan.FromSeconds(30)); var authenticator = new NullAuthenticator(); var edgeHubIdentity = new ModuleIdentity(iotHubName, edgeDeviceId, edgeModuleName); var tokenCredentials = new TokenCredentials(edgeHubIdentity, "qwerty", "test-product", Option.Some("test-model"), Option.None <string>(), false); var systemComponentProvider = new SystemComponentIdProvider(tokenCredentials); var connectionHandler = default(ConnectionHandler); connectionHandler = new ConnectionHandler( Task.FromResult <IConnectionProvider>(connectionProvider), Task.FromResult <IAuthenticator>(authenticator), identityProvider, systemComponentProvider, DeviceProxyFactory); DeviceProxy DeviceProxyFactory(IIdentity identity, bool isDirectClient) { return(new DeviceProxy(identity, isDirectClient, connectionHandler, Mock.Of <ITwinHandler>(), Mock.Of <IModuleToModuleMessageHandler>(), Mock.Of <ICloud2DeviceMessageHandler>(), Mock.Of <IDirectMethodHandler>())); } var cloud2DeviceMessageHandler = new Cloud2DeviceMessageHandler(connectionHandler); var moduleToModuleMessageHandler = new ModuleToModuleMessageHandler(connectionHandler, identityProvider, new ModuleToModuleResponseTimeout(TimeSpan.FromSeconds(10))); var directMethodHandler = new DirectMethodHandler(connectionHandler, identityProvider); var twinHandler = new TwinHandler(connectionHandler, identityProvider); var subscriptionChangeHandler = new SubscriptionChangeHandler( cloud2DeviceMessageHandler, moduleToModuleMessageHandler, directMethodHandler, twinHandler, connectionHandler, identityProvider); return(subscriptionChangeHandler, cloudProxyDispatcher, brokerConnector); }
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); }
public async Task TestGetTwin() { // Arrange const string Id = "id1"; var identity = Mock.Of <IIdentity>(i => i.Id == Id); var twinMessageConverter = new TwinMessageConverter(); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var messageConverterProvider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Message), new DeviceClientMessageConverter() }, { typeof(Shared.Twin), twinMessageConverter }, { typeof(TwinCollection), twinCollectionMessageConverter } }); var edgeHubTokenProvider = new Mock <ITokenProvider>(); var clientWatcher = new ClientWatcher(); var clientProvider = new Mock <IClientProvider>(); clientProvider.Setup(c => c.Create(identity, edgeHubTokenProvider.Object, It.IsAny <ITransportSettings[]>(), Option.None <string>())) .Returns(() => new ThrowingClient(clientWatcher, 3)); var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>(); deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(Id)) .ReturnsAsync( Option.Some( new ServiceIdentity( Id, "dummy", new List <string>(), new ServiceAuthentication(new SymmetricKeyAuthentication("foo", "bar")), ServiceIdentityStatus.Enabled))); deviceScopeIdentitiesCache.Setup(d => d.GetAuthChain(It.Is <string>(i => i == Id))) .ReturnsAsync(Option.Some(Id)); var edgeHubIdentity = Mock.Of <IIdentity>(); ConnectionMetadata connectionMetadata = new ConnectionMetadata("edgeProdInfo"); var metadataStore = new Mock <IMetadataStore>(); metadataStore.Setup(p => p.GetMetadata(Id)) .ReturnsAsync(connectionMetadata); var identityProvider = new Mock <IIdentityProvider>(); identityProvider.Setup(i => i.Create(Id)).Returns(identity); var credentialsCache = new Mock <ICredentialsCache>(); var edgeHub = new Mock <IEdgeHub>(); var connectionProvider = new CloudConnectionProvider( messageConverterProvider, 1, clientProvider.Object, Option.None <UpstreamProtocol>(), edgeHubTokenProvider.Object, deviceScopeIdentitiesCache.Object, credentialsCache.Object, edgeHubIdentity, TimeSpan.FromMinutes(10), false, TimeSpan.FromMinutes(10), false, Option.None <IWebProxy>(), metadataStore.Object, true); connectionProvider.BindEdgeHub(edgeHub.Object); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); var connectionManager = new ConnectionManager(connectionProvider, credentialsCache.Object, identityProvider.Object, deviceConnectivityManager); // Act Option <ICloudProxy> cloudProxyOption = await connectionManager.GetCloudConnection(Id); // Assert Assert.True(cloudProxyOption.HasValue); ICloudProxy cloudProxy = cloudProxyOption.OrDefault(); Assert.True(cloudProxy.IsActive); // Act await RunGetTwin(cloudProxy, 10); // Assert Assert.Equal(5, clientWatcher.OpenAsyncCount); Assert.True(cloudProxy.IsActive); Assert.Equal(10, clientWatcher.GetTwinCount); }
public async Task TestMultipleOperations() { // Arrange const string Id = "id1"; var identity = Mock.Of <IIdentity>(i => i.Id == Id); var twinMessageConverter = new TwinMessageConverter(); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var messageConverterProvider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter> { { typeof(Message), new DeviceClientMessageConverter() }, { typeof(Shared.Twin), twinMessageConverter }, { typeof(TwinCollection), twinCollectionMessageConverter } }); var edgeHubTokenProvider = new Mock <ITokenProvider>(); var clientWatcher = new ClientWatcher(); var clientProvider = new Mock <IClientProvider>(); clientProvider.Setup(c => c.Create(identity, edgeHubTokenProvider.Object, It.IsAny <ITransportSettings[]>())) .Returns(() => new ThrowingClient(clientWatcher, 15)); var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>(); deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(Id, false)) .ReturnsAsync( Option.Some( new ServiceIdentity( Id, "dummy", new List <string>(), new ServiceAuthentication(new SymmetricKeyAuthentication("foo", "bar")), ServiceIdentityStatus.Enabled))); var edgeHubIdentity = Mock.Of <IIdentity>(); var productInfoStore = new Mock <IProductInfoStore>(); productInfoStore.Setup(p => p.GetEdgeProductInfo(Id)) .ReturnsAsync("ProdInfo1"); var identityProvider = new Mock <IIdentityProvider>(); identityProvider.Setup(i => i.Create(Id)).Returns(identity); var credentialsCache = new Mock <ICredentialsCache>(); var edgeHub = new Mock <IEdgeHub>(); var connectionProvider = new CloudConnectionProvider( messageConverterProvider, 1, clientProvider.Object, Option.None <UpstreamProtocol>(), edgeHubTokenProvider.Object, deviceScopeIdentitiesCache.Object, credentialsCache.Object, edgeHubIdentity, TimeSpan.FromMinutes(10), false, TimeSpan.FromMinutes(10), Option.None <IWebProxy>(), productInfoStore.Object); connectionProvider.BindEdgeHub(edgeHub.Object); var connectionManager = new ConnectionManager(connectionProvider, credentialsCache.Object, identityProvider.Object); async Task <ICloudProxy> GetCloudProxy(IConnectionManager cm) { // Act Option <ICloudProxy> cloudProxyOption = await cm.GetCloudConnection(Id); // Assert Assert.True(cloudProxyOption.HasValue); ICloudProxy cloudProxy = cloudProxyOption.OrDefault(); Assert.True(cloudProxy.IsActive); return(cloudProxy); } var messagesToSend = new List <IMessage>(); for (int i = 0; i < 60; i++) { var message = new EdgeMessage.Builder(new byte[i]) .SetSystemProperties( new Dictionary <string, string>() { [SystemProperties.MessageId] = i.ToString() }) .Build(); messagesToSend.Add(message); } // Act ICloudProxy cloudProxy1 = await GetCloudProxy(connectionManager); ICloudProxy cloudProxy2 = await GetCloudProxy(connectionManager); ICloudProxy cloudProxy3 = await GetCloudProxy(connectionManager); // Act var tasks = new[] { RunGetTwin(cloudProxy1, 10), RunGetTwin(cloudProxy2, 30), RunGetTwin(cloudProxy3, 10), RunSendMessages(cloudProxy1, messagesToSend.Take(20), 2), RunSendMessages(cloudProxy2, messagesToSend.Skip(20).Take(10)), RunSendMessages(cloudProxy3, messagesToSend.Skip(30).Take(30), 3) }; await Task.WhenAll(tasks); // Assert Assert.Equal(50, clientWatcher.GetTwinCount); List <string> expectedMessageIds = messagesToSend .Select(m => m.SystemProperties[SystemProperties.MessageId]) .OrderBy(s => s) .ToList(); List <string> receivedMessageIds = clientWatcher.ReceivedMessages .Select(m => m.MessageId) .OrderBy(s => s) .ToList(); Assert.Equal(expectedMessageIds.Count, receivedMessageIds.Count); Assert.Equal(expectedMessageIds, receivedMessageIds); }
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); }
public async Task RefreshTokenWithRetryTest() { string iothubHostName = "test.azure-devices.net"; string deviceId = "device1"; IClientCredentials GetClientCredentialsWithExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddMinutes(3)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty)); } IClientCredentials GetClientCredentialsWithNonExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddMinutes(10)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty)); } IAuthenticationMethod authenticationMethod = null; IClientProvider clientProvider = GetMockDeviceClientProviderWithToken((s, a, t) => authenticationMethod = a); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var receivedStatuses = new List <CloudConnectionStatus>(); void ConnectionStatusHandler(string id, CloudConnectionStatus status) => receivedStatuses.Add(status); var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); var cloudConnection = new CloudConnection(ConnectionStatusHandler, transportSettings, messageConverterProvider, clientProvider, Mock.Of <ICloudListener>(), TokenProvider, DeviceScopeIdentitiesCache, TimeSpan.FromMinutes(60), true); IClientCredentials clientCredentialsWithExpiringToken1 = GetClientCredentialsWithExpiringToken(); ICloudProxy cloudProxy1 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken1); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudConnection.CloudProxy.OrDefault()); Assert.NotNull(authenticationMethod); var deviceAuthenticationWithTokenRefresh = authenticationMethod as DeviceAuthenticationWithTokenRefresh; Assert.NotNull(deviceAuthenticationWithTokenRefresh); // Try to refresh token but get an expiring token Task <string> getTokenTask = deviceAuthenticationWithTokenRefresh.GetTokenAsync(iothubHostName); Assert.False(getTokenTask.IsCompleted); Assert.Equal(1, receivedStatuses.Count); Assert.Equal(receivedStatuses[0], CloudConnectionStatus.TokenNearExpiry); ICloudProxy cloudProxy2 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithExpiringToken1); // Wait for the task to process await Task.Delay(TimeSpan.FromSeconds(5)); Assert.False(getTokenTask.IsCompletedSuccessfully); Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy2.IsActive); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudProxy2); // Wait for 20 secs for retry to happen await Task.Delay(TimeSpan.FromSeconds(20)); // Check if retry happened Assert.Equal(2, receivedStatuses.Count); Assert.Equal(receivedStatuses[1], CloudConnectionStatus.TokenNearExpiry); IClientCredentials clientCredentialsWithNonExpiringToken = GetClientCredentialsWithNonExpiringToken(); ICloudProxy cloudProxy3 = await cloudConnection.CreateOrUpdateAsync(clientCredentialsWithNonExpiringToken); // Wait for the task to complete await Task.Delay(TimeSpan.FromSeconds(5)); Assert.True(getTokenTask.IsCompletedSuccessfully); Assert.Equal(cloudProxy3, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy3.IsActive); Assert.True(cloudProxy1.IsActive); Assert.Equal(cloudProxy1, cloudProxy3); Assert.Equal(getTokenTask.Result, (clientCredentialsWithNonExpiringToken as ITokenCredentials)?.Token); }
public async Task TestEdgeHubConnection() { const string EdgeDeviceId = "testHubEdgeDevice1"; var twinMessageConverter = new TwinMessageConverter(); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var messageConverterProvider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Message), new DeviceClientMessageConverter() }, { typeof(Twin), twinMessageConverter }, { typeof(TwinCollection), twinCollectionMessageConverter } }); string iotHubConnectionString = await SecretsHelper.GetSecretFromConfigKey("iotHubConnStrKey"); IotHubConnectionStringBuilder iotHubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString); RegistryManager registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString); await registryManager.OpenAsync(); string iothubHostName = iotHubConnectionStringBuilder.HostName; var identityProvider = new IdentityProvider(iothubHostName); var identityFactory = new ClientCredentialsFactory(identityProvider); (string edgeDeviceId, string deviceConnStr) = await RegistryManagerHelper.CreateDevice(EdgeDeviceId, iotHubConnectionString, registryManager, true, false); string edgeHubConnectionString = $"{deviceConnStr};ModuleId={EdgeHubModuleId}"; IClientCredentials edgeHubCredentials = identityFactory.GetWithConnectionString(edgeHubConnectionString); string sasKey = ConnectionStringHelper.GetSharedAccessKey(deviceConnStr); var signatureProvider = new SharedAccessKeySignatureProvider(sasKey); var credentialsCache = Mock.Of <ICredentialsCache>(); var metadataStore = new Mock <IMetadataStore>(); metadataStore.Setup(m => m.GetMetadata(It.IsAny <string>())).ReturnsAsync(new ConnectionMetadata("dummyValue")); var cloudConnectionProvider = new CloudConnectionProvider( messageConverterProvider, 1, new ClientProvider(), Option.None <UpstreamProtocol>(), new ClientTokenProvider(signatureProvider, iothubHostName, edgeDeviceId, TimeSpan.FromMinutes(60)), Mock.Of <IDeviceScopeIdentitiesCache>(), credentialsCache, edgeHubCredentials.Identity, TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20), false, Option.None <IWebProxy>(), metadataStore.Object); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); var connectionManager = new ConnectionManager(cloudConnectionProvider, Mock.Of <ICredentialsCache>(), identityProvider, deviceConnectivityManager); try { Mock.Get(credentialsCache) .Setup(c => c.Get(edgeHubCredentials.Identity)) .ReturnsAsync(Option.Some(edgeHubCredentials)); Assert.NotNull(edgeHubCredentials); Assert.NotNull(edgeHubCredentials.Identity); // Set Edge hub desired properties await this.SetDesiredProperties(registryManager, edgeDeviceId); var endpointFactory = new EndpointFactory(connectionManager, new RoutingMessageConverter(), edgeDeviceId, 10, 10); var routeFactory = new EdgeRouteFactory(endpointFactory); var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); IEntityStore <string, TwinInfo> twinStore = storeProvider.GetEntityStore <string, TwinInfo>("twins"); var twinManager = new TwinManager(connectionManager, twinCollectionMessageConverter, twinMessageConverter, Option.Some(twinStore)); var routerConfig = new RouterConfig(Enumerable.Empty <Route>()); TimeSpan defaultTimeout = TimeSpan.FromSeconds(60); var endpointExecutorFactory = new SyncEndpointExecutorFactory(new EndpointExecutorConfig(defaultTimeout, new FixedInterval(0, TimeSpan.FromSeconds(1)), defaultTimeout, true)); Router router = await Router.CreateAsync(Guid.NewGuid().ToString(), iothubHostName, routerConfig, endpointExecutorFactory); IInvokeMethodHandler invokeMethodHandler = new InvokeMethodHandler(connectionManager); var subscriptionProcessor = new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager); IEdgeHub edgeHub = new RoutingEdgeHub(router, new RoutingMessageConverter(), connectionManager, twinManager, edgeDeviceId, invokeMethodHandler, subscriptionProcessor); cloudConnectionProvider.BindEdgeHub(edgeHub); var versionInfo = new VersionInfo("v1", "b1", "c1"); // Create Edge Hub connection EdgeHubConnection edgeHubConnection = await EdgeHubConnection.Create( edgeHubCredentials.Identity, edgeHub, twinManager, connectionManager, routeFactory, twinCollectionMessageConverter, versionInfo, new NullDeviceScopeIdentitiesCache()); await Task.Delay(TimeSpan.FromMinutes(1)); TwinConfigSource configSource = new TwinConfigSource(edgeHubConnection, edgeHubCredentials.Identity.Id, versionInfo, twinManager, twinMessageConverter, twinCollectionMessageConverter, routeFactory); // Get and Validate EdgeHubConfig Option <EdgeHubConfig> edgeHubConfigOption = await configSource.GetConfig(); Assert.True(edgeHubConfigOption.HasValue); EdgeHubConfig edgeHubConfig = edgeHubConfigOption.OrDefault(); Assert.Equal("1.0", edgeHubConfig.SchemaVersion); Assert.NotNull(edgeHubConfig.Routes); Assert.NotNull(edgeHubConfig.StoreAndForwardConfiguration); Assert.Equal(20, edgeHubConfig.StoreAndForwardConfiguration.TimeToLiveSecs); IReadOnlyDictionary <string, RouteConfig> routes = edgeHubConfig.Routes; Assert.Equal(4, routes.Count); RouteConfig route1 = routes["route1"]; Assert.True(route1.Route.Endpoint.GetType() == typeof(CloudEndpoint)); Assert.Equal("route1", route1.Name); Assert.Equal("from /* INTO $upstream", route1.Value); RouteConfig route2 = routes["route2"]; Endpoint endpoint = route2.Route.Endpoint; Assert.True(endpoint.GetType() == typeof(ModuleEndpoint)); Assert.Equal($"{edgeDeviceId}/module2/input1", endpoint.Id); Assert.Equal("route2", route2.Name); Assert.Equal("from /modules/module1 INTO BrokeredEndpoint(\"/modules/module2/inputs/input1\")", route2.Value); RouteConfig route3 = routes["route3"]; endpoint = route3.Route.Endpoint; Assert.True(endpoint.GetType() == typeof(ModuleEndpoint)); Assert.Equal($"{edgeDeviceId}/module3/input1", endpoint.Id); Assert.Equal("route3", route3.Name); Assert.Equal("from /modules/module2 INTO BrokeredEndpoint(\"/modules/module3/inputs/input1\")", route3.Value); RouteConfig route4 = routes["route4"]; endpoint = route4.Route.Endpoint; Assert.True(endpoint.GetType() == typeof(ModuleEndpoint)); Assert.Equal($"{edgeDeviceId}/module4/input1", endpoint.Id); Assert.Equal("route4", route4.Name); Assert.Equal("from /modules/module3 INTO BrokeredEndpoint(\"/modules/module4/inputs/input1\")", route4.Value); // Make sure reported properties were updated appropriately EdgeHubConnection.ReportedProperties reportedProperties = await this.GetReportedProperties(registryManager, edgeDeviceId); Assert.Equal(200, reportedProperties.LastDesiredStatus.Code); Assert.NotNull(reportedProperties.Clients); Assert.Equal(0, reportedProperties.Clients.Count); Assert.Equal("1.0", reportedProperties.SchemaVersion); Assert.Equal(versionInfo, reportedProperties.VersionInfo); // Simulate a module and a downstream device that connects to Edge Hub. string moduleId = "module1"; string sasToken = TokenHelper.CreateSasToken($"{iothubHostName}/devices/{edgeDeviceId}/modules/{moduleId}"); string moduleConnectionstring = $"HostName={iothubHostName};DeviceId={edgeDeviceId};ModuleId={moduleId};SharedAccessSignature={sasToken}"; IClientCredentials moduleClientCredentials = identityFactory.GetWithConnectionString(moduleConnectionstring); var moduleProxy = Mock.Of <IDeviceProxy>(d => d.IsActive); string downstreamDeviceId = "device1"; sasToken = TokenHelper.CreateSasToken($"{iothubHostName}/devices/{downstreamDeviceId}"); string downstreamDeviceConnectionstring = $"HostName={iothubHostName};DeviceId={downstreamDeviceId};SharedAccessSignature={sasToken}"; IClientCredentials downstreamDeviceCredentials = identityFactory.GetWithConnectionString(downstreamDeviceConnectionstring); var downstreamDeviceProxy = Mock.Of <IDeviceProxy>(d => d.IsActive); // Connect the module and downstream device and make sure the reported properties are updated as expected. await connectionManager.AddDeviceConnection(moduleClientCredentials.Identity, moduleProxy); await connectionManager.AddDeviceConnection(downstreamDeviceCredentials.Identity, downstreamDeviceProxy); string moduleIdKey = $"{edgeDeviceId}/{moduleId}"; await Task.Delay(TimeSpan.FromSeconds(10)); reportedProperties = await this.GetReportedProperties(registryManager, edgeDeviceId); Assert.Equal(2, reportedProperties.Clients.Count); Assert.Equal(ConnectionStatus.Connected, reportedProperties.Clients[moduleIdKey].Status); Assert.NotNull(reportedProperties.Clients[moduleIdKey].LastConnectedTimeUtc); Assert.Null(reportedProperties.Clients[moduleIdKey].LastDisconnectTimeUtc); Assert.Equal(ConnectionStatus.Connected, reportedProperties.Clients[downstreamDeviceId].Status); Assert.NotNull(reportedProperties.Clients[downstreamDeviceId].LastConnectedTimeUtc); Assert.Null(reportedProperties.Clients[downstreamDeviceId].LastDisconnectTimeUtc); Assert.Equal(200, reportedProperties.LastDesiredStatus.Code); Assert.Equal("1.0", reportedProperties.SchemaVersion); Assert.Equal(versionInfo, reportedProperties.VersionInfo); // Update desired propertied and make sure callback is called with valid values bool callbackCalled = false; Task ConfigUpdatedCallback(EdgeHubConfig updatedConfig) { Assert.NotNull(updatedConfig); Assert.NotNull(updatedConfig.StoreAndForwardConfiguration); Assert.NotNull(updatedConfig.Routes); routes = updatedConfig.Routes; Assert.Equal(4, routes.Count); route1 = routes["route1"]; Assert.True(route1.Route.Endpoint.GetType() == typeof(CloudEndpoint)); Assert.Equal("route1", route1.Name); Assert.Equal("from /* INTO $upstream", route1.Value); route2 = routes["route2"]; endpoint = route2.Route.Endpoint; Assert.True(endpoint.GetType() == typeof(ModuleEndpoint)); Assert.Equal($"{edgeDeviceId}/module2/input1", endpoint.Id); Assert.Equal("route2", route2.Name); Assert.Equal("from /modules/module1 INTO BrokeredEndpoint(\"/modules/module2/inputs/input1\")", route2.Value); route3 = routes["route4"]; endpoint = route3.Route.Endpoint; Assert.True(endpoint.GetType() == typeof(ModuleEndpoint)); Assert.Equal($"{edgeDeviceId}/module5/input1", endpoint.Id); Assert.Equal("route4", route3.Name); Assert.Equal("from /modules/module3 INTO BrokeredEndpoint(\"/modules/module5/inputs/input1\")", route3.Value); route4 = routes["route5"]; endpoint = route4.Route.Endpoint; Assert.True(endpoint.GetType() == typeof(ModuleEndpoint)); Assert.Equal($"{edgeDeviceId}/module6/input1", endpoint.Id); Assert.Equal("route5", route4.Name); Assert.Equal("from /modules/module5 INTO BrokeredEndpoint(\"/modules/module6/inputs/input1\")", route4.Value); callbackCalled = true; return(Task.CompletedTask); } configSource.SetConfigUpdatedCallback(ConfigUpdatedCallback); await this.UpdateDesiredProperties(registryManager, edgeDeviceId); await Task.Delay(TimeSpan.FromSeconds(5)); Assert.True(callbackCalled); reportedProperties = await this.GetReportedProperties(registryManager, edgeDeviceId); Assert.Equal(200, reportedProperties.LastDesiredStatus.Code); Assert.NotNull(reportedProperties.Clients); Assert.Equal(2, reportedProperties.Clients.Count); Assert.Equal("1.0", reportedProperties.SchemaVersion); Assert.Equal(versionInfo, reportedProperties.VersionInfo); // Disconnect the downstream device and make sure the reported properties are updated as expected. await connectionManager.RemoveDeviceConnection(moduleIdKey); await connectionManager.RemoveDeviceConnection(downstreamDeviceId); await Task.Delay(TimeSpan.FromSeconds(10)); reportedProperties = await this.GetReportedProperties(registryManager, edgeDeviceId); Assert.Equal(1, reportedProperties.Clients.Count); Assert.True(reportedProperties.Clients.ContainsKey(moduleIdKey)); Assert.False(reportedProperties.Clients.ContainsKey(downstreamDeviceId)); Assert.Equal(ConnectionStatus.Disconnected, reportedProperties.Clients[moduleIdKey].Status); Assert.NotNull(reportedProperties.Clients[moduleIdKey].LastConnectedTimeUtc); Assert.NotNull(reportedProperties.Clients[moduleIdKey].LastDisconnectTimeUtc); Assert.Equal(200, reportedProperties.LastDesiredStatus.Code); Assert.Equal("1.0", reportedProperties.SchemaVersion); Assert.Equal(versionInfo, reportedProperties.VersionInfo); // If the edge hub restarts, clear out the connected devices in the reported properties. await EdgeHubConnection.Create( edgeHubCredentials.Identity, edgeHub, twinManager, connectionManager, routeFactory, twinCollectionMessageConverter, versionInfo, new NullDeviceScopeIdentitiesCache()); await Task.Delay(TimeSpan.FromMinutes(1)); reportedProperties = await this.GetReportedProperties(registryManager, edgeDeviceId); Assert.Null(reportedProperties.Clients); Assert.Equal("1.0", reportedProperties.SchemaVersion); Assert.Equal(versionInfo, reportedProperties.VersionInfo); } finally { try { await RegistryManagerHelper.RemoveDevice(edgeDeviceId, registryManager); } catch (Exception) { // ignored } } }
public async Task TestSendMessages() { // Arrange const string Id = "id1"; var identity = Mock.Of <IIdentity>(i => i.Id == Id); var twinMessageConverter = new TwinMessageConverter(); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var messageConverterProvider = new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Message), new DeviceClientMessageConverter() }, { typeof(Shared.Twin), twinMessageConverter }, { typeof(TwinCollection), twinCollectionMessageConverter } }); var edgeHubTokenProvider = new Mock <ITokenProvider>(); var clientWatcher = new ClientWatcher(); var clientProvider = new Mock <IClientProvider>(); clientProvider.Setup(c => c.Create(identity, edgeHubTokenProvider.Object, It.IsAny <ITransportSettings[]>(), Option.None <string>())) .Returns(() => new ThrowingClient(clientWatcher, 3)); var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>(); deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(Id)) .ReturnsAsync( Option.Some( new ServiceIdentity( Id, "dummy", new List <string>(), new ServiceAuthentication(new SymmetricKeyAuthentication("foo", "bar")), ServiceIdentityStatus.Enabled))); deviceScopeIdentitiesCache.Setup(d => d.GetAuthChain(It.Is <string>(i => i == Id))) .ReturnsAsync(Option.Some(Id)); var edgeHubIdentity = Mock.Of <IIdentity>(); ConnectionMetadata connectionMetadata = new ConnectionMetadata("edgeProdInfo"); var metadataStore = new Mock <IMetadataStore>(); metadataStore.Setup(p => p.GetMetadata(Id)) .ReturnsAsync(connectionMetadata); var identityProvider = new Mock <IIdentityProvider>(); identityProvider.Setup(i => i.Create(Id)).Returns(identity); var credentialsCache = new Mock <ICredentialsCache>(); var edgeHub = new Mock <IEdgeHub>(); var connectionProvider = new CloudConnectionProvider( messageConverterProvider, 1, clientProvider.Object, Option.None <UpstreamProtocol>(), edgeHubTokenProvider.Object, deviceScopeIdentitiesCache.Object, credentialsCache.Object, edgeHubIdentity, TimeSpan.FromMinutes(10), false, TimeSpan.FromMinutes(10), false, Option.None <IWebProxy>(), metadataStore.Object, scopeAuthenticationOnly: true, trackDeviceState: true, true); connectionProvider.BindEdgeHub(edgeHub.Object); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); var connectionManager = new ConnectionManager(connectionProvider, credentialsCache.Object, identityProvider.Object, deviceConnectivityManager); var messagesToSend = new List <IMessage>(); for (int i = 0; i < 10; i++) { var message = new EdgeMessage.Builder(new byte[i]) .SetSystemProperties( new Dictionary <string, string>() { [SystemProperties.MessageId] = i.ToString() }) .Build(); messagesToSend.Add(message); } // Act Option <ICloudProxy> cloudProxyOption = await connectionManager.GetCloudConnection(Id); // Assert Assert.True(cloudProxyOption.HasValue); ICloudProxy cloudProxy = cloudProxyOption.OrDefault(); Assert.True(cloudProxy.IsActive); // Act await RunSendMessages(cloudProxy, messagesToSend); // Assert Assert.Equal(messagesToSend.Count, clientWatcher.ReceivedMessages.Count()); Assert.Equal(5, clientWatcher.OpenAsyncCount); Assert.True(cloudProxy.IsActive); IEnumerable <string> expectedMessageIds = messagesToSend.Select(m => m.SystemProperties[SystemProperties.MessageId]); IEnumerable <string> receivedMessageIds = clientWatcher.ReceivedMessages.Select(m => m.MessageId); Assert.Equal(expectedMessageIds, receivedMessageIds); }
public async Task RefreshTokenTest() { string iothubHostName = "test.azure-devices.net"; string deviceId = "device1"; ITokenCredentials GetClientCredentialsWithExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddMinutes(3)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty, false)); } ITokenCredentials GetClientCredentialsWithNonExpiringToken() { string token = TokenHelper.CreateSasToken(iothubHostName, DateTime.UtcNow.AddMinutes(10)); var identity = new DeviceIdentity(iothubHostName, deviceId); return(new TokenCredentials(identity, token, string.Empty, false)); } ITokenProvider tokenProvider = null; IClientProvider clientProvider = GetMockDeviceClientProviderWithToken((s, a, t) => tokenProvider = a); var transportSettings = new ITransportSettings[] { new AmqpTransportSettings(TransportType.Amqp_Tcp_Only) }; var receivedStatus = CloudConnectionStatus.ConnectionEstablished; void ConnectionStatusHandler(string id, CloudConnectionStatus status) => receivedStatus = status; var messageConverterProvider = new MessageConverterProvider(new Dictionary <Type, IMessageConverter> { [typeof(TwinCollection)] = Mock.Of <IMessageConverter>() }); ITokenCredentials clientCredentialsWithExpiringToken1 = GetClientCredentialsWithExpiringToken(); ClientTokenCloudConnection cloudConnection = await ClientTokenCloudConnection.Create( clientCredentialsWithExpiringToken1, ConnectionStatusHandler, transportSettings, messageConverterProvider, clientProvider, Mock.Of <ICloudListener>(), TimeSpan.FromMinutes(60), true, TimeSpan.FromSeconds(20)); Option <ICloudProxy> cloudProxy1 = cloudConnection.CloudProxy; Assert.True(cloudProxy1.HasValue); Assert.True(cloudProxy1.OrDefault().IsActive); Assert.NotNull(tokenProvider); Task <string> getTokenTask = tokenProvider.GetTokenAsync(Option.None <TimeSpan>()); Assert.False(getTokenTask.IsCompleted); Assert.Equal(receivedStatus, CloudConnectionStatus.TokenNearExpiry); ITokenCredentials clientCredentialsWithExpiringToken2 = GetClientCredentialsWithNonExpiringToken(); ICloudProxy cloudProxy2 = await cloudConnection.UpdateTokenAsync(clientCredentialsWithExpiringToken2); // Wait for the task to complete await Task.Delay(TimeSpan.FromSeconds(10)); Assert.True(getTokenTask.IsCompletedSuccessfully); Assert.Equal(cloudProxy2, cloudConnection.CloudProxy.OrDefault()); Assert.True(cloudProxy2.IsActive); Assert.True(cloudProxy1.OrDefault().IsActive); Assert.Equal(cloudProxy1.OrDefault(), cloudProxy2); Assert.Equal(getTokenTask.Result, clientCredentialsWithExpiringToken2.Token); }