public async Task CanReturnClientResultErrorToHub()
    {
        using (StartVerifiableLog(write => write.EventId.Name == "FailedInvokingHubMethod"))
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
            {
                // Waiting for a client result blocks the hub dispatcher pipeline, need to allow multiple invocations
                builder.AddSignalR(o =>
                {
                    o.MaximumParallelInvocationsPerClient = 2;
                    o.EnableDetailedErrors = true;
                });
            }, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();

                var invocationId = await client.SendHubMessageAsync(new InvocationMessage("1", nameof(MethodHub.GetClientResult), new object[] { 5 })).DefaultTimeout();

                // Hub asks client for a result, this is an invocation message with an ID
                var invocationMessage = Assert.IsType <InvocationMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.NotNull(invocationMessage.InvocationId);
                await client.SendHubMessageAsync(CompletionMessage.WithError(invocationMessage.InvocationId, "Client error")).DefaultTimeout();

                var completion = Assert.IsType <CompletionMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.Equal("An unexpected error occurred invoking 'GetClientResult' on the server. Exception: Client error", completion.Error);
                Assert.Equal(invocationId, completion.InvocationId);
            }
        }
    }
    public async Task ThrowsWhenParallelHubInvokesNotEnabled()
    {
        using (StartVerifiableLog(write => write.EventId.Name == "FailedInvokingHubMethod"))
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
            {
                builder.AddSignalR(o =>
                {
                    o.MaximumParallelInvocationsPerClient = 1;
                    o.EnableDetailedErrors = true;
                });
            }, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();

                var invocationId = await client.SendHubMessageAsync(new InvocationMessage("1", nameof(MethodHub.GetClientResult), new object[] { 5 })).DefaultTimeout();

                // Hub asks client for a result, this is an invocation message with an ID
                var completionMessage = Assert.IsType <CompletionMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.Equal(invocationId, completionMessage.InvocationId);
                Assert.Equal("An unexpected error occurred invoking 'GetClientResult' on the server. InvalidOperationException: Client results inside a Hub method requires HubOptions.MaximumParallelInvocationsPerClient to be greater than 1.",
                             completionMessage.Error);
            }
        }
    }
    public async Task CanReturnClientResultToTypedHubTwoWays()
    {
        using (StartVerifiableLog())
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
            {
                // Waiting for a client result blocks the hub dispatcher pipeline, need to allow multiple invocations
                builder.AddSignalR(o => o.MaximumParallelInvocationsPerClient = 2);
            }, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <HubT> >();

            using var client = new TestClient(invocationBinder: new GetClientResultThreeWaysInvocationBinder());

            var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();

            var invocationId = await client.SendHubMessageAsync(new InvocationMessage(
                                                                    invocationId : "1",
                                                                    nameof(HubT.GetClientResultTwoWays),
                                                                    new object[] { 7, 3 })).DefaultTimeout();

            // Send back "value + 4" to both invocations.
            for (int i = 0; i < 2; i++)
            {
                // Hub asks client for a result, this is an invocation message with an ID.
                var invocationMessage = Assert.IsType <InvocationMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.NotNull(invocationMessage.InvocationId);
                var res = 4 + (int)invocationMessage.Arguments[0];
                await client.SendHubMessageAsync(CompletionMessage.WithResult(invocationMessage.InvocationId, res)).DefaultTimeout();
            }

            var completion = Assert.IsType <CompletionMessage>(await client.ReadAsync().DefaultTimeout());
            Assert.Equal(new ClientResults(11, 7), completion.Result);
        }
    }
    public async Task CanUseClientResultsWithIHubContextT()
    {
        using (StartVerifiableLog())
        {
            var serviceProvider   = HubConnectionHandlerTestUtils.CreateServiceProvider(null, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <HubT> >();

            using var client = new TestClient();
            var connectionId = client.Connection.ConnectionId;

            var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

            // Wait for a connection, or for the endpoint to fail.
            await client.Connected.OrThrowIfOtherFails(connectionHandlerTask).DefaultTimeout();

            var context = serviceProvider.GetRequiredService <IHubContext <HubT, ITest> >();

            var resultTask = context.Clients.Client(connectionId).GetClientResult(1);

            var message = await client.ReadAsync().DefaultTimeout();

            var invocation = Assert.IsType <InvocationMessage>(message);

            Assert.Single(invocation.Arguments);
            Assert.Equal(1L, invocation.Arguments[0]);
            Assert.Equal("GetClientResult", invocation.Target);

            await client.SendHubMessageAsync(CompletionMessage.WithResult(invocation.InvocationId, 2)).DefaultTimeout();

            var result = await resultTask.DefaultTimeout();

            Assert.Equal(2, result);
        }
    }
    public async Task ThrowsWhenUsedInOnDisconnectedAsync()
    {
        using (StartVerifiableLog(write => write.EventId.Name == "ErrorDispatchingHubEvent"))
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
            {
                builder.AddSignalR(o =>
                {
                    o.MaximumParallelInvocationsPerClient = 2;
                    o.EnableDetailedErrors = true;
                });
            }, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <OnDisconnectedClientResultHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();

                client.Connection.Abort();

                // Hub asks client for a result, this is an invocation message with an ID
                var closeMessage = Assert.IsType <CloseMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.Null(closeMessage.Error);

                var ex = await Assert.ThrowsAsync <IOException>(() => connectionHandlerTask).DefaultTimeout();

                Assert.Equal($"Connection '{client.Connection.ConnectionId}' disconnected.", ex.Message);
            }
        }

        Assert.Single(TestSink.Writes.Where(write => write.EventId.Name == "ErrorDispatchingHubEvent"));
    }
