Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
add testcases
  • Loading branch information
zhiyuanliang-ms committed May 20, 2025
commit af4843ef705ffdeafed48a9d62bf103ac4195eaf
Original file line number Diff line number Diff line change
Expand Up @@ -218,17 +218,28 @@ private IEnumerable<IConfigurationSection> GetDotnetFeatureDefinitionSections()

private IEnumerable<IConfigurationSection> GetMicrosoftFeatureDefinitionSections()
{
var configurationRoot = _configuration as IConfigurationRoot;
if (configurationRoot == null)
var featureDefinitionSections = new List<IConfigurationSection>();

FindFeatureFlags(_configuration, featureDefinitionSections);

return featureDefinitionSections;
}

private void FindFeatureFlags(IConfiguration configuration, List<IConfigurationSection> featureDefinitionSections)
{
if (!(configuration is IConfigurationRoot configurationRoot))
{
// Fallback to current behavior if not an IConfigurationRoot
return _configuration
IConfigurationSection featureFlagsSection = configuration
.GetSection(MicrosoftFeatureManagementFields.FeatureManagementSectionName)
.GetSection(MicrosoftFeatureManagementFields.FeatureFlagsSectionName)
.GetChildren();
}
.GetSection(MicrosoftFeatureManagementFields.FeatureFlagsSectionName);

var mergedSections = new List<IConfigurationSection>();
if (featureFlagsSection.Exists())
{
featureDefinitionSections.AddRange(featureFlagsSection.GetChildren());
}

return;
}

foreach (IConfigurationProvider provider in configurationRoot.Providers)
{
Expand All @@ -248,18 +259,14 @@ private IEnumerable<IConfigurationSection> GetMicrosoftFeatureDefinitionSections

if (featureFlagsSection.Exists())
{
mergedSections.AddRange(featureFlagsSection.GetChildren());
featureDefinitionSections.AddRange(featureFlagsSection.GetChildren());
}
}
else if (provider is ChainedConfigurationProvider chainedProvider)
{
IConfigurationSection featureFlagsSection = chainedProvider.Configuration
.GetSection(MicrosoftFeatureManagementFields.FeatureManagementSectionName)
.GetSection(MicrosoftFeatureManagementFields.FeatureFlagsSectionName);
FindFeatureFlags(chainedProvider.Configuration, featureDefinitionSections);
}
}

return mergedSections;
}

private FeatureDefinition ParseDotnetSchemaFeatureDefinition(IConfigurationSection configurationSection)
Expand Down
44 changes: 44 additions & 0 deletions tests/Tests.FeatureManagement/FeatureManagementTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,50 @@ public async Task LastFeatureFlagWins()

Assert.True(await featureManager.IsEnabledAsync(Features.DuplicateFlag));
}

[Fact]
public async Task MergesFeatureFlagsFromDifferentConfigurationSources()
{
/*
* appsettings1.json
* Feature1: true
* Feature2: true
* FeatureA: true
*
* appsettings2.json
* Feature1: true
* Feature2: false
* FeatureB: true
*
* appsettings3.json
* Feature1: false
* Feature2: false
* FeatureC: true
*/

IConfiguration configuration1 = new ConfigurationBuilder()
.AddJsonFile("appsettings1.json")
.AddJsonFile("appsettings2.json")
.Build();

IConfiguration configuration2 = new ConfigurationBuilder()
.AddConfiguration(configuration1) // chained configuration
.AddJsonFile("appsettings3.json")
.Build();

var featureManager1 = new FeatureManager(new ConfigurationFeatureDefinitionProvider(configuration1));
Assert.True(await featureManager1.IsEnabledAsync("FeatureA"));
Assert.True(await featureManager1.IsEnabledAsync("FeatureB"));
Assert.True(await featureManager1.IsEnabledAsync("Feature1"));
Assert.False(await featureManager1.IsEnabledAsync("Feature2")); // appsettings2 should override appsettings1

var featureManager2 = new FeatureManager(new ConfigurationFeatureDefinitionProvider(configuration2));
Assert.True(await featureManager2.IsEnabledAsync("FeatureA"));
Assert.True(await featureManager2.IsEnabledAsync("FeatureB"));
Assert.True(await featureManager2.IsEnabledAsync("FeatureC"));
Assert.False(await featureManager2.IsEnabledAsync("Feature1")); // appsettings3 should override previous settings
Assert.False(await featureManager2.IsEnabledAsync("Feature2")); // appsettings3 should override previous settings
}
}

public class FeatureManagementFeatureFilterGeneralTest
Expand Down
11 changes: 10 additions & 1 deletion tests/Tests.FeatureManagement/Tests.FeatureManagement.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net8.0;net9.0</TargetFrameworks>
Expand Down Expand Up @@ -43,6 +43,15 @@
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings1.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings2.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings3.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="DotnetFeatureManagementSchema.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
18 changes: 18 additions & 0 deletions tests/Tests.FeatureManagement/appsettings1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"feature_management": {
"feature_flags": [
{
"id": "Feature1",
"enabled": true
},
{
"id": "Feature2",
"enabled": true
},
{
"id": "FeatureA",
"enabled": true
}
]
}
}
18 changes: 18 additions & 0 deletions tests/Tests.FeatureManagement/appsettings2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"feature_management": {
"feature_flags": [
{
"id": "Feature1",
"enabled": true
},
{
"id": "Feature2",
"enabled": false
},
{
"id": "FeatureB",
"enabled": true
}
]
}
}
18 changes: 18 additions & 0 deletions tests/Tests.FeatureManagement/appsettings3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"feature_management": {
"feature_flags": [
{
"id": "Feature1",
"enabled": false
},
{
"id": "Feature2",
"enabled": false
},
{
"id": "FeatureC",
"enabled": true
}
]
}
}