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)));
        }
Beispiel #6
0
 public bool AllDependenciesAreSatisfiedForTheFeatureSetting(
     FeatureSetting <TFeatureEnum, DefaultTenantEnum> f,
     EmptyArgs availabilityCheckArgs)
 {
     return(_featureSettingAvailabilityChecker.RecursivelyCheckAvailability(f,
                                                                            _featureSettingRepository
                                                                            .GetFeatureSettings(),
                                                                            availabilityCheckArgs));
 }
Beispiel #7
0
 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));
        }
Beispiel #10
0
 /// <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);
 }
Beispiel #11
0
 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";
		}