public async Task NonTransientErrorInFirstBatch_LetsTryTheRest_ButReportsSendFailure()
        {
            var batchSize = 10;

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxy = ThrowingCloudProxy
                             .Create()
                             .WithBatchSize(batchSize)
                             .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Exception>())
                             .WithReportSuccessfulBatch(2)
                             .Build();

            Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy));

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None);

            Assert.True(sinkResult.IsSuccessful); // non-transient errors are ignored, but reported in SendFailureDetails
            Assert.Equal(2 * batchSize, sinkResult.Succeeded.Count);
            Assert.Equal(0, sinkResult.Failed.Count);
            Assert.Equal(batchSize, sinkResult.InvalidDetailsList.Count);
            Assert.True(sinkResult.SendFailureDetails.HasValue);
            Assert.Equal(FailureKind.InvalidInput, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind);
        }
Exemplo n.º 2
0
        public void TestFromMessageCases(byte[] messageBytes,
                                         IDictionary <string, string> properties,
                                         IDictionary <string, string> systemProperties)
        {
            Core.IMessageConverter <IRoutingMessage> messageConverter = new RoutingMessageConverter();
            IMessage        inputMessage   = new EdgeMessage(messageBytes, properties, systemProperties);
            IRoutingMessage routingMessage = messageConverter.FromMessage(inputMessage);

            Assert.Equal(inputMessage.Body, routingMessage.Body);
            foreach (KeyValuePair <string, string> property in properties)
            {
                Assert.True(routingMessage.Properties.ContainsKey(property.Key));
                Assert.Equal(property.Value, routingMessage.Properties[property.Key]);
            }

            foreach (KeyValuePair <string, string> property in systemProperties)
            {
                Assert.True(routingMessage.SystemProperties.ContainsKey(property.Key));
                Assert.Equal(property.Value, routingMessage.SystemProperties[property.Key]);
            }

            Assert.Equal(DateTime.MinValue, routingMessage.EnqueuedTime);
            Assert.Equal(routingMessage.Offset, 0);
            Assert.True(routingMessage.MessageSource.IsTelemetry());
        }
        public async Task NoErrorFromCloudProxy_NoErrorDetailsReturned()
        {
            var batchSize = 10;

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxy = ThrowingCloudProxy
                             .Create()
                             .WithBatchSize(batchSize)
                             .WithReportSuccessfulBatch(3)
                             .Build();

            Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy));

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, batchSize);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None);

            Assert.True(sinkResult.IsSuccessful);
            Assert.Equal(3 * batchSize, sinkResult.Succeeded.Count);
            Assert.Equal(0, sinkResult.Failed.Count);
            Assert.Equal(0, sinkResult.InvalidDetailsList.Count);
            Assert.Equal(Option.None <SendFailureDetails>(), sinkResult.SendFailureDetails);
        }
Exemplo n.º 4
0
        public async Task TransientErrorInSecondBatch_OverwritesNonTransientFailureDetails()
        {
            var batchSize = 10;

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxy = ThrowingCloudProxy
                             .CreateWithResponses(3, ThrowingCloudProxy.Success())
                             .Then(ThrowingCloudProxy.Throw <Exception>())                         // non-transient error
                             .ThenMany(batchSize - 4, ThrowingCloudProxy.Success())                // first batch ends here (3 success + 1 fail -> 10 - 4 to go)
                             .ThenMany(3, ThrowingCloudProxy.Success())
                             .Then(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>()) // transient error
                             .ThenMany(batchSize - 4, ThrowingCloudProxy.Success())                // second batch ends here
                             .ThenMany(1 * batchSize, ThrowingCloudProxy.Success())
                             .Build();

            Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy));

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None);

            Assert.False(sinkResult.IsSuccessful);
            Assert.Equal(batchSize, sinkResult.Succeeded.Count);
            Assert.Equal(batchSize, sinkResult.Failed.Count);
            Assert.Equal(batchSize, sinkResult.InvalidDetailsList.Count);
            Assert.True(sinkResult.SendFailureDetails.HasValue);
            Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind);
        }
        public async Task TransientErrorInSecondBatch_FastFailsRest_OverwritesNonTransientResult()
        {
            var batchSize = 10;

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxy = ThrowingCloudProxy
                             .Create()
                             .WithBatchSize(batchSize)
                             .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Exception>())
                             .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>())
                             .WithReportSuccessfulBatch()
                             .Build();

            Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxy));

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None);

            Assert.False(sinkResult.IsSuccessful);
            Assert.Equal(0, sinkResult.Succeeded.Count);
            Assert.Equal(2 * batchSize, sinkResult.Failed.Count);
            Assert.Equal(1 * batchSize, sinkResult.InvalidDetailsList.Count);
            Assert.True(sinkResult.SendFailureDetails.HasValue);
            Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind);
        }
