Skip to content

Commit

Permalink
Add HubConnection.State (#2204)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed May 14, 2018
1 parent ffc665c commit 7625bbc
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ public partial class HubConnection
public TimeSpan ServerTimeout { get; set; } = DefaultServerTimeout;
public TimeSpan HandshakeTimeout { get; set; } = DefaultHandshakeTimeout;

/// <summary>
/// Indicates the state of the <see cref="HubConnection"/> to the server.
/// </summary>
public HubConnectionState State
{
get
{
// Copy reference for thread-safety
var connectionState = _connectionState;
if (connectionState == null || connectionState.Stopped)
{
return HubConnectionState.Disconnected;
}

return HubConnectionState.Connected;
}
}

/// <summary>
/// Initializes a new instance of the <see cref="HubConnection"/> class.
/// </summary>
Expand Down Expand Up @@ -994,6 +1012,8 @@ public bool Stopping
set => _stopping = value;
}

public bool Stopped => _stopTcs?.Task.Status == TaskStatus.RanToCompletion;

public ConnectionState(ConnectionContext connection, HubConnection hubConnection)
{
_hubConnection = hubConnection;
Expand Down
20 changes: 20 additions & 0 deletions src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Describes the current state of the <see cref="HubConnection"/> to the server.
/// </summary>
public enum HubConnectionState
{
/// <summary>
/// The hub connection is disconnected.
/// </summary>
Disconnected,
/// <summary>
/// The hub connection is open.
/// </summary>
Connected
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@ public async Task StartAsyncStartsTheUnderlyingConnection()
var testConnection = new TestConnection();
await AsyncUsing(CreateHubConnection(testConnection), async connection =>
{
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await connection.StartAsync();
Assert.True(testConnection.Started.IsCompleted);
Assert.Equal(HubConnectionState.Connected, connection.State);
});
}

Expand Down Expand Up @@ -104,12 +107,18 @@ Task DisposeAsync(ConnectionContext connection)

await AsyncUsing(CreateHubConnection(ConnectionFactory, DisposeAsync), async connection =>
{
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await connection.StartAsync().OrTimeout();
Assert.Equal(1, createCount);
Assert.Equal(HubConnectionState.Connected, connection.State);
await connection.StopAsync().OrTimeout();
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await connection.StartAsync().OrTimeout();
Assert.Equal(2, createCount);
Assert.Equal(HubConnectionState.Connected, connection.State);
});
}

Expand Down Expand Up @@ -216,6 +225,58 @@ public async Task MethodsThatRequireStartedConnectionWaitForStartIfConnectionIsC
});
}

[Fact]
public async Task StatusIsNotConnectedUntilStartAsyncIsFinished()
{
// Set up StartAsync to wait on the syncPoint when starting
var testConnection = new TestConnection(onStart: SyncPoint.Create(out var syncPoint));
await AsyncUsing(CreateHubConnection(testConnection), async connection =>
{
// Start, and wait for the sync point to be hit
var startTask = connection.StartAsync().OrTimeout();
Assert.False(startTask.IsCompleted);
await syncPoint.WaitForSyncPoint();
Assert.Equal(HubConnectionState.Disconnected, connection.State);
// Release the SyncPoint
syncPoint.Continue();
// Wait for start to finish
await startTask;
Assert.Equal(HubConnectionState.Connected, connection.State);
});
}

[Fact]
public async Task StatusIsDisconnectedInCloseEvent()
{
var testConnection = new TestConnection();
await AsyncUsing(CreateHubConnection(testConnection), async connection =>
{
var closed = new TaskCompletionSource<object>();
connection.Closed += exception =>
{
closed.TrySetResult(null);
Assert.Equal(HubConnectionState.Disconnected, connection.State);
return Task.CompletedTask;
};
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await connection.StartAsync().OrTimeout();
Assert.True(testConnection.Started.IsCompleted);
Assert.Equal(HubConnectionState.Connected, connection.State);
await connection.StopAsync().OrTimeout();
await testConnection.Disposed.OrTimeout();
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await closed.Task.OrTimeout();
});
}

[Fact]
public async Task StopAsyncStopsConnection()
{
Expand Down Expand Up @@ -247,13 +308,18 @@ public async Task StopAsyncNoOpsIfConnectionAlreadyStopped()
var testConnection = new TestConnection();
await AsyncUsing(CreateHubConnection(testConnection), async connection =>
{
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await connection.StartAsync().OrTimeout();
Assert.True(testConnection.Started.IsCompleted);
Assert.Equal(HubConnectionState.Connected, connection.State);
await connection.StopAsync().OrTimeout();
await testConnection.Disposed.OrTimeout();
Assert.Equal(HubConnectionState.Disconnected, connection.State);
await connection.StopAsync().OrTimeout();
Assert.Equal(HubConnectionState.Disconnected, connection.State);
});
}

Expand Down Expand Up @@ -396,6 +462,7 @@ public async Task ClientTimesoutWhenHandshakeResponseTakesTooLong()
hubConnection.HandshakeTimeout = TimeSpan.FromMilliseconds(1);

await Assert.ThrowsAsync<OperationCanceledException>(() => hubConnection.StartAsync().OrTimeout());
Assert.Equal(HubConnectionState.Disconnected, hubConnection.State);
}
finally
{
Expand Down

0 comments on commit 7625bbc

Please sign in to comment.