Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): implement IAsyncDisposable on HttpMockServer #89

Merged
merged 1 commit into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions src/MockHttp.Server/MockHttpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ namespace MockHttp;
/// <summary>
/// A mock HTTP server that listens on a specific URL and responds according to a configured <see cref="MockHttpHandler" />.
/// </summary>
public sealed class MockHttpServer : IDisposable
public sealed class MockHttpServer
: IDisposable,
IAsyncDisposable
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly Uri _hostUri;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly SemaphoreSlim _lock = new(1);
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IWebHostBuilder _webHostBuilder;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IWebHost? _host;
private Action<IApplicationBuilder>? _configureAppBuilder;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly Uri _hostUri;
private bool _disposed;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Action<IApplicationBuilder>? _configureAppBuilder;
private IWebHost? _host;

/// <summary>
/// Initializes a new instance of the <see cref="MockHttpServer" /> using specified <paramref name="mockHttpHandler" /> and configures it to listen on specified <paramref name="hostUrl" />.
Expand Down Expand Up @@ -77,10 +81,20 @@ public MockHttpServer(MockHttpHandler mockHttpHandler, ILoggerFactory? loggerFac
/// <inheritdoc />
public void Dispose()
{
_lock.Dispose();
DisposeAsync().AsTask().GetAwaiter().GetResult();
}

/// <inheritdoc />
public async ValueTask DisposeAsync()
{
if (_disposed)
{
return;
}

_host?.Dispose();
_host = null;
await StopAsync().ConfigureAwait(false);
_lock.Dispose();
_disposed = true;
}

/// <summary>
Expand All @@ -103,6 +117,8 @@ public Uri HostUri
{
get
{
CheckDisposed();

_lock.Wait();
try
{
Expand All @@ -121,13 +137,15 @@ public Uri HostUri
/// <summary>
/// Gets whether the host is started.
/// </summary>
public bool IsStarted => _host is not null;
public bool IsStarted => !_disposed && _host is not null;

/// <summary>
/// Starts listening on the configured addresses.
/// </summary>
public async Task StartAsync(CancellationToken cancellationToken = default)
{
CheckDisposed();

await _lock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
Expand All @@ -150,6 +168,8 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
/// </summary>
public async Task StopAsync(CancellationToken cancellationToken = default)
{
CheckDisposed();

await _lock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
Expand All @@ -158,16 +178,20 @@ public async Task StopAsync(CancellationToken cancellationToken = default)
return;
}

// Make local copy, so we can null it before disposing.
IWebHost host = _host;
_host = null;
using (host)
{
await host.StopAsync(cancellationToken).ConfigureAwait(false);
}
await _host.StopAsync(cancellationToken).ConfigureAwait(false);
}
finally
{
if (_host is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync().ConfigureAwait(false);
}
else
{
_host?.Dispose();
}

_host = null;
_lock.Release();
}
}
Expand All @@ -177,6 +201,7 @@ public async Task StopAsync(CancellationToken cancellationToken = default)
/// </summary>
public HttpClient CreateClient()
{
CheckDisposed();
return new HttpClient { BaseAddress = HostUri };
}

Expand Down Expand Up @@ -238,4 +263,12 @@ private void AddMockHttpServerHeader(IApplicationBuilder applicationBuilder)
await next().ConfigureAwait(false);
});
}

private void CheckDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().FullName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public Task InitializeAsync()

public Task DisposeAsync()
{
return Server.StopAsync();
return Server.DisposeAsync().AsTask();
}

private static bool SupportsIpv6()
Expand Down
Loading
Loading