Exemplo n.º 6
0
        public async Task ModuleMessageProcessor_ProcessAsyncTest_InactiveDeviceProxy()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var deviceProxy = new Mock <IDeviceProxy>();

            deviceProxy.Setup(d => d.SendMessageAsync(It.IsAny <IMessage>(), It.IsAny <string>())).Returns(Task.CompletedTask);
            deviceProxy.Setup(d => d.IsActive).Returns(false);
            var    routingMessage        = Mock.Of <IRoutingMessage>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";
            IReadOnlyDictionary <DeviceSubscription, bool> deviceSubscriptions = new ReadOnlyDictionary <DeviceSubscription, bool>(
                new Dictionary <DeviceSubscription, bool>
            {
                [DeviceSubscription.ModuleMessages] = true
            });
            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.GetDeviceConnection(It.IsAny <string>())).Returns(Option.Some(deviceProxy.Object));
            connectionManager.Setup(c => c.GetSubscriptions(It.IsAny <string>())).Returns(Option.Some(deviceSubscriptions));
            var moduleEndpoint = new ModuleEndpoint($"{moduleId}/{moduleEndpointAddress}", moduleId, moduleEndpointAddress, connectionManager.Object, routingMessageConverter);

            IProcessor moduleMessageProcessor        = moduleEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await moduleMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.True(sinkResult.Failed.Contains(routingMessage));
            Assert.Equal(FailureKind.None, sinkResult.SendFailureDetails.Map(x => x.FailureKind).GetOrElse(FailureKind.None));
        }
Exemplo n.º 7
0
        public async Task TransientErrorInFirstBatch_FastFailsRest()
        {
            var batchSize = 10;

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxy = ThrowingCloudProxy
                             .Create()
                             .WithBatchSize(batchSize)
                             .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>())
                             .WithReportSuccessfulBatch(2)
                             .Build();

            Task <Try <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Try.Success(cloudProxy));

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, true);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            var sinkResult = await cloudMessageProcessor.ProcessAsync(GetMessages("device1", 3 * batchSize), CancellationToken.None);

            // although the test is setup to succeed with batch 2 and 3, they will fast fail because of the first one
            Assert.False(sinkResult.IsSuccessful);
            Assert.Equal(0, sinkResult.Succeeded.Count);
            Assert.Equal(30, sinkResult.Failed.Count);
            Assert.Equal(0, sinkResult.InvalidDetailsList.Count);
            Assert.True(sinkResult.SendFailureDetails.HasValue);
            Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind);
        }
