mirror of
https://github.com/microsoft/autogen.git
synced 2025-07-17 14:01:06 +00:00

* integration tests used to use the samples - now they are separate * patch dictionary problem in serializer * add Message Registry with dead letter queue that gets checked on new subs.
230 lines
10 KiB
C#
230 lines
10 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// HelloAppHostIntegrationTests.cs
|
|
|
|
using System.Text.Json;
|
|
using Xunit.Abstractions;
|
|
|
|
namespace Microsoft.AutoGen.Integration.Tests;
|
|
|
|
public class HelloAppHostIntegrationTests(ITestOutputHelper testOutput)
|
|
{
|
|
private const string AppHostAssemblyName = "XlangTests.AppHost";
|
|
private const string DotNetResourceName = "HelloAgentTestsDotNET";
|
|
private const string PythonResourceName = "HelloAgentTestsPython";
|
|
private const string BackendResourceName = "AgentHost";
|
|
|
|
[Fact]
|
|
public async Task AppHostRunsCleanly()
|
|
{
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
app.EnsureNoErrorsLogged();
|
|
await app.StopAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Test_Dotnet_Sends_AgentHost_Delivers_and_Python_Receives()
|
|
{
|
|
//Prepare
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync(new[] { KnownResourceStates.Running }).WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
//Act
|
|
var expectedMessage = "INFO:autogen_core:Received a message from host: cloudEvent {";
|
|
var containsExpectedMessage = false;
|
|
app.EnsureNoErrorsLogged();
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(PythonResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
expectedMessage = "Hello World!";
|
|
containsExpectedMessage = false;
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(PythonResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
await app.StopAsync();
|
|
|
|
//Assert
|
|
Assert.True(containsExpectedMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Test_Python_Sends_AgentHost_Delivers_and_DotNet_Receives()
|
|
{
|
|
//Prepare
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync(new[] { KnownResourceStates.Running }).WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
//Act
|
|
var expectedMessage = "from Python!";
|
|
var containsExpectedMessage = false;
|
|
app.EnsureNoErrorsLogged();
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(DotNetResourceName, expectedMessage, TimeSpan.FromSeconds(60));
|
|
await app.StopAsync();
|
|
|
|
//Assert
|
|
Assert.True(containsExpectedMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Test_Python_Agent_Sends_And_AgentHost_Receives()
|
|
{
|
|
//Prepare
|
|
Environment.SetEnvironmentVariable("XLANG_TEST_NO_DOTNET", "true");
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync(new[] { KnownResourceStates.Running }).WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
//Act
|
|
var expectedMessage = "\"source\": \"HelloAgents/python\"";
|
|
var containsExpectedMessage = false;
|
|
app.EnsureNoErrorsLogged();
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(BackendResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
await app.StopAsync();
|
|
|
|
//Assert
|
|
Assert.True(containsExpectedMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Test_Dotnet_Agent_Sends_And_AgentHost_Receives()
|
|
{
|
|
//Prepare
|
|
Environment.SetEnvironmentVariable("XLANG_TEST_NO_PYTHON", "true");
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync(new[] { KnownResourceStates.Running }).WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
//Act
|
|
var expectedMessage = "\"source\": \"HelloAgents/dotnet\"";
|
|
var containsExpectedMessage = false;
|
|
app.EnsureNoErrorsLogged();
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(BackendResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
await app.StopAsync();
|
|
|
|
//Assert
|
|
Assert.True(containsExpectedMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Test_Dotnet_Agent_Sends_And_AgentHost_Delivers_Back_To_It()
|
|
{
|
|
//Prepare
|
|
Environment.SetEnvironmentVariable("XLANG_TEST_NO_PYTHON", "true");
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync(new[] { KnownResourceStates.Running }).WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
//Act
|
|
var expectedMessage = "Hello World!";
|
|
var containsExpectedMessage = false;
|
|
app.EnsureNoErrorsLogged();
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(DotNetResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
expectedMessage = "HelloAgent said Goodbye";
|
|
containsExpectedMessage = false;
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(DotNetResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
await app.StopAsync();
|
|
|
|
//Assert
|
|
Assert.True(containsExpectedMessage);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Test_Python_Agent_Sends_And_AgentHost_Delivers_Back_To_It()
|
|
{
|
|
//Prepare
|
|
Environment.SetEnvironmentVariable("XLANG_TEST_NO_DOTNET", "true");
|
|
var appHostPath = GetAssemblyPath(AppHostAssemblyName);
|
|
var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
|
|
await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
|
|
await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
|
|
await app.WaitForResourcesAsync(new[] { KnownResourceStates.Running }).WaitAsync(TimeSpan.FromSeconds(120));
|
|
|
|
//Act
|
|
var expectedMessage = "INFO:autogen_core:Received a message from host: cloudEvent {";
|
|
var containsExpectedMessage = false;
|
|
app.EnsureNoErrorsLogged();
|
|
containsExpectedMessage = await app.WaitForExpectedMessageInResourceLogs(PythonResourceName, expectedMessage, TimeSpan.FromSeconds(120));
|
|
await app.StopAsync();
|
|
//Assert
|
|
Assert.True(containsExpectedMessage);
|
|
}
|
|
|
|
private static string GetAssemblyPath(string assemblyName)
|
|
{
|
|
var parentDir = Directory.GetParent(AppContext.BaseDirectory)?.FullName;
|
|
var grandParentDir = parentDir is not null ? Directory.GetParent(parentDir)?.FullName : null;
|
|
var greatGrandParentDir = grandParentDir is not null ? Directory.GetParent(grandParentDir)?.FullName : null
|
|
?? AppContext.BaseDirectory;
|
|
var options = new EnumerationOptions { RecurseSubdirectories = true, MatchCasing = MatchCasing.CaseInsensitive };
|
|
if (greatGrandParentDir is not null)
|
|
{
|
|
var foundFile = Directory.GetFiles(greatGrandParentDir, $"{assemblyName}.dll", options).FirstOrDefault();
|
|
if (foundFile is not null)
|
|
{
|
|
return foundFile;
|
|
}
|
|
}
|
|
throw new FileNotFoundException($"Could not find {assemblyName}.dll in {grandParentDir ?? "unknown"} directory");
|
|
}
|
|
}
|
|
|
|
public class TestEndpoints : IXunitSerializable
|
|
{
|
|
// Required for deserialization
|
|
public TestEndpoints() { }
|
|
|
|
public TestEndpoints(string appHost, Dictionary<string, List<string>> resourceEndpoints)
|
|
{
|
|
AppHost = appHost;
|
|
ResourceEndpoints = resourceEndpoints;
|
|
}
|
|
|
|
public string? AppHost { get; set; }
|
|
|
|
public List<ResourceWait>? WaitForResources { get; set; }
|
|
|
|
public Dictionary<string, List<string>>? ResourceEndpoints { get; set; }
|
|
|
|
public void Deserialize(IXunitSerializationInfo info)
|
|
{
|
|
AppHost = info.GetValue<string>(nameof(AppHost));
|
|
WaitForResources = JsonSerializer.Deserialize<List<ResourceWait>>(info.GetValue<string>(nameof(WaitForResources)));
|
|
ResourceEndpoints = JsonSerializer.Deserialize<Dictionary<string, List<string>>>(info.GetValue<string>(nameof(ResourceEndpoints)));
|
|
}
|
|
|
|
public void Serialize(IXunitSerializationInfo info)
|
|
{
|
|
info.AddValue(nameof(AppHost), AppHost);
|
|
info.AddValue(nameof(WaitForResources), JsonSerializer.Serialize(WaitForResources));
|
|
info.AddValue(nameof(ResourceEndpoints), JsonSerializer.Serialize(ResourceEndpoints));
|
|
}
|
|
|
|
public override string? ToString() => $"{AppHost} ({ResourceEndpoints?.Count ?? 0} resources)";
|
|
|
|
public class ResourceWait(string resourceName, string targetState)
|
|
{
|
|
public string ResourceName { get; } = resourceName;
|
|
|
|
public string TargetState { get; } = targetState;
|
|
|
|
public void Deconstruct(out string resourceName, out string targetState)
|
|
{
|
|
resourceName = ResourceName;
|
|
targetState = TargetState;
|
|
}
|
|
}
|
|
}
|