Skip to content

Commit a6209f3

Browse files
Copilotdavidfowl
andcommitted
Add idempotency tests for environment callbacks
Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
1 parent cd7c709 commit a6209f3

5 files changed

Lines changed: 158 additions & 0 deletions

File tree

tests/Aspire.Hosting.Kafka.Tests/AddKafkaTests.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Net.Sockets;
55
using Aspire.Hosting.ApplicationModel;
6+
using Aspire.Hosting.Eventing;
67
using Aspire.Hosting.Utils;
78
using Microsoft.Extensions.DependencyInjection;
89

@@ -176,4 +177,55 @@ public void WithKafkaUIAddsAnUniqueContainerSetsItsNameAndInvokesConfigurationCa
176177
Assert.Equal(8080, kafkaUiEndpoint.TargetPort);
177178
Assert.Equal(port, kafkaUiEndpoint.Port);
178179
}
180+
181+
[Fact]
182+
public async Task KafkaEnvironmentCallbackIsIdempotent()
183+
{
184+
using var appBuilder = TestDistributedApplicationBuilder.Create();
185+
186+
var kafka = appBuilder.AddKafka("kafka")
187+
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27017));
188+
189+
// Call GetEnvironmentVariableValuesAsync multiple times to ensure callbacks are idempotent
190+
var config1 = await kafka.Resource.GetEnvironmentVariableValuesAsync();
191+
var config2 = await kafka.Resource.GetEnvironmentVariableValuesAsync();
192+
193+
// Both calls should succeed and return the same values
194+
Assert.Equal(config1.Count, config2.Count);
195+
Assert.Contains(config1, kvp => kvp.Key == "KAFKA_LISTENERS");
196+
Assert.Contains(config2, kvp => kvp.Key == "KAFKA_LISTENERS");
197+
Assert.Equal(
198+
config1.First(kvp => kvp.Key == "KAFKA_LISTENERS").Value,
199+
config2.First(kvp => kvp.Key == "KAFKA_LISTENERS").Value);
200+
}
201+
202+
[Fact]
203+
public async Task KafkaUIEnvironmentCallbackIsIdempotent()
204+
{
205+
using var appBuilder = TestDistributedApplicationBuilder.Create();
206+
207+
var kafka = appBuilder.AddKafka("kafka1")
208+
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27017))
209+
.WithKafkaUI();
210+
211+
using var app = appBuilder.Build();
212+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
213+
var kafkaUiResource = Assert.Single(appModel.Resources.OfType<KafkaUIContainerResource>());
214+
215+
// Trigger the BeforeResourceStartedEvent to add environment callbacks
216+
await appBuilder.Eventing.PublishAsync(
217+
new BeforeResourceStartedEvent(kafkaUiResource, app.Services),
218+
EventDispatchBehavior.BlockingSequential);
219+
220+
// Call GetEnvironmentVariableValuesAsync multiple times to ensure callbacks are idempotent
221+
var config1 = await kafkaUiResource.GetEnvironmentVariableValuesAsync();
222+
var config2 = await kafkaUiResource.GetEnvironmentVariableValuesAsync();
223+
224+
// Both calls should succeed and return the same values
225+
Assert.Equal(config1.Count, config2.Count);
226+
Assert.Contains(config1, kvp => kvp.Key == "KAFKA_CLUSTERS_0_NAME");
227+
Assert.Contains(config2, kvp => kvp.Key == "KAFKA_CLUSTERS_0_NAME");
228+
Assert.Equal("kafka1", config1.First(kvp => kvp.Key == "KAFKA_CLUSTERS_0_NAME").Value);
229+
Assert.Equal("kafka1", config2.First(kvp => kvp.Key == "KAFKA_CLUSTERS_0_NAME").Value);
230+
}
179231
}

tests/Aspire.Hosting.MongoDB.Tests/AddMongoDBTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,30 @@ public void CanAddDatabasesWithTheSameNameOnMultipleServers()
286286
Assert.Equal("mongodb://admin:{mongo1-password.value}@{mongo1.bindings.tcp.host}:{mongo1.bindings.tcp.port}/imports?authSource=admin&authMechanism=SCRAM-SHA-256", db1.Resource.ConnectionStringExpression.ValueExpression);
287287
Assert.Equal("mongodb://admin:{mongo2-password.value}@{mongo2.bindings.tcp.host}:{mongo2.bindings.tcp.port}/imports?authSource=admin&authMechanism=SCRAM-SHA-256", db2.Resource.ConnectionStringExpression.ValueExpression);
288288
}
289+
290+
[Fact]
291+
public async Task MongoExpressEnvironmentCallbackIsIdempotent()
292+
{
293+
using var appBuilder = TestDistributedApplicationBuilder.Create();
294+
295+
var mongo = appBuilder.AddMongoDB("mongo")
296+
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27017))
297+
.WithMongoExpress();
298+
299+
using var app = appBuilder.Build();
300+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
301+
var mongoExpressResource = Assert.Single(appModel.Resources.OfType<MongoExpressContainerResource>());
302+
303+
// Call GetEnvironmentVariableValuesAsync multiple times to ensure callbacks are idempotent
304+
var config1 = await mongoExpressResource.GetEnvironmentVariableValuesAsync();
305+
var config2 = await mongoExpressResource.GetEnvironmentVariableValuesAsync();
306+
307+
// Both calls should succeed and return the same values
308+
Assert.Equal(config1.Count, config2.Count);
309+
Assert.Contains(config1, kvp => kvp.Key == "ME_CONFIG_MONGODB_SERVER");
310+
Assert.Contains(config2, kvp => kvp.Key == "ME_CONFIG_MONGODB_SERVER");
311+
Assert.Equal(
312+
config1.First(kvp => kvp.Key == "ME_CONFIG_MONGODB_SERVER").Value,
313+
config2.First(kvp => kvp.Key == "ME_CONFIG_MONGODB_SERVER").Value);
314+
}
289315
}