Exemplo n.º 8
0
        public async Task EdgeHubChecksMessageSize()
        {
            // Create a mock endpoint capable of returning a mock processor
            var processor = Mock.Of <IProcessor>();
            var endpoint  = new Mock <Endpoint>("myId");

            endpoint.Setup(ep => ep.CreateProcessor()).Returns(processor);
            endpoint.SetupGet(ep => ep.Id).Returns("myId");

            // Create a mock endpoint executor factory to create the endpoint executor to verify invocation
            var endpointExecutor = Mock.Of <IEndpointExecutor>();

            Mock.Get(endpointExecutor).SetupGet(ee => ee.Endpoint).Returns(() => endpoint.Object);
            var endpointExecutorFactory = Mock.Of <IEndpointExecutorFactory>();

            Mock.Get(endpointExecutorFactory).Setup(eef => eef.CreateAsync(It.IsAny <Endpoint>())).ReturnsAsync(endpointExecutor);

            // Create a route to map to the message
            var endpoints = new HashSet <Endpoint> {
                endpoint.Object
            };
            var route = new Route("myRoute", "true", "myIotHub", TelemetryMessageSource.Instance, endpoints);

            // Create a router
            var    routerConfig = new RouterConfig(new[] { route });
            Router router       = await Router.CreateAsync("myRouter", "myIotHub", routerConfig, endpointExecutorFactory);

            // Create mock for IConnectionManager
            var connectionManager = Mock.Of <IConnectionManager>();

            // Mock of twin manager
            var twinManager = Mock.Of <ITwinManager>();

            // Mock of identity
            var identity = new Mock <IIdentity>();

            identity.SetupGet(id => id.Id).Returns("something");

            var messageConverter = new RoutingMessageConverter();

            Message badMessage = new Message.Builder(new byte[300 * 1024]).Build();

            var routingEdgeHub = new RoutingEdgeHub(router, messageConverter, connectionManager, twinManager, "testEdgeDevice", Mock.Of <IInvokeMethodHandler>());

            await Assert.ThrowsAsync <InvalidOperationException>(() => routingEdgeHub.ProcessDeviceMessage(identity.Object, badMessage));

            string badString     = System.Text.Encoding.UTF8.GetString(new byte[300 * 1024], 0, 300 * 1024);
            var    badProperties = new Dictionary <string, string> {
                ["toolong"] = badString
            };

            badMessage = new Message.Builder(new byte[1]).SetProperties(badProperties).Build();

            await Assert.ThrowsAsync <InvalidOperationException>(() => routingEdgeHub.ProcessDeviceMessage(identity.Object, badMessage));

            badMessage = new Message(new byte[1], new Dictionary <string, string>(), badProperties);

            await Assert.ThrowsAsync <InvalidOperationException>(() => routingEdgeHub.ProcessDeviceMessage(identity.Object, badMessage));
        }
Exemplo n.º 9
0
        public async Task ProcessAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();

            const string Mod1Id        = "device1/module1";
            const string ModEndpointId = "in1";

            var deviceProxyMock = new Mock <IDeviceProxy>();

            deviceProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>(), It.Is <string>((ep) => ep.Equals(ModEndpointId, StringComparison.OrdinalIgnoreCase))))
            .Returns(Task.CompletedTask);

            deviceProxyMock.SetupGet(p => p.IsActive).Returns(true);

            IReadOnlyDictionary <DeviceSubscription, bool> deviceSubscriptions = new ReadOnlyDictionary <DeviceSubscription, bool>(
                new Dictionary <DeviceSubscription, bool>
            {
                [DeviceSubscription.ModuleMessages] = true
            });
            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.GetDeviceConnection(It.IsAny <string>())).Returns(Option.Some(deviceProxyMock.Object));
            connectionManager.Setup(c => c.GetSubscriptions(It.IsAny <string>())).Returns(Option.Some(deviceSubscriptions));

            byte[] messageBody = Encoding.UTF8.GetBytes("Message body");
            var    properties  = new Dictionary <string, string>()
            {
                { "Prop1", "Val1" },
                { "Prop2", "Val2" },
            };

            var systemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, Mod1Id }
            };

            var message1 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, systemProperties);
            var message2 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, systemProperties);

            var        moduleEndpoint         = new ModuleEndpoint($"{Mod1Id}/{ModEndpointId}", Mod1Id, ModEndpointId, connectionManager.Object, routingMessageConverter);
            IProcessor moduleMessageProcessor = moduleEndpoint.CreateProcessor();

            ISinkResult <IRoutingMessage> result = await moduleMessageProcessor.ProcessAsync(message1, CancellationToken.None);

            Assert.NotNull(result);
            Assert.NotEmpty(result.Succeeded);
            Assert.Empty(result.Failed);
            Assert.Empty(result.InvalidDetailsList);
            Assert.False(result.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatch = await moduleMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(resultBatch);
            Assert.NotEmpty(resultBatch.Succeeded);
            Assert.Empty(resultBatch.Failed);
            Assert.Empty(resultBatch.InvalidDetailsList);
            Assert.False(resultBatch.SendFailureDetails.HasValue);
        }
Exemplo n.º 10
0
        public void TestGetMessageSource(IDictionary <string, string> systemProperties, BaseMessageSource expectedMessageSource)
        {
            var            routingMessageConverter = new RoutingMessageConverter();
            IMessageSource messageSource           = routingMessageConverter.GetMessageSource(systemProperties);

            Assert.NotNull(messageSource);
            Assert.IsType(expectedMessageSource.GetType(), messageSource);
            var baseMessageSource = messageSource as BaseMessageSource;

            Assert.True(expectedMessageSource.Equals(baseMessageSource));
        }
