Skip to content

Commit

Permalink
test: add go feature flag integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Odonno committed Jan 30, 2025
1 parent 8e5d60e commit 9498942
Show file tree
Hide file tree
Showing 14 changed files with 783 additions and 0 deletions.
14 changes: 14 additions & 0 deletions CommunityToolkit.Aspire.sln
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hos
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.GoFeatureFlag", "src\CommunityToolkit.Aspire.GoFeatureFlag\CommunityToolkit.Aspire.GoFeatureFlag.csproj", "{C40D5274-DACF-4962-A58A-F08BDA80D0E2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.GoFeatureFlag.Tests", "tests\CommunityToolkit.Aspire.GoFeatureFlag.Tests\CommunityToolkit.Aspire.GoFeatureFlag.Tests.csproj", "{F4891827-BE07-4547-AF89-2734FB8DE6D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests", "tests\CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests\CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests.csproj", "{96458513-CAA8-498B-B4EE-3BF994140741}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -611,6 +615,14 @@ Global
{C40D5274-DACF-4962-A58A-F08BDA80D0E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C40D5274-DACF-4962-A58A-F08BDA80D0E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C40D5274-DACF-4962-A58A-F08BDA80D0E2}.Release|Any CPU.Build.0 = Release|Any CPU
{F4891827-BE07-4547-AF89-2734FB8DE6D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4891827-BE07-4547-AF89-2734FB8DE6D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4891827-BE07-4547-AF89-2734FB8DE6D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4891827-BE07-4547-AF89-2734FB8DE6D5}.Release|Any CPU.Build.0 = Release|Any CPU
{96458513-CAA8-498B-B4EE-3BF994140741}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96458513-CAA8-498B-B4EE-3BF994140741}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96458513-CAA8-498B-B4EE-3BF994140741}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96458513-CAA8-498B-B4EE-3BF994140741}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -738,6 +750,8 @@ Global
{C4C113D8-7E40-4962-BBD8-735B478933D6} = {002E2F54-BB99-41F2-98D5-D6CC3B6A2845}
{3CC919A7-3550-4046-99CF-BC164F817E63} = {002E2F54-BB99-41F2-98D5-D6CC3B6A2845}
{C40D5274-DACF-4962-A58A-F08BDA80D0E2} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{F4891827-BE07-4547-AF89-2734FB8DE6D5} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{96458513-CAA8-498B-B4EE-3BF994140741} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {08B1D4B8-D2C5-4A64-BB8B-E1A2B29525F0}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Aspire.Components.Common.Tests;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using OpenFeature.Contrib.Providers.GOFeatureFlag;

namespace CommunityToolkit.Aspire.GoFeatureFlag.Tests;

