public async Task CloseSendsDisconnectSignal() { var connectionProvider = Mock.Of <IConnectionProvider>(); Mock.Get(connectionProvider) .Setup(p => p.GetDeviceListenerAsync( It.IsAny <Identity>(), It.IsAny <Option <string> >())) .Returns(Task.FromResult(Mock.Of <IDeviceListener>())); var authenticator = Mock.Of <IAuthenticator>(); Mock.Get(authenticator) .Setup(p => p.AuthenticateAsync(It.IsAny <IClientCredentials>())) .Returns(Task.FromResult(true)); var connectionProviderGetter = Task.FromResult(connectionProvider); var authenticatorGetter = Task.FromResult(authenticator); var identityProvider = new IdentityProvider("hub"); var systemComponentIdProvider = new SystemComponentIdProvider( new TokenCredentials( new ModuleIdentity("hub", "device1", "$edgeHub"), "token", "prodinfo", Option.Some("x"), Option.None <string>(), false)); var identity = identityProvider.Create("device_test"); var brokerConnector = Mock.Of <IMqttBrokerConnector>(); Mock.Get(brokerConnector) .Setup(p => p.SendAsync(It.IsAny <string>(), It.IsAny <byte[]>())) .Returns(() => Task.FromResult(true)); var sut = default(ConnectionHandler); DeviceProxy.Factory deviceProxyFactory = GetProxy; sut = new ConnectionHandler(connectionProviderGetter, authenticatorGetter, identityProvider, systemComponentIdProvider, deviceProxyFactory); sut.SetConnector(brokerConnector); await sut.HandleAsync(new MqttPublishInfo("$edgehub/connected", Encoding.UTF8.GetBytes("[\"device_test\"]"))); await sut.CloseConnectionAsync(identity); Mock.Get(brokerConnector).Verify( c => c.SendAsync( It.Is <string>(topic => topic.Equals("$edgehub/disconnect")), It.Is <byte[]>(payload => Encoding.UTF8.GetString(payload).Equals($"\"device_test\""))), Times.Once); DeviceProxy GetProxy(IIdentity identity, bool isDirectClient = true) { return(new DeviceProxy( identity, isDirectClient, sut, Mock.Of <ITwinHandler>(), Mock.Of <IModuleToModuleMessageHandler>(), Mock.Of <ICloud2DeviceMessageHandler>(), Mock.Of <IDirectMethodHandler>())); } }
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 ReconnectAsDirectRemovesNestedInstance() { var connectionManager = Mock.Of <IConnectionManager>(); Mock.Get(connectionManager) .Setup(p => p.RemoveDeviceConnection(It.IsAny <string>())) .Returns(() => Task.CompletedTask); var edgeHub = Mock.Of <IEdgeHub>(); var connectionProvider = new ConnectionProvider(connectionManager, edgeHub, TimeSpan.FromSeconds(30)) as IConnectionProvider; var authenticator = Mock.Of <IAuthenticator>(); Mock.Get(authenticator) .Setup(p => p.AuthenticateAsync(It.IsAny <IClientCredentials>())) .Returns(Task.FromResult(true)); var connectionProviderGetter = Task.FromResult(connectionProvider); var authenticatorGetter = Task.FromResult(authenticator); var identityProvider = new IdentityProvider("hub"); var systemComponentIdProvider = new SystemComponentIdProvider( new TokenCredentials( new ModuleIdentity("hub", "device1", "$edgeHub"), "token", "prodinfo", Option.Some("x"), Option.None <string>(), false)); var brokerConnector = Mock.Of <IMqttBrokerConnector>(); Mock.Get(brokerConnector) .Setup(p => p.SendAsync(It.IsAny <string>(), It.IsAny <byte[]>(), It.IsAny <bool>())) .Returns(() => Task.FromResult(true)); var sut = default(ConnectionHandler); DeviceProxy.Factory deviceProxyFactory = GetProxy; sut = new ConnectionHandler(connectionProviderGetter, authenticatorGetter, identityProvider, systemComponentIdProvider, deviceProxyFactory); sut.SetConnector(brokerConnector); await sut.GetOrCreateDeviceListenerAsync(new ModuleIdentity("hub", "device1", "direct_module"), true); await sut.GetOrCreateDeviceListenerAsync(new ModuleIdentity("hub", "device1", "indirect_module"), false); await sut.GetOrCreateDeviceListenerAsync(new ModuleIdentity("hub", "device1", "$edgeHub"), false); await sut.GetOrCreateDeviceListenerAsync(new ModuleIdentity("hub", "device1", "indirect_reconnecting"), false); // after indirect_reconnecting comes back as direct, the broker would send 3 connected clients: [direct_module, $edgeHub, indirect_reconnecting] // $edgeHub is indirect but listed, yet it should not be bothered as it is a special case. // indirect_module is not listed, but as indirect, it should not be removed // direct_module should keep its state // indirect_reconnecting should be recreated as direct await sut.HandleAsync(new MqttPublishInfo("$edgehub/connected", Encoding.UTF8.GetBytes("[\"device1/direct_module\", \"device1/$edgeHub\", \"device1/indirect_reconnecting\"]"))); var knownConnections = sut.AsPrivateAccessible().knownConnections as ConcurrentDictionary <IIdentity, IDeviceListener>; Assert.Equal(4, knownConnections.Count()); Assert.True(HasModule(knownConnections, "direct_module", true)); Assert.True(HasModule(knownConnections, "indirect_module", false)); Assert.True(HasModule(knownConnections, "$edgeHub", false)); Assert.True(HasModule(knownConnections, "indirect_reconnecting", true)); bool HasModule(ConcurrentDictionary <IIdentity, IDeviceListener> knownConnections, string name, bool isDirect) { return(knownConnections.Values.OfType <IDeviceProxy>().Any(p => p.IsDirectClient == isDirect && p.Identity is ModuleIdentity i && string.Equals(i.ModuleId, name))); } DeviceProxy GetProxy(IIdentity identity, bool isDirectClient = true) { return(new DeviceProxy( identity, isDirectClient, sut, Mock.Of <ITwinHandler>(), Mock.Of <IModuleToModuleMessageHandler>(), Mock.Of <ICloud2DeviceMessageHandler>(), Mock.Of <IDirectMethodHandler>())); } }