Exemplo n.º 11
0
        public void BasicTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    connectionManager = new Mock <IConnectionManager>();
            string modId             = "device1/module1";
            string moduleEndpointId  = "in1";

            var        moduleEndpoint         = new ModuleEndpoint($"{modId}/{moduleEndpointId}", modId, moduleEndpointId, connectionManager.Object, routingMessageConverter);
            IProcessor moduleMessageProcessor = moduleEndpoint.CreateProcessor();

            Assert.Equal(moduleEndpoint, moduleMessageProcessor.Endpoint);
            Assert.False(moduleMessageProcessor.ErrorDetectionStrategy.IsTransient(new Exception()));
        }
Exemplo n.º 12
0
        public void CloudMessageProcessor_CloseAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    cloudProxy      = Mock.Of <ICloudProxy>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Option.Some(cloudProxy)), routingMessageConverter);

            IProcessor moduleMessageProcessor = cloudEndpoint.CreateProcessor();
            Task       result = moduleMessageProcessor.CloseAsync(CancellationToken.None);

            Assert.Equal(TaskEx.Done, result);
        }
Exemplo n.º 13
0
        public void CloudEndpoint_CreateProcessorTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    cloudProxy      = Mock.Of <ICloudProxy>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Option.Some(cloudProxy)), routingMessageConverter);

            IProcessor processor = cloudEndpoint.CreateProcessor();

            Assert.NotNull(processor);
            Assert.Equal(cloudEndpoint, processor.Endpoint);
        }
Exemplo n.º 14
0
        public void ModuleMessageProcessor_CreateProcessorTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    connectionManager     = Mock.Of <IConnectionManager>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";

            var moduleEndpoint = new ModuleEndpoint($"{moduleId}/{moduleEndpointAddress}", moduleId, moduleEndpointAddress, connectionManager, routingMessageConverter);

            IProcessor moduleMessageProcessor = moduleEndpoint.CreateProcessor();

            Assert.NotNull(moduleMessageProcessor);
            Assert.Equal(moduleEndpoint, moduleMessageProcessor.Endpoint);
        }
Exemplo n.º 15
0
        public void ModuleMessageProcessor_CloseAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    connectionManager     = Mock.Of <IConnectionManager>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";

            var moduleEndpoint = new ModuleEndpoint($"{moduleId}/{moduleEndpointAddress}", moduleId, moduleEndpointAddress, connectionManager, routingMessageConverter);

            IProcessor moduleMessageProcessor = moduleEndpoint.CreateProcessor();
            Task       result = moduleMessageProcessor.CloseAsync(CancellationToken.None);

            Assert.Equal(TaskEx.Done, result);
        }
Exemplo n.º 16
0
        public void ModuleEndpoint_MembersTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    connectionManager     = Mock.Of <IConnectionManager>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";
            string endpointId            = $"{moduleId}/{moduleEndpointAddress}";
            var    moduleEndpoint        = new ModuleEndpoint(endpointId, moduleId, moduleEndpointAddress, connectionManager, routingMessageConverter);

            Assert.Equal(endpointId, moduleEndpoint.Id);
            Assert.Equal("ModuleEndpoint", moduleEndpoint.Type);
            Assert.Equal(endpointId, moduleEndpoint.Name);
            Assert.Equal(string.Empty, moduleEndpoint.IotHubName);
        }
Exemplo n.º 17
0
        public void BasicTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    cloudProxyMock  = new Mock <ICloudProxy>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(cloudProxyMock.Object));

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            Assert.Equal(cloudEndpoint, cloudMessageProcessor.Endpoint);
            Assert.False(cloudMessageProcessor.ErrorDetectionStrategy.IsTransient(new Exception()));
        }
