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 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); }
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 BigSegmentStateIsQueriedOnlyOncePerUserEvenIfFlagReferencesMultipleSegments() { var segment1 = new SegmentBuilder("segmentkey1").Unbounded(true).Generation(2).Build(); var segment2 = new SegmentBuilder("segmentkey2").Unbounded(true).Generation(3).Build(); var bigSegments = new MockBigSegmentProvider(); var membership = MockMembership.New().Include(segment2); bigSegments.Membership[baseUser.Key] = membership; var flag = new FeatureFlagBuilder("key").On(true) .Variations(LdValue.Of(false), LdValue.Of(true)) .FallthroughVariation(0) .Rules( new RuleBuilder().Variation(1).Clauses(ClauseBuilder.ShouldMatchSegment(segment1.Key)).Build(), new RuleBuilder().Variation(1).Clauses(ClauseBuilder.ShouldMatchSegment(segment2.Key)).Build() ) .Build(); var evaluator = BasicEvaluator.WithStoredSegments(segment1, segment2).WithBigSegments(bigSegments); var result = evaluator.Evaluate(flag, baseUser, EventFactory.Default); Assert.Equal(LdValue.Of(true), result.Result.Value); Assert.Equal(BigSegmentsStatus.Healthy, result.Result.Reason.BigSegmentsStatus); Assert.Equal(1, bigSegments.MembershipQueryCount); Assert.Equal(new List <string> { MakeBigSegmentRef(segment1), MakeBigSegmentRef(segment2) }, membership.Queries); }
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(); }
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 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 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); }
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 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 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); } }
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()); }
public void standarize_string_expression(string expression, string standarizedExpression) { // Arrange BasicEvaluator stringEvaluator = new BasicEvaluator(); // Act stringEvaluator.ValidateAndStandarize(ref expression); // Assert Assert.AreEqual(expression, standarizedExpression); }
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)); }
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); }
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 get_list_of_factors(string expression, string[] exprectedListOfFactors) { // Arrange BasicEvaluator stringEvaluator = new BasicEvaluator(); // Act ICollection <string> expressionFactors = stringEvaluator.GetSplitExpression(expression); // Assert Assert.AreEqual(exprectedListOfFactors.Length, expressionFactors.Count); Assert.AreEqual(exprectedListOfFactors.ToList(), expressionFactors.ToList()); }
public void BigSegmentWithNoProviderIsNotMatched() { var segment = new SegmentBuilder("segmentkey").Unbounded(true).Generation(1) .Included(baseUser.Key) // Included should be ignored for a Big Segment .Build(); var flag = new FeatureFlagBuilder("key").BooleanMatchingSegment(segment.Key).Build(); var evaluator = BasicEvaluator.WithStoredSegments(segment); var result = evaluator.Evaluate(flag, baseUser, EventFactory.Default); Assert.Equal(LdValue.Of(false), result.Result.Value); Assert.Equal(BigSegmentsStatus.NotConfigured, result.Result.Reason.BigSegmentsStatus); }
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")); }
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); }
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")); }
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 MatchedWithInclude() { var segment = new SegmentBuilder("segmentkey").Unbounded(true).Generation(2).Build(); var bigSegments = new MockBigSegmentProvider(); bigSegments.Membership[baseUser.Key] = MockMembership.New().Include(segment); var flag = new FeatureFlagBuilder("key").BooleanMatchingSegment(segment.Key).Build(); var evaluator = BasicEvaluator.WithStoredSegments(segment).WithBigSegments(bigSegments); var result = evaluator.Evaluate(flag, baseUser, EventFactory.Default); Assert.Equal(LdValue.Of(true), result.Result.Value); Assert.Equal(BigSegmentsStatus.Healthy, result.Result.Reason.BigSegmentsStatus); }
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 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); }
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); }
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); }