RecursivelyCheckAvailability_ADependsOnBAndAStartDateIsInFuture_AIsNotAvailable() { var allFeatureSettings = new[] { new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureA, Dependencies = new[] { Feature.TestFeatureB }, FeatureState = FeatureState.Enabled, StartDtg = 1.Day().Hence(), }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureB, Dependencies = new Feature[0], FeatureState = FeatureState.Enabled, }, }; FeatureSetting <Feature, Tenant> featureSetting = allFeatureSettings[0]; Assert.That(!_dependencyChecker.RecursivelyCheckAvailability(featureSetting, allFeatureSettings, new Tuple <FeatureVisibilityMode, Tenant , DateTime>( FeatureVisibilityMode.Normal, Tenant.All, DateTime.Now))); }
RecursivelyCheckAvailability_ADependsOnBAndBIsPreviewableAndModeIsNormal_AIsNotAvailable_BecauseModeShouldBePreview () { var allFeatureSettings = new[] { new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureA, Dependencies = new[] { Feature.TestFeatureB }, FeatureState = FeatureState.Enabled, }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureB, Dependencies = new Feature[0], FeatureState = FeatureState. Previewable, }, }; FeatureSetting <Feature, Tenant> featureSetting = allFeatureSettings[0]; Assert.That(!_dependencyChecker.RecursivelyCheckAvailability(featureSetting, allFeatureSettings, new Tuple <FeatureVisibilityMode, Tenant , DateTime>( FeatureVisibilityMode.Normal, Tenant.All, DateTime.Now))); }
RecursivelyCheckAvailability_AIsEstablishedAndDependsOnBAndBIsNotEstablished_ExceptionIsThrown_BecauseAllDependenciesOfEstablishedFeaturesMustThemselvesBeEstablished () { var allFeatureSettings = new[] { new FeatureSetting <Feature, Tenant> //A { Feature = Feature.TestFeatureA, Dependencies = new[] { Feature.TestFeatureB }, FeatureState = FeatureState.Established, StartDtg = 1.Day().Ago(), }, new FeatureSetting <Feature, Tenant> //B { Feature = Feature.TestFeatureB, Dependencies = new Feature[0], FeatureState = FeatureState.Enabled, StartDtg = 1.Day().Ago(), }, }; FeatureSetting <Feature, Tenant> featureSetting = allFeatureSettings[0]; Assert.Throws <EstablishedFeatureDependencyException <Feature> >( () => _dependencyChecker.RecursivelyCheckAvailability(featureSetting, allFeatureSettings, new Tuple <FeatureVisibilityMode, Tenant, DateTime>( FeatureVisibilityMode.Normal, Tenant.All, DateTime.Now) )); }
public void RecursivelyCheckAvailability_ADependsOnBAndBothEnabled_AIsAvailable() { var allFeatureSettings = new[] { new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureA, Dependencies = new[] { Feature.TestFeatureB }, FeatureState = FeatureState.Enabled, }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureB, Dependencies = new Feature[0], FeatureState = FeatureState.Enabled, }, }; FeatureSetting <Feature, Tenant> featureSetting = allFeatureSettings[0]; Assert.That(_dependencyChecker.RecursivelyCheckAvailability(featureSetting, allFeatureSettings, new Tuple <FeatureVisibilityMode, Tenant, DateTime>( FeatureVisibilityMode.Normal, Tenant.All, DateTime.Now))); }
RecursivelyCheckAvailability_ADependsOnBAndBDependsOnA_CircularDependencyExceptionIsThrown() { var allFeatureSettings = new[] { new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureA, Dependencies = new[] { Feature.TestFeatureB }, FeatureState = FeatureState.Enabled, }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureB, Dependencies = new[] { Feature.TestFeatureA }, FeatureState = FeatureState.Enabled, }, }; FeatureSetting <Feature, Tenant> featureSetting = allFeatureSettings[0]; Assert.Throws <CircularFeatureSettingDependencyException>( () => _dependencyChecker.RecursivelyCheckAvailability(featureSetting, allFeatureSettings, new Tuple <FeatureVisibilityMode, Tenant, DateTime>( FeatureVisibilityMode.Normal, Tenant.All, DateTime.Now))); }
public bool AllDependenciesAreSatisfiedForTheFeatureSetting( FeatureSetting <TFeatureEnum, DefaultTenantEnum> f, EmptyArgs availabilityCheckArgs) { return(_featureSettingAvailabilityChecker.RecursivelyCheckAvailability(f, _featureSettingRepository .GetFeatureSettings(), availabilityCheckArgs)); }
public static bool AvailabilityCheckFunction <TFeatureEnum>( FeatureSetting <TFeatureEnum, DefaultTenantEnum> s, Tuple <FeatureVisibilityMode, DateTime> args) where TFeatureEnum : struct { return((s.FeatureState == FeatureState.Enabled || (s.FeatureState == FeatureState.Previewable && args.Item1 == FeatureVisibilityMode.Preview)) && s.StartDtg <= args.Item2 && s.EndDtg > args.Item2); }
RecursivelyCheckAvailability_ADependsOnBAndDAndBDependsOnCAndAllAreEnabled_AIsEnabled() //a single feature can have multiple dependencies { var allFeatureSettings = new[] { new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureA, Dependencies = new[] { Feature. TestFeatureB, Feature. TestFeatureD }, FeatureState = FeatureState.Enabled, }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureB, Dependencies = new[] { Feature.TestFeatureC }, FeatureState = FeatureState.Enabled, }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureC, Dependencies = new Feature[0], FeatureState = FeatureState.Enabled, }, new FeatureSetting <Feature, Tenant> { Feature = Feature.TestFeatureD, Dependencies = new Feature[0], FeatureState = FeatureState.Enabled, }, }; FeatureSetting <Feature, Tenant> featureSetting = allFeatureSettings[0]; Assert.That(_dependencyChecker.RecursivelyCheckAvailability(featureSetting, allFeatureSettings, new Tuple <FeatureVisibilityMode, Tenant, DateTime>( FeatureVisibilityMode.Normal, Tenant.All, DateTime.Now))); }
/// <summary> /// Responsible for checking whether the dependencies for a feature are met. TODO: review use of tuple for params for custom availability checking fucntionality. /// </summary> public bool RecursivelyCheckAvailability( FeatureSetting <TFeatureEnum, TTenant> featureSettingToCheck, FeatureSetting <TFeatureEnum, TTenant>[] allFeatureSettings, TAvailabilityCheckArgs availabilityCheckArgs = default(TAvailabilityCheckArgs), List <FeatureSetting <TFeatureEnum, TTenant> > featuresCurrentlyUnderAnalysis = null) { Ensure.That <ArgumentNullException>(featureSettingToCheck.IsNotNull(), "featureSetting not supplied.") .And <ArgumentNullException>(allFeatureSettings.IsNotNull(), "allFeatureSettings not supplied."); featuresCurrentlyUnderAnalysis = featuresCurrentlyUnderAnalysis ?? new List <FeatureSetting <TFeatureEnum, TTenant> >(); if (featuresCurrentlyUnderAnalysis.Contains(featureSettingToCheck)) //see note 1 { throw new CircularFeatureSettingDependencyException(); } featuresCurrentlyUnderAnalysis.Add(featureSettingToCheck); foreach (TFeatureEnum dependency in featureSettingToCheck.Dependencies) { try { TFeatureEnum dependencyClosedOver = dependency; FeatureSetting <TFeatureEnum, TTenant> dependencySetting = allFeatureSettings.First(s => s.Feature.Equals(dependencyClosedOver)); if (featureSettingToCheck.FeatureState == FeatureState.Established && dependencySetting.FeatureState != FeatureState.Established) //see note 2 { throw new EstablishedFeatureDependencyException <TFeatureEnum>( featureSettingToCheck.Feature, dependencyClosedOver); } if (!RecursivelyCheckAvailability(dependencySetting, allFeatureSettings, availabilityCheckArgs, featuresCurrentlyUnderAnalysis)) { return(false); } } catch (InvalidOperationException e) { throw new FeatureNotConfiguredException <TFeatureEnum>(dependency, e); } } featuresCurrentlyUnderAnalysis.Remove(featureSettingToCheck); //see note 3 return(AvailabilityCheckFunction(featureSettingToCheck, availabilityCheckArgs)); }
/// <summary> /// The default implementation of the availability checker. Checks the tenancy, feature state and date/time. Can of course be substituted for by your own function. For example, your own function might take into consideration a number indicating site load or user role. /// </summary> public static bool AvailabilityCheckFunction <TFeatureEnum, TTenantEnum>( FeatureSetting <TFeatureEnum, TTenantEnum> s, Tuple <FeatureVisibilityMode, TTenantEnum, DateTime> args) where TFeatureEnum : struct where TTenantEnum : struct { return ((s.SupportedTenants.Contains((TTenantEnum)Enum.ToObject(typeof(TTenantEnum), 0)) || s.SupportedTenants.Contains(args.Item2)) && (s.FeatureState == FeatureState.Enabled || (s.FeatureState == FeatureState.Previewable && args.Item1 == FeatureVisibilityMode.Preview)) && s.StartDtg <= args.Item3 && s.EndDtg > args.Item3); }
public static bool IsAvailable <TFeatureEnum, TTenantEnum>( this FeatureSetting <TFeatureEnum, TTenantEnum> f, FeatureVisibilityMode m, TTenantEnum tenant, DateTime currentDtg) where TFeatureEnum : struct where TTenantEnum : struct { return((f.SupportedTenants.Contains((TTenantEnum)Enum.ToObject(typeof(TTenantEnum), 0)) || f.SupportedTenants.Contains(tenant)) && (f.FeatureState == FeatureState.Enabled || (f.FeatureState == FeatureState.Previewable && m == FeatureVisibilityMode.Preview)) && f.StartDtg <= currentDtg && f.EndDtg > currentDtg); }
/// <summary> /// Designed for use for features that the feature subsystem itself depends upon. Provides a way of retrieving feature setting information without the FeatureManifest being pre-instantiated. /// </summary> internal static string Setting <TFeatureEnum, TTenantEnum>(this TFeatureEnum feature, Enum settingName, IFeatureSettingRepository <TFeatureEnum, TTenantEnum> featureSettingRepository) where TFeatureEnum : struct where TTenantEnum : struct { try { FeatureSetting <TFeatureEnum, TTenantEnum>[] featureSettings = featureSettingRepository.GetFeatureSettings(); FeatureSetting <TFeatureEnum, TTenantEnum> featureSetting = featureSettings.First(s => s.Feature.Equals(feature)); //was == Ensure.That <FeatureConfigurationException <TFeatureEnum> >(featureSetting.IsRequiredByFeatureSubsystem, "Specified feature not marked as being required by the feature subsystem."); return(featureSetting.Settings[Enum.GetName(settingName.GetType(), settingName)]); } catch (Exception e) { throw new Exception(string.Format("Unable to find setting \"{0}\".", settingName), e); } }
/// <summary> /// A function to test the availability checking behavior. /// </summary> private static bool MyAvailabilityCheckFunction(FeatureSetting<Feature, DefaultTenantEnum> s, EmptyArgs args) { Func<bool> f = () => true; return Enum.GetName(typeof (Feature), s.Feature) == "NDecorate"; }
/// <summary> /// A function to test the availability checking behavior. /// </summary> private static bool MyAvailabilityCheckFunction(FeatureSetting <Feature, Tenant> s, EmptyArgs args) { return(Enum.GetName(typeof(Feature), s.Feature) == "TestFeatureE"); }
/// <summary> /// A function to test the availability checking behavior. /// </summary> private static bool MyAvailabilityCheckFunction(FeatureSetting<Feature, DefaultTenantEnum> s, EmptyArgs args) { return Enum.GetName(typeof (Feature), s.Feature) == "TestFeatureE"; }