Exemplo n.º 18
0
        public async Task ModuleMessageProcessor_RetryableExceptionTest(Exception exception, bool isRetryable)
        {
            // Arrange
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var deviceProxy = new Mock <IDeviceProxy>();

            deviceProxy.Setup(d => d.SendMessageAsync(It.IsAny <IMessage>(), It.IsAny <string>()))
            .ThrowsAsync(exception);
            deviceProxy.Setup(d => d.IsActive).Returns(true);
            IReadOnlyDictionary <DeviceSubscription, bool> deviceSubscriptions = new ReadOnlyDictionary <DeviceSubscription, bool>(
                new Dictionary <DeviceSubscription, bool>
            {
                [DeviceSubscription.ModuleMessages] = true
            });
            var connectionManager = new Mock <IConnectionManager>();

            connectionManager.Setup(c => c.GetDeviceConnection(It.IsAny <string>())).Returns(Option.Some(deviceProxy.Object));
            connectionManager.Setup(c => c.GetSubscriptions(It.IsAny <string>())).Returns(Option.Some(deviceSubscriptions));
            var    routingMessage        = Mock.Of <IRoutingMessage>();
            string moduleId              = "device1/module1";
            string moduleEndpointAddress = "in1";

            var moduleEndpoint = new ModuleEndpoint($"{moduleId}/{moduleEndpointAddress}", moduleId, moduleEndpointAddress, connectionManager.Object, routingMessageConverter);

            // Act
            IProcessor moduleMessageProcessor    = moduleEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> result = await moduleMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            // Assert
            Assert.NotNull(result);
            if (isRetryable)
            {
                Assert.Equal(1, result.Failed.Count);
                Assert.Equal(0, result.Succeeded.Count);
                Assert.Equal(0, result.InvalidDetailsList.Count);
                Assert.Equal(routingMessage, result.Failed.First());
            }
            else
            {
                Assert.Equal(1, result.InvalidDetailsList.Count);
                Assert.Equal(0, result.Succeeded.Count);
                Assert.Equal(0, result.Failed.Count);
                Assert.Equal(routingMessage, result.InvalidDetailsList.First().Item);
                Assert.Equal(FailureKind.InvalidInput, result.InvalidDetailsList.First().FailureKind);
            }
        }
Exemplo n.º 19
0
        public async Task Events_CloudProxyNotFoundWithDeviceInvalidStateException_DropMessage_Test()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "connectionDeviceId", "myConnectionDeviceId" }
            });
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Try <ICloudProxy> .Failure(new DeviceInvalidStateException("Device removed from scope"))), routingMessageConverter, trackDeviceState: true);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.Equal(FailureKind.InvalidInput, sinkResult.SendFailureDetails.OrDefault().FailureKind);
            Assert.Equal(typeof(DeviceInvalidStateException), sinkResult.SendFailureDetails.OrDefault().RawException.GetType());
        }
Exemplo n.º 20
0
        public async Task Events_CloudProxyNotFoundTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "connectionDeviceId", "myConnectionDeviceId" }
            });
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Option.None <ICloudProxy>()), routingMessageConverter);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.Equal(FailureKind.None, sinkResult.SendFailureDetails.OrDefault().FailureKind);
            Assert.Equal(typeof(EdgeHubConnectionException), sinkResult.SendFailureDetails.OrDefault().RawException.GetType());
        }
Exemplo n.º 21
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);
        }
Exemplo n.º 22
0
        public void CloudEndpoint_MembersTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    cloudProxy      = Mock.Of <ICloudProxy>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, (id) => Option.Some(cloudProxy), routingMessageConverter);

            Assert.Equal(cloudEndpointId, cloudEndpoint.Id);
            Assert.Equal("CloudEndpoint", cloudEndpoint.Type);
            Assert.Equal(cloudEndpointId, cloudEndpoint.Name);
            Assert.Equal(string.Empty, cloudEndpoint.IotHubName);

            IProcessor processor = cloudEndpoint.CreateProcessor();

            Assert.NotNull(processor);
            Assert.Equal(cloudEndpoint, processor.Endpoint);
        }
Exemplo n.º 23
0
        public async Task CloudMessageProcessor_ProcessAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            var    cloudProxy      = Mock.Of <ICloudProxy>(c => c.IsActive);
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "connectionDeviceId", "myConnectionDeviceId" }
            });
            Mock.Get(cloudProxy).Setup(cp => cp.SendMessageAsync(It.IsAny <IMessage>())).Returns(Task.FromResult(true));
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Option.Some(cloudProxy)), routingMessageConverter);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.True(sinkResult.Succeeded.Contains(routingMessage));
        }
