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")); }
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(); } } }
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")); }
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(); } } }
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); } } }
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(); } } }
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); } } }
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(); } } }
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); } } }
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); } }
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); } }
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); } }