private static void AssertVariationIndexFromRollout(
            int expectedVariation,
            Rollout rollout,
            User user,
            string flagKey,
            string salt
            )
        {
            var flag1 = new FeatureFlagBuilder(flagKey)
                        .On(true)
                        .GeneratedVariations(3)
                        .FallthroughRollout(rollout)
                        .Salt(salt)
                        .Build();
            var result1 = BasicEvaluator.Evaluate(flag1, user, EventFactory.Default);

            Assert.Equal(EvaluationReason.FallthroughReason, result1.Result.Reason);
            Assert.Equal(expectedVariation, result1.Result.VariationIndex);

            // Make sure we consistently apply the rollout regardless of whether it's in a rule or a fallthrough
            var flag2 = new FeatureFlagBuilder(flagKey)
                        .On(true)
                        .GeneratedVariations(3)
                        .Rules(new RuleBuilder().Id("id")
                               .Rollout(rollout)
                               .Clauses(new ClauseBuilder().Attribute(UserAttribute.Key).Op(Operator.In).Values(LdValue.Of(user.Key)).Build())
                               .Build())
                        .Salt(salt)
                        .Build();
            var result2 = BasicEvaluator.Evaluate(flag2, user, EventFactory.Default);

            Assert.Equal(EvaluationReason.RuleMatchReason(0, "id"), result2.Result.Reason);
            Assert.Equal(expectedVariation, result2.Result.VariationIndex);
        }
