public void GlobalSetup()
    {
        var serviceCollection = new ServiceCollection();

        serviceCollection.AddSignalRCore();

        var provider = serviceCollection.BuildServiceProvider();

        var serviceScopeFactory = provider.GetService <IServiceScopeFactory>();

        var hubLifetimeManager = new DefaultHubLifetimeManager <TestHub>(NullLogger <DefaultHubLifetimeManager <TestHub> > .Instance);

        _dispatcher = new DefaultHubDispatcher <TestHub>(
            serviceScopeFactory,
            new HubContext <TestHub>(hubLifetimeManager),
            enableDetailedErrors: false,
            disableImplicitFromServiceParameters: true,
            new Logger <DefaultHubDispatcher <TestHub> >(NullLoggerFactory.Instance),
            hubFilters: null,
            hubLifetimeManager);

        var pair       = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
        var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);

        var contextOptions = new HubConnectionContextOptions()
        {
            KeepAliveInterval    = TimeSpan.Zero,
            StreamBufferCapacity = 10,
        };

        _connectionContext = new NoErrorHubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);

        _connectionContext.Protocol = new FakeHubProtocol();
    }
Exemplo n.º 2
0
    /// <inheritdoc />
    public override Task SendGroupsAsync(IReadOnlyList <string> groupNames, string methodName, object?[] args, CancellationToken cancellationToken = default)
    {
        // Each task represents the list of tasks for each of the writes within a group
        List <Task>?         tasks   = null;
        SerializedHubMessage?message = null;

        foreach (var groupName in groupNames)
        {
            if (string.IsNullOrEmpty(groupName))
            {
                throw new InvalidOperationException("Cannot send to an empty group name.");
            }

            var group = _groups[groupName];
            if (group != null)
            {
                DefaultHubLifetimeManager <THub> .SendToGroupConnections(methodName, args, group, null, null, ref tasks, ref message, cancellationToken);
            }
        }

        if (tasks != null)
        {
            return(Task.WhenAll(tasks));
        }

        return(Task.CompletedTask);
    }
        public async Task InvokeGroupAsyncWritesToAllConnectionsInGroupOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var output1 = Channel.CreateUnbounded <HubMessage>();
                    var output2 = Channel.CreateUnbounded <HubMessage>();

                    var manager     = new DefaultHubLifetimeManager <MyHub>();
                    var connection1 = new HubConnectionContext(output1, client1.Connection);
                    var connection2 = new HubConnectionContext(output2, client2.Connection);

                    await manager.OnConnectedAsync(connection1);

                    await manager.OnConnectedAsync(connection2);

                    await manager.AddGroupAsync(connection1.ConnectionId, "gunit");

                    await manager.InvokeGroupAsync("gunit", "Hello", new object[] { "World" });

                    Assert.True(output1.In.TryRead(out var item));
                    var message = item as InvocationMessage;
                    Assert.NotNull(message);
                    Assert.Equal("Hello", message.Target);
                    Assert.Single(message.Arguments);
                    Assert.Equal("World", (string)message.Arguments[0]);

                    Assert.False(output2.In.TryRead(out item));
                }
        }
        public async Task InvokeAllAsyncDoesNotWriteToDisconnectedConnectionsOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var output1 = Channel.CreateUnbounded <HubMessage>();
                    var output2 = Channel.CreateUnbounded <HubMessage>();

                    var manager     = new DefaultHubLifetimeManager <MyHub>();
                    var connection1 = new HubConnectionContext(output1, client1.Connection);
                    var connection2 = new HubConnectionContext(output2, client2.Connection);

                    await manager.OnConnectedAsync(connection1).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.OnDisconnectedAsync(connection2).OrTimeout();

                    await manager.InvokeAllAsync("Hello", new object[] { "World" }).OrTimeout();

                    Assert.True(output1.Reader.TryRead(out var item));
                    var message = Assert.IsType <InvocationMessage>(item);
                    Assert.Equal("Hello", message.Target);
                    Assert.Single(message.Arguments);
                    Assert.Equal("World", (string)message.Arguments[0]);

                    Assert.False(output2.Reader.TryRead(out item));
                }
        }