Exemplo n.º 24
0
        public async Task TransientErrorOfFirstIdentity_DoesNotFastFailsSecondIdentity_ButReportsError()
        {
            var batchSize = 10;

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            // this wont fast fail
            var cloudProxy1 = ThrowingCloudProxy
                              .Create()
                              .WithBatchSize(batchSize)
                              .WithReportSuccessfulBatch(3)
                              .Build();

            // this will fast fail after a batch (skipping the second and the third)
            var cloudProxy2 = ThrowingCloudProxy
                              .Create()
                              .WithBatchSize(batchSize)
                              .WithReportSuccessfulBatch()
                              .WithReportErrorInBatch(ThrowingCloudProxy.Throw <Client.Exceptions.IotHubException>())
                              .WithReportSuccessfulBatch()
                              .Build();

            var proxyMap = new Dictionary <string, ICloudProxy> {
                ["device1"] = cloudProxy1, ["device2"] = cloudProxy2
            };

            Task <Option <ICloudProxy> > GetCloudProxy(string id) => Task.FromResult(Option.Some(proxyMap[id]));

            var cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            var cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            var random     = new Random(35325);
            var messages   = GetMessages("device1", 3 * batchSize).Concat(GetMessages("device2", 3 * batchSize)).OrderBy(order => random.Next()).ToList();
            var sinkResult = await cloudMessageProcessor.ProcessAsync(messages, CancellationToken.None);

            Assert.False(sinkResult.IsSuccessful);                                   // one batch went wrong, should report here
            Assert.Equal(3 * batchSize + 1 * batchSize, sinkResult.Succeeded.Count); // dev1 all good, dev2 1st good
            Assert.Equal(2 * batchSize, sinkResult.Failed.Count);
            Assert.Equal(0, sinkResult.InvalidDetailsList.Count);
            Assert.True(sinkResult.SendFailureDetails.HasValue);
            Assert.Equal(FailureKind.Transient, sinkResult.SendFailureDetails.Expect(() => new Exception()).FailureKind);
        }
Exemplo n.º 25
0
        public void TestToMessageCases(IRoutingMessage routingMessage)
        {
            Core.IMessageConverter <IRoutingMessage> messageConverter = new RoutingMessageConverter();
            IMessage message = messageConverter.ToMessage(routingMessage);

            Assert.Equal(routingMessage.Body, message.Body);
            Assert.Equal(routingMessage.Properties.Count, message.Properties.Count);
            foreach (KeyValuePair <string, string> property in routingMessage.Properties)
            {
                Assert.True(message.Properties.ContainsKey(property.Key));
                Assert.Equal(property.Value, message.Properties[property.Key]);
            }

            Assert.Equal(routingMessage.SystemProperties.Count, message.SystemProperties.Count);
            foreach (KeyValuePair <string, string> property in routingMessage.SystemProperties)
            {
                Assert.True(message.SystemProperties.ContainsKey(property.Key));
                Assert.Equal(property.Value, message.SystemProperties[property.Key]);
            }
        }
Exemplo n.º 26
0
        public async Task Events_DeviceIdNotFoundTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            var    routingMessage  = Mock.Of <IRoutingMessage>();
            string cloudEndpointId = Guid.NewGuid().ToString();

            Mock.Get(routingMessage).Setup(rm => rm.SystemProperties).Returns(new Dictionary <string, string> {
                { "messageId", "myConnectionDeviceId" }
            });
            var cloudProxy    = Mock.Of <ICloudProxy>();
            var cloudEndpoint = new CloudEndpoint(cloudEndpointId, id => Task.FromResult(Try.Success(cloudProxy)), routingMessageConverter, trackDeviceState: false);

            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(routingMessage, CancellationToken.None);

            Assert.Equal(FailureKind.InvalidInput, sinkResult.SendFailureDetails.OrDefault().FailureKind);
            Assert.Equal(typeof(InvalidOperationException), sinkResult.SendFailureDetails.OrDefault().RawException.GetType());
            Assert.Equal(1, sinkResult.InvalidDetailsList.Count);
            Assert.Equal(0, sinkResult.Failed.Count);
            Assert.Equal(0, sinkResult.Succeeded.Count);
        }
