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 async Task RoundtripTokenCredentialsWithEncryptionTest() { // Arrange string iothubHostName = "iothub1.azure.net"; string callerProductInfo = "productInfo"; string sasToken = TokenHelper.CreateSasToken($"{iothubHostName}/devices/device1/modules/moduleId"); var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var credentials = new TokenCredentials(identity, sasToken, callerProductInfo, false); var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); var encryptedStore = new EncryptedStore <string, string>(storeProvider.GetEntityStore <string, string>("tokenCredentials"), new TestEncryptionProvider()); var tokenCredentialsStore = new PersistedTokenCredentialsCache(encryptedStore); // Act await tokenCredentialsStore.Add(credentials); Option <IClientCredentials> storedCredentials = await tokenCredentialsStore.Get(identity); // Assert Assert.True(storedCredentials.HasValue); var storedTokenCredentials = storedCredentials.OrDefault() as ITokenCredentials; Assert.NotNull(storedTokenCredentials); Assert.Equal(sasToken, storedTokenCredentials.Token); Assert.Equal(credentials.IsUpdatable, storedTokenCredentials.IsUpdatable); }
static IEntityStore <string, TwinStoreEntity> GetTwinEntityStore() { var dbStoreProvider = new InMemoryDbStoreProvider(); var entityStoreProvider = new StoreProvider(dbStoreProvider); IEntityStore <string, TwinStoreEntity> entityStore = entityStoreProvider.GetEntityStore <string, TwinStoreEntity>($"twin{Guid.NewGuid()}"); return(entityStore); }
static IEntityStore <string, TwinStoreEntity> GetReportedPropertiesEntityStore() { var dbStoreProvider = new InMemoryDbStoreProvider(); var entityStoreProvider = new StoreProvider(dbStoreProvider); IEntityStore <string, TwinStoreEntity> entityStore = entityStoreProvider.GetEntityStore <string, TwinStoreEntity>($"rp{Guid.NewGuid()}"); return(entityStore); }
async Task <(IMessageStore, ICheckpointStore)> GetMessageStore(int ttlSecs = 300) { var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); ICheckpointStore checkpointStore = CheckpointStore.Create(storeProvider); IMessageStore messageStore = new MessageStore(storeProvider, checkpointStore, TimeSpan.FromSeconds(ttlSecs)); await messageStore.AddEndpoint("module1"); await messageStore.AddEndpoint("module2"); return(messageStore, checkpointStore); }
async Task <(IMessageStore, ICheckpointStore, InMemoryDbStore)> GetMessageStore(bool checkEntireQueueOnCleanup, int ttlSecs = 300, int messageCleanupIntervalSecs = 30) { var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); InMemoryDbStore inMemoryDbStore = dbStoreProvider.GetDbStore("messages") as InMemoryDbStore; ICheckpointStore checkpointStore = CheckpointStore.Create(storeProvider); IMessageStore messageStore = new MessageStore(storeProvider, checkpointStore, TimeSpan.FromSeconds(ttlSecs), checkEntireQueueOnCleanup, messageCleanupIntervalSecs); await messageStore.AddEndpoint("module1"); await messageStore.AddEndpoint("module2"); return(messageStore, checkpointStore, inMemoryDbStore); }
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 async Task RoundtripNonTokenCredentialsTest() { // Arrange string callerProductInfo = "productInfo"; var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var credentials = new X509CertCredentials(identity, callerProductInfo); var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); var tokenCredentialsStore = new TokenCredentialsStore(storeProvider.GetEntityStore <string, string>("tokenCredentials"), new NullEncryptionProvider()); // Act await tokenCredentialsStore.Add(credentials); Option <IClientCredentials> storedCredentials = await tokenCredentialsStore.Get(identity); // Assert Assert.False(storedCredentials.HasValue); }
async Task <(IMessageStore, ICheckpointStore)> GetMessageStore(long initialCheckpointOffset, bool checkEntireQueueOnCleanup, int ttlSecs = 300) { var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); IEntityStore <string, CheckpointStore.CheckpointEntity> checkpointUnderlyingStore = storeProvider.GetEntityStore <string, CheckpointStore.CheckpointEntity>($"Checkpoint{Guid.NewGuid().ToString()}"); if (initialCheckpointOffset >= 0) { await checkpointUnderlyingStore.Put("module1", new CheckpointStore.CheckpointEntity(initialCheckpointOffset, null, null)); await checkpointUnderlyingStore.Put("module2", new CheckpointStore.CheckpointEntity(initialCheckpointOffset, null, null)); } ICheckpointStore checkpointStore = new CheckpointStore(checkpointUnderlyingStore); IMessageStore messageStore = new MessageStore(storeProvider, checkpointStore, TimeSpan.FromSeconds(ttlSecs), checkEntireQueueOnCleanup, 1800); await messageStore.AddEndpoint("module1"); await messageStore.AddEndpoint("module2"); return(messageStore, checkpointStore); }
public async Task RoundtripNonTokenCredentialsTest() { // Arrange string callerProductInfo = "productInfo"; var identity = Mock.Of <IIdentity>(i => i.Id == "d1"); var clientCertificate = new X509Certificate2(); var clientCertChain = new List <X509Certificate2>(); var credentials = new X509CertCredentials(identity, callerProductInfo, Option.None <string>(), Option.None <string>(), clientCertificate, clientCertChain); var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); var encryptedStore = new EncryptedStore <string, string>(storeProvider.GetEntityStore <string, string>("tokenCredentials"), new TestEncryptionProvider()); var tokenCredentialsStore = new PersistedTokenCredentialsCache(encryptedStore); // Act await tokenCredentialsStore.Add(credentials); Option <IClientCredentials> storedCredentials = await tokenCredentialsStore.Get(identity); // Assert Assert.False(storedCredentials.HasValue); }
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 } } }
public async Task MessageStoreAddRemoveEndpointTest(bool checkEntireQueueOnCleanup) { // Arrange var dbStoreProvider = new InMemoryDbStoreProvider(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); ICheckpointStore checkpointStore = CheckpointStore.Create(storeProvider); IMessageStore messageStore = new MessageStore(storeProvider, checkpointStore, TimeSpan.FromHours(1), checkEntireQueueOnCleanup, 1800); // Act await messageStore.AddEndpoint("module1"); for (int i = 0; i < 10; i++) { await messageStore.Add("module1", this.GetMessage(i), 0); } // Assert IMessageIterator module1Iterator = messageStore.GetMessageIterator("module1"); Assert.NotNull(module1Iterator); IEnumerable <IMessage> batch = await module1Iterator.GetNext(1000); List <IMessage> batchItemsAsList = batch.ToList(); Assert.Equal(10, batchItemsAsList.Count); for (int i = 0; i < 10; i++) { Assert.Equal($"{i}", batchItemsAsList.ElementAt(i).SystemProperties[SystemProperties.MessageId]); } // Remove await messageStore.RemoveEndpoint("module1"); // Assert await Assert.ThrowsAsync <InvalidOperationException>(() => messageStore.Add("module1", this.GetMessage(0), 0)); Assert.Throws <InvalidOperationException>(() => messageStore.GetMessageIterator("module1")); // Act await messageStore.AddEndpoint("module1"); for (int i = 20; i < 30; i++) { await messageStore.Add("module1", this.GetMessage(i), 0); } // Assert module1Iterator = messageStore.GetMessageIterator("module1"); Assert.NotNull(module1Iterator); batch = await module1Iterator.GetNext(1000); batchItemsAsList = batch.ToList(); Assert.Equal(10, batchItemsAsList.Count); for (int i = 20; i < 30; i++) { Assert.Equal($"{i}", batchItemsAsList.ElementAt(i - 20).SystemProperties[SystemProperties.MessageId]); } }
public async Task SpaceCheckViolationsTest() { Option <long> maxStorageBytes = Option.Some(90L); IStorageSpaceChecker checker = new MemorySpaceChecker(() => 0L); checker.SetMaxSizeBytes(maxStorageBytes); InMemoryDbStoreProvider storeProvider = new InMemoryDbStoreProvider(Option.Some(checker)); string store1Name = "store1"; IDbStore store1 = storeProvider.GetDbStore(store1Name); string store2Name = "store2"; IDbStore store2 = storeProvider.GetDbStore(store2Name); byte[] message1 = new byte[10]; byte[] message2 = new byte[20]; await store1.Put(message1, message1); await store2.Put(message2, message2); // Current sizes - // store1 -> (message1 * 2) // store2 -> (message2 * 2) // Aggregated size is less than limit, adding another item should succeed. byte[] message3 = new byte[30]; await store1.Put(message3, message3, CancellationToken.None); // Current sizes - // store1 -> (message1 * 2) + (message3 * 2) // store2 -> (message2 * 2) // Aggregated size is greater than limit, adding another item should fail. byte[] message4 = new byte[40]; await Assert.ThrowsAsync <StorageFullException>(() => store2.Put(message4, message4)); await Assert.ThrowsAsync <StorageFullException>(() => store2.Put(message4, message4, CancellationToken.None)); // Remove store2. The usage of store1 alone should be less than the max limit. // Current sizes - // store1 -> (message1 * 2) + (message3 * 2) // store2 -> X // Aggregated size is less than limit, adding another item should succeed. storeProvider.RemoveDbStore(store2Name); await store1.Put(message4, message4); // Current sizes - // store1 -> (message1 * 2) + (message3 * 2) + (message4 * 2) // store2 -> X // Aggregated size is greater than limit, adding another item should fail. byte[] message5 = new byte[45]; await Assert.ThrowsAsync <StorageFullException>(() => store1.Put(message5, message5)); // Re-add store2. store2 = storeProvider.GetDbStore(store2Name); await store1.Remove(message4); // Current sizes - // store1 -> (message1 * 2) + (message3 * 2) // store2 -> X // Aggregated size is less than limit, adding another item should succeed. await store2.Put(message1, message1); // Current sizes - // store1 -> (message1 * 2) + (message3 * 2) // store2 -> (message1 * 2) // Aggregated size is greater than limit, adding another item should fail. await Assert.ThrowsAsync <StorageFullException>(() => store2.Put(message5, message5)); // Remove an item from store1 and then try adding a smaller item to store2 which should succeed. await store1.Remove(message3, CancellationToken.None); // Current sizes - // store1 -> (message1 * 2) // store2 -> (message1 * 2) // Aggregated size is less than limit, adding another item should succeed. await store2.Put(message3, message3, CancellationToken.None); // Current sizes - // store1 -> (message1 * 2) // store2 -> (message1 * 2) + (message3 * 2) // Aggregated size is greater than limit, adding another item should fail. await Assert.ThrowsAsync <StorageFullException>(() => store2.Put(message4, message4)); // Set max storage size to be greater than the current db size. Option <long> newMaxStorageBytes = Option.Some((message1.Length * 2) * 2L + (message3.Length * 2) + 10); checker.SetMaxSizeBytes(newMaxStorageBytes); // Adding another item should now succeed after the limits have been increased. await store1.Put(message4, message4); // Adding a new item to store1 should fail. // Current sizes - // store1 -> (message1 * 2) + (message4 * 2) // store2 -> (message1 * 2) + (message3 * 2) // Aggregated size is greater than limit, adding another item should fail. await Assert.ThrowsAsync <StorageFullException>(() => store1.Put(message5, message5)); // Updating the message4 item in store1 should succeed as the size difference between // the existing and updated value is zero bytes which doesn't lead to the limit being breached. await store1.Put(message4, message4); }
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); }