예제 #2
0
        static void Main(string[] args)
        {
            Console.WriteLine("******");
            Console.WriteLine("Please put expression consisting of non-negative integers and the [+ - / *] operators only, then press enter:");
            Console.WriteLine("******");

            Console.WriteLine();
            Console.Write("Expression: ");
            string expression = Console.ReadLine();

            try
            {
                BasicEvaluator basicEvaluator = new BasicEvaluator();
                decimal        result         = basicEvaluator.Evaluate(expression);

                Console.WriteLine();
                Console.WriteLine($"Result: {result}");
                Console.WriteLine();
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.DarkRed;
                Console.WriteLine($"Error: {ex.Message}");
                Console.ResetColor();
            }

            Console.WriteLine();
            Console.Write("Press any key...");
            Console.ReadKey();
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        public static T Evaluate <T>(RPNExpression expression)
        {
            try
            {
                var context = new RPNContext(expression);
                while (context.CanMove)
                {
                    context.MoveNext();

                    if (DefaultEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (BasicEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (MathEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (LogicEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (StringEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (RegexEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (DateTimeEvaluator.Evaluate(context))
                    {
                        continue;
                    }
                    if (ControlEvaluator.Evaluate <T>(context))
                    {
                        continue;
                    }

                    context.Stack.Push(context.Current);
                }
                return(context.GetResult <T>());
            }
            catch (RPNException)
            {
                throw;
            }
            catch
            {
                throw new ParsingException(expression.Expression);
            }
        }
예제 #8
0
        public void throws_error_when_number_is_too_big(string expression)
        {
            // Arrange
            BasicEvaluator stringEvaluator = new BasicEvaluator();

            // Act
            void evaluateDelegate() => stringEvaluator.Evaluate(expression);

            // Assert
            Exception ex = Assert.Throws <OverflowException>(() => evaluateDelegate());
        }
        public void FlagReturnsInExperimentForRuleMatchWhenInExperimentVariationButNonExperimentRollout()
        {
            var user    = User.WithKey("userkey");
            var rollout = BuildRollout(RolloutKind.Rollout, false);
            var rule    = new RuleBuilder().Id("id").Rollout(rollout).Clauses(ClauseBuilder.ShouldMatchUser(user)).Build();
            var f       = FeatureFlagWithRules(rule);
            var result  = BasicEvaluator.Evaluate(f, baseUser, EventFactory.Default);

            Assert.Equal(EvaluationReasonKind.RuleMatch, result.Result.Reason.Kind);
            Assert.False(result.Result.Reason.InExperiment);
        }
예제 #10
0
        public void get_result_from_string_expression(string expression, decimal expectedResult)
        {
            // Arrange
            BasicEvaluator stringEvaluator = new BasicEvaluator();

            // Act
            decimal result = stringEvaluator.Evaluate(expression);

            // Assert
            Assert.That(expectedResult, Is.EqualTo(result).Within(0.00000001));
        }
예제 #11
0
        public void throws_error_when_dividing_by_zero(string expression)
        {
            // Arrange
            BasicEvaluator stringEvaluator = new BasicEvaluator();

            // Act
            void evaluateDelegate() => stringEvaluator.Evaluate(expression);

            // Assert
            Exception ex = Assert.Throws <DivideByZeroException>(() => evaluateDelegate());
        }
예제 #12
0
        public void throws_error_if_string_expression_is_empty()
        {
            // Arrange
            BasicEvaluator stringEvaluator = new BasicEvaluator();

            // Act
            void evaluateDelegate() => stringEvaluator.Evaluate(string.Empty);

            // Assert
            Exception ex = Assert.Throws <ArgumentException>(() => evaluateDelegate());

            Assert.That(ex.Message, Is.EqualTo("Expression cannot be null or empty"));
        }
예제 #13
0
        public void throws_error_if_string_expression_is_not_valid(string expression)
        {
            // Arrange
            BasicEvaluator stringEvaluator = new BasicEvaluator();

            // Act
            void evaluateDelegate() => stringEvaluator.Evaluate(expression);

            // Assert
            Exception ex = Assert.Throws <ArgumentException>(() => evaluateDelegate());

            Assert.That(ex.Message, Is.EqualTo("Expression is not valid"));
        }
예제 #14
0
        public void FlagReturnsInExperimentForFallthroughWhenInExperimentVariationButNonExperimentRollout()
        {
            var rollout = BuildRollout(RolloutKind.Rollout, false);
            var f       = new FeatureFlagBuilder("feature")
                          .On(true)
                          .FallthroughRollout(rollout)
                          .Variations(fallthroughValue, offValue, onValue)
                          .Build();
            var result = BasicEvaluator.Evaluate(f, baseUser, EventFactory.Default);

            Assert.Equal(EvaluationReasonKind.Fallthrough, result.Result.Reason.Kind);
            Assert.False(result.Result.Reason.InExperiment);
        }
예제 #15
0
        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 RuleWithNoVariationOrRolloutReturnsMalformedFlagError()
        {
            var user   = User.WithKey("userkey");
            var clause = ClauseBuilder.ShouldMatchUser(user);
            var rule   = new RuleBuilder().Id("ruleid").Clauses(clause).Build();
            var f      = FeatureFlagWithRules(rule);

            var result = BasicEvaluator.Evaluate(f, user, 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);
        }
예제 #17
0
        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);
        }
예제 #18
0
        public void FlagReturnsErrorIfFallthroughHasEmptyRolloutVariationList()
        {
            var f = new FeatureFlagBuilder("feature")
                    .On(true)
                    .OffVariation(1)
                    .FallthroughRollout(new Rollout(RolloutKind.Rollout, null, 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);
        }
예제 #19
0
        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);
        }
예제 #20
0
        private static void AssertVariationIndexAndExperimentStateForRollout(
            int expectedVariation,
            bool expectedInExperiment,
            Rollout rollout,
            User user,
            string flagKey,
            string salt
            )
        {
            var flag = new FeatureFlagBuilder(flagKey)
                       .On(true)
                       .GeneratedVariations(3)
                       .FallthroughRollout(rollout)
                       .Salt(salt)
                       .Build();
            var result = BasicEvaluator.Evaluate(flag, user, EventFactory.Default);

            Assert.Equal(expectedVariation, result.Result.VariationIndex);
            Assert.Equal(EvaluationReasonKind.Fallthrough, result.Result.Reason.Kind);
            Assert.Equal(expectedInExperiment, result.Result.Reason.InExperiment);
        }