Exemplo n.º 5
0
    // Tasks and message are passed by ref so they can be lazily created inside the method post-filtering,
    // while still being re-usable when sending to multiple groups
    private static void SendToGroupConnections(string methodName, object?[] args, ConcurrentDictionary <string, HubConnectionContext> connections, Func <HubConnectionContext, object?, bool>?include, object?state, ref List <Task>?tasks, ref SerializedHubMessage?message, CancellationToken cancellationToken)
    {
        // foreach over ConcurrentDictionary avoids allocating an enumerator
        foreach (var connection in connections)
        {
            if (include != null && !include(connection.Value, state))
            {
                continue;
            }

            if (message == null)
            {
                message = DefaultHubLifetimeManager <THub> .CreateSerializedInvocationMessage(methodName, args);
            }

            var task = connection.Value.WriteAsync(message, cancellationToken);

            if (!task.IsCompletedSuccessfully)
            {
                if (tasks == null)
                {
                    tasks = new List <Task>();
                }

                tasks.Add(task.AsTask());
            }
            else
            {
                // If it's a IValueTaskSource backed ValueTask,
                // inform it its result has been read so it can reset
                task.GetAwaiter().GetResult();
            }
        }
    }
Exemplo n.º 6
0
    /// <inheritdoc />
    public override Task SendGroupAsync(string groupName, string methodName, object?[] args, CancellationToken cancellationToken = default)
    {
        if (groupName == null)
        {
            throw new ArgumentNullException(nameof(groupName));
        }

        var group = _groups[groupName];

        if (group != null)
        {
            // Can't optimize for sending to a single connection in a group because
            // group might be modified inbetween checking and sending
            List <Task>?         tasks   = null;
            SerializedHubMessage?message = null;
            DefaultHubLifetimeManager <THub> .SendToGroupConnections(methodName, args, group, null, null, ref tasks, ref message, cancellationToken);

            if (tasks != null)
            {
                return(Task.WhenAll(tasks));
            }
        }

        return(Task.CompletedTask);
    }
Exemplo n.º 7
0
        public async Task SendAllAsyncSendsToAllConnectionsEvenWhenSomeFailToSend()
        {
            using (var client = new TestClient())
                using (var client2 = new TestClient())
                {
                    var manager = new DefaultHubLifetimeManager <MyHub>(new Logger <DefaultHubLifetimeManager <MyHub> >(NullLoggerFactory.Instance));

                    var connectionMock  = HubConnectionContextUtils.CreateMock(client.Connection);
                    var connectionMock2 = HubConnectionContextUtils.CreateMock(client2.Connection);

                    var tcs  = new TaskCompletionSource <object>();
                    var tcs2 = new TaskCompletionSource <object>();
                    // Force an exception when writing to connection
                    connectionMock.Setup(m => m.WriteAsync(It.IsAny <HubMessage>())).Callback(() => tcs.TrySetResult(null)).Throws(new Exception("Message"));
                    connectionMock2.Setup(m => m.WriteAsync(It.IsAny <HubMessage>())).Callback(() => tcs2.TrySetResult(null)).Throws(new Exception("Message"));
                    var connection  = connectionMock.Object;
                    var connection2 = connectionMock2.Object;

                    await manager.OnConnectedAsync(connection).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.SendAllAsync("Hello", new object[] { "World" }).OrTimeout();

                    // Check that all connections were "written" to
                    await tcs.Task.OrTimeout();

                    await tcs2.Task.OrTimeout();
                }
        }
