Inheritance: IConfigurationManager
        public void DefaultKeepAliveThrowsWhenNegative()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = -1);
        }
        public void KeepAliveThrowsWhenZero()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(0));
        }
        public void DefaultValues()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Equal(config.ConnectionTimeout.TotalSeconds, 110);
            Assert.Equal(config.DisconnectTimeout.TotalSeconds, 40);
            Assert.Equal(config.HeartbeatInterval.TotalSeconds, 10);
            Assert.Equal(config.KeepAlive, 2);
        }
        public void DefaultValues()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Equal(110, config.ConnectionTimeout.TotalSeconds);
            Assert.Equal(30, config.DisconnectTimeout.TotalSeconds);
            Assert.Equal(10, config.KeepAlive.Value.TotalSeconds);
            Assert.Equal(20, config.KeepAliveTimeout().Value.TotalSeconds);
            Assert.Equal(5, config.HeartbeatInterval().TotalSeconds);
            Assert.Equal(100, config.TopicTtl().TotalSeconds);
        }
        public void TwoSecondsAndNullOnlyValidKeepAliveValuesWhenDisconnectTimeoutIsSixSeconds()
        {
            // Arrange
            var config = new DefaultConfigurationManager();
            config.DisconnectTimeout = TimeSpan.FromSeconds(6);

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(1.99));
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(2.01));

            // Assert doesn't throw
            config.KeepAlive = TimeSpan.FromSeconds(2);
            config.KeepAlive = null;
        }
Example #6
0
        public async Task FarmDisconnectRaisesUncleanDisconnects()
        {
            // Each node shares the same bus but are independent servers
            const int nodeCount = 3;
            var counters = new Infrastructure.PerformanceCounterManager();
            var configurationManager = new DefaultConfigurationManager();
            configurationManager.DisconnectTimeout = TimeSpan.FromSeconds(6);

            using (EnableDisposableTracing())
            using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000))
            using (var loadBalancer = new LoadBalancer(nodeCount))
            {
                var broadcasters = new List<IConnection>();
                var disconnectCounter = new DisconnectCounter();
                loadBalancer.Configure(app =>
                {
                    var resolver = new DefaultDependencyResolver();

                    resolver.Register(typeof(IMessageBus), () => bus);
                    resolver.Register(typeof(IConfigurationManager), () => configurationManager);
                    resolver.Register(typeof(FarmConnection), () => new FarmConnection(disconnectCounter));

                    var connectionManager = resolver.Resolve<IConnectionManager>();
                    broadcasters.Add(connectionManager.GetConnectionContext<FarmConnection>().Connection);

                    app.MapSignalR<FarmConnection>("/echo", new ConnectionConfiguration
                    {
                        Resolver = resolver
                    });
                });

                var transport = new Client.Transports.LongPollingTransport(loadBalancer);
                var connection = new Client.Connection("http://goo/echo");

                await connection.Start(transport);

                for (int i = 0; i < nodeCount; i++)
                {
                    broadcasters[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1)).Wait();
                    await Task.Delay(TimeSpan.FromSeconds(1));
                }

                ((Client.IConnection)connection).Disconnect();

                await Task.Delay(TimeSpan.FromTicks(TimeSpan.FromSeconds(5).Ticks * nodeCount));

                Assert.Equal(0, disconnectCounter.CleanDisconnectCount);
                Assert.Equal(3, disconnectCounter.UncleanDisconnectCount);
            }
        }
        public void KeepAliveThrowsWhenGreaterThanAThirdOfTheDisconnectTimeout()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(10.01));
            config.KeepAlive = TimeSpan.FromSeconds(10);

            // Arrange
            config = new DefaultConfigurationManager();
            config.DisconnectTimeout = TimeSpan.FromSeconds(15);

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(5.01));
            config.KeepAlive = TimeSpan.FromSeconds(5);
        }
        public void TopicTopicTimeToLiveIsDoubleTheDisconnectTimeoutWhenKeepAliveIsNull()
        {
            var config = new DefaultConfigurationManager();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(6, 31536000)); // 12 seconds to a year
            config.KeepAlive = null;

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks * 2), config.TopicTtl());
        }
        public void HeartbeatIntervalIsHalfTheKeepAlive()
        {
            // Arrange
            var config = new DefaultConfigurationManager();
            var random = new Random();
            config.KeepAlive = TimeSpan.FromSeconds(random.NextDouble() * 8 + 2); // 2 to 10 seconds

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.KeepAlive.Value.Ticks / 2), config.HeartbeatInterval());
        }
        public void KeepAliveTimeoutIsTwiceTheKeepAlive()
        {
            // Arrange
            var config = new DefaultConfigurationManager();
            var random = new Random();
            config.KeepAlive = TimeSpan.FromSeconds(random.NextDouble() * 8 + 2); // 2 to 10 seconds

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.KeepAlive.Value.Ticks * 2), config.KeepAliveTimeout());

            // Arrange
            config.KeepAlive = null;

            // Assert
            Assert.Equal(null, config.KeepAliveTimeout());
        }
        public void KeepAliveCannotBeConfiguredBeforeDisconnectTimeout()
        {
            // Arrange
            var config = new DefaultConfigurationManager();
            config.KeepAlive = TimeSpan.FromSeconds(5);

            // Assert
            Assert.Throws(typeof(InvalidOperationException), () => config.DisconnectTimeout = TimeSpan.FromSeconds(40));

            // Arrange
            config = new DefaultConfigurationManager();
            config.KeepAlive = null;

            // Assert
            Assert.Throws(typeof(InvalidOperationException), () => config.DisconnectTimeout = TimeSpan.FromSeconds(40));
        }
        public void SettingDisconnectTimeoutSetKeepAliveToAThirdOfItself()
        {
            // Arrange
            var config = new DefaultConfigurationManager();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(6, 31536000)); // 6 seconds to a year

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / 3), config.KeepAlive);
        }
        public void DisconnectTimeoutThrowsWhenLessThanSixSeconds()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.DisconnectTimeout = TimeSpan.FromSeconds(5.99));
            config.DisconnectTimeout = TimeSpan.FromSeconds(6);
        }