tests/Aspire.Hosting.MySql.Tests/AddMySqlTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Net.Sockets;
55
using System.Text.RegularExpressions;
66
using Aspire.Hosting.ApplicationModel;
7+
using Aspire.Hosting.Eventing;
78
using Aspire.Hosting.Tests.Utils;
89
using Aspire.Hosting.Utils;
910
using Microsoft.Extensions.DependencyInjection;
@@ -365,4 +366,35 @@ public async Task VerifyMySqlServerResourceWithPassword()
365366
var connectionString = await connectionStringResource.ConnectionStringExpression.GetValueAsync(default);
366367
Assert.Equal("Server=localhost;Port=2000;User ID=root;Password=p@ssw0rd1", connectionString);
367368
}
369+
370+
[Fact]
371+
public async Task PhpMyAdminEnvironmentCallbackIsIdempotent()
372+
{
373+
using var appBuilder = TestDistributedApplicationBuilder.Create();
374+
375+
var mysql = appBuilder.AddMySql("mysql")
376+
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 3306))
377+
.WithPhpMyAdmin();
378+
379+
using var app = appBuilder.Build();
380+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
381+
var phpMyAdminResource = Assert.Single(appModel.Resources.OfType<PhpMyAdminContainerResource>());
382+
383+
// Trigger the BeforeResourceStartedEvent to add environment callbacks
384+
await appBuilder.Eventing.PublishAsync(
385+
new BeforeResourceStartedEvent(phpMyAdminResource, app.Services),
386+
EventDispatchBehavior.BlockingSequential);
387+
388+
// Call GetEnvironmentVariableValuesAsync multiple times to ensure callbacks are idempotent
389+
var config1 = await phpMyAdminResource.GetEnvironmentVariableValuesAsync();
390+
var config2 = await phpMyAdminResource.GetEnvironmentVariableValuesAsync();
391+
392+
// Both calls should succeed and return the same values
393+
Assert.Equal(config1.Count, config2.Count);
394+
Assert.Contains(config1, kvp => kvp.Key == "PMA_HOST");
395+
Assert.Contains(config2, kvp => kvp.Key == "PMA_HOST");
396+
Assert.Equal(
397+
config1.First(kvp => kvp.Key == "PMA_HOST").Value,
398+
config2.First(kvp => kvp.Key == "PMA_HOST").Value);
399+
}
368400
}

tests/Aspire.Hosting.PostgreSQL.Tests/AddPostgresTests.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,4 +684,26 @@ public async Task VerifyPostgresServerResourceWithUserName()
684684
Assert.Equal($"Host=localhost;Port=2000;Username=user1;Password={postgres.Resource.PasswordParameter.Value}", connectionString);
685685
#pragma warning restore CS0618 // Type or member is obsolete
686686
}
687+
688+
[Fact]
689+
public async Task PostgresEnvironmentCallbackIsIdempotent()
690+
{
691+
using var appBuilder = TestDistributedApplicationBuilder.Create();
692+
693+
var postgres = appBuilder.AddPostgres("postgres")
694+
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5432));
695+
696+
// Call GetEnvironmentVariableValuesAsync multiple times to ensure callbacks are idempotent
697+
var config1 = await postgres.Resource.GetEnvironmentVariableValuesAsync();
698+
var config2 = await postgres.Resource.GetEnvironmentVariableValuesAsync();
699+
700+
// Both calls should succeed and return the same values
701+
Assert.Equal(config1.Count, config2.Count);
702+
// Verify that environment variables are set consistently across multiple calls
703+
Assert.All(config1, kvp =>
704+
{
705+
Assert.True(config2.ContainsKey(kvp.Key), $"Key {kvp.Key} should exist in second call");
706+
Assert.Equal(kvp.Value, config2[kvp.Key]);
707+
});
708+
}
687709
}

tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,4 +701,30 @@ public async Task AddRedisContainerWithPasswordAnnotationMetadata()
701701
Assert.Equal("{myRedis.bindings.tcp.host}:{myRedis.bindings.tcp.port},password={pass.value}", connectionStringResource.ConnectionStringExpression.ValueExpression);
702702
Assert.StartsWith($"localhost:5001,password={password}", connectionString);
703703
}
704+
705+
[Fact]
706+
public async Task RedisInsightEnvironmentCallbackIsIdempotent()
707+
{
708+
using var appBuilder = TestDistributedApplicationBuilder.Create();
709+
710+
var redis = appBuilder.AddRedis("redis")
711+
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 6379))
712+
.WithRedisInsight();
713+
714+
using var app = appBuilder.Build();
715+
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
716+
var redisInsightResource = Assert.Single(appModel.Resources.OfType<RedisInsightResource>());
717+
718+
// Call GetEnvironmentVariableValuesAsync multiple times to ensure callbacks are idempotent
719+
var config1 = await redisInsightResource.GetEnvironmentVariableValuesAsync();
720+
var config2 = await redisInsightResource.GetEnvironmentVariableValuesAsync();
721+
722+
// Both calls should succeed and return the same values
723+
Assert.Equal(config1.Count, config2.Count);
724+
Assert.Contains(config1, kvp => kvp.Key == "RI_REDIS_HOST1");
725+
Assert.Contains(config2, kvp => kvp.Key == "RI_REDIS_HOST1");
726+
Assert.Equal(
727+
config1.First(kvp => kvp.Key == "RI_REDIS_HOST1").Value,
728+
config2.First(kvp => kvp.Key == "RI_REDIS_HOST1").Value);
729+
}
704730
}

0 commit comments

Comments
 (0)