public void FlagReturnsFallthroughVariationAndEventIfPrerequisiteIsMetAndThereAreNoRules()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                     .Version(1)
                     .Build();
            var f1 = new FeatureFlagBuilder("feature1")
                     .On(true)
                     .FallthroughVariation(1) // this is what makes the prerequisite pass
                     .Variations(new JValue("nogo"), new JValue("go"))
                     .Version(2)
                     .Build();

            featureStore.Upsert(VersionedDataKind.Features, f1);

            var result = f0.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Of("fall"), 0, EvaluationReason.FallthroughReason);

            Assert.Equal(expected, result.Result);

            Assert.Equal(1, result.PrerequisiteEvents.Count);
            FeatureRequestEvent e = result.PrerequisiteEvents[0];

            Assert.Equal(f1.Key, e.Key);
            Assert.Equal(LdValue.Of("go"), e.LdValue);
            Assert.Equal(f1.Version, e.Version);
            Assert.Equal(f0.Key, e.PrereqOf);
        }
        public void FlagReturnsOffVariationAndEventIfPrerequisiteIsOff()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                     .Version(1)
                     .Build();
            var f1 = new FeatureFlagBuilder("feature1")
                     .On(false)
                     .OffVariation(1)
                     // note that even though it returns the desired variation, it is still off and therefore not a match
                     .Variations(new JValue("nogo"), new JValue("go"))
                     .Version(2)
                     .Build();

            featureStore.Upsert(VersionedDataKind.Features, f1);

            var result = f0.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Of("off"), 1,
                                                          EvaluationReason.PrerequisiteFailedReason("feature1"));

            Assert.Equal(expected, result.Result);

            Assert.Equal(1, result.PrerequisiteEvents.Count);
            FeatureRequestEvent e = result.PrerequisiteEvents[0];

            Assert.Equal(f1.Key, e.Key);
            Assert.Equal(LdValue.Of("go"), e.LdValue);
            Assert.Equal(f1.Version, e.Version);
            Assert.Equal(f0.Key, e.PrereqOf);
        }
        public void MultipleLevelsOfPrerequisitesProduceMultipleEvents()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new List <Prerequisite> {
                new Prerequisite("feature1", 1)
            })
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(new List <JToken> {
                new JValue("fall"), new JValue("off"), new JValue("on")
            })
                     .Version(1)
                     .Build();
            var f1 = new FeatureFlagBuilder("feature1")
                     .On(true)
                     .Prerequisites(new List <Prerequisite> {
                new Prerequisite("feature2", 1)
            })
                     .FallthroughVariation(1)
                     .Variations(new List <JToken> {
                new JValue("nogo"), new JValue("go")
            })
                     .Version(2)
                     .Build();
            var f2 = new FeatureFlagBuilder("feature2")
                     .On(true)
                     .FallthroughVariation(1)
                     .Variations(new List <JToken> {
                new JValue("nogo"), new JValue("go")
            })
                     .Version(3)
                     .Build();

            featureStore.Upsert(VersionedDataKind.Features, f1);
            featureStore.Upsert(VersionedDataKind.Features, f2);

            var result = f0.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <JToken>(new JValue("fall"), 0, EvaluationReason.Fallthrough.Instance);

            Assert.Equal(expected, result.Result);

            Assert.Equal(2, result.PrerequisiteEvents.Count);

            FeatureRequestEvent e0 = result.PrerequisiteEvents[0];

            Assert.Equal(f2.Key, e0.Key);
            Assert.Equal(new JValue("go"), e0.Value);
            Assert.Equal(f2.Version, e0.Version);
            Assert.Equal(f1.Key, e0.PrereqOf);

            FeatureRequestEvent e1 = result.PrerequisiteEvents[1];

            Assert.Equal(f1.Key, e1.Key);
            Assert.Equal(new JValue("go"), e1.Value);
            Assert.Equal(f1.Version, e1.Version);
            Assert.Equal(f0.Key, e1.PrereqOf);
        }
        public void FlagReturnsNullIfFlagIsOffAndOffVariationIsUnspecified()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(false)
                    .FallthroughVariation(0)
                    .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                    .Build();
            var result = f.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Null, null, EvaluationReason.OffReason);

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagReturnsFallthroughIfFlagIsOnAndThereAreNoRules()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(true)
                    .OffVariation(1)
                    .FallthroughVariation(0)
                    .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                    .Build();
            var result = f.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Of("fall"), 0, EvaluationReason.FallthroughReason);

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagReturnsErrorIfFallthroughHasEmptyRolloutVariationList()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(true)
                    .OffVariation(1)
                    .Fallthrough(new VariationOrRollout(null, new Rollout(new List <WeightedVariation>(), null)))
                    .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                    .Build();
            var result = f.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Null, null,
                                                          EvaluationReason.ErrorReason(EvaluationErrorKind.MALFORMED_FLAG));

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagReturnsOffVariationIfFlagIsOff()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(false)
                    .OffVariation(1)
                    .FallthroughVariation(0)
                    .Variations(new List <JToken> {
                new JValue("fall"), new JValue("off"), new JValue("on")
            })
                    .Build();
            var result = f.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <JToken>(new JValue("off"), 1, EvaluationReason.Off.Instance);

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagReturnsOffVariationIfPrerequisiteIsNotFound()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                     .Build();
            var result = f0.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Of("off"), 1,
                                                          EvaluationReason.PrerequisiteFailedReason("feature1"));

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagReturnsErrorIfFlagIsOffAndOffVariationIsNegative()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(false)
                    .OffVariation(-1)
                    .FallthroughVariation(0)
                    .Variations(new List <JToken> {
                new JValue("fall"), new JValue("off"), new JValue("on")
            })
                    .Build();
            var result = f.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <JToken>(null, null,
                                                         new EvaluationReason.Error(EvaluationErrorKind.MALFORMED_FLAG));

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagMatchesUserFromTargets()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(true)
                    .Targets(new Target(new List <string> {
                "whoever", "userkey"
            }, 2))
                    .FallthroughVariation(0)
                    .OffVariation(1)
                    .Variations(new JValue("fall"), new JValue("off"), new JValue("on"))
                    .Build();
            var user   = User.WithKey("userkey");
            var result = f.Evaluate(user, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(LdValue.Of("on"), 2, EvaluationReason.TargetMatchReason);

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void FlagReturnsOffVariationAndEventIfPrerequisiteIsNotMet()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new List <Prerequisite> {
                new Prerequisite("feature1", 1)
            })
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(new List <JToken> {
                new JValue("fall"), new JValue("off"), new JValue("on")
            })
                     .Version(1)
                     .Build();
            var f1 = new FeatureFlagBuilder("feature1")
                     .On(true)
                     .FallthroughVariation(0)
                     .Variations(new List <JToken> {
                new JValue("nogo"), new JValue("go")
            })
                     .Version(2)
                     .Build();

            featureStore.Upsert(VersionedDataKind.Features, f1);

            var result = f0.Evaluate(baseUser, featureStore, EventFactory.Default);

            var expected = new EvaluationDetail <JToken>(new JValue("off"), 1,
                                                         new EvaluationReason.PrerequisiteFailed("feature1"));

            Assert.Equal(expected, result.Result);

            Assert.Equal(1, result.PrerequisiteEvents.Count);
            FeatureRequestEvent e = result.PrerequisiteEvents[0];

            Assert.Equal(f1.Key, e.Key);
            Assert.Equal(new JValue("nogo"), e.Value);
            Assert.Equal(f1.Version, e.Version);
            Assert.Equal(f0.Key, e.PrereqOf);
        }