public void FlagReturnsFallthroughVariationAndEventIfPrerequisiteIsMetAndThereAreNoRules()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(fallthroughValue, offValue, onValue)
                     .Version(1)
                     .Build();
            var f1 = new FeatureFlagBuilder("feature1")
                     .On(true)
                     .FallthroughVariation(1) // this is what makes the prerequisite pass
                     .Variations(LdValue.Of("nogo"), LdValue.Of("go"))
                     .Version(2)
                     .Build();
            var evaluator = BasicEvaluator.WithStoredFlags(f1);

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

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

            Assert.Equal(expected, result.Result);

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

            Assert.Equal(f1.Key, e.FlagKey);
            Assert.Equal(LdValue.Of("go"), e.Value);
            Assert.Equal(f1.Version, e.FlagVersion);
            Assert.Equal(f0.Key, e.PrerequisiteOf);
        }
        public void FlagReturnsOffVariationAndEventIfPrerequisiteIsOff()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(fallthroughValue, offValue, onValue)
                     .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(LdValue.Of("nogo"), LdValue.Of("go"))
                     .Version(2)
                     .Build();
            var evaluator = BasicEvaluator.WithStoredFlags(f1);

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

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

            Assert.Equal(expected, result.Result);

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

            Assert.Equal(f1.Key, e.FlagKey);
            Assert.Equal(LdValue.Of("go"), e.Value);
            Assert.Equal(f1.Version, e.FlagVersion);
            Assert.Equal(f0.Key, e.PrerequisiteOf);
        }
        private bool SegmentMatchesUser(Segment segment, User user)
        {
            var flag      = new FeatureFlagBuilder("key").BooleanMatchingSegment(segment.Key).Build();
            var evaluator = BasicEvaluator.WithStoredSegments(segment);
            var result    = evaluator.Evaluate(flag, user, EventFactory.Default);

            return(result.Result.Value.AsBool);
        }
        public void SegmentMatchClauseFallsThroughIfSegmentNotFound()
        {
            var f         = new FeatureFlagBuilder("key").BooleanMatchingSegment("segkey").Build();
            var user      = User.WithKey("foo");
            var evaluator = BasicEvaluator.WithNonexistentSegment("segkey");

            Assert.Equal(LdValue.Of(false), evaluator.Evaluate(f, user, EventFactory.Default).Result.Value);
        }
        public void ClauseWithUnknownOperatorDoesNotMatch()
        {
            var clause = new ClauseBuilder().Attribute("name").Op("invalidOp").Values(LdValue.Of("Bob")).Build();
            var f      = new FeatureFlagBuilder("key").BooleanWithClauses(clause).Build();
            var user   = User.Builder("key").Name("Bob").Build();

            Assert.Equal(LdValue.Of(false), BasicEvaluator.Evaluate(f, user, EventFactory.Default).Result.Value);
        }
        public void ClauseReturnsFalseForMissingAttribute()
        {
            var clause = new ClauseBuilder().Attribute("legs").Op("in").Values(LdValue.Of(4)).Build();
            var f      = new FeatureFlagBuilder("key").BooleanWithClauses(clause).Build();
            var user   = User.Builder("key").Name("bob").Build();

            Assert.Equal(LdValue.Of(false), BasicEvaluator.Evaluate(f, user, EventFactory.Default).Result.Value);
        }
        public void ClauseCanMatchCustomAttribute()
        {
            var clause = new ClauseBuilder().Attribute("legs").Op("in").Values(LdValue.Of(4)).Build();
            var f      = new FeatureFlagBuilder("key").BooleanWithClauses(clause).Build();
            var user   = User.Builder("key").Custom("legs", 4).Build();

            Assert.Equal(LdValue.Of(true), BasicEvaluator.Evaluate(f, user, EventFactory.Default).Result.Value);
        }
        public void ClauseCanBeNegated()
        {
            var clause = new ClauseBuilder().Attribute("name").Op("in").Values(LdValue.Of("Bob"))
                         .Negate(true).Build();
            var f    = new FeatureFlagBuilder("key").BooleanWithClauses(clause).Build();
            var user = User.Builder("key").Name("Bob").Build();

            Assert.Equal(LdValue.Of(false), BasicEvaluator.Evaluate(f, user, EventFactory.Default).Result.Value);
        }
        public void SegmentMatchClauseRetrievesSegmentFromStore()
        {
            var segment   = new SegmentBuilder("segkey").Version(1).Included("foo").Build();
            var evaluator = BasicEvaluator.WithStoredSegments(segment);

            var f    = new FeatureFlagBuilder("key").BooleanMatchingSegment("segkey").Build();
            var user = User.WithKey("foo");

            Assert.Equal(LdValue.Of(true), evaluator.Evaluate(f, user, EventFactory.Default).Result.Value);
        }
        public void FlagReturnsNullIfFlagIsOffAndOffVariationIsUnspecified()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(false)
                    .FallthroughVariation(0)
                    .Variations(fallthroughValue, offValue, onValue)
                    .Build();
            var result = BasicEvaluator.Evaluate(f, baseUser, 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(fallthroughValue, offValue, onValue)
                    .Build();
            var result = BasicEvaluator.Evaluate(f, baseUser, EventFactory.Default);

            var expected = new EvaluationDetail <LdValue>(fallthroughValue, 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(fallthroughValue, offValue, onValue)
                    .Build();
            var result = BasicEvaluator.Evaluate(f, baseUser, EventFactory.Default);

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

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }
        public void MultipleLevelsOfPrerequisitesProduceMultipleEvents()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(fallthroughValue, offValue, onValue)
                     .Version(1)
                     .Build();
            var f1 = new FeatureFlagBuilder("feature1")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature2", 1))
                     .FallthroughVariation(1)
                     .Variations(LdValue.Of("nogo"), LdValue.Of("go"))
                     .Version(2)
                     .Build();
            var f2 = new FeatureFlagBuilder("feature2")
                     .On(true)
                     .FallthroughVariation(1)
                     .Variations(LdValue.Of("nogo"), LdValue.Of("go"))
                     .Version(3)
                     .Build();
            var evaluator = BasicEvaluator.WithStoredFlags(f1, f2);

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

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

            Assert.Equal(expected, result.Result);

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

            EvaluationEvent e0 = result.PrerequisiteEvents[0];

            Assert.Equal(f2.Key, e0.FlagKey);
            Assert.Equal(LdValue.Of("go"), e0.Value);
            Assert.Equal(f2.Version, e0.FlagVersion);
            Assert.Equal(f1.Key, e0.PrerequisiteOf);

            EvaluationEvent e1 = result.PrerequisiteEvents[1];

            Assert.Equal(f1.Key, e1.FlagKey);
            Assert.Equal(LdValue.Of("go"), e1.Value);
            Assert.Equal(f1.Version, e1.FlagVersion);
            Assert.Equal(f0.Key, e1.PrerequisiteOf);
        }
        public void FlagReturnsOffVariationIfPrerequisiteIsNotFound()
        {
            var f0 = new FeatureFlagBuilder("feature0")
                     .On(true)
                     .Prerequisites(new Prerequisite("feature1", 1))
                     .OffVariation(1)
                     .FallthroughVariation(0)
                     .Variations(fallthroughValue, offValue, onValue)
                     .Build();
            var evaluator = BasicEvaluator.WithNonexistentFlag("feature1");
            var result    = evaluator.Evaluate(f0, baseUser, EventFactory.Default);

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

            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 HashSet <string> {
                "whoever", "userkey"
            }, 2))
                    .FallthroughVariation(0)
                    .OffVariation(1)
                    .Variations(fallthroughValue, offValue, onValue)
                    .Build();
            var user   = User.WithKey("userkey");
            var result = BasicEvaluator.Evaluate(f, user, EventFactory.Default);

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

            Assert.Equal(expected, result.Result);
            Assert.Equal(0, result.PrerequisiteEvents.Count);
        }