You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

HelloAppHostIntegrationTests.cs 4.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // HelloAppHostIntegrationTests.cs
  3. using System.Text.Json;
  4. using Xunit.Abstractions;
  5. namespace Microsoft.AutoGen.Integration.Tests;
  6. public class HelloAppHostIntegrationTests(ITestOutputHelper testOutput)
  7. {
  8. [Theory, Trait("Category", "Integration")]
  9. [MemberData(nameof(AppHostAssemblies))]
  10. public async Task AppHostRunsCleanly(string appHostPath)
  11. {
  12. var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
  13. await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
  14. await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
  15. await app.WaitForResourcesAsync().WaitAsync(TimeSpan.FromSeconds(120));
  16. app.EnsureNoErrorsLogged();
  17. await app.StopAsync().WaitAsync(TimeSpan.FromSeconds(15));
  18. }
  19. [Theory, Trait("Category", "Integration")]
  20. [MemberData(nameof(TestEndpoints))]
  21. public async Task AppHostLogsHelloAgentE2E(TestEndpoints testEndpoints)
  22. {
  23. var appHostName = testEndpoints.AppHost!;
  24. var appHostPath = $"{appHostName}.dll";
  25. var appHost = await DistributedApplicationTestFactory.CreateAsync(appHostPath, testOutput);
  26. await using var app = await appHost.BuildAsync().WaitAsync(TimeSpan.FromSeconds(15));
  27. await app.StartAsync().WaitAsync(TimeSpan.FromSeconds(120));
  28. await app.WaitForResourcesAsync().WaitAsync(TimeSpan.FromSeconds(120));
  29. if (testEndpoints.WaitForResources?.Count > 0)
  30. {
  31. // Wait until each resource transitions to the required state
  32. var timeout = TimeSpan.FromMinutes(5);
  33. foreach (var (ResourceName, TargetState) in testEndpoints.WaitForResources)
  34. {
  35. await app.WaitForResource(ResourceName, TargetState).WaitAsync(timeout);
  36. }
  37. }
  38. //sleep to make sure the app is running
  39. await Task.Delay(20000);
  40. app.EnsureNoErrorsLogged();
  41. app.EnsureLogContains("HelloAgent said Goodbye");
  42. app.EnsureLogContains("Wild Hello from Python!");
  43. await app.StopAsync().WaitAsync(TimeSpan.FromSeconds(15));
  44. }
  45. public static TheoryData<string> AppHostAssemblies()
  46. {
  47. var appHostAssemblies = GetSamplesAppHostAssemblyPaths();
  48. var theoryData = new TheoryData<string, bool>();
  49. return new(appHostAssemblies.Select(p => Path.GetRelativePath(AppContext.BaseDirectory, p)));
  50. }
  51. public static TheoryData<TestEndpoints> TestEndpoints() =>
  52. new([
  53. new TestEndpoints("Hello.AppHost", new() {
  54. { "backend", ["/"] }
  55. }),
  56. ]);
  57. private static IEnumerable<string> GetSamplesAppHostAssemblyPaths()
  58. {
  59. // All the AppHost projects are referenced by this project so we can find them by looking for all their assemblies in the base directory
  60. return Directory.GetFiles(AppContext.BaseDirectory, "*.AppHost.dll")
  61. .Where(fileName => !fileName.EndsWith("Aspire.Hosting.AppHost.dll", StringComparison.OrdinalIgnoreCase));
  62. }
  63. }
  64. public class TestEndpoints : IXunitSerializable
  65. {
  66. // Required for deserialization
  67. public TestEndpoints() { }
  68. public TestEndpoints(string appHost, Dictionary<string, List<string>> resourceEndpoints)
  69. {
  70. AppHost = appHost;
  71. ResourceEndpoints = resourceEndpoints;
  72. }
  73. public string? AppHost { get; set; }
  74. public List<ResourceWait>? WaitForResources { get; set; }
  75. public Dictionary<string, List<string>>? ResourceEndpoints { get; set; }
  76. public void Deserialize(IXunitSerializationInfo info)
  77. {
  78. AppHost = info.GetValue<string>(nameof(AppHost));
  79. WaitForResources = JsonSerializer.Deserialize<List<ResourceWait>>(info.GetValue<string>(nameof(WaitForResources)));
  80. ResourceEndpoints = JsonSerializer.Deserialize<Dictionary<string, List<string>>>(info.GetValue<string>(nameof(ResourceEndpoints)));
  81. }
  82. public void Serialize(IXunitSerializationInfo info)
  83. {
  84. info.AddValue(nameof(AppHost), AppHost);
  85. info.AddValue(nameof(WaitForResources), JsonSerializer.Serialize(WaitForResources));
  86. info.AddValue(nameof(ResourceEndpoints), JsonSerializer.Serialize(ResourceEndpoints));
  87. }
  88. public override string? ToString() => $"{AppHost} ({ResourceEndpoints?.Count ?? 0} resources)";
  89. public class ResourceWait(string resourceName, string targetState)
  90. {
  91. public string ResourceName { get; } = resourceName;
  92. public string TargetState { get; } = targetState;
  93. public void Deconstruct(out string resourceName, out string targetState)
  94. {
  95. resourceName = ResourceName;
  96. targetState = TargetState;
  97. }
  98. }
  99. }