Exemplo n.º 27
0
        public async Task ProcessAsyncTest()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxyMock = new Mock <ICloudProxy>();

            cloudProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .Callback <IMessage>(
                msg =>
            {
                if (msg.Properties.ContainsKey("Delay"))
                {
                    Task.Delay(TimeSpan.FromSeconds(10)).Wait();
                }
            })
            .Returns(Task.CompletedTask);
            cloudProxyMock.SetupGet(p => p.IsActive).Returns(true);

            string device1Id = "device1";
            string device2Id = "device2";

            byte[] messageBody = Encoding.UTF8.GetBytes("Message body");
            var    properties  = new Dictionary <string, string>()
            {
                { "Prop1", "Val1" },
                { "Prop2", "Val2" }
            };

            var device1SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device1Id }
            };

            var device2SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device2Id }
            };

            var cancelProperties = new Dictionary <string, string>()
            {
                { "Delay", "true" },
                { "Prop2", "Val2" }
            };

            var message1 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device1SystemProperties);
            var message2 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device2SystemProperties);
            var message3 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, cancelProperties, device1SystemProperties);

            Task <Option <ICloudProxy> > GetCloudProxy(string id)
            {
                return(Task.FromResult(
                           id.Equals(device1Id)
                        ? Option.Some(cloudProxyMock.Object)
                        : Option.None <ICloudProxy>()));
            }

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, maxBatchSize: 1);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            ISinkResult <IRoutingMessage> result1 = await cloudMessageProcessor.ProcessAsync(message1, CancellationToken.None);

            Assert.NotNull(result1);
            Assert.NotEmpty(result1.Succeeded);
            Assert.Empty(result1.Failed);
            Assert.Empty(result1.InvalidDetailsList);
            Assert.False(result1.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> result2 = await cloudMessageProcessor.ProcessAsync(message2, CancellationToken.None);

            Assert.NotNull(result2);
            Assert.Empty(result2.InvalidDetailsList);
            Assert.NotEmpty(result2.Failed);
            Assert.Empty(result2.Succeeded);
            Assert.True(result2.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatch = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(resultBatch);
            Assert.Equal(1, resultBatch.Succeeded.Count);
            Assert.Equal(1, resultBatch.Failed.Count);
            Assert.Empty(resultBatch.InvalidDetailsList);
            Assert.True(resultBatch.SendFailureDetails.HasValue);

            ISinkResult <IRoutingMessage> resultBatchCancelled = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, new CancellationToken(true));

            Assert.NotNull(resultBatchCancelled);
            Assert.Empty(resultBatchCancelled.Succeeded);
            Assert.NotEmpty(resultBatchCancelled.Failed);
            Assert.Empty(resultBatchCancelled.InvalidDetailsList);
            Assert.True(resultBatchCancelled.SendFailureDetails.HasValue);

            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
            ISinkResult <IRoutingMessage> resultBatchCancelled2 = await cloudMessageProcessor.ProcessAsync(new[] { message1, message3, message1 }, cts.Token);

            Assert.NotNull(resultBatchCancelled2);
            Assert.Equal(2, resultBatchCancelled2.Succeeded.Count);
            Assert.Equal(1, resultBatchCancelled2.Failed.Count);
            Assert.Empty(resultBatchCancelled2.InvalidDetailsList);
            Assert.True(resultBatchCancelled2.SendFailureDetails.HasValue);
        }
