From d3182ea5b53bf6d34cfbc62129c46146dd0c7fae Mon Sep 17 00:00:00 2001 From: Joseph Woodward Date: Wed, 10 Jun 2020 09:35:20 +0100 Subject: [PATCH 1/2] Enable missing feature switch --- .../FeatureManagementError.cs | 7 ++- .../FeatureManagementOptions.cs | 6 ++ .../FeatureManager.cs | 3 + .../FeatureManagement.cs | 62 +++++++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.FeatureManagement/FeatureManagementError.cs b/src/Microsoft.FeatureManagement/FeatureManagementError.cs index a1e3319f..1979cff1 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementError.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementError.cs @@ -16,6 +16,11 @@ public enum FeatureManagementError /// /// A feature filter configured for the feature being evaluated is an ambiguous reference to multiple registered feature filters. /// - AmbiguousFeatureFilter + AmbiguousFeatureFilter, + + /// + /// A feature filter is missing configuration + /// + MissingFeature } } diff --git a/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs b/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs index 9322934e..eb763537 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs @@ -13,5 +13,11 @@ public class FeatureManagementOptions /// If missing feature filters are not ignored an exception will be thrown when attempting to evaluate a feature that depends on a missing feature filter. /// public bool IgnoreMissingFeatureFilters { get; set; } + + /// + /// Controls the behavior of feature evaluation when the dependent feature declaration is missing. + /// If missing feature declaration is not ignored an exception will be thrown when attempting to evaluate a feature that depends on a missing feature declaration. + /// + public bool IgnoreMissingFeatures { get; set; } } } diff --git a/src/Microsoft.FeatureManagement/FeatureManager.cs b/src/Microsoft.FeatureManagement/FeatureManager.cs index 6f0b2a14..f14c2d6d 100644 --- a/src/Microsoft.FeatureManagement/FeatureManager.cs +++ b/src/Microsoft.FeatureManagement/FeatureManager.cs @@ -140,6 +140,9 @@ private async Task IsEnabledAsync(string feature, TContext appCo } } } + } else if (!_options.IgnoreMissingFeatures) + { + throw new FeatureManagementException(FeatureManagementError.MissingFeature, $"The feature declaration for specified feature '{feature}' was not found."); } foreach (ISessionManager sessionManager in _sessionManagers) diff --git a/tests/Tests.FeatureManagement/FeatureManagement.cs b/tests/Tests.FeatureManagement/FeatureManagement.cs index 1076d81c..5bf76f70 100644 --- a/tests/Tests.FeatureManagement/FeatureManagement.cs +++ b/tests/Tests.FeatureManagement/FeatureManagement.cs @@ -14,6 +14,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Reflection; using System.Threading.Tasks; using Xunit; @@ -25,6 +26,7 @@ public class FeatureManagement private const string OffFeature = "OffFeature"; private const string ConditionalFeature = "ConditionalFeature"; private const string ContextualFeature = "ContextualFeature"; + private const string MissingFeature = "MissingFeature"; [Fact] public async Task ReadsConfiguration() @@ -33,6 +35,12 @@ public async Task ReadsConfiguration() var services = new ServiceCollection(); + services + .Configure(options => + { + options.IgnoreMissingFeatures = true; + }); + services .AddSingleton(config) .AddFeatureManagement() @@ -483,5 +491,59 @@ public async Task SwallowsExceptionForMissingFeatureFilter() Assert.False(isEnabled); } + + [Fact] + public async Task ThrowsOnMissingFeature() + { + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + var services = new ServiceCollection(); + + services + .Configure(options => + { + options.IgnoreMissingFeatures = false; + }); + + services + .AddSingleton(config) + .AddFeatureManagement() + .AddFeatureFilter(); + + ServiceProvider serviceProvider = services.BuildServiceProvider(); + + IFeatureManager featureManager = serviceProvider.GetRequiredService(); + + FeatureManagementException e = await Assert.ThrowsAsync(async () => await featureManager.IsEnabledAsync(MissingFeature)); + + Assert.Equal(FeatureManagementError.MissingFeature, e.Error); + } + + [Fact] + public async Task SwallowsOnMissingFeature() + { + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + var services = new ServiceCollection(); + + services + .Configure(options => + { + options.IgnoreMissingFeatures = true; + }); + + services + .AddSingleton(config) + .AddFeatureManagement() + .AddFeatureFilter(); + + ServiceProvider serviceProvider = services.BuildServiceProvider(); + + IFeatureManager featureManager = serviceProvider.GetRequiredService(); + + var isEnabled = await featureManager.IsEnabledAsync(ConditionalFeature); + + Assert.False(isEnabled); + } } } From 822825f0df54236f524b4280fc3acbd73921d5b0 Mon Sep 17 00:00:00 2001 From: Joseph Woodward Date: Sun, 28 Jun 2020 19:23:02 +0100 Subject: [PATCH 2/2] Updates following feedback --- src/Microsoft.FeatureManagement/FeatureManagementError.cs | 2 +- src/Microsoft.FeatureManagement/FeatureManagementOptions.cs | 4 ++-- src/Microsoft.FeatureManagement/FeatureManager.cs | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.FeatureManagement/FeatureManagementError.cs b/src/Microsoft.FeatureManagement/FeatureManagementError.cs index 1979cff1..4631dd09 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementError.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementError.cs @@ -19,7 +19,7 @@ public enum FeatureManagementError AmbiguousFeatureFilter, /// - /// A feature filter is missing configuration + /// The specified feature does not exist. /// MissingFeature } diff --git a/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs b/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs index eb763537..0c444c1b 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs @@ -15,8 +15,8 @@ public class FeatureManagementOptions public bool IgnoreMissingFeatureFilters { get; set; } /// - /// Controls the behavior of feature evaluation when the dependent feature declaration is missing. - /// If missing feature declaration is not ignored an exception will be thrown when attempting to evaluate a feature that depends on a missing feature declaration. + /// Controls the behavior of feature evaluation when the specified feature does not exist. + /// If missing features are not ignored, an exception will be thrown when attempting to evaluate them. /// public bool IgnoreMissingFeatures { get; set; } } diff --git a/src/Microsoft.FeatureManagement/FeatureManager.cs b/src/Microsoft.FeatureManagement/FeatureManager.cs index f14c2d6d..2bbe542b 100644 --- a/src/Microsoft.FeatureManagement/FeatureManager.cs +++ b/src/Microsoft.FeatureManagement/FeatureManager.cs @@ -140,7 +140,8 @@ private async Task IsEnabledAsync(string feature, TContext appCo } } } - } else if (!_options.IgnoreMissingFeatures) + } + else if (!_options.IgnoreMissingFeatures) { throw new FeatureManagementException(FeatureManagementError.MissingFeature, $"The feature declaration for specified feature '{feature}' was not found."); }