Пример #6
0
    public async Task HubFilterDoesNotNeedToImplementMethods()
    {
        using (StartVerifiableLog())
        {
            var tcsService      = new TcsService();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR().AddHubOptions <DynamicTestHub>(options =>
                {
                    options.AddFilter(typeof(EmptyFilter));
                });
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <DynamicTestHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                await client.Connected.DefaultTimeout();

                var completion = await client.InvokeAsync(nameof(DynamicTestHub.Echo), "hello");

                Assert.Null(completion.Error);
                Assert.Equal("hello", completion.Result);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();
            }
        }
    }
Пример #7
0
    public async Task InvokeFailsWhenFilterCallsNonExistantMethod()
    {
        bool ExpectedErrors(WriteContext writeContext)
        {
            return(writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" &&
                   writeContext.EventId.Name == "FailedInvokingHubMethod");
        }

        using (StartVerifiableLog(expectedErrorsFilter: ExpectedErrors))
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.EnableDetailedErrors = true;
                    options.AddFilter <ChangeMethodFilter>();
                });
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                var message = await client.InvokeAsync("Echo", "Hello");

                Assert.Equal("An unexpected error occurred invoking 'Echo' on the server. HubException: Unknown hub method 'BaseMethod'", message.Error);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();
            }
        }
    }
    public async Task ThrowsWhenUsedInOnConnectedAsync()
    {
        using (StartVerifiableLog(write => write.EventId.Name == "ErrorDispatchingHubEvent"))
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
            {
                builder.AddSignalR(o =>
                {
                    o.MaximumParallelInvocationsPerClient = 2;
                    o.EnableDetailedErrors = true;
                });
            }, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <OnConnectedClientResultHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();

                // Hub asks client for a result, this is an invocation message with an ID
                var closeMessage = Assert.IsType <CloseMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.Equal("Connection closed with an error. InvalidOperationException: Client results inside OnConnectedAsync Hub methods are not allowed.", closeMessage.Error);
            }
        }

        Assert.Single(TestSink.Writes.Where(write => write.EventId.Name == "ErrorDispatchingHubEvent"));
    }
Пример #9
0
    public async Task FilterCanSkipCallingHubMethod()
    {
        using (StartVerifiableLog())
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.AddFilter(new SkipNextFilter(skipInvoke: true));
                });
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                await client.Connected.DefaultTimeout();

                var message = await client.InvokeAsync(nameof(MethodHub.Echo), "Hello world!").DefaultTimeout();

                Assert.Null(message.Error);
                Assert.Null(message.Result);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();
            }
        }
    }
