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

[tests] Improve Cosmos EndToEnd test #5639

Closed
wants to merge 6 commits into from
Closed
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: 63 additions & 0 deletions tests/Aspire.EndToEnd.Tests/IntegrationServicesFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using Xunit.Abstractions;
using Aspire.TestProject;
using Aspire.Workload.Tests;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using Xunit.Sdk;

namespace Aspire.EndToEnd.Tests;

Expand All @@ -24,6 +27,8 @@ public sealed class IntegrationServicesFixture : IAsyncLifetime
#endif

public static string? TestScenario { get; } = EnvironmentVariables.TestScenario;
private const int DefaultWaitForTextsTimeoutSecs = 8 * 60;

public Dictionary<string, ProjectInfo> Projects => Project?.InfoTable ?? throw new InvalidOperationException("Project is not initialized");
private TestResourceNames _resourcesToSkip;
private readonly IMessageSink _diagnosticMessageSink;
Expand Down Expand Up @@ -82,11 +87,60 @@ public async Task InitializeAsync()
extraArgs += $"--skip-resources {skipArg}";
}
await Project.StartAppHostAsync([extraArgs]);
var waitForTextsTask = WaitForAllTextAsync(TimeSpan.FromSeconds(DefaultWaitForTextsTimeoutSecs));

foreach (var project in Projects.Values)
{
project.Client = AspireProject.Client.Value;
}

await waitForTextsTask;
}

public async Task WaitForAllTextAsync(TimeSpan timeSpan)
{
string[] waitForTexts = GetWaitForTexts();
if (waitForTexts.Length == 0)
{
return;
}

ConcurrentDictionary<string, Regex> waitForTextRegexes = new();
foreach (var waitForText in waitForTexts)
{
waitForTextRegexes.TryAdd(waitForText, new Regex(waitForText));
}

TaskCompletionSource tcs = new();
Project.AppHostProcess!.OutputDataReceived += (_, e) => CheckText(e.Data);
Project.AppHostProcess!.ErrorDataReceived += (_, e) => CheckText(e.Data);

try
{
await tcs.Task.WaitAsync(timeSpan);
}
catch (TimeoutException te)
{
throw new XunitException($"Timed out waiting for the following texts after {timeSpan.TotalSeconds} secs: '{string.Join("', '", waitForTextRegexes.Keys)}'", te);
}

void CheckText(string? line)
{
if (string.IsNullOrEmpty(line))
{
return;
}

if (waitForTextRegexes.Where(r => r.Value.IsMatch(line)).Select(kvp => kvp.Key).FirstOrDefault() is string matched)
{
waitForTextRegexes.TryRemove(matched, out _);
}

if (waitForTextRegexes.IsEmpty)
{
tcs.TrySetResult();
}
}
}

public Task DumpComponentLogsAsync(TestResourceNames resource, ITestOutputHelper? testOutputArg = null)
Expand Down Expand Up @@ -165,4 +219,13 @@ private static TestResourceNames GetResourcesToSkip()

return resourcesToSkip;
}

private static string[] GetWaitForTexts() => TestScenario switch
{
"cosmos" => [
"TestProject.AppHost.Resources.cosmos\\[0\\] .* Started$",
"TestProject.AppHost.Resources.integrationservicea\\[0\\] .* Application started"
],
_ => []
};
}
1 change: 1 addition & 0 deletions tests/Aspire.EndToEnd.Tests/IntegrationServicesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public Task VerifyComponentWorks(TestResourceNames resourceName)
_integrationServicesFixture.EnsureAppHasResources(resourceName);
try
{
_testOutput.WriteLine($"**** Sending request for {resourceName}");
var response = await _integrationServicesFixture.IntegrationServiceA.HttpGetAsync("http", $"/{resourceName}/verify");
var responseContent = await response.Content.ReadAsStringAsync();

Expand Down
17 changes: 16 additions & 1 deletion tests/testproject/TestProject.AppHost/TestProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Aspire.Hosting.Testing;
using Aspire.TestProject;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

public class TestProgram : IDisposable
{
Expand Down Expand Up @@ -85,7 +86,9 @@ private TestProgram(
}
if (!resourcesToSkip.HasFlag(TestResourceNames.cosmos) || !resourcesToSkip.HasFlag(TestResourceNames.efcosmos))
{
var cosmos = AppBuilder.AddAzureCosmosDB("cosmos").RunAsEmulator();
var cosmos = AppBuilder
.AddAzureCosmosDB("cosmos")
.RunAsEmulator();
IntegrationServiceABuilder = IntegrationServiceABuilder.WithReference(cosmos);
}
if (!resourcesToSkip.HasFlag(TestResourceNames.eventhubs))
Expand All @@ -95,6 +98,18 @@ private TestProgram(
}
}

AppBuilder.Services.AddLogging(logging =>
{
logging.ClearProviders();
logging.AddSimpleConsole(configure =>
{
configure.SingleLine = true;
});
logging.SetMinimumLevel(LogLevel.Debug);
logging.AddFilter("Aspire", LogLevel.Debug);
logging.AddFilter(builder.Environment.ApplicationName, LogLevel.Debug);
});

AppBuilder.Services.AddHostedService<ResourceLoggerForwarderService>();
AppBuilder.Services.AddLifecycleHook<EndPointWriterHook>();
AppBuilder.Services.AddHttpClient();
Expand Down
2 changes: 1 addition & 1 deletion tests/testproject/TestProject.WorkerA/Worker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Worker running at: {Time}", DateTimeOffset.Now);
}
await Task.Delay(1000, stoppingToken);
await Task.Delay(30_000, stoppingToken);
}
}
}