public async Task UpdateReportedPropertiesTest() { string id = "d1"; var reported1 = new TwinCollection { ["p1"] = "vp1", ["p3"] = "v3" }; TwinCollection receivedTwinPatch = null; var twinStore = new Mock <ITwinStore>(MockBehavior.Strict); twinStore.Setup(c => c.UpdateReportedProperties(id, It.IsAny <TwinCollection>())) .Callback <string, TwinCollection>((s, t) => receivedTwinPatch = t) .Returns(Task.CompletedTask); TwinCollection receivedTwinPatch2 = null; var reportedPropertiesStore = new Mock <IReportedPropertiesStore>(MockBehavior.Strict); reportedPropertiesStore.Setup(r => r.InitSyncToCloud(id)); reportedPropertiesStore.Setup(r => r.Update(id, It.IsAny <TwinCollection>())) .Callback <string, TwinCollection>((s, t) => receivedTwinPatch2 = t) .Returns(Task.CompletedTask); var cloudSync = Mock.Of <ICloudSync>(); var twinMessageConverter = new TwinMessageConverter(); var connectionManager = Mock.Of <IConnectionManager>(); var twinCollectionConverter = new TwinCollectionMessageConverter(); var reportedPropertiesValidator = Mock.Of <IValidator <TwinCollection> >(); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); var twinManager = new StoringTwinManager( connectionManager, twinCollectionConverter, twinMessageConverter, reportedPropertiesValidator, twinStore.Object, reportedPropertiesStore.Object, cloudSync, deviceConnectivityManager, TimeSpan.FromMinutes(10)); IMessage reportedPropertiesMessage = twinCollectionConverter.ToMessage(reported1); // Act await twinManager.UpdateReportedPropertiesAsync(id, reportedPropertiesMessage); // Assert twinStore.VerifyAll(); reportedPropertiesStore.VerifyAll(); Assert.NotNull(receivedTwinPatch); Assert.NotNull(receivedTwinPatch2); Assert.Equal(reported1.ToJson(), receivedTwinPatch.ToJson()); Assert.Equal(reported1.ToJson(), receivedTwinPatch2.ToJson()); }
public async Task DeviceConnectionNoSubscriptionTest() { string id = "d1"; var identity = Mock.Of <IIdentity>(i => i.Id == id); var twinStore = new Mock <ITwinStore>(MockBehavior.Strict); twinStore.Setup(c => c.Get(id)) .ReturnsAsync(Option.None <Twin>()); var reportedPropertiesStore = new Mock <IReportedPropertiesStore>(MockBehavior.Strict); reportedPropertiesStore.Setup(r => r.SyncToCloud(id)) .Returns(Task.CompletedTask); var deviceProxy = new Mock <IDeviceProxy>(MockBehavior.Strict); var cloudSync = new Mock <ICloudSync>(MockBehavior.Strict); var twinMessageConverter = new TwinMessageConverter(); var twinCollectionConverter = new TwinCollectionMessageConverter(); var reportedPropertiesValidator = Mock.Of <IValidator <TwinCollection> >(); var connectionManager = Mock.Of <IConnectionManager>( c => c.CheckClientSubscription(id, DeviceSubscription.DesiredPropertyUpdates) == false && c.GetConnectedClients() == new[] { identity }); var deviceConnectivityManager = new Mock <IDeviceConnectivityManager>(); var twinManager = new StoringTwinManager( connectionManager, twinCollectionConverter, twinMessageConverter, reportedPropertiesValidator, twinStore.Object, reportedPropertiesStore.Object, cloudSync.Object, deviceConnectivityManager.Object, TimeSpan.FromMinutes(10)); // Act deviceConnectivityManager.Raise(d => d.DeviceConnected += null, this, new EventArgs()); // Assert await Task.Delay(TimeSpan.FromSeconds(3)); twinStore.VerifyAll(); reportedPropertiesStore.VerifyAll(); Mock.Get(connectionManager).VerifyAll(); cloudSync.VerifyAll(); deviceProxy.VerifyAll(); }
protected override void Load(ContainerBuilder builder) { // IMessageConverter<IRoutingMessage> builder.Register(c => new RoutingMessageConverter()) .As <Core.IMessageConverter <IRoutingMessage> >() .SingleInstance(); // IRoutingPerfCounter builder.Register( c => { Routing.PerfCounter = NullRoutingPerfCounter.Instance; return(Routing.PerfCounter); }) .As <IRoutingPerfCounter>() .AutoActivate() .SingleInstance(); // IRoutingUserAnalyticsLogger builder.Register( c => { Routing.UserAnalyticsLogger = NullUserAnalyticsLogger.Instance; return(Routing.UserAnalyticsLogger); }) .As <IRoutingUserAnalyticsLogger>() .AutoActivate() .SingleInstance(); // IRoutingUserMetricLogger builder.Register( c => { Routing.UserMetricLogger = NullRoutingUserMetricLogger.Instance; return(Routing.UserMetricLogger); }) .As <IRoutingUserMetricLogger>() .AutoActivate() .SingleInstance(); // IMessageConverter<Message> builder.Register(c => new DeviceClientMessageConverter()) .As <Core.IMessageConverter <Message> >() .SingleInstance(); // IMessageConverter<Twin> builder.Register(c => new TwinMessageConverter()) .As <Core.IMessageConverter <Twin> >() .SingleInstance(); // IMessageConverter<TwinCollection> builder.Register(c => new TwinCollectionMessageConverter()) .As <Core.IMessageConverter <TwinCollection> >() .SingleInstance(); // IMessageConverterProvider builder.Register( c => new MessageConverterProvider( new Dictionary <Type, IMessageConverter>() { { typeof(Message), c.Resolve <Core.IMessageConverter <Message> >() }, { typeof(Twin), c.Resolve <Core.IMessageConverter <Twin> >() }, { typeof(TwinCollection), c.Resolve <Core.IMessageConverter <TwinCollection> >() } })) .As <IMessageConverterProvider>() .SingleInstance(); // IDeviceConnectivityManager builder.Register( c => { var edgeHubCredentials = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials"); IDeviceConnectivityManager deviceConnectivityManager = this.experimentalFeatures.DisableConnectivityCheck ? new NullDeviceConnectivityManager() : new DeviceConnectivityManager(this.connectivityCheckFrequency, TimeSpan.FromMinutes(2), edgeHubCredentials.Identity) as IDeviceConnectivityManager; return(deviceConnectivityManager); }) .As <IDeviceConnectivityManager>() .SingleInstance(); // IDeviceClientProvider builder.Register( c => { IClientProvider underlyingClientProvider = new ClientProvider(); IClientProvider connectivityAwareClientProvider = new ConnectivityAwareClientProvider(underlyingClientProvider, c.Resolve <IDeviceConnectivityManager>()); return(connectivityAwareClientProvider); }) .As <IClientProvider>() .SingleInstance(); // Task<ICloudConnectionProvider> builder.Register( async c => { var productInfoStore = await c.Resolve <Task <IProductInfoStore> >(); var messageConverterProvider = c.Resolve <IMessageConverterProvider>(); var clientProvider = c.Resolve <IClientProvider>(); var tokenProvider = c.ResolveNamed <ITokenProvider>("EdgeHubClientAuthTokenProvider"); var credentialsCacheTask = c.Resolve <Task <ICredentialsCache> >(); var edgeHubCredentials = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials"); var deviceScopeIdentitiesCacheTask = c.Resolve <Task <IDeviceScopeIdentitiesCache> >(); var proxy = c.Resolve <Option <IWebProxy> >(); IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache = await deviceScopeIdentitiesCacheTask; ICredentialsCache credentialsCache = await credentialsCacheTask; ICloudConnectionProvider cloudConnectionProvider = new CloudConnectionProvider( messageConverterProvider, this.connectionPoolSize, clientProvider, this.upstreamProtocol, tokenProvider, deviceScopeIdentitiesCache, credentialsCache, edgeHubCredentials.Identity, this.cloudConnectionIdleTimeout, this.closeCloudConnectionOnIdleTimeout, this.operationTimeout, this.useServerHeartbeat, proxy, productInfoStore); return(cloudConnectionProvider); }) .As <Task <ICloudConnectionProvider> >() .SingleInstance(); // IIdentityProvider builder.Register(_ => new IdentityProvider(this.iotHubName)) .As <IIdentityProvider>() .SingleInstance(); // Task<IConnectionManager> builder.Register( async c => { var cloudConnectionProviderTask = c.Resolve <Task <ICloudConnectionProvider> >(); var credentialsCacheTask = c.Resolve <Task <ICredentialsCache> >(); var identityProvider = c.Resolve <IIdentityProvider>(); var deviceConnectivityManager = c.Resolve <IDeviceConnectivityManager>(); ICloudConnectionProvider cloudConnectionProvider = await cloudConnectionProviderTask; ICredentialsCache credentialsCache = await credentialsCacheTask; IConnectionManager connectionManager = new ConnectionManager( cloudConnectionProvider, credentialsCache, identityProvider, deviceConnectivityManager, this.maxConnectedClients, this.closeCloudConnectionOnDeviceDisconnect); return(connectionManager); }) .As <Task <IConnectionManager> >() .SingleInstance(); // Task<IEndpointFactory> builder.Register( async c => { var messageConverter = c.Resolve <Core.IMessageConverter <IRoutingMessage> >(); IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >(); return(new EndpointFactory(connectionManager, messageConverter, this.edgeDeviceId, this.maxUpstreamBatchSize, this.upstreamFanOutFactor) as IEndpointFactory); }) .As <Task <IEndpointFactory> >() .SingleInstance(); // Task<RouteFactory> builder.Register(async c => new EdgeRouteFactory(await c.Resolve <Task <IEndpointFactory> >()) as RouteFactory) .As <Task <RouteFactory> >() .SingleInstance(); // RouterConfig builder.Register(c => new RouterConfig(Enumerable.Empty <Route>())) .As <RouterConfig>() .SingleInstance(); if (!this.isStoreAndForwardEnabled) { // EndpointExecutorConfig builder.Register( c => { RetryStrategy defaultRetryStrategy = new FixedInterval(0, TimeSpan.FromSeconds(1)); TimeSpan defaultRevivePeriod = TimeSpan.FromHours(1); TimeSpan defaultTimeout = TimeSpan.FromSeconds(60); return(new EndpointExecutorConfig(defaultTimeout, defaultRetryStrategy, defaultRevivePeriod, true)); }) .As <EndpointExecutorConfig>() .SingleInstance(); // IEndpointExecutorFactory builder.Register(c => new SyncEndpointExecutorFactory(c.Resolve <EndpointExecutorConfig>())) .As <IEndpointExecutorFactory>() .SingleInstance(); // Task<Router> builder.Register( async c => { var endpointExecutorFactory = c.Resolve <IEndpointExecutorFactory>(); var routerConfig = c.Resolve <RouterConfig>(); Router router = await Router.CreateAsync(Guid.NewGuid().ToString(), this.iotHubName, routerConfig, endpointExecutorFactory); return(router); }) .As <Task <Router> >() .SingleInstance(); // Task<ITwinManager> builder.Register( async c => { if (!this.useV1TwinManager) { var messageConverterProvider = c.Resolve <IMessageConverterProvider>(); IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >(); ITwinManager twinManager = new PassThroughTwinManager(connectionManager, messageConverterProvider); return(twinManager); } else { var messageConverterProvider = c.Resolve <IMessageConverterProvider>(); IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >(); return(TwinManager.CreateTwinManager(connectionManager, messageConverterProvider, Option.None <IStoreProvider>())); } }) .As <Task <ITwinManager> >() .SingleInstance(); } else { // EndpointExecutorConfig builder.Register( c => { // Endpoint executor config values - // ExponentialBackoff - minBackoff = 1s, maxBackoff = 60s, delta (used to add randomness to backoff) - 1s (default) // Num of retries = int.MaxValue(we want to keep retrying till the message is sent) // Revive period - period for which the endpoint should be considered dead if it doesn't respond - 1 min (we want to try continuously till the message expires) // Timeout - time for which we want for the ack from the endpoint = 30s // TODO - Should the number of retries be tied to the Store and Forward ttl? Not // doing that right now as that value can be changed at runtime, but these settings // cannot. Need to make the number of retries dynamically configurable for that. TimeSpan minWait = TimeSpan.FromSeconds(1); TimeSpan maxWait = TimeSpan.FromSeconds(60); TimeSpan delta = TimeSpan.FromSeconds(1); int retries = int.MaxValue; RetryStrategy retryStrategy = new ExponentialBackoff(retries, minWait, maxWait, delta); TimeSpan timeout = TimeSpan.FromSeconds(30); TimeSpan revivePeriod = TimeSpan.FromSeconds(30); return(new EndpointExecutorConfig(timeout, retryStrategy, revivePeriod)); }) .As <EndpointExecutorConfig>() .SingleInstance(); // Task<ICheckpointStore> builder.Register( async c => { var dbStoreProvider = await c.Resolve <Task <IDbStoreProvider> >(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); ICheckpointStore checkpointStore = CheckpointStore.Create(storeProvider); return(checkpointStore); }) .As <Task <ICheckpointStore> >() .SingleInstance(); // Task<IMessageStore> builder.Register( async c => { var checkpointStore = await c.Resolve <Task <ICheckpointStore> >(); var dbStoreProvider = await c.Resolve <Task <IDbStoreProvider> >(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); IMessageStore messageStore = new MessageStore(storeProvider, checkpointStore, this.storeAndForwardConfiguration.TimeToLive, this.checkEntireQueueOnCleanup); return(messageStore); }) .As <Task <IMessageStore> >() .SingleInstance(); // Task<IEndpointExecutorFactory> builder.Register( async c => { var endpointExecutorConfig = c.Resolve <EndpointExecutorConfig>(); var messageStore = await c.Resolve <Task <IMessageStore> >(); IEndpointExecutorFactory endpointExecutorFactory = new StoringAsyncEndpointExecutorFactory(endpointExecutorConfig, new AsyncEndpointExecutorOptions(10, TimeSpan.FromSeconds(10)), messageStore); return(endpointExecutorFactory); }) .As <Task <IEndpointExecutorFactory> >() .SingleInstance(); // Task<Router> builder.Register( async c => { var checkpointStore = await c.Resolve <Task <ICheckpointStore> >(); var routerConfig = c.Resolve <RouterConfig>(); var endpointExecutorFactory = await c.Resolve <Task <IEndpointExecutorFactory> >(); return(await Router.CreateAsync(Guid.NewGuid().ToString(), this.iotHubName, routerConfig, endpointExecutorFactory, checkpointStore)); }) .As <Task <Router> >() .SingleInstance(); // Task<ITwinManager> builder.Register( async c => { if (this.useV1TwinManager) { var dbStoreProvider = await c.Resolve <Task <IDbStoreProvider> >(); var messageConverterProvider = c.Resolve <IMessageConverterProvider>(); IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >(); return(TwinManager.CreateTwinManager(connectionManager, messageConverterProvider, Option.Some <IStoreProvider>(new StoreProvider(dbStoreProvider)))); } else { var messageConverterProvider = c.Resolve <IMessageConverterProvider>(); var deviceConnectivityManager = c.Resolve <IDeviceConnectivityManager>(); var connectionManagerTask = c.Resolve <Task <IConnectionManager> >(); IEntityStore <string, TwinStoreEntity> entityStore = await this.GetTwinStore(c); IConnectionManager connectionManager = await connectionManagerTask; ITwinManager twinManager = StoringTwinManager.Create( connectionManager, messageConverterProvider, entityStore, deviceConnectivityManager, new ReportedPropertiesValidator(), this.minTwinSyncPeriod, this.reportedPropertiesSyncFrequency); return(twinManager); } }) .As <Task <ITwinManager> >() .SingleInstance(); } // IClientCredentials "EdgeHubCredentials" builder.Register( c => { var identityFactory = c.Resolve <IClientCredentialsFactory>(); IClientCredentials edgeHubCredentials = this.connectionString.Map(cs => identityFactory.GetWithConnectionString(cs)).GetOrElse( () => identityFactory.GetWithIotEdged(this.edgeDeviceId, this.edgeModuleId)); return(edgeHubCredentials); }) .Named <IClientCredentials>("EdgeHubCredentials") .SingleInstance(); // Task<IInvokeMethodHandler> builder.Register( async c => { IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >(); return(new InvokeMethodHandler(connectionManager) as IInvokeMethodHandler); }) .As <Task <IInvokeMethodHandler> >() .SingleInstance(); // Task<ISubscriptionProcessor> builder.Register( async c => { var connectionManagerTask = c.Resolve <Task <IConnectionManager> >(); if (this.experimentalFeatures.DisableCloudSubscriptions) { return(new LocalSubscriptionProcessor(await connectionManagerTask) as ISubscriptionProcessor); } else { var invokeMethodHandlerTask = c.Resolve <Task <IInvokeMethodHandler> >(); var deviceConnectivityManager = c.Resolve <IDeviceConnectivityManager>(); IConnectionManager connectionManager = await connectionManagerTask; IInvokeMethodHandler invokeMethodHandler = await invokeMethodHandlerTask; return(new SubscriptionProcessor(connectionManager, invokeMethodHandler, deviceConnectivityManager) as ISubscriptionProcessor); } }) .As <Task <ISubscriptionProcessor> >() .SingleInstance(); // Task<IEdgeHub> builder.Register( async c => { var routingMessageConverter = c.Resolve <Core.IMessageConverter <IRoutingMessage> >(); var routerTask = c.Resolve <Task <Router> >(); var twinManagerTask = c.Resolve <Task <ITwinManager> >(); var invokeMethodHandlerTask = c.Resolve <Task <IInvokeMethodHandler> >(); var connectionManagerTask = c.Resolve <Task <IConnectionManager> >(); var subscriptionProcessorTask = c.Resolve <Task <ISubscriptionProcessor> >(); Router router = await routerTask; ITwinManager twinManager = await twinManagerTask; IConnectionManager connectionManager = await connectionManagerTask; IInvokeMethodHandler invokeMethodHandler = await invokeMethodHandlerTask; ISubscriptionProcessor subscriptionProcessor = await subscriptionProcessorTask; IEdgeHub hub = new RoutingEdgeHub( router, routingMessageConverter, connectionManager, twinManager, this.edgeDeviceId, invokeMethodHandler, subscriptionProcessor); return(hub); }) .As <Task <IEdgeHub> >() .SingleInstance(); // Task<ConfigUpdater> builder.Register( async c => { IMessageStore messageStore = this.isStoreAndForwardEnabled ? await c.Resolve <Task <IMessageStore> >() : null; var storageSpaceChecker = c.Resolve <IStorageSpaceChecker>(); var edgeHubCredentials = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials"); RouteFactory routeFactory = await c.Resolve <Task <RouteFactory> >(); Router router = await c.Resolve <Task <Router> >(); var twinManagerTask = c.Resolve <Task <ITwinManager> >(); var twinMessageConverter = c.Resolve <Core.IMessageConverter <Twin> >(); var twinManager = await twinManagerTask; var configUpdater = new ConfigUpdater(router, messageStore, this.configUpdateFrequency, storageSpaceChecker); return(configUpdater); }) .As <Task <ConfigUpdater> >() .SingleInstance(); // Task<IConfigSource> builder.Register <Task <IConfigSource> >( async c => { RouteFactory routeFactory = await c.Resolve <Task <RouteFactory> >(); if (this.useTwinConfig) { var edgeHubCredentials = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials"); var twinCollectionMessageConverter = c.Resolve <Core.IMessageConverter <TwinCollection> >(); var twinMessageConverter = c.Resolve <Core.IMessageConverter <Twin> >(); var twinManagerTask = c.Resolve <Task <ITwinManager> >(); var edgeHubTask = c.Resolve <Task <IEdgeHub> >(); ITwinManager twinManager = await twinManagerTask; IEdgeHub edgeHub = await edgeHubTask; IConnectionManager connectionManager = await c.Resolve <Task <IConnectionManager> >(); IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache = await c.Resolve <Task <IDeviceScopeIdentitiesCache> >(); var edgeHubConnection = await EdgeHubConnection.Create( edgeHubCredentials.Identity, edgeHub, twinManager, connectionManager, routeFactory, twinCollectionMessageConverter, this.versionInfo, deviceScopeIdentitiesCache); return(new TwinConfigSource(edgeHubConnection, edgeHubCredentials.Identity.Id, this.versionInfo, twinManager, twinMessageConverter, twinCollectionMessageConverter, routeFactory)); } else { return(new LocalConfigSource(routeFactory, this.routes, this.storeAndForwardConfiguration)); } }) .As <Task <IConfigSource> >() .SingleInstance(); // Task<IConnectionProvider> builder.Register( async c => { var connectionManagerTask = c.Resolve <Task <IConnectionManager> >(); var edgeHubTask = c.Resolve <Task <IEdgeHub> >(); IConnectionManager connectionManager = await connectionManagerTask; IEdgeHub edgeHub = await edgeHubTask; IConnectionProvider connectionProvider = new ConnectionProvider(connectionManager, edgeHub, this.messageAckTimeout); return(connectionProvider); }) .As <Task <IConnectionProvider> >() .SingleInstance(); base.Load(builder); }
public async Task DeviceConnectionSyncPeriodTest() { string id = "d1"; var identity = Mock.Of <IIdentity>(i => i.Id == id); var desired2 = new TwinCollection { ["p1"] = "vp1", ["p2"] = "v2", ["p3"] = "v3", ["$version"] = 2 }; var reported2 = new TwinCollection { ["p2"] = "vp2", ["$version"] = 2 }; var twin2 = new Twin { Properties = new TwinProperties { Reported = reported2, Desired = desired2 } }; var twinStore = new Mock <ITwinStore>(MockBehavior.Strict); twinStore.Setup(c => c.Get(id)) .ReturnsAsync(Option.Some(twin2)); Twin storedTwin = null; twinStore.Setup(c => c.Update(id, It.IsAny <Twin>())) .Callback <string, Twin>((s, t) => storedTwin = t) .Returns(Task.CompletedTask); var reportedPropertiesStore = new Mock <IReportedPropertiesStore>(MockBehavior.Strict); reportedPropertiesStore.Setup(r => r.SyncToCloud(id)) .Returns(Task.CompletedTask); var deviceProxy = new Mock <IDeviceProxy>(MockBehavior.Strict); var cloudSync = new Mock <ICloudSync>(MockBehavior.Strict); cloudSync.Setup(c => c.GetTwin(id)) .ReturnsAsync(Option.Some(twin2)); var twinMessageConverter = new TwinMessageConverter(); var twinCollectionConverter = new TwinCollectionMessageConverter(); var reportedPropertiesValidator = Mock.Of <IValidator <TwinCollection> >(); var connectionManager = Mock.Of <IConnectionManager>( c => c.CheckClientSubscription(id, DeviceSubscription.DesiredPropertyUpdates) && c.GetDeviceConnection(id) == Option.Some(deviceProxy.Object) && c.GetConnectedClients() == new[] { identity }); var deviceConnectivityManager = new Mock <IDeviceConnectivityManager>(); var twinManager = new StoringTwinManager( connectionManager, twinCollectionConverter, twinMessageConverter, reportedPropertiesValidator, twinStore.Object, reportedPropertiesStore.Object, cloudSync.Object, deviceConnectivityManager.Object, TimeSpan.FromMinutes(10)); // Act IMessage getTwinMessage = await twinManager.GetTwinAsync(id); // Assert Assert.NotNull(getTwinMessage); Twin getTwin = twinMessageConverter.FromMessage(getTwinMessage); Assert.NotNull(getTwin); Assert.Equal(twin2.ToJson(), getTwin.ToJson()); // Act deviceConnectivityManager.Raise(d => d.DeviceConnected += null, this, new EventArgs()); // Assert await Task.Delay(TimeSpan.FromSeconds(3)); twinStore.VerifyAll(); reportedPropertiesStore.VerifyAll(); deviceProxy.VerifyAll(); cloudSync.Verify(c => c.GetTwin(id), Times.AtMostOnce); Assert.NotNull(storedTwin); Assert.Equal(twin2.ToJson(), storedTwin.ToJson()); }
public async Task UpdateDesiredPropertiesWithIncorrectPatchTest() { string id = "d1"; var desired0 = new TwinCollection { ["p0"] = "vp0", ["$version"] = 0 }; var reported0 = new TwinCollection { ["p0"] = "vp0", ["$version"] = 0 }; var twinBase = new Twin { Properties = new TwinProperties { Reported = reported0, Desired = desired0 } }; var desired2 = new TwinCollection { ["p1"] = "vp1", ["p2"] = "v2", ["p3"] = "v3", ["$version"] = 2 }; var reported2 = new TwinCollection { ["p2"] = "vp2", ["$version"] = 2 }; var twin2 = new Twin { Properties = new TwinProperties { Reported = reported2, Desired = desired2 } }; var desired2Patch = new TwinCollection { ["p1"] = "vp1", ["$version"] = 2 }; var twinStore = new Mock <ITwinStore>(MockBehavior.Strict); twinStore.Setup(c => c.Get(id)) .ReturnsAsync(Option.Some(twinBase)); Twin storedTwin = null; twinStore.Setup(c => c.Update(id, It.IsAny <Twin>())) .Callback <string, Twin>((s, t) => storedTwin = t) .Returns(Task.CompletedTask); var reportedPropertiesStore = new Mock <IReportedPropertiesStore>(MockBehavior.Strict); IMessage receivedTwinPatchMessage = null; var deviceProxy = new Mock <IDeviceProxy>(); deviceProxy.Setup(d => d.OnDesiredPropertyUpdates(It.IsAny <IMessage>())) .Callback <IMessage>(m => receivedTwinPatchMessage = m) .Returns(Task.CompletedTask); var cloudSync = Mock.Of <ICloudSync>(c => c.GetTwin(id) == Task.FromResult(Option.Some(twin2))); var twinMessageConverter = new TwinMessageConverter(); var twinCollectionConverter = new TwinCollectionMessageConverter(); var reportedPropertiesValidator = Mock.Of <IValidator <TwinCollection> >(); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); var connectionManager = Mock.Of <IConnectionManager>( c => c.CheckClientSubscription(id, DeviceSubscription.DesiredPropertyUpdates) && c.GetDeviceConnection(id) == Option.Some(deviceProxy.Object)); var twinManager = new StoringTwinManager( connectionManager, twinCollectionConverter, twinMessageConverter, reportedPropertiesValidator, twinStore.Object, reportedPropertiesStore.Object, cloudSync, deviceConnectivityManager, TimeSpan.FromMinutes(10)); IMessage desiredPropertiesMessage = twinCollectionConverter.ToMessage(desired2Patch); // Act await twinManager.UpdateDesiredPropertiesAsync(id, desiredPropertiesMessage); // Assert twinStore.VerifyAll(); reportedPropertiesStore.VerifyAll(); Assert.NotNull(storedTwin); Assert.NotNull(receivedTwinPatchMessage); Assert.Equal(twin2.ToJson(), storedTwin.ToJson()); TwinCollection receivedTwinPatch2 = twinCollectionConverter.FromMessage(receivedTwinPatchMessage); Assert.Equal("{\"p0\":null,\"$version\":2,\"p1\":\"vp1\",\"p2\":\"v2\",\"p3\":\"v3\"}", receivedTwinPatch2.ToJson()); }
public async Task GetTwinTest() { // Arrange string id = "d1"; var desired1 = new TwinCollection { ["p1"] = "vp1", ["p3"] = "v3", ["$version"] = 1 }; var reported1 = new TwinCollection { ["p1"] = "vp1", ["p3"] = "v3", ["$version"] = 1 }; var twin1 = new Twin { Properties = new TwinProperties { Desired = desired1, Reported = reported1 } }; var cloudSync = new Mock <ICloudSync>(); cloudSync.SetupSequence(c => c.GetTwin(id)) .ReturnsAsync(Option.None <Twin>()) .ReturnsAsync(Option.Some(twin1)) .ReturnsAsync(Option.None <Twin>()); Twin receivedTwin = null; var twinStore = new Mock <ITwinStore>(); twinStore.Setup(c => c.Update(id, It.IsAny <Twin>())) .Callback <string, Twin>((s, t) => receivedTwin = t) .Returns(Task.CompletedTask); twinStore.Setup(c => c.Get(id)) .ReturnsAsync(() => Option.Maybe(receivedTwin)); var twinMessageConverter = new TwinMessageConverter(); var connectionManager = Mock.Of <IConnectionManager>(); var twinCollectionConverter = Mock.Of <IMessageConverter <TwinCollection> >(); var reportedPropertiesValidator = Mock.Of <IValidator <TwinCollection> >(); var reportedPropertiesStore = Mock.Of <IReportedPropertiesStore>(); var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>(); var twinManager = new StoringTwinManager( connectionManager, twinCollectionConverter, twinMessageConverter, reportedPropertiesValidator, twinStore.Object, reportedPropertiesStore, cloudSync.Object, deviceConnectivityManager, TimeSpan.FromMinutes(10)); // Act IMessage twinMessage = await twinManager.GetTwinAsync(id); // Assert Assert.NotNull(twinMessage); Twin twin = twinMessageConverter.FromMessage(twinMessage); Assert.NotNull(twin); Assert.Equal("{\"deviceId\":null,\"etag\":null,\"version\":null,\"properties\":{\"desired\":{},\"reported\":{}}}", twin.ToJson()); // Act twinMessage = await twinManager.GetTwinAsync(id); // Assert Assert.NotNull(twinMessage); twin = twinMessageConverter.FromMessage(twinMessage); Assert.NotNull(twin); Assert.NotNull(receivedTwin); Assert.Equal(receivedTwin.ToJson(), twin.ToJson()); Assert.Equal(twin1.ToJson(), twin.ToJson()); // Act twinMessage = await twinManager.GetTwinAsync(id); // Assert Assert.NotNull(twinMessage); twin = twinMessageConverter.FromMessage(twinMessage); Assert.NotNull(twin); Assert.NotNull(receivedTwin); Assert.Equal(receivedTwin.ToJson(), twin.ToJson()); Assert.Equal(twin1.ToJson(), twin.ToJson()); }