Fixing a bug where pending invocations were not terminated correctly

This commit is contained in:
moozzyk 2017-02-17 13:42:41 -08:00
parent 12c6a4b917
commit 9709139a27
2 changed files with 60 additions and 5 deletions

View File

@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
{ {
if (_connectionActive.IsCancellationRequested) if (_connectionActive.IsCancellationRequested)
{ {
throw new InvalidOperationException("Connection has been terminated"); throw new InvalidOperationException("Connection has been terminated.");
} }
_pendingCalls.Add(descriptor.Id, irq); _pendingCalls.Add(descriptor.Id, irq);
} }
@ -185,11 +185,11 @@ namespace Microsoft.AspNetCore.SignalR.Client
{ {
if (ex != null) if (ex != null)
{ {
call.Completion.TrySetCanceled(); call.Completion.TrySetException(ex);
} }
else else
{ {
call.Completion.TrySetException(ex); call.Completion.TrySetCanceled();
} }
} }
_pendingCalls.Clear(); _pendingCalls.Clear();

View File

@ -108,8 +108,6 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
Assert.Equal("Cannot invoke methods on disposed connections.", exception.Message); Assert.Equal("Cannot invoke methods on disposed connections.", exception.Message);
} }
// TODO: If HubConnection takes (I)Connection we could just tests if events are wired up
[Fact] [Fact]
public async Task HubConnectionConnectedEventRaisedWhenTheClientIsConnected() public async Task HubConnectionConnectedEventRaisedWhenTheClientIsConnected()
{ {
@ -167,5 +165,62 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
Assert.Null(await closedEventTcs.Task.OrTimeout()); Assert.Null(await closedEventTcs.Task.OrTimeout());
} }
} }
[Fact]
public async Task CannotCallInvokeOnClosedHubConnection()
{
var mockConnection = new Mock<IConnection>();
mockConnection
.Setup(m => m.DisposeAsync())
.Callback(() => mockConnection.Raise(c => c.Closed += null, (Exception)null))
.Returns(Task.FromResult<object>(null));
var hubConnection = new HubConnection(mockConnection.Object, Mock.Of<IInvocationAdapter>(), new LoggerFactory());
await hubConnection.StartAsync(Mock.Of<ITransport>());
await hubConnection.DisposeAsync();
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
async () => await hubConnection.Invoke("test", typeof(int)));
Assert.Equal("Connection has been terminated.", exception.Message);
}
[Fact]
public async Task PendingInvocationsAreCancelledWhenConnectionClosesCleanly()
{
var mockConnection = new Mock<IConnection>();
mockConnection
.Setup(m => m.DisposeAsync())
.Callback(() => mockConnection.Raise(c => c.Closed += null, (Exception)null))
.Returns(Task.FromResult<object>(null));
var hubConnection = new HubConnection(mockConnection.Object, Mock.Of<IInvocationAdapter>(), new LoggerFactory());
await hubConnection.StartAsync(Mock.Of<ITransport>());
var invokeTask = hubConnection.Invoke("testMethod", typeof(int));
await hubConnection.DisposeAsync();
await Assert.ThrowsAsync<TaskCanceledException>(async () => await invokeTask);
}
[Fact]
public async Task PendingInvocationsAreTerminatedWithExceptionWhenConnectionClosesDueToError()
{
var exception = new InvalidOperationException();
var mockConnection = new Mock<IConnection>();
mockConnection
.Setup(m => m.DisposeAsync())
.Callback(() => mockConnection.Raise(c => c.Closed += null, exception))
.Returns(Task.FromResult<object>(null));
var hubConnection = new HubConnection(mockConnection.Object, Mock.Of<IInvocationAdapter>(), new LoggerFactory());
await hubConnection.StartAsync(Mock.Of<ITransport>());
var invokeTask = hubConnection.Invoke("testMethod", typeof(int));
await hubConnection.DisposeAsync();
var thrown = await Assert.ThrowsAsync(exception.GetType(), async () => await invokeTask);
Assert.Same(exception, thrown);
}
} }
} }