Skip to content
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
7 changes: 3 additions & 4 deletions src/Aspire.Hosting/Dashboard/DashboardServiceData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Aspire.Hosting.Dashboard;
/// Models the state for <see cref="DashboardService"/>, as that service is constructed
/// for each gRPC request. This long-lived object holds state across requests.
/// </summary>
internal sealed class DashboardServiceData : IAsyncDisposable
internal sealed class DashboardServiceData : IDisposable
{
private readonly CancellationTokenSource _cts = new();
private readonly ResourcePublisher _resourcePublisher;
Expand Down Expand Up @@ -102,10 +102,9 @@ await _resourcePublisher.IntegrateAsync(@event.Resource, snapshot, ResourceSnaps
cancellationToken);
}

public async ValueTask DisposeAsync()
public void Dispose()
{
await _cts.CancelAsync().ConfigureAwait(false);

_cts.Cancel();
_cts.Dispose();
}

Expand Down
1 change: 1 addition & 0 deletions tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<Compile Include="$(TestsSharedDir)Logging\*.cs" LinkBase="shared/Logging" />
<Compile Include="$(TestsSharedDir)ConsoleLogging\*.cs" LinkBase="shared" />
<Compile Include="$(TestsSharedDir)AsyncTestHelpers.cs" Link="shared/AsyncTestHelpers.cs" />
<Compile Include="$(TestsSharedDir)TaskExtensions.cs" Link="shared/TaskExtensions.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.PostgreSQL\PostgresContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Redis\RedisContainerImageTags.cs" />
<Compile Include="$(RepoRoot)src\Aspire.Hosting.Testing\ResourceLoggerForwarderService.cs" Link="Utils\ResourceLoggerForwarderService.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options;
using Xunit;
using Xunit.Abstractions;

namespace Aspire.Hosting.Tests.Dashboard;