public class AspireGoFeatureFlagClientExtensionsTest(GoFeatureFlagContainerFixture containerFixture) : IClassFixture<GoFeatureFlagContainerFixture>
{
private const string DefaultConnectionName = "goff";

private string DefaultConnectionString =>
RequiresDockerAttribute.IsSupported ? containerFixture.GetConnectionString() : "http://localhost:27011";

[Theory]
[InlineData(true)]
[InlineData(false)]
[RequiresDocker]
public async Task AddGoFeatureFlagClient_HealthCheckShouldBeRegisteredWhenEnabled(bool useKeyed)
{
var key = DefaultConnectionName;

var builder = CreateBuilder(DefaultConnectionString);

if (useKeyed)
{
builder.AddKeyedGoFeatureFlagClient(key, settings =>
{
settings.DisableHealthChecks = false;
});
}
else
{
builder.AddGoFeatureFlagClient(DefaultConnectionName, settings =>
{
settings.DisableHealthChecks = false;
});
}

using var host = builder.Build();

var healthCheckService = host.Services.GetRequiredService<HealthCheckService>();

var healthCheckReport = await healthCheckService.CheckHealthAsync();

var healthCheckName = useKeyed ? $"Goff_{key}" : "Goff";

Assert.Contains(healthCheckReport.Entries, x => x.Key == healthCheckName);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void AddGoFeatureFlagClient_HealthCheckShouldNotBeRegisteredWhenDisabled(bool useKeyed)
{
var builder = CreateBuilder(DefaultConnectionString);

if (useKeyed)
{
builder.AddKeyedGoFeatureFlagClient(DefaultConnectionName, settings =>
{
settings.DisableHealthChecks = true;
});
}
else
{
builder.AddGoFeatureFlagClient(DefaultConnectionName, settings =>
{
settings.DisableHealthChecks = true;
});
}

using var host = builder.Build();

var healthCheckService = host.Services.GetService<HealthCheckService>();

Assert.Null(healthCheckService);
}

[Fact]
public void CanAddMultipleKeyedServices()
{
var builder = Host.CreateEmptyApplicationBuilder(null);
builder.Configuration.AddInMemoryCollection([
new KeyValuePair<string, string?>("ConnectionStrings:goff1", "http://localhost:19530"),
new KeyValuePair<string, string?>("ConnectionStrings:goff2", "http://localhost:19531"),
new KeyValuePair<string, string?>("ConnectionStrings:goff3", "http://localhost:19532"),
]);

builder.AddGoFeatureFlagClient("goff1");
builder.AddKeyedGoFeatureFlagClient("goff2");
builder.AddKeyedGoFeatureFlagClient("goff3");

using var host = builder.Build();

var client1 = host.Services.GetRequiredService<GoFeatureFlagProvider>();
var client2 = host.Services.GetRequiredKeyedService<GoFeatureFlagProvider>("goff2");
var client3 = host.Services.GetRequiredKeyedService<GoFeatureFlagProvider>("goff3");

Assert.NotSame(client1, client2);
Assert.NotSame(client1, client3);
Assert.NotSame(client2, client3);
}

[Fact]
public void CanAddClientFromEncodedConnectionString()
{
var builder = Host.CreateEmptyApplicationBuilder(null);

builder.Configuration.AddInMemoryCollection([
new KeyValuePair<string, string?>("ConnectionStrings:goff1", "Endpoint=http://localhost:19530"),
new KeyValuePair<string, string?>("ConnectionStrings:goff2", "Endpoint=http://localhost:19531"),
]);

builder.AddGoFeatureFlagClient("goff1");
builder.AddKeyedGoFeatureFlagClient("goff2");

using var host = builder.Build();

var client1 = host.Services.GetRequiredService<GoFeatureFlagProvider>();
var client2 = host.Services.GetRequiredKeyedService<GoFeatureFlagProvider>("goff2");

Assert.NotSame(client1, client2);
}

private static HostApplicationBuilder CreateBuilder(string connectionString)
{
var builder = Host.CreateEmptyApplicationBuilder(null);

builder.Configuration.AddInMemoryCollection([
new KeyValuePair<string, string?>($"ConnectionStrings:{DefaultConnectionName}", connectionString)
]);
return builder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Testcontainers" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\CommunityToolkit.Aspire.GoFeatureFlag\CommunityToolkit.Aspire.GoFeatureFlag.csproj" />
<ProjectReference Include="..\CommunityToolkit.Aspire.Testing\CommunityToolkit.Aspire.Testing.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)src\CommunityToolkit.Aspire.Hosting.GoFeatureFlag\GoFeatureFlagContainerImageTags.cs" />
</ItemGroup>

<ItemGroup>
<None Update="goff\*.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace CommunityToolkit.Aspire.GoFeatureFlag.Tests;

public class ConfigurationTests
{
[Fact]
public void EndpointIsNullByDefault() =>
Assert.Null(new GoFeatureFlagClientSettings().Endpoint);

[Fact]
public void HealthChecksEnabledByDefault() =>
Assert.False(new GoFeatureFlagClientSettings().DisableHealthChecks);
}
115 changes: 115 additions & 0 deletions tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using OpenFeature.Contrib.Providers.GOFeatureFlag;
using OpenFeature.Model;

namespace CommunityToolkit.Aspire.GoFeatureFlag.Tests;

public class ConformanceTests : ConformanceTests<GoFeatureFlagProvider, GoFeatureFlagClientSettings>, IClassFixture<GoFeatureFlagContainerFixture>
{
private readonly GoFeatureFlagContainerFixture _containerFixture;

protected override ServiceLifetime ServiceLifetime => ServiceLifetime.Singleton;

protected override string ActivitySourceName => string.Empty;

protected override string[] RequiredLogCategories => [];

protected override bool CanConnectToServer => RequiresDockerAttribute.IsSupported;

protected override bool SupportsKeyedRegistrations => true;

public ConformanceTests(GoFeatureFlagContainerFixture containerFixture)
{
_containerFixture = containerFixture;
}

protected override void PopulateConfiguration(ConfigurationManager configuration, string? key = null)
{
var connectionString = RequiresDockerAttribute.IsSupported ?
$"{_containerFixture.GetConnectionString()}" :
"Endpoint=http://localhost:27017";

configuration.AddInMemoryCollection(
[
new KeyValuePair<string, string?>(CreateConfigKey("Aspire:GoFeatureFlag:Client", key, "Endpoint"), GetConnectionStringKeyValue(connectionString,"Endpoint")),
new KeyValuePair<string, string?>($"ConnectionStrings:{key}", $"{connectionString}")
]);
}

internal static string GetConnectionStringKeyValue(string connectionString, string configKey)
{
// from the connection string, extract the key value of the configKey
var parts = connectionString.Split(';');
foreach (var part in parts)
{
var keyValue = part.Split('=');
if (keyValue.Length == 2 && keyValue[0].Equals(configKey, StringComparison.OrdinalIgnoreCase))
{
return keyValue[1];
}
}
return string.Empty;
}

protected override void RegisterComponent(HostApplicationBuilder builder, Action<GoFeatureFlagClientSettings>? configure = null, string? key = null)
{
if (key is null)
{
builder.AddGoFeatureFlagClient("goff", configureSettings: configure);
}
else
{
builder.AddKeyedGoFeatureFlagClient(key, configureSettings: configure);
}
}

protected override string ValidJsonConfig => """
{
"Aspire": {
"GoFeatureFlag": {
"Client": {
"Endpoint": "http://localhost:19530"
}
}
}
}
""";

protected override (string json, string error)[] InvalidJsonToErrorMessage => new[]
{
("""{"Aspire": { "GoFeatureFlag":{ "Client": { "Endpoint": 3 }}}}""", "Value is \"integer\" but should be \"string\""),
("""{"Aspire": { "GoFeatureFlag":{ "Client": { "Endpoint": "hello" }}}}""", "Value does not match format \"uri\"")
};

protected override void SetHealthCheck(GoFeatureFlagClientSettings options, bool enabled)
{
options.DisableHealthChecks = !enabled;
}

protected override void SetMetrics(GoFeatureFlagClientSettings options, bool enabled)
{
throw new NotImplementedException();
}

protected override void SetTracing(GoFeatureFlagClientSettings options, bool enabled)
{
throw new NotImplementedException();
}

protected override void TriggerActivity(GoFeatureFlagProvider service)
{
using var source = new CancellationTokenSource(100);

var context = EvaluationContext.Builder()
.Set("targetingKey", Guid.NewGuid().ToString())
.Set("anonymous", true)
.Build();
service.InitializeAsync(context, source.Token).Wait();
}
}
Loading

0 comments on commit 9498942

Please sign in to comment.