Example #14
0
        public async Task FarmDisconnectOnlyRaisesUncleanDisconnects()
        {
            EnableTracing();

            // Each node shares the same bus but are indepenent servers
            var counters = new SignalR.Infrastructure.PerformanceCounterManager();
            var configurationManager = new DefaultConfigurationManager();
            var protectedData = new DefaultProtectedData();
            using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000))
            {
                var nodeCount = 3;
                var nodes = new List<ServerNode>();
                for (int i = 0; i < nodeCount; i++)
                {
                    nodes.Add(new ServerNode(bus));
                }

                var timeout = TimeSpan.FromSeconds(5);
                foreach (var node in nodes)
                {
                    var config = node.Resolver.Resolve<IConfigurationManager>();
                    config.DisconnectTimeout = TimeSpan.FromSeconds(6);

                    IDependencyResolver resolver = node.Resolver;
                    node.Server.Configure(app =>
                    {
                        app.MapSignalR<FarmConnection>("/echo", new ConnectionConfiguration
                        {
                            Resolver = resolver
                        });

                        resolver.Register(typeof(IProtectedData), () => protectedData);
                    });
                }

                var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray());
                var transport = new Client.Transports.LongPollingTransport(loadBalancer);

                var connection = new Client.Connection("http://goo/echo");

                await connection.Start(transport);

                for (int i = 0; i < nodes.Count; i++)
                {
                    nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1));
                    await Task.Delay(TimeSpan.FromSeconds(1));
                }

                ((Client.IConnection)connection).Disconnect();

                await Task.Delay(TimeSpan.FromTicks(timeout.Ticks * nodes.Count));

                Assert.Equal(0, FarmConnection.OldOnDisconnectedCalls);
                Assert.Equal(0, FarmConnection.CleanDisconnectCount);
                Assert.Equal(3, FarmConnection.UncleanDisconnectCount);
            }
        }
Example #15
0
        public void FarmDisconnectOnlyRaisesEventOnce()
        {
            // Each node shares the same bus but are indepenent servers
            var counters = new SignalR.Infrastructure.PerformanceCounterManager();
            var configurationManager = new DefaultConfigurationManager();
            using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000))
            {
                var nodeCount = 3;
                var nodes = new List<ServerNode>();
                for (int i = 0; i < nodeCount; i++)
                {
                    nodes.Add(new ServerNode(bus));
                }

                var timeout = TimeSpan.FromSeconds(5);
                foreach (var node in nodes)
                {
                    var config = node.Resolver.Resolve<IConfigurationManager>();
                    config.DisconnectTimeout = TimeSpan.FromSeconds(6);

                    IDependencyResolver resolver = node.Resolver;
                    node.Server.Configure(app =>
                    {
                        app.MapConnection<FarmConnection>("/echo", new ConnectionConfiguration
                        {
                            Resolver = resolver
                        });
                    });
                }

                var loadBalancer = new LoadBalancer(nodes.Select(f => f.Server).ToArray());
                var transport = new Client.Transports.LongPollingTransport(loadBalancer);

                var connection = new Client.Connection("http://goo/echo");

                connection.Start(transport).Wait();

                for (int i = 0; i < nodes.Count; i++)
                {
                    nodes[i].Broadcast(String.Format("From Node {0}: {1}", i, i + 1));
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }

                connection.Disconnect();

                Thread.Sleep(TimeSpan.FromTicks(timeout.Ticks * nodes.Count));

                Assert.Equal(1, nodes.Sum(n => n.Connection.DisconnectCount));
            }
        }
        public void DisconnectTimeoutThrowsWhenNegative()
        {
            // Arrange
            var config = new DefaultConfigurationManager();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(-1));
        }