Exemplo n.º 8
0
        public void GlobalSetup()
        {
            _hubLifetimeManager = new DefaultHubLifetimeManager <Hub>(NullLogger <DefaultHubLifetimeManager <Hub> > .Instance);


            IHubProtocol protocol;

            if (Protocol == "json")
            {
                protocol = new JsonHubProtocol();
            }
            else
            {
                protocol = new MessagePackHubProtocol();
            }

            for (var i = 0; i < Connections; ++i)
            {
                var pair          = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
                var connection    = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
                var hubConnection = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
                hubConnection.Protocol = protocol;
                _hubLifetimeManager.OnConnectedAsync(hubConnection).Wait();
            }

            _hubContext = new HubContext <Hub>(_hubLifetimeManager);
        }
        public async Task InvokeAllAsyncDoesNotWriteToDisconnectedConnectionsOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var manager     = new DefaultHubLifetimeManager <MyHub>();
                    var connection1 = HubConnectionContextUtils.Create(client1.Connection);
                    var connection2 = HubConnectionContextUtils.Create(client2.Connection);

                    await manager.OnConnectedAsync(connection1).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.OnDisconnectedAsync(connection2).OrTimeout();

                    await manager.SendAllAsync("Hello", new object[] { "World" }).OrTimeout();

                    var message = Assert.IsType <InvocationMessage>(client1.TryRead());
                    Assert.Equal("Hello", message.Target);
                    Assert.Single(message.Arguments);
                    Assert.Equal("World", (string)message.Arguments[0]);

                    Assert.Null(client2.TryRead());
                }
        }
Exemplo n.º 10
0
        public async Task SendGroupAsyncWritesToAllConnectionsInGroupOutput()
        {
            using (var client1 = new TestClient())
                using (var client2 = new TestClient())
                {
                    var manager     = new DefaultHubLifetimeManager <MyHub>(new Logger <DefaultHubLifetimeManager <MyHub> >(NullLoggerFactory.Instance));
                    var connection1 = HubConnectionContextUtils.Create(client1.Connection);
                    var connection2 = HubConnectionContextUtils.Create(client2.Connection);

                    await manager.OnConnectedAsync(connection1).OrTimeout();

                    await manager.OnConnectedAsync(connection2).OrTimeout();

                    await manager.AddGroupAsync(connection1.ConnectionId, "gunit").OrTimeout();

                    await manager.SendGroupAsync("gunit", "Hello", new object[] { "World" }).OrTimeout();

                    var message = Assert.IsType <InvocationMessage>(client1.TryRead());
                    Assert.Equal("Hello", message.Target);
                    Assert.Single(message.Arguments);
                    Assert.Equal("World", (string)message.Arguments[0]);

                    Assert.Null(client2.TryRead());
                }
        }
Exemplo n.º 11
0
        public void GlobalSetup()
        {
            _hubLifetimeManager = new DefaultHubLifetimeManager <Hub>(NullLogger <DefaultHubLifetimeManager <Hub> > .Instance);

            IHubProtocol protocol;

            if (Protocol == "json")
            {
                protocol = new NewtonsoftJsonHubProtocol();
            }
            else
            {
                protocol = new MessagePackHubProtocol();
            }

            var options = new PipeOptions();

            for (var i = 0; i < Connections; ++i)
            {
                var pair          = DuplexPipe.CreateConnectionPair(options, options);
                var connection    = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
                var hubConnection = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
                hubConnection.Protocol = protocol;
                _hubLifetimeManager.OnConnectedAsync(hubConnection).GetAwaiter().GetResult();
                _hubLifetimeManager.AddToGroupAsync(connection.ConnectionId, TestGroupName).GetAwaiter().GetResult();

                _ = ConsumeAsync(connection.Application);
            }

            _hubContext = new HubContext <Hub>(_hubLifetimeManager);
        }
