Exemple #1
0
        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));
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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));
        }
Exemple #4
0
        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));
        }
Exemple #5
0
        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));
        }
Exemple #6
0
        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);
            }
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        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);
        }
Exemple #9
0
        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
                }
            }
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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]);
        }
Exemple #15
0
        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);
        }