Example #17
0
        public async Task ContextGroupAddCompletesSuccessfully()
        {
            // https://github.com/SignalR/SignalR/issues/3337
            // Each node shares the same bus but are independent servers
            var counters = new Infrastructure.PerformanceCounterManager();
            var configurationManager = new DefaultConfigurationManager();

            using (EnableDisposableTracing())
            using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000))
            using (var memoryHost = new MemoryHost())
            {
                memoryHost.Configure(app =>
                {
                    var resolver = new DefaultDependencyResolver();
                    resolver.Register(typeof(IMessageBus), () => bus);
                    app.MapSignalR(new HubConfiguration { Resolver = resolver });
                });

                using (var connection = new HubConnection("http://goo/"))
                {
                    var proxy = connection.CreateHubProxy("FarmGroupHub");

                    const string group = "group";
                    const string message = "message";

                    var mre = new AsyncManualResetEvent();
                    proxy.On<string>("message", m =>
                    {
                        if (m == message)
                        {
                            mre.Set();
                        }
                    });

                    await connection.Start(memoryHost);

                    // Add the connection to a group via an IHubContext on a "second" server.
                    var secondResolver = new DefaultDependencyResolver();
                    secondResolver.Register(typeof(IMessageBus), () => bus);
                    var secondConnectionManager = secondResolver.Resolve<IConnectionManager>();
                    var secondHubContext = secondConnectionManager.GetHubContext<FarmGroupHub>();
                    await secondHubContext.Groups.Add(connection.ConnectionId, group);
                    await proxy.Invoke("SendToGroup", group, message);

                    Assert.True(await mre.WaitAsync(TimeSpan.FromSeconds(5)));
                }
            }
        }
        public void HeartbeatIntervalIsASixthOfTheDisconnectTimeoutIfTheKeepAliveIsNull()
        {
            // Arrange
            var config = new DefaultConfigurationManager();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(6, 31536000)); // 6 seconds to a year
            config.KeepAlive = null;

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / 6), config.HeartbeatInterval());
        }
Example #19
0
        public async Task FarmGroupAddCompletesSuccessfully(TransportType transportType)
        {
            // https://github.com/SignalR/SignalR/issues/3337
            // Each node shares the same bus but are independent servers
            const int nodeCount = 2;
            var counters = new Infrastructure.PerformanceCounterManager();
            var configurationManager = new DefaultConfigurationManager();

            // Ensure /send and /connect requests get handled by different servers
            Func<string, int> scheduler = url => url.Contains("/send") ? 0 : 1;

            using (EnableDisposableTracing())
            using (var bus = new MessageBus(new StringMinifier(), new TraceManager(), counters, configurationManager, 5000))
            using (var loadBalancer = new LoadBalancer(nodeCount, scheduler))
            {
                loadBalancer.Configure(app =>
                {
                    var resolver = new DefaultDependencyResolver();
                    resolver.Register(typeof(IMessageBus), () => bus);
                    app.MapSignalR(new HubConfiguration { Resolver = resolver });
                });

                using (var connection = new HubConnection("http://goo/"))
                {
                    var proxy = connection.CreateHubProxy("FarmGroupHub");

                    const string group = "group";
                    const string message = "message";

                    var mre = new AsyncManualResetEvent();
                    proxy.On<string>("message", m =>
                    {
                        if (m == message)
                        {
                            mre.Set();
                        }
                    });

                    Client.Transports.IClientTransport transport;

                    switch (transportType)
                    {
                        case TransportType.LongPolling:
                            transport = new Client.Transports.LongPollingTransport(loadBalancer);
                            break;
                        case TransportType.ServerSentEvents:
                            transport = new Client.Transports.ServerSentEventsTransport(loadBalancer);
                            break;
                        default:
                            throw new ArgumentException("transportType");
                    }

                    await connection.Start(transport);

                    await proxy.Invoke("JoinGroup", group);
                    await proxy.Invoke("SendToGroup", group, message);

                    Assert.True(await mre.WaitAsync(TimeSpan.FromSeconds(5)));
                }
            }
        }
        public void TopicTimeToLiveIsDoubleTheDisconnectAndKeepAliveTimeouts()
        {
            var config = new DefaultConfigurationManager();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(12, 31536000)); // 12 seconds to a year
            config.KeepAlive = TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / 6); // Set custom keep-alive to half the default

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks * 2 + config.KeepAliveTimeout().Value.Ticks * 2),
                         config.TopicTtl());
        }