Exemplo n.º 12
0
        public async Task SendConnectionAsyncDoesNotThrowIfConnectionFailsToWrite()
        {
            using (var client = new TestClient())
            {
                var manager = new DefaultHubLifetimeManager <MyHub>(new Logger <DefaultHubLifetimeManager <MyHub> >(NullLoggerFactory.Instance));

                var connectionMock = HubConnectionContextUtils.CreateMock(client.Connection);
                // Force an exception when writing to connection
                connectionMock.Setup(m => m.WriteAsync(It.IsAny <HubMessage>())).Throws(new Exception("Message"));
                var connection = connectionMock.Object;

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.SendConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();
            }
        }
        public async Task InvokeConnectionAsyncWritesToConnectionOutput()
        {
            using (var client = new TestClient())
            {
                var manager    = new DefaultHubLifetimeManager <MyHub>();
                var connection = HubConnectionContextUtils.Create(client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.SendConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();

                var message = Assert.IsType <InvocationMessage>(client.TryRead());
                Assert.Equal("Hello", message.Target);
                Assert.Single(message.Arguments);
                Assert.Equal("World", (string)message.Arguments[0]);
            }
        }
Exemplo n.º 14
0
    private Task SendToAllConnections(string methodName, object?[] args, Func <HubConnectionContext, object?, bool>?include, object?state = null, CancellationToken cancellationToken = default)
    {
        List <Task>?         tasks   = null;
        SerializedHubMessage?message = null;

        // foreach over HubConnectionStore avoids allocating an enumerator
        foreach (var connection in _connections)
        {
            if (include != null && !include(connection, state))
            {
                continue;
            }

            if (message == null)
            {
                message = DefaultHubLifetimeManager <THub> .CreateSerializedInvocationMessage(methodName, args);
            }

            var task = connection.WriteAsync(message, cancellationToken);

            if (!task.IsCompletedSuccessfully)
            {
                if (tasks == null)
                {
                    tasks = new List <Task>();
                }

                tasks.Add(task.AsTask());
            }
            else
            {
                // If it's a IValueTaskSource backed ValueTask,
                // inform it its result has been read so it can reset
                task.GetAwaiter().GetResult();
            }
        }

        if (tasks == null)
        {
            return(Task.CompletedTask);
        }

        // Some connections are slow
        return(Task.WhenAll(tasks));
    }
Exemplo n.º 15
0
        public async Task InvokeConnectionAsyncThrowsIfConnectionFailsToWrite()
        {
            using (var client = new TestClient())
            {
                // Force an exception when writing to connection
                var output = new Mock <Channel <HubMessage> >();
                output.Setup(o => o.Out.WaitToWriteAsync(It.IsAny <CancellationToken>())).Throws(new Exception("Message"));

                var manager    = new DefaultHubLifetimeManager <MyHub>();
                var connection = new HubConnectionContext(output.Object, client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                var exception = await Assert.ThrowsAsync <Exception>(() => manager.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout());

                Assert.Equal("Message", exception.Message);
            }
        }
        public async Task InvokeConnectionAsyncThrowsIfConnectionFailsToWrite()
        {
            using (var client = new TestClient())
            {
                // Force an exception when writing to connection
                var manager = new DefaultHubLifetimeManager <MyHub>();

                var connectionMock = HubConnectionContextUtils.CreateMock(client.Connection);
                connectionMock.Setup(m => m.WriteAsync(It.IsAny <HubMessage>())).Throws(new Exception("Message"));
                var connection = connectionMock.Object;

                await manager.OnConnectedAsync(connection).OrTimeout();

                var exception = await Assert.ThrowsAsync <Exception>(() => manager.SendConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout());

                Assert.Equal("Message", exception.Message);
            }
        }
        public async Task InvokeConnectionAsyncWritesToConnectionOutput()
        {
            using (var client = new TestClient())
            {
                var output     = Channel.CreateUnbounded <HubMessage>();
                var manager    = new DefaultHubLifetimeManager <MyHub>();
                var connection = new HubConnectionContext(output, client.Connection);

                await manager.OnConnectedAsync(connection).OrTimeout();

                await manager.InvokeConnectionAsync(connection.ConnectionId, "Hello", new object[] { "World" }).OrTimeout();

                Assert.True(output.Reader.TryRead(out var item));
                var message = Assert.IsType <InvocationMessage>(item);
                Assert.Equal("Hello", message.Target);
                Assert.Single(message.Arguments);
                Assert.Equal("World", (string)message.Arguments[0]);
            }
        }
Exemplo n.º 18
0
        public void GlobalSetup()
        {
            _hubLifetimeManager = new DefaultHubLifetimeManager <Hub>();
            var options = new UnboundedChannelOptions {
                AllowSynchronousContinuations = true
            };

            for (var i = 0; i < Connections; ++i)
            {
                var transportToApplication = Channel.CreateUnbounded <byte[]>(options);
                var applicationToTransport = Channel.CreateUnbounded <byte[]>(options);

                var application = ChannelConnection.Create <byte[]>(input: applicationToTransport, output: transportToApplication);
                var transport   = ChannelConnection.Create <byte[]>(input: transportToApplication, output: applicationToTransport);
                var connection  = new DefaultConnectionContext(Guid.NewGuid().ToString(), transport, application);

                _hubLifetimeManager.OnConnectedAsync(new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance)).Wait();
            }

            _hubContext = new HubContext <Hub>(_hubLifetimeManager);
        }
Exemplo n.º 19
0
    public void GlobalSetup()
    {
        _hubLifetimeManager  = new DefaultHubLifetimeManager <Hub>(NullLogger <DefaultHubLifetimeManager <Hub> > .Instance);
        _connectionIds       = new List <string>();
        _subsetConnectionIds = new List <string>();
        _groupNames          = new List <string>();
        _userIdentifiers     = new List <string>();

        var jsonHubProtocol = new NewtonsoftJsonHubProtocol();

        for (int i = 0; i < 100; i++)
        {
            string connectionId   = "connection-" + i;
            string groupName      = "group-" + i % 10;
            string userIdentifier = "user-" + i % 20;
            AddUnique(_connectionIds, connectionId);
            AddUnique(_groupNames, groupName);
            AddUnique(_userIdentifiers, userIdentifier);
            if (i % 3 == 0)
            {
                _subsetConnectionIds.Add(connectionId);
            }

            var connectionContext = new TestConnectionContext
            {
                ConnectionId = connectionId,
                Transport    = new TestDuplexPipe(ForceAsync)
            };
            var contextOptions = new HubConnectionContextOptions()
            {
                KeepAliveInterval = TimeSpan.Zero,
            };
            var hubConnectionContext = new HubConnectionContext(connectionContext, contextOptions, NullLoggerFactory.Instance);
            hubConnectionContext.UserIdentifier = userIdentifier;
            hubConnectionContext.Protocol       = jsonHubProtocol;

            _hubLifetimeManager.OnConnectedAsync(hubConnectionContext).GetAwaiter().GetResult();
            _hubLifetimeManager.AddToGroupAsync(connectionId, groupName);
        }
    }
Exemplo n.º 20
0
    /// <inheritdoc />
    public override Task SendGroupExceptAsync(string groupName, string methodName, object?[] args, IReadOnlyList <string> excludedConnectionIds, CancellationToken cancellationToken = default)
    {
        if (groupName == null)
        {
            throw new ArgumentNullException(nameof(groupName));
        }

        var group = _groups[groupName];

        if (group != null)
        {
            List <Task>?         tasks   = null;
            SerializedHubMessage?message = null;

            DefaultHubLifetimeManager <THub> .SendToGroupConnections(methodName, args, group, (connection, state) => !((IReadOnlyList <string>)state !).Contains(connection.ConnectionId), excludedConnectionIds, ref tasks, ref message, cancellationToken);

            if (tasks != null)
            {
                return(Task.WhenAll(tasks));
            }
        }

        return(Task.CompletedTask);
    }
Exemplo n.º 21
0
 public async Task SendConnectionAsyncOnNonExistentConnectionNoops()
 {
     var manager = new DefaultHubLifetimeManager <MyHub>(new Logger <DefaultHubLifetimeManager <MyHub> >(NullLoggerFactory.Instance));
     await manager.SendConnectionAsync("NotARealConnectionId", "Hello", new object[] { "World" }).OrTimeout();
 }
 public async Task RemoveGroupOnNonExistentConnectionNoops()
 {
     var manager = new DefaultHubLifetimeManager <MyHub>();
     await manager.RemoveGroupAsync("NotARealConnectionId", "MyGroup");
 }
 public async Task InvokeConnectionAsyncOnNonExistentConnectionNoops()
 {
     var manager = new DefaultHubLifetimeManager <MyHub>();
     await manager.InvokeConnectionAsync("NotARealConnectionId", "Hello", new object[] { "World" });
 }
Exemplo n.º 24
0
 public async Task RemoveGroupOnNonExistentConnectionNoops()
 {
     var manager = new DefaultHubLifetimeManager <MyHub>(new Logger <DefaultHubLifetimeManager <MyHub> >(NullLoggerFactory.Instance));
     await manager.RemoveGroupAsync("NotARealConnectionId", "MyGroup").OrTimeout();
 }