public class DashboardLifecycleHookTests
public class DashboardLifecycleHookTests(ITestOutputHelper testOutputHelper)
{
[Theory]
[MemberData(nameof(Data))]
Expand All @@ -30,12 +31,13 @@ public async Task WatchDashboardLogs_WrittenToHostLoggerFactory(DateTime? timest
{
b.SetMinimumLevel(LogLevel.Trace);
b.AddProvider(new TestLoggerProvider(testSink));
b.AddXunit(testOutputHelper);
});
var logChannel = Channel.CreateUnbounded<WriteContext>();
testSink.MessageLogged += c => logChannel.Writer.TryWrite(c);

var resourceLoggerService = new ResourceLoggerService();
var resourceNotificationService = ResourceNotificationServiceTestHelpers.Create();
var resourceNotificationService = ResourceNotificationServiceTestHelpers.Create(logger: factory.CreateLogger<ResourceNotificationService>());
var configuration = new ConfigurationBuilder().Build();
var hook = CreateHook(resourceLoggerService, resourceNotificationService, configuration, loggerFactory: factory);

Expand All @@ -59,10 +61,17 @@ public async Task WatchDashboardLogs_WrittenToHostLoggerFactory(DateTime? timest
dashboardLoggerState.AddLog(LogEntry.Create(timestamp, logMessage, isErrorMessage: false), inMemorySource: true);

// Assert
var logContext = await logChannel.Reader.ReadAsync();
Assert.Equal(expectedCategory, logContext.LoggerName);
Assert.Equal(expectedMessage, logContext.Message);
Assert.Equal(expectedLevel, logContext.LogLevel);
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
while (!cts.IsCancellationRequested)
{
var logContext = await logChannel.Reader.ReadAsync(cts.Token);
if (logContext.LoggerName == expectedCategory)
{
Assert.Equal(expectedMessage, logContext.Message);
Assert.Equal(expectedLevel, logContext.LogLevel);
break;
}
}
}

[Fact]
Expand Down
74 changes: 52 additions & 22 deletions tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Aspire.Hosting.Tests.Dashboard;

public class DashboardResourceTests
public class DashboardResourceTests(ITestOutputHelper testOutputHelper)
{
[Fact]
public async Task DashboardIsAutomaticallyAddedAsHiddenResource()
{
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

// Ensure any ambient configuration doesn't impact this test.
builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
Expand Down Expand Up @@ -52,7 +56,9 @@ public async Task DashboardIsAutomaticallyAddedAsHiddenResource()
[Fact]
public async Task DashboardIsAddedFirst()
{
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.AddContainer("my-container", "my-image");

Expand All @@ -71,7 +77,9 @@ public async Task DashboardIsAddedFirst()
[Fact]
public async Task DashboardDoesNotAddResource_ConfiguresExistingDashboard()
{
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.Services.AddSingleton<IDashboardEndpointProvider, MockDashboardEndpointProvider>();

Expand Down Expand Up @@ -144,7 +152,9 @@ public async Task DashboardDoesNotAddResource_ConfiguresExistingDashboard()
[Fact]
public async Task DashboardWithDllPathLaunchesDotnet()
{
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

var dashboardPath = Path.GetFullPath("dashboard.dll");

Expand Down Expand Up @@ -173,7 +183,9 @@ public async Task DashboardWithDllPathLaunchesDotnet()
public async Task DashboardAuthConfigured_EnvVarsPresent()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.Services.AddSingleton<IDashboardEndpointProvider, MockDashboardEndpointProvider>();

Expand Down Expand Up @@ -208,7 +220,9 @@ public async Task DashboardAuthConfigured_EnvVarsPresent()
public async Task DashboardAuthRemoved_EnvVarsUnsecured()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.Services.AddSingleton<IDashboardEndpointProvider, MockDashboardEndpointProvider>();

Expand Down Expand Up @@ -238,7 +252,9 @@ public async Task DashboardAuthRemoved_EnvVarsUnsecured()
public async Task DashboardResourceServiceUriIsSet()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.Services.AddSingleton<IDashboardEndpointProvider, MockDashboardEndpointProvider>();

Expand Down Expand Up @@ -267,7 +283,10 @@ public async Task DashboardResourceServiceUriIsSet()
public async Task DashboardResource_OtlpHttpEndpoint_CorsEnvVarSet()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.AddContainer("my-container", "my-image").WithHttpEndpoint(port: 8080, targetPort: 58080);

builder.Services.AddSingleton<IDashboardEndpointProvider, MockDashboardEndpointProvider>();
Expand Down Expand Up @@ -303,7 +322,10 @@ public async Task DashboardResource_OtlpHttpEndpoint_CorsEnvVarSet()
public async Task DashboardResource_OtlpGrpcEndpoint_CorsEnvVarNotSet()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

builder.AddContainer("my-container", "my-image").WithHttpEndpoint(port: 8080, targetPort: 58080);

builder.Services.AddSingleton<IDashboardEndpointProvider, MockDashboardEndpointProvider>();
Expand Down Expand Up @@ -333,11 +355,13 @@ public async Task DashboardResource_OtlpGrpcEndpoint_CorsEnvVarNotSet()
[Fact]
public async Task DashboardIsNotAddedInPublishMode()
{
using var builder = TestDistributedApplicationBuilder.Create(options =>
{
options.DisableDashboard = false;
options.Args = ["--publisher", "manifest"];
});
using var builder = TestDistributedApplicationBuilder.Create(
options =>
{
options.DisableDashboard = false;
options.Args = ["--publisher", "manifest"];
},
testOutputHelper: testOutputHelper);

using var app = builder.Build();

Expand All @@ -351,7 +375,9 @@ public async Task DashboardIsNotAddedInPublishMode()
[Fact]
public async Task DashboardIsNotAddedIfDisabled()
{
using var builder = TestDistributedApplicationBuilder.Create(options => options.DisableDashboard = true);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = true,
testOutputHelper: testOutputHelper);

var app = builder.Build();

Expand All @@ -366,11 +392,13 @@ public async Task DashboardIsNotAddedIfDisabled()
public void ContainerIsValidWithDashboardIsDisabled()
{
// Set the host environment to "Development" so that the container validates services.
using var builder = TestDistributedApplicationBuilder.Create(options =>
{
options.DisableDashboard = true;
options.Args = ["--environment", "Development"];
});
using var builder = TestDistributedApplicationBuilder.Create(
options =>
{
options.DisableDashboard = true;
options.Args = ["--environment", "Development"];
},
testOutputHelper: testOutputHelper);

// Container validation logic runs when the service provider is built.
using var app = builder.Build();
Expand All @@ -385,7 +413,9 @@ public void ContainerIsValidWithDashboardIsDisabled()
[InlineData(LogLevel.Trace)]
public async Task DashboardLifecycleHookWatchesLogs(LogLevel logLevel)
{
using var builder = TestDistributedApplicationBuilder.Create(o => o.DisableDashboard = false);
using var builder = TestDistributedApplicationBuilder.Create(
options => options.DisableDashboard = false,
testOutputHelper: testOutputHelper);

var loggerProvider = new TestLoggerProvider();

Expand Down
Loading