Exemplo n.º 28
0
        public async Task ProcessInBatchesWithBatchSizeTest()
        {
            // Arrange
            string device1 = "d1";
            string device2 = "d2";
            string device3 = "d3";

            IList <IRoutingMessage> device1Messages = GetMessages(device1, 45);
            IList <IRoutingMessage> device2Messages = GetMessages(device2, 25);
            IList <IRoutingMessage> device3Messages = GetMessages(device3, 30);

            IList <IRoutingMessage> messagesToProcess = device1Messages
                                                        .Concat(device2Messages)
                                                        .Concat(device3Messages)
                                                        .ToList();

            Mock <ICloudProxy> InitCloudProxy(List <int> receivedMsgCountList)
            {
                var cp = new Mock <ICloudProxy>();

                cp.Setup(c => c.SendMessageBatchAsync(It.IsAny <IEnumerable <IMessage> >()))
                .Callback <IEnumerable <IMessage> >(b => receivedMsgCountList.Add(b.Count()))
                .Returns(Task.CompletedTask);
                cp.SetupGet(p => p.IsActive).Returns(true);
                return(cp);
            }

            var device1CloudReceivedMessagesCountList = new List <int>();
            Mock <ICloudProxy> device1CloudProxy      = InitCloudProxy(device1CloudReceivedMessagesCountList);

            var device2CloudReceivedMessagesCountList = new List <int>();
            Mock <ICloudProxy> device2CloudProxy      = InitCloudProxy(device2CloudReceivedMessagesCountList);

            var device3CloudReceivedMessagesCountList = new List <int>();
            Mock <ICloudProxy> device3CloudProxy      = InitCloudProxy(device3CloudReceivedMessagesCountList);

            Task <Option <ICloudProxy> > GetCloudProxy(string id)
            {
                ICloudProxy cp = null;

                if (id == device1)
                {
                    cp = device1CloudProxy.Object;
                }
                else if (id == device2)
                {
                    cp = device2CloudProxy.Object;
                }
                else if (id == device3)
                {
                    cp = device3CloudProxy.Object;
                }

                return(Task.FromResult(Option.Maybe(cp)));
            }

            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();
            var    cloudEndpoint   = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter, 30);

            // Act
            IProcessor cloudMessageProcessor         = cloudEndpoint.CreateProcessor();
            ISinkResult <IRoutingMessage> sinkResult = await cloudMessageProcessor.ProcessAsync(messagesToProcess, CancellationToken.None);

            // Assert
            Assert.Equal(messagesToProcess, sinkResult.Succeeded);
            Assert.Equal(device1CloudReceivedMessagesCountList, new[] { 30, 15 });
            Assert.Equal(device2CloudReceivedMessagesCountList, new[] { 25 });
            Assert.Equal(device3CloudReceivedMessagesCountList, new[] { 30 });
        }
Exemplo n.º 29
0
 public void TestToMessageErrorCases(IRoutingMessage inputMessage, Type exceptionType)
 {
     Core.IMessageConverter <IRoutingMessage> messageConverter = new RoutingMessageConverter();
     Assert.Throws(exceptionType, () => messageConverter.ToMessage(inputMessage));
 }
Exemplo n.º 30
0
        public async Task ProcessAsync_SendThrows_Test()
        {
            Core.IMessageConverter <IRoutingMessage> routingMessageConverter = new RoutingMessageConverter();
            string cloudEndpointId = Guid.NewGuid().ToString();

            var cloudProxyMock = new Mock <ICloudProxy>();

            cloudProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .Throws <TimeoutException>();
            cloudProxyMock.SetupGet(p => p.IsActive).Returns(true);

            string device1Id = "device1";
            string device2Id = "device2";

            byte[] messageBody = Encoding.UTF8.GetBytes("Message body");
            var    properties  = new Dictionary <string, string>()
            {
                { "Prop1", "Val1" },
                { "Prop2", "Val2" }
            };

            var device1SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device1Id }
            };

            var device2SystemProperties = new Dictionary <string, string>
            {
                { SystemProperties.DeviceId, device2Id }
            };

            var message1 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device1SystemProperties);
            var message2 = new RoutingMessage(TelemetryMessageSource.Instance, messageBody, properties, device2SystemProperties);

            Task <Option <ICloudProxy> > GetCloudProxy(string id)
            {
                return(Task.FromResult(Option.Some(cloudProxyMock.Object)));
            }

            var        cloudEndpoint         = new CloudEndpoint(cloudEndpointId, GetCloudProxy, routingMessageConverter);
            IProcessor cloudMessageProcessor = cloudEndpoint.CreateProcessor();

            ISinkResult <IRoutingMessage> result = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(result);
            Assert.Empty(result.Succeeded);
            Assert.Equal(2, result.Failed.Count);
            Assert.Empty(result.InvalidDetailsList);
            Assert.True(result.SendFailureDetails.HasValue);

            // throw non-retryable
            cloudProxyMock.Setup(c => c.SendMessageAsync(It.IsAny <IMessage>()))
            .Throws <Exception>();

            ISinkResult <IRoutingMessage> result1 = await cloudMessageProcessor.ProcessAsync(new[] { message1, message2 }, CancellationToken.None);

            Assert.NotNull(result1);
            Assert.Empty(result1.Succeeded);
            Assert.Empty(result1.Failed);
            Assert.Equal(2, result1.InvalidDetailsList.Count);
            Assert.True(result1.SendFailureDetails.HasValue);
        }