Пример #10
0
    public async Task InstanceFiltersWithIAsyncDisposableAreNotDisposed()
    {
        using (StartVerifiableLog())
        {
            var tcsService      = new TcsService();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.EnableDetailedErrors = true;
                    options.AddFilter(new AsyncDisposableFilter(tcsService));
                });

                services.AddSingleton(tcsService);
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                var message = await client.InvokeAsync("Echo", "Hello");

                Assert.Equal("Hello", message.Result);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();

                Assert.False(tcsService.StartedMethod.Task.IsCompleted);
            }
        }
    }
Пример #11
0
    public async Task GlobalFiltersRunBeforeHubSpecificFilters()
    {
        using (StartVerifiableLog())
        {
            var syncPoint1      = SyncPoint.Create(3, out var syncPoints1);
            var syncPoint2      = SyncPoint.Create(3, out var syncPoints2);
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.AddFilter(new SyncPointFilter(syncPoints1));
                })
                .AddHubOptions <MethodHub>(options =>
                {
                    options.AddFilter(new SyncPointFilter(syncPoints2));
                });
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                await syncPoints1[0].WaitForSyncPoint().DefaultTimeout();
                // Second filter wont run yet because first filter is waiting on SyncPoint
                Assert.False(syncPoints2[0].WaitForSyncPoint().IsCompleted);
                syncPoints1[0].Continue();

                await syncPoints2[0].WaitForSyncPoint().DefaultTimeout();
                syncPoints2[0].Continue();
                await client.Connected.DefaultTimeout();

                var invokeTask = client.InvokeAsync(nameof(MethodHub.Echo), "Hello world!");

                await syncPoints1[1].WaitForSyncPoint().DefaultTimeout();
                // Second filter wont run yet because first filter is waiting on SyncPoint
                Assert.False(syncPoints2[1].WaitForSyncPoint().IsCompleted);
                syncPoints1[1].Continue();

                await syncPoints2[1].WaitForSyncPoint().DefaultTimeout();
                syncPoints2[1].Continue();
                var message = await invokeTask.DefaultTimeout();

                Assert.Null(message.Error);

                client.Dispose();

                await syncPoints1[2].WaitForSyncPoint().DefaultTimeout();
                // Second filter wont run yet because first filter is waiting on SyncPoint
                Assert.False(syncPoints2[2].WaitForSyncPoint().IsCompleted);
                syncPoints1[2].Continue();

                await syncPoints2[2].WaitForSyncPoint().DefaultTimeout();
                syncPoints2[2].Continue();

                await connectionHandlerTask.DefaultTimeout();
            }
        }
    }
Пример #12
0
    public async Task ConnectionContinuesIfOnConnectedAsyncNotCalledByFilter()
    {
        using (StartVerifiableLog())
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.EnableDetailedErrors = true;
                    options.AddFilter(new SkipNextFilter(skipOnConnected: true));
                });
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                // Verify connection still connected, can't invoke a method if the connection is disconnected
                var message = await client.InvokeAsync("Method");

                Assert.Equal("Failed to invoke 'Method' due to an error on the server. HubException: Method does not exist.", message.Error);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();
            }
        }
    }
    public async Task CanReturnClientResultToHub()
    {
        using (StartVerifiableLog())
        {
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
            {
                // Waiting for a client result blocks the hub dispatcher pipeline, need to allow multiple invocations
                builder.AddSignalR(o => o.MaximumParallelInvocationsPerClient = 2);
            }, LoggerFactory);
            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();

                var invocationId = await client.SendHubMessageAsync(new InvocationMessage("1", nameof(MethodHub.GetClientResult), new object[] { 5 })).DefaultTimeout();

                // Hub asks client for a result, this is an invocation message with an ID
                var invocationMessage = Assert.IsType <InvocationMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.NotNull(invocationMessage.InvocationId);
                var res = 4 + ((long)invocationMessage.Arguments[0]);
                await client.SendHubMessageAsync(CompletionMessage.WithResult(invocationMessage.InvocationId, res)).DefaultTimeout();

                var completion = Assert.IsType <CompletionMessage>(await client.ReadAsync().DefaultTimeout());
                Assert.Equal(9L, completion.Result);
                Assert.Equal(invocationId, completion.InvocationId);
            }
        }
    }
Пример #14
0
    public async Task MixingTypeAndInstanceHubSpecificFilters_MethodsAreCalled()
    {
        using (StartVerifiableLog())
        {
            var tcsService1     = new TcsService();
            var tcsService2     = new TcsService();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR()
                .AddHubOptions <MethodHub>(options =>
                {
                    options.AddFilter(new VerifyMethodFilter(tcsService1));
                    options.AddFilter <VerifyMethodFilter>();
                });

                services.AddSingleton(tcsService2);
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                await tcsService1.StartedMethod.Task.DefaultTimeout();

                await tcsService2.StartedMethod.Task.DefaultTimeout();

                await client.Connected.DefaultTimeout();

                await tcsService1.EndMethod.Task.DefaultTimeout();

                await tcsService2.EndMethod.Task.DefaultTimeout();

                tcsService1.Reset();
                tcsService2.Reset();
                var message = await client.InvokeAsync(nameof(MethodHub.Echo), "Hello world!").DefaultTimeout();

                await tcsService1.EndMethod.Task.DefaultTimeout();

                await tcsService2.EndMethod.Task.DefaultTimeout();

                tcsService1.Reset();
                tcsService2.Reset();

                Assert.Null(message.Error);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();

                await tcsService1.EndMethod.Task.DefaultTimeout();

                await tcsService2.EndMethod.Task.DefaultTimeout();
            }
        }
    }
Пример #15
0
    public async Task FiltersHaveTransientScopeByDefault()
    {
        using (StartVerifiableLog())
        {
            var counter         = new FilterCounter();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.AddFilter <CounterFilter>();
                });

                services.AddSingleton(counter);
            }, LoggerFactory);

            var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

            using (var client = new TestClient())
            {
                var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                await client.Connected.DefaultTimeout();

                // Filter is transient, so these counts are reset every time the filter is created
                Assert.Equal(1, counter.OnConnectedAsyncCount);
                Assert.Equal(0, counter.InvokeMethodAsyncCount);
                Assert.Equal(0, counter.OnDisconnectedAsyncCount);

                var message = await client.InvokeAsync(nameof(MethodHub.Echo), "Hello world!").DefaultTimeout();

                // Filter is transient, so these counts are reset every time the filter is created
                Assert.Equal(0, counter.OnConnectedAsyncCount);
                Assert.Equal(1, counter.InvokeMethodAsyncCount);
                Assert.Equal(0, counter.OnDisconnectedAsyncCount);

                Assert.Null(message.Error);

                client.Dispose();

                await connectionHandlerTask.DefaultTimeout();

                // Filter is transient, so these counts are reset every time the filter is created
                Assert.Equal(0, counter.OnConnectedAsyncCount);
                Assert.Equal(0, counter.InvokeMethodAsyncCount);
                Assert.Equal(1, counter.OnDisconnectedAsyncCount);
            }
        }
    }
Пример #16
0
    public async Task PerHubFilterByInstance_MethodsAreCalled()
    {
        using (StartVerifiableLog())
        {
            var tcsService      = new TcsService();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR().AddHubOptions <MethodHub>(options =>
                {
                    options.AddFilter(new VerifyMethodFilter(tcsService));
                });
            }, LoggerFactory);

            await AssertMethodsCalled(serviceProvider, tcsService);
        }
    }
Пример #17
0
    public async Task GlobalHubFilterByType_MethodsAreCalled()
    {
        using (StartVerifiableLog())
        {
            var tcsService      = new TcsService();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.AddFilter <VerifyMethodFilter>();
                });

                services.AddSingleton(tcsService);
            }, LoggerFactory);

            await AssertMethodsCalled(serviceProvider, tcsService);
        }
    }
Пример #18
0
    public async Task FilterCanBeResolvedFromDI()
    {
        using (StartVerifiableLog())
        {
            var tcsService      = new TcsService();
            var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
            {
                services.AddSignalR(options =>
                {
                    options.AddFilter <VerifyMethodFilter>();
                });

                // If this instance wasn't resolved, then the tcsService.StartedMethod waits would never trigger and fail the test
                services.AddSingleton(new VerifyMethodFilter(tcsService));
            }, LoggerFactory);

            await AssertMethodsCalled(serviceProvider, tcsService);
        }
    }