public async Task HandleDeviceConnectedDisconnectedEvents() { // Arrange var edgeHubIdentity = Mock.Of <IModuleIdentity>(i => i.Id == "edgeD1/$edgeHub"); var twinManager = Mock.Of <ITwinManager>(); var routeFactory = new EdgeRouteFactory(Mock.Of <IEndpointFactory>()); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var twinMessageConverter = new TwinMessageConverter(); var versionInfo = new VersionInfo("1.0", "1", "123"); var deviceScopeIdentitiesCache = Mock.Of <IDeviceScopeIdentitiesCache>(); var edgeHubConnection = new EdgeHubConnection(edgeHubIdentity, twinManager, routeFactory, twinCollectionMessageConverter, twinMessageConverter, versionInfo, deviceScopeIdentitiesCache); Mock.Get(twinManager).Setup(t => t.UpdateReportedPropertiesAsync(It.IsAny <string>(), It.IsAny <IMessage>())).Returns(Task.CompletedTask); // Act edgeHubConnection.DeviceConnected(this, Mock.Of <IIdentity>(i => i.Id == "d1")); edgeHubConnection.DeviceConnected(this, Mock.Of <IIdentity>(i => i.Id == "edgeD1/$edgeHub")); // Assert await Task.Delay(TimeSpan.FromSeconds(2)); Mock.Get(twinManager).Verify(t => t.UpdateReportedPropertiesAsync(It.IsAny <string>(), It.IsAny <IMessage>()), Times.Once); // Act edgeHubConnection.DeviceDisconnected(this, Mock.Of <IIdentity>(i => i.Id == "d1")); edgeHubConnection.DeviceDisconnected(this, Mock.Of <IIdentity>(i => i.Id == "edgeD1/$edgeHub")); // Assert await Task.Delay(TimeSpan.FromSeconds(2)); Mock.Get(twinManager).Verify(t => t.UpdateReportedPropertiesAsync(It.IsAny <string>(), It.IsAny <IMessage>()), Times.Exactly(2)); }
public async Task HandleMethodInvocationBadInputTest() { // Arrange var edgeHubIdentity = Mock.Of <IModuleIdentity>(); var twinManager = Mock.Of <ITwinManager>(); var routeFactory = new EdgeRouteFactory(Mock.Of <IEndpointFactory>()); var twinCollectionMessageConverter = Mock.Of <Core.IMessageConverter <TwinCollection> >(); var twinMessageConverter = Mock.Of <Core.IMessageConverter <Shared.Twin> >(); var versionInfo = new VersionInfo("1.0", "1", "123"); var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>(); deviceScopeIdentitiesCache.Setup(d => d.RefreshServiceIdentities(It.IsAny <IEnumerable <string> >())).Returns(Task.CompletedTask); var edgeHubConnection = new EdgeHubConnection(edgeHubIdentity, twinManager, routeFactory, twinCollectionMessageConverter, twinMessageConverter, versionInfo, deviceScopeIdentitiesCache.Object); string correlationId = Guid.NewGuid().ToString(); var requestPayload = new[] { "d1", "d2" }; byte[] requestBytes = requestPayload.ToBytes(); var directMethodRequest = new DirectMethodRequest(correlationId, Constants.ServiceIdentityRefreshMethodName, requestBytes, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); // Act DirectMethodResponse directMethodResponse = await edgeHubConnection.HandleMethodInvocation(directMethodRequest); // Assert Assert.NotNull(directMethodResponse); Assert.Equal(HttpStatusCode.BadRequest, directMethodResponse.HttpStatusCode); }
public void GetEdgeHubConfig_BridgeValidatorReturnsError_ExpectedException() { var validator = new Mock <BrokerPropertiesValidator>(); validator .Setup(v => v.ValidateAuthorizationConfig(It.IsAny <AuthorizationProperties>())) .Returns(new List <string>()); validator .Setup(v => v.ValidateBridgeConfig(It.IsAny <BridgeConfig>())) .Returns(new List <string> { "Validation error has occurred" }); var routeFactory = new EdgeRouteFactory(new Mock <IEndpointFactory>().Object); var configParser = new EdgeHubConfigParser(routeFactory, validator.Object); var bridgeConfig = new BridgeConfig { new Bridge("floor2", new List <Settings> { }) }; var brokerProperties = new BrokerProperties(bridgeConfig, new AuthorizationProperties()); var properties = new EdgeHubDesiredProperties_1_2( "1.2.0", new Dictionary <string, RouteSpec>(), new StoreAndForwardConfiguration(100), brokerProperties); // assert Assert.Throws <InvalidOperationException>(() => configParser.GetEdgeHubConfig(properties)); }
public static TwinConfigSource GetTwinConfigSource(Option <X509Certificate2> manifestTrustBundle) { var connectionManager = new ConnectionManager(Mock.Of <ICloudConnectionProvider>(), Mock.Of <ICredentialsCache>(), Mock.Of <IIdentityProvider>(), Mock.Of <IDeviceConnectivityManager>()); var endpointFactory = new EndpointFactory(connectionManager, new RoutingMessageConverter(), "testHubEdgeDevice1", 10, 10, false); var routeFactory = new EdgeRouteFactory(endpointFactory); var configParser = new EdgeHubConfigParser(routeFactory, new BrokerPropertiesValidator()); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var twinMessageConverter = new TwinMessageConverter(); 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 versionInfo = new VersionInfo(string.Empty, string.Empty, string.Empty); // Create Edge Hub connection EdgeHubConnection edgeHubConnection = GetEdgeHubConnection().Result; // TwinConfig Source return(new TwinConfigSource( edgeHubConnection, string.Empty, versionInfo, twinManager, twinMessageConverter, twinCollectionMessageConverter, configParser, manifestTrustBundle)); }
public void GetEdgeHubConfig_AuthorizationValidatorReturnsError_ExpectedException() { var validator = new Mock <BrokerPropertiesValidator>(); validator .Setup(v => v.ValidateAuthorizationConfig(It.IsAny <AuthorizationProperties>())) .Returns(new List <string> { "Validation error has occurred" }); var routeFactory = new EdgeRouteFactory(new Mock <IEndpointFactory>().Object); var configParser = new EdgeHubConfigParser(routeFactory, validator.Object); var authzProperties = new AuthorizationProperties { new AuthorizationProperties.Statement( identities: new List <string> { "device_1", "device_3" }, allow: new List <AuthorizationProperties.Rule>(), deny: new List <AuthorizationProperties.Rule>()) }; var brokerProperties = new BrokerProperties(new BridgeConfig(), authzProperties); var properties = new EdgeHubDesiredProperties_1_2( "1.2.0", new Dictionary <string, RouteSpec>(), new StoreAndForwardConfiguration(100), brokerProperties); // assert Assert.Throws <InvalidOperationException>(() => configParser.GetEdgeHubConfig(properties)); }
public void SchemaVersionCheckTest(string manifest, Type expectedException) { var validator = new Mock <BrokerPropertiesValidator>(); validator .Setup(v => v.ValidateAuthorizationConfig(It.IsAny <AuthorizationProperties>())) .Returns(new List <string>()); validator .Setup(v => v.ValidateBridgeConfig(It.IsAny <BridgeConfig>())) .Returns(new List <string>()); var endpointFactory = new Mock <IEndpointFactory>(); endpointFactory .Setup(v => v.CreateSystemEndpoint(It.IsAny <string>())) .Returns(new NullEndpoint("$upstream")); var routeFactory = new EdgeRouteFactory(endpointFactory.Object); var configParser = new EdgeHubConfigParser(routeFactory, validator.Object); if (expectedException != null) { Assert.Throws(expectedException, () => configParser.GetEdgeHubConfig(manifest)); } else { configParser.GetEdgeHubConfig(manifest); } }
public async Task TestInitialConfigUpdate_WaitForInit() { // Arrange string id = "id"; string iotHub = "foo.azure-devices.net"; var routerConfig = new RouterConfig(Enumerable.Empty <Route>()); var messageStore = new Mock <IMessageStore>(); messageStore.Setup(m => m.SetTimeToLive(It.IsAny <TimeSpan>())); var storageSpaceChecker = new Mock <IStorageSpaceChecker>(); storageSpaceChecker.Setup(m => m.SetMaxSizeBytes(It.IsAny <Option <long> >())); TimeSpan updateFrequency = TimeSpan.FromSeconds(10); Endpoint GetEndpoint() => new ModuleEndpoint("id", Guid.NewGuid().ToString(), "in1", Mock.Of <IConnectionManager>(), Mock.Of <Core.IMessageConverter <IMessage> >()); var endpointFactory = new Mock <IEndpointFactory>(); endpointFactory.Setup(e => e.CreateSystemEndpoint($"$upstream")).Returns(GetEndpoint); var routeFactory = new EdgeRouteFactory(endpointFactory.Object); var endpointExecutorFactory = new Mock <IEndpointExecutorFactory>(); endpointExecutorFactory.Setup(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>())) .Returns <Endpoint, IList <uint>, ICheckpointerFactory>((endpoint, priorities, checkpointerFactory) => Task.FromResult(Mock.Of <IEndpointExecutor>(e => e.Endpoint == endpoint))); Router router = await Router.CreateAsync(id, iotHub, routerConfig, endpointExecutorFactory.Object); var routes1 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration1 = new StoreAndForwardConfiguration(7200); var edgeHubConfig1 = new EdgeHubConfig("1.0", routes1, storeAndForwardConfiguration1, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var configProvider = new Mock <IConfigSource>(); configProvider.SetupSequence(c => c.GetConfig()) .Returns(async() => { await Task.Delay(5000); return(Option.Some(edgeHubConfig1)); }); configProvider.Setup(c => c.GetCachedConfig()) .Returns(() => Task.FromResult(Option.None <EdgeHubConfig>())); // Act var configUpdater = new ConfigUpdater(router, messageStore.Object, updateFrequency, storageSpaceChecker.Object); await configUpdater.Init(configProvider.Object); // Assert Assert.Equal(2, router.Routes.Count); // After 6 seconds no updates await Task.Delay(TimeSpan.FromSeconds(6)); Assert.Equal(2, router.Routes.Count); }
static async Task <(IEdgeHub, IConnectionManager)> SetupEdgeHub(IEnumerable <string> routes, IoTHub iotHub, string edgeDeviceId) { string iotHubName = "testHub"; Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance; Routing.PerfCounter = NullRoutingPerfCounter.Instance; Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance; RetryStrategy defaultRetryStrategy = new FixedInterval(0, TimeSpan.FromSeconds(1)); TimeSpan defaultRevivePeriod = TimeSpan.FromHours(1); TimeSpan defaultTimeout = TimeSpan.FromSeconds(60); var endpointExecutorConfig = new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true); var cloudProxy = new Mock <ICloudProxy>(); cloudProxy.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>())).Callback <IMessage>(m => iotHub.ReceivedMessages.Add(m)).Returns(Task.CompletedTask); cloudProxy.Setup(c => c.SendMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >())).Callback <IEnumerable <IMessage> >(m => iotHub.ReceivedMessages.AddRange(m)).Returns(Task.CompletedTask); cloudProxy.Setup(c => c.UpdateReportedPropertiesAsync(It.IsAny <IMessage>())).Callback <IMessage>(m => iotHub.ReceivedMessages.Add(m)).Returns(Task.CompletedTask); cloudProxy.SetupGet(c => c.IsActive).Returns(true); var cloudConnection = Mock.Of <ICloudConnection>(c => c.IsActive && c.CloudProxy == Option.Some(cloudProxy.Object)); var cloudConnectionProvider = new Mock <ICloudConnectionProvider>(); cloudConnectionProvider.Setup(c => c.Connect(It.IsAny <IClientCredentials>(), It.IsAny <Action <string, CloudConnectionStatus> >())).ReturnsAsync(Try.Success(cloudConnection)); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); IConnectionManager connectionManager = new ConnectionManager(cloudConnectionProvider.Object, Mock.Of <ICredentialsCache>(), new IdentityProvider(iotHubName), deviceConnectivityManager); var routingMessageConverter = new RoutingMessageConverter(); RouteFactory routeFactory = new EdgeRouteFactory(new EndpointFactory(connectionManager, routingMessageConverter, edgeDeviceId, 10, 10)); IEnumerable <Route> routesList = routeFactory.Create(routes).ToList(); IEnumerable <Endpoint> endpoints = routesList.Select(r => r.Endpoint); var routerConfig = new RouterConfig(endpoints, routesList); IDbStoreProvider dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); IMessageStore messageStore = new MessageStore(storeProvider, CheckpointStore.Create(storeProvider), TimeSpan.MaxValue); IEndpointExecutorFactory endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(1, TimeSpan.FromMilliseconds(10)), messageStore); Router router = await Router.CreateAsync(Guid.NewGuid().ToString(), iotHubName, routerConfig, endpointExecutorFactory); ITwinManager twinManager = new TwinManager(connectionManager, new TwinCollectionMessageConverter(), new TwinMessageConverter(), Option.None <IEntityStore <string, TwinInfo> >()); var invokeMethodHandler = Mock.Of <IInvokeMethodHandler>(); var subscriptionProcessor = new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager); IEdgeHub edgeHub = new RoutingEdgeHub(router, routingMessageConverter, connectionManager, twinManager, edgeDeviceId, invokeMethodHandler, subscriptionProcessor); return(edgeHub, connectionManager); }
public static async Task <EdgeHubConnection> GetEdgeHubConnection() { var connectionManager = new ConnectionManager(Mock.Of <ICloudConnectionProvider>(), Mock.Of <ICredentialsCache>(), Mock.Of <IIdentityProvider>(), Mock.Of <IDeviceConnectivityManager>()); var endpointFactory = new EndpointFactory(connectionManager, new RoutingMessageConverter(), "testHubEdgeDevice1", 10, 10, false); var routeFactory = new EdgeRouteFactory(endpointFactory); var twinCollectionMessageConverter = new TwinCollectionMessageConverter(); var twinMessageConverter = new TwinMessageConverter(); 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 versionInfo = new VersionInfo(string.Empty, string.Empty, string.Empty); return(await EdgeHubConnection.Create( Mock.Of <IIdentity>(i => i.Id == "someid"), Mock.Of <IEdgeHub>(), twinManager, Mock.Of <IConnectionManager>(), routeFactory, twinCollectionMessageConverter, versionInfo, new NullDeviceScopeIdentitiesCache())); }
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 } } }
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 TestPeriodicConfigUpdate() { // Arrange string id = "id"; string iotHub = "foo.azure-devices.net"; var routerConfig = new RouterConfig(Enumerable.Empty <Route>()); var messageStore = new Mock <IMessageStore>(); messageStore.Setup(m => m.SetTimeToLive(It.IsAny <TimeSpan>())); TimeSpan updateFrequency = TimeSpan.FromSeconds(10); Endpoint GetEndpoint() => new ModuleEndpoint("id", Guid.NewGuid().ToString(), "in1", Mock.Of <IConnectionManager>(), Mock.Of <Core.IMessageConverter <IMessage> >()); var endpointFactory = new Mock <IEndpointFactory>(); endpointFactory.Setup(e => e.CreateSystemEndpoint($"$upstream")).Returns(GetEndpoint); var routeFactory = new EdgeRouteFactory(endpointFactory.Object); var endpointExecutorFactory = new Mock <IEndpointExecutorFactory>(); endpointExecutorFactory.Setup(e => e.CreateAsync(It.IsAny <Endpoint>())) .Returns <Endpoint>(endpoint => Task.FromResult(Mock.Of <IEndpointExecutor>(e => e.Endpoint == endpoint))); Router router = await Router.CreateAsync(id, iotHub, routerConfig, endpointExecutorFactory.Object); var routes1 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration1 = new StoreAndForwardConfiguration(7200); var edgeHubConfig1 = new EdgeHubConfig("1.0", routes1, storeAndForwardConfiguration1); var routes2 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration2 = new StoreAndForwardConfiguration(7200); var edgeHubConfig2 = new EdgeHubConfig("1.0", routes2, storeAndForwardConfiguration2); var routes3 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration3 = new StoreAndForwardConfiguration(7200); var edgeHubConfig3 = new EdgeHubConfig("1.0", routes3, storeAndForwardConfiguration3); var routes4 = Routes.Skip(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration4 = new StoreAndForwardConfiguration(7200); var edgeHubConfig4 = new EdgeHubConfig("1.0", routes4, storeAndForwardConfiguration4); var routes5 = Routes .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration5 = new StoreAndForwardConfiguration(7200); var edgeHubConfig5 = new EdgeHubConfig("1.0", routes5, storeAndForwardConfiguration5); var routes6 = Routes .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration6 = new StoreAndForwardConfiguration(3600); var edgeHubConfig6 = new EdgeHubConfig("1.0", routes6, storeAndForwardConfiguration6); var configProvider = new Mock <IConfigSource>(); configProvider.SetupSequence(c => c.GetConfig()) .ReturnsAsync(Option.Some(edgeHubConfig1)) .ReturnsAsync(Option.Some(edgeHubConfig2)) .ReturnsAsync(Option.Some(edgeHubConfig3)) .ReturnsAsync(Option.Some(edgeHubConfig4)) .ReturnsAsync(Option.Some(edgeHubConfig5)) .ReturnsAsync(Option.Some(edgeHubConfig6)); configProvider.Setup(c => c.SetConfigUpdatedCallback(It.IsAny <Func <EdgeHubConfig, Task> >())); // Act var configUpdater = new ConfigUpdater(router, messageStore.Object, updateFrequency); configUpdater.Init(configProvider.Object); // Assert await Task.Delay(TimeSpan.FromSeconds(8)); configProvider.Verify(c => c.GetConfig(), Times.Once); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Once); await Task.Delay(TimeSpan.FromSeconds(20)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(3)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Once); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(4)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(2)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(5)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(3)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(6)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(4)); }
public async Task TestPeriodicAndCallbackConfigUpdate() { // Arrange string id = "id"; string iotHub = "foo.azure-devices.net"; var routerConfig = new RouterConfig(Enumerable.Empty <Route>()); var messageStore = new Mock <IMessageStore>(); messageStore.Setup(m => m.SetTimeToLive(It.IsAny <TimeSpan>())); var storageSpaceChecker = new Mock <IStorageSpaceChecker>(); storageSpaceChecker.Setup(m => m.SetMaxSizeBytes(It.IsAny <Option <long> >())); TimeSpan updateFrequency = TimeSpan.FromSeconds(10); Endpoint GetEndpoint() => new ModuleEndpoint("id", Guid.NewGuid().ToString(), "in1", Mock.Of <IConnectionManager>(), Mock.Of <Core.IMessageConverter <IMessage> >()); var endpointFactory = new Mock <IEndpointFactory>(); endpointFactory.Setup(e => e.CreateSystemEndpoint($"$upstream")).Returns(GetEndpoint); var routeFactory = new EdgeRouteFactory(endpointFactory.Object); var endpointExecutorFactory = new Mock <IEndpointExecutorFactory>(); endpointExecutorFactory.Setup(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >())) .Returns <Endpoint, IList <uint> >((endpoint, priorities) => Task.FromResult(Mock.Of <IEndpointExecutor>(e => e.Endpoint == endpoint))); Router router = await Router.CreateAsync(id, iotHub, routerConfig, endpointExecutorFactory.Object); var routes1 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration1 = new StoreAndForwardConfiguration(7200); var edgeHubConfig1 = new EdgeHubConfig("1.0", routes1, storeAndForwardConfiguration1); var routes2 = Routes.Take(3) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration2 = new StoreAndForwardConfiguration(7200); var edgeHubConfig2 = new EdgeHubConfig("1.0", routes2, storeAndForwardConfiguration2); var routes3 = Routes.Take(4) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration3 = new StoreAndForwardConfiguration(7200); var edgeHubConfig3 = new EdgeHubConfig("1.0", routes3, storeAndForwardConfiguration3); Func <EdgeHubConfig, Task> updateCallback = null; var configProvider = new Mock <IConfigSource>(); configProvider.SetupSequence(c => c.GetConfig()) .ReturnsAsync(Option.Some(edgeHubConfig1)) .ReturnsAsync(Option.Some(edgeHubConfig2)) .ReturnsAsync(Option.Some(edgeHubConfig3)); configProvider.Setup(c => c.SetConfigUpdatedCallback(It.IsAny <Func <EdgeHubConfig, Task> >())) .Callback <Func <EdgeHubConfig, Task> >(callback => { updateCallback = callback; }); configProvider.Setup(c => c.GetCachedConfig()) .Returns(() => Task.FromResult(Option.None <EdgeHubConfig>())); // Act var configUpdater = new ConfigUpdater(router, messageStore.Object, updateFrequency, storageSpaceChecker.Object); await configUpdater.Init(configProvider.Object); // Assert configProvider.Verify(c => c.GetConfig(), Times.Once); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Once); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Once); // call update with no changes await updateCallback(edgeHubConfig1); configProvider.Verify(c => c.GetConfig(), Times.Exactly(1)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Once); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Once); await Task.Delay(TimeSpan.FromSeconds(12)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(2)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(2)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(2)); // call update with changes await updateCallback(edgeHubConfig3); configProvider.Verify(c => c.GetConfig(), Times.Exactly(2)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(3)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(3)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(3)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(3)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(3)); }
public void GetEdgeHubConfig_ValidInput_MappingIsCorrect() { var validator = new Mock <BrokerPropertiesValidator>(); validator .Setup(v => v.ValidateAuthorizationConfig(It.IsAny <AuthorizationProperties>())) .Returns(new List <string>()); var routeFactory = new EdgeRouteFactory(new Mock <IEndpointFactory>().Object); var configParser = new EdgeHubConfigParser(routeFactory, validator.Object); EdgeHubDesiredProperties properties = ConfigTestData.GetTestData(); // act EdgeHubConfig result = configParser.GetEdgeHubConfig(properties); // assert validator.Verify(v => v.ValidateAuthorizationConfig(properties.BrokerConfiguration.Authorizations), Times.Once()); Assert.Equal("1.2.0", result.SchemaVersion); AuthorizationConfig authzConfig = result .BrokerConfiguration .Expect(() => new InvalidOperationException("missing broker config")) .Authorizations .Expect(() => new InvalidOperationException("missing authorization config")); Assert.Equal(3, authzConfig.Statements.Count); var result0 = authzConfig.Statements[0]; Assert.Equal(Effect.Deny, result0.Effect); Assert.Equal(2, result0.Identities.Count); Assert.Equal("device_1", result0.Identities[0]); Assert.Equal("device_3", result0.Identities[1]); Assert.Equal(1, result0.Operations.Count); Assert.Equal("mqtt:publish", result0.Operations[0]); Assert.Equal(2, result0.Resources.Count); Assert.Equal("system/alerts/+", result0.Resources[0]); Assert.Equal("core/#", result0.Resources[1]); var result1 = authzConfig.Statements[1]; Assert.Equal(Effect.Allow, result1.Effect); Assert.Equal(2, result1.Identities.Count); Assert.Equal("device_1", result1.Identities[0]); Assert.Equal("device_3", result1.Identities[1]); Assert.Equal(2, result1.Operations.Count); Assert.Equal("mqtt:publish", result1.Operations[0]); Assert.Equal("mqtt:subscribe", result1.Operations[1]); Assert.Equal(2, result1.Resources.Count); Assert.Equal("topic/a", result1.Resources[0]); Assert.Equal("topic/b", result1.Resources[1]); var result2 = authzConfig.Statements[2]; Assert.Equal(Effect.Allow, result2.Effect); Assert.Equal(1, result2.Identities.Count); Assert.Equal("device_2", result2.Identities[0]); Assert.Equal(2, result2.Operations.Count); Assert.Equal("mqtt:publish", result2.Operations[0]); Assert.Equal("mqtt:subscribe", result2.Operations[1]); Assert.Equal(2, result2.Resources.Count); Assert.Equal("topic1", result2.Resources[0]); Assert.Equal("topic2", result2.Resources[1]); }
public async Task TestPeriodicConfigUpdate() { // Arrange string id = "id"; string iotHub = "foo.azure-devices.net"; var routerConfig = new RouterConfig(Enumerable.Empty <Route>()); var messageStore = new Mock <IMessageStore>(); messageStore.Setup(m => m.SetTimeToLive(It.IsAny <TimeSpan>())); var storageSpaceChecker = new Mock <IStorageSpaceChecker>(); storageSpaceChecker.Setup(m => m.SetMaxSizeBytes(It.IsAny <Option <long> >())); TimeSpan updateFrequency = TimeSpan.FromSeconds(10); Endpoint GetEndpoint() => new ModuleEndpoint("id", Guid.NewGuid().ToString(), "in1", Mock.Of <IConnectionManager>(), Mock.Of <Core.IMessageConverter <IMessage> >()); var endpointFactory = new Mock <IEndpointFactory>(); endpointFactory.Setup(e => e.CreateSystemEndpoint($"$upstream")).Returns(GetEndpoint); var routeFactory = new EdgeRouteFactory(endpointFactory.Object); var endpointExecutorFactory = new Mock <IEndpointExecutorFactory>(); endpointExecutorFactory.Setup(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>())) .Returns <Endpoint, IList <uint>, ICheckpointerFactory>((endpoint, priorities, checkpointerFactory) => Task.FromResult(Mock.Of <IEndpointExecutor>(e => e.Endpoint == endpoint))); Router router = await Router.CreateAsync(id, iotHub, routerConfig, endpointExecutorFactory.Object); var routes1 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration1 = new StoreAndForwardConfiguration(7200); var edgeHubConfig1 = new EdgeHubConfig("1.0", routes1, storeAndForwardConfiguration1, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes2 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration2 = new StoreAndForwardConfiguration(7200); var edgeHubConfig2 = new EdgeHubConfig("1.0", routes2, storeAndForwardConfiguration2, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes3 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration3 = new StoreAndForwardConfiguration(7200); var edgeHubConfig3 = new EdgeHubConfig("1.0", routes3, storeAndForwardConfiguration3, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes4 = Routes.Skip(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration4 = new StoreAndForwardConfiguration(7200); var edgeHubConfig4 = new EdgeHubConfig("1.0", routes4, storeAndForwardConfiguration4, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes5 = Routes .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration5 = new StoreAndForwardConfiguration(7200); var edgeHubConfig5 = new EdgeHubConfig("1.0", routes5, storeAndForwardConfiguration5, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes6 = Routes .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration6 = new StoreAndForwardConfiguration(3600); var edgeHubConfig6 = new EdgeHubConfig("1.0", routes6, storeAndForwardConfiguration6, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes7 = Routes .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration7 = new StoreAndForwardConfiguration(3600, new StoreLimits(10L)); var edgeHubConfig7 = new EdgeHubConfig("1.0", routes7, storeAndForwardConfiguration7, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var routes8 = Routes .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration8 = new StoreAndForwardConfiguration(3600, new StoreLimits(20L)); var edgeHubConfig8 = new EdgeHubConfig("1.0", routes8, storeAndForwardConfiguration8, Option.None <BrokerConfig>(), Option.None <ManifestIntegrity>()); var configProvider = new Mock <IConfigSource>(); configProvider.SetupSequence(c => c.GetConfig()) .ReturnsAsync(Option.Some(edgeHubConfig1)) .ReturnsAsync(Option.Some(edgeHubConfig2)) .ReturnsAsync(Option.Some(edgeHubConfig3)) .ReturnsAsync(Option.Some(edgeHubConfig4)) .ReturnsAsync(Option.Some(edgeHubConfig5)) .ReturnsAsync(Option.Some(edgeHubConfig6)) .ReturnsAsync(Option.Some(edgeHubConfig7)) .ReturnsAsync(Option.Some(edgeHubConfig8)) .ReturnsAsync(Option.Some(edgeHubConfig8)); configProvider.Setup(c => c.GetCachedConfig()) .Returns(() => Task.FromResult(Option.None <EdgeHubConfig>())); // Act var configUpdater = new ConfigUpdater(router, messageStore.Object, updateFrequency, storageSpaceChecker.Object); await configUpdater.Init(configProvider.Object); // Assert configProvider.Verify(c => c.GetConfig(), Times.Once); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Once); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Once); // After 5 seconds, the periodic task should not have run. await Task.Delay(TimeSpan.FromSeconds(5)); configProvider.Verify(c => c.GetConfig(), Times.Once); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Once); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Once); await Task.Delay(TimeSpan.FromSeconds(20)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(3)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(3)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(3)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(4)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(4)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(4)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(5)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(5)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(5)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(6)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(6)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => x.Equals(Option.None <long>()))), Times.Exactly(6)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(7)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(7)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => !x.Equals(Option.None <long>()))), Times.Exactly(1)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(8)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(8)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => !x.Equals(Option.None <long>()))), Times.Exactly(2)); await Task.Delay(TimeSpan.FromSeconds(10)); configProvider.Verify(c => c.GetConfig(), Times.Exactly(9)); endpointExecutorFactory.Verify(e => e.CreateAsync(It.IsAny <Endpoint>(), It.IsAny <IList <uint> >(), It.IsAny <ICheckpointerFactory>()), Times.Once); messageStore.Verify(m => m.SetTimeToLive(It.IsAny <TimeSpan>()), Times.Exactly(8)); storageSpaceChecker.Verify(m => m.SetMaxSizeBytes(It.Is <Option <long> >(x => !x.Equals(Option.None <long>()))), Times.Exactly(2)); }
public async Task TestInitialConfigUpdate_NoWaitForInit() { // Arrange string id = "id"; string iotHub = "foo.azure-devices.net"; var routerConfig = new RouterConfig(Enumerable.Empty<Route>()); var messageStore = new Mock<IMessageStore>(); messageStore.Setup(m => m.SetTimeToLive(It.IsAny<TimeSpan>())); TimeSpan updateFrequency = TimeSpan.FromMinutes(10); Endpoint GetEndpoint() => new ModuleEndpoint("id", Guid.NewGuid().ToString(), "in1", Mock.Of<IConnectionManager>(), Mock.Of<Core.IMessageConverter<IMessage>>()); var endpointFactory = new Mock<IEndpointFactory>(); endpointFactory.Setup(e => e.CreateSystemEndpoint($"$upstream")).Returns(GetEndpoint); var routeFactory = new EdgeRouteFactory(endpointFactory.Object); var endpointExecutorFactory = new Mock<IEndpointExecutorFactory>(); endpointExecutorFactory.Setup(e => e.CreateAsync(It.IsAny<Endpoint>())) .Returns<Endpoint>(endpoint => Task.FromResult(Mock.Of<IEndpointExecutor>(e => e.Endpoint == endpoint))); Router router = await Router.CreateAsync(id, iotHub, routerConfig, endpointExecutorFactory.Object); var routes1 = Routes.Take(2) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration1 = new StoreAndForwardConfiguration(7200); var edgeHubConfig1 = new EdgeHubConfig("1.0", routes1, storeAndForwardConfiguration1); var routes2 = Routes.Take(3) .ToDictionary(r => r.Key, r => new RouteConfig(r.Key, r.Value, routeFactory.Create(r.Value))); var storeAndForwardConfiguration2 = new StoreAndForwardConfiguration(7200); var edgeHubConfig2 = new EdgeHubConfig("1.0", routes2, storeAndForwardConfiguration2); var configProvider = new Mock<IConfigSource>(); configProvider.SetupSequence(c => c.GetConfig()) .Returns(async () => { await Task.Delay(5000); return Option.Some(edgeHubConfig2); }); configProvider.Setup(c => c.SetConfigUpdatedCallback(It.IsAny<Func<EdgeHubConfig, Task>>())); var initialConfigSource = new Mock<IConfigSource>(); initialConfigSource.Setup(c => c.GetConfig()) .Returns(() => { return Task.FromResult(Option.Some(edgeHubConfig1)); }); // Act var configUpdater = new ConfigUpdater(router, messageStore.Object, updateFrequency, Option.Some(initialConfigSource.Object)); await configUpdater.Init(configProvider.Object); // Assert // First only has updated from prefeched config Assert.Equal(2, router.Routes.Count); // After 6 seconds updates from init received await Task.Delay(TimeSpan.FromSeconds(6)); Assert.Equal(3, router.Routes.Count); }