public bool Evaluate(Constraint constraint, UnleashContext context)
        {
            var contextValueString = context.GetByName(constraint.ContextName);

            if (string.IsNullOrWhiteSpace(contextValueString))
            {
                return(false);
            }

            if (!double.TryParse(contextValueString, NumberStyles.Number, CultureInfo.InvariantCulture, out var contextNumber))
            {
                return(false);
            }

            if (string.IsNullOrWhiteSpace(constraint.Value) || !double.TryParse(constraint.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var constraintNumber))
            {
                return(false);
            }

            if (constraint.Inverted)
            {
                return(!Eval(constraint.Operator, constraintNumber, contextNumber));
            }

            return(Eval(constraint.Operator, constraintNumber, contextNumber));
        }
예제 #2
0
        static void Main(string[] args)
        {
            var unleashConfig = new UnleashConfig.Builder()
                                .AppName("c-sharp-test")
                                .InstanceId("instance y")
                                .UnleashAPI("https://unleash.herokuapp.com/api/")
                                .FetchTogglesInterval(1)
                                .SendMetricsInterval(2)
                                .Build();

            var context = UnleashContext.CreateBuilder()
                          .SessionId(new Random().Next(10000) + "")
                          .UserId(new Random().Next(10000) + "")
                          .RemoteAddress("192.168.1.1")
                          .Build();

            // var executor = new UnleashScheduledExecutorImpl();
            // var repository = new FeatureToggleRepository(
            //         unleashConfig,
            //         executor,
            //         new HttpToggleFetcher(unleashConfig),
            //         new ToggleBackupHandlerFile(unleashConfig));
            var unleash = new DefaultUnleash(unleashConfig,
                                             //repository,
                                             new ActiveForUserWithIdStrategy()
                                             );


            //var test =  executor.SetInterval(s => repository.UpdateToggles(s).Wait(), 0, unleashConfig.FetchTogglesInterval);

            Run(unleash, context, "test", 200);
        }
        public bool Evaluate(Constraint constraint, UnleashContext context)
        {
            var             contextValue = context.GetByName(constraint.ContextName);
            SemanticVersion contextSemver;

            if (!SemanticVersion.TryParse(contextValue, out contextSemver))
            {
                Logger.Info("Couldn't parse version {0} from context");
                return(false);
            }

            if (!string.IsNullOrWhiteSpace(constraint.Value))
            {
                SemanticVersion constraintSemver;
                if (!SemanticVersion.TryParse(constraint.Value, out constraintSemver))
                {
                    return(false);
                }

                if (constraint.Inverted)
                {
                    return(!Eval(constraint.Operator, contextSemver, constraintSemver));
                }

                return(Eval(constraint.Operator, contextSemver, constraintSemver));
            }

            return(false);
        }
        public void should_be_disabled_when_missing_user_id()
        {
            var context = UnleashContext.New().Build();
            var gradualRolloutStrategy = new GradualRolloutUserIdStrategy();

            gradualRolloutStrategy.IsEnabled(new Dictionary <string, string>(), context).Should().BeFalse();
        }
예제 #5
0
 public override bool IsEnabled(Dictionary <string, string> parameters, UnleashContext context) =>
 parameters.ContainsKey(PARAM) ?
 parameters[PARAM]
 .Split(',')
 .Select(n => n.Trim())
 .Contains(context.RemoteAddress) :
 false;
        public void ShouldReturnVariant2()
        {
            // Arrange
            var v1 = new VariantDefinition("a", 33, new Payload("string", "asd"), new Collection <VariantOverride>());
            var v2 = new VariantDefinition("b", 33);
            var v3 = new VariantDefinition("c", 34);

            var toggle = new FeatureToggle(
                "test.variants",
                "release",
                true,
                new List <ActivationStrategy> {
                defaultStrategy
            },
                new List <VariantDefinition> {
                v1, v2, v3
            });

            var context = new UnleashContext
            {
                UserId        = "163",
                SessionId     = "sessionId",
                RemoteAddress = "remoteAddress",
                Properties    = new Dictionary <string, string>()
            };

            // Act
            var variant = VariantUtils.SelectVariant(toggle, context, Variant.DISABLED_VARIANT);

            // Assert
            variant.Name.Should().Be(v2.Name);
        }
예제 #7
0
        public void test(string actualIp, string parameterstring, bool expected)
        {
            var context    = UnleashContext.New().RemoteAddress(actualIp).Build();
            var parameters = setupParameterMap(parameterstring);

            strategy.IsEnabled(parameters, context).Should().Be(expected);
        }
        public void should_at_most_miss_with_one_percent_when_rolling_out_to_specified_percentage()
        {
            string groupId      = "group1";
            int    percentage   = 25;
            int    rounds       = 20000;
            int    enabledCount = 0;

            var paramseters = buildParams(percentage, groupId);

            var gradualRolloutStrategy = new GradualRolloutUserIdStrategy();

            for (var userId = 0; userId < rounds; userId++)
            {
                var context = UnleashContext.New().UserId("user" + userId).Build();

                if (gradualRolloutStrategy.IsEnabled(paramseters, context))
                {
                    enabledCount++;
                }
            }

            var actualPercentage = (enabledCount / (double)rounds) * 100.0;

            ((percentage - 1) < actualPercentage)
            .Should().BeTrue("Expected " + percentage + "%, but was " + actualPercentage + "%");

            ((percentage + 1) > actualPercentage).Should()
            .BeTrue("Expected " + percentage + "%, but was " + actualPercentage + "%");
        }
        private static Func <VariantOverride, bool> OverrideMatchesContext(UnleashContext context)
        {
            return((variantOverride) =>
            {
                string contextValue = null;
                switch (variantOverride.ContextName)
                {
                case "userId":
                    contextValue = context.UserId;
                    break;

                case "sessionId":
                    contextValue = context.SessionId;
                    break;

                case "remoteAddress":
                    contextValue = context.RemoteAddress;
                    break;

                default:
                    context.Properties.TryGetValue(variantOverride.ContextName, out contextValue);
                    break;
                }
                return variantOverride.Values.Contains(contextValue ?? "");
            });
        }
예제 #10
0
        public void should_be_disabled_when_missing_user_id()
        {
            var context = UnleashContext.CreateBuilder().Build();
            var gradualRolloutStrategy = new GradualRolloutSessionIdStrategy();

            Assert.False(gradualRolloutStrategy.IsEnabled(new Dictionary <string, string>(), context));
        }
        private static bool ValidateConstraint(Constraint constraint, UnleashContext context)
        {
            var contextValue = context.GetByName(constraint.ContextName);
            var isIn         = contextValue != null && constraint.Values.Contains(contextValue.Trim());

            return((constraint.Operator == Operator.IN) == isIn);
        }
예제 #12
0
        public void Should_be_disabled_when_not_all_constrains_are_satisfied()
        {
            // Arrange
            var strategy   = new AlwaysEnabledStrategy();
            var parameters = new Dictionary <string, string>();
            var context    = new UnleashContext
            {
                Environment = "test",
                UserId      = "123",
                Properties  = new Dictionary <string, string>
                {
                    { "customerId", "orange" }
                }
            };
            var constraints = new List <Constraint>
            {
                new Constraint("environment", Operator.IN, false, false, "test", "prod"),
                new Constraint("userId", Operator.IN, false, false, "123"),
                new Constraint("customerId", Operator.IN, false, false, "red", "blue")
            };

            // Act
            var enabled = strategy.IsEnabled(parameters, context, constraints);

            // Assert
            enabled.Should().BeFalse();
        }
예제 #13
0
 private static string GetIdentifier(UnleashContext context)
 {
     return(context.UserId
            ?? context.SessionId
            ?? context.RemoteAddress
            ?? new Random().NextDouble().ToString());
 }
예제 #14
0
        public static Variant SelectVariant(FeatureToggle featureToggle, UnleashContext context, Variant defaultVariant)
        {
            var variantDefinitions = featureToggle.Variants;
            var totalWeight        = variantDefinitions.Sum(v => v.Weight);

            if (totalWeight == 0)
            {
                return(defaultVariant);
            }

            var variantOverride = GetOverride(variantDefinitions, context);

            if (variantOverride != null)
            {
                return(variantOverride.ToVariant());
            }

            var target = StrategyUtils.GetNormalizedNumber(GetIdentifier(context), featureToggle.Name, totalWeight);

            var counter = 0;

            foreach (var variantDefinition in variantDefinitions)
            {
                if (variantDefinition.Weight != 0)
                {
                    counter += variantDefinition.Weight;
                    if (counter >= target)
                    {
                        return(variantDefinition.ToVariant());
                    }
                }
            }

            return(defaultVariant);
        }
예제 #15
0
        public void IsEnabled_Always_ShouldReturnFalse()
        {
            var context    = UnleashContext.New().Build();
            var parameters = new Dictionary <string, string>();

            var result = Strategy.IsEnabled(parameters, context);

            Assert.False(result);
        }
예제 #16
0
        public void IsEnabled_WhenUserIdIsMissing_ShouldReturnFalse()
        {
            var context = UnleashContext.New().Build();
            var gradualRolloutStrategy = new GradualRolloutUserIdStrategy();

            var result = gradualRolloutStrategy.IsEnabled(new Dictionary <string, string>(), context);

            Assert.False(result);
        }
예제 #17
0
        public void should_match_csv_without_space()
        {
            var parameters = new Dictionary <string, string>();

            var context = UnleashContext.New().UserId("123").Build();

            parameters.Add(strategy.UserIdsConst, "123,122,121");

            strategy.IsEnabled(parameters, context).Should().BeTrue();;
        }
예제 #18
0
        public void should_match_middle_userId_in_list()
        {
            var parameters = new Dictionary <string, string>();

            var context = UnleashContext.New().UserId("122").Build();

            parameters.Add(strategy.UserIdsConst, "123, 122, 121");

            strategy.IsEnabled(parameters, context).Should().BeTrue();
        }
예제 #19
0
        public void should_be_enabled_when_using_100percent_rollout()
        {
            var context = UnleashContext.CreateBuilder().SessionId("1574576830").Build();
            var gradualRolloutStrategy = new GradualRolloutSessionIdStrategy();

            var parms  = BuildParams(100, "innfinn");
            var result = gradualRolloutStrategy.IsEnabled(parms, context);

            Assert.True(result);
        }
예제 #20
0
 public override bool IsEnabled(Dictionary <string, string> parameters, UnleashContext context)
 {
     return(parameters.ContainsKey(PARAM) ?
            parameters[PARAM]
            .Split(',')
            .Select(n => n.Trim())
            .Any(userId => userId == context.UserId)
             :
            false);
 }
예제 #21
0
        public void should_not_be_enabled_when_0percent_rollout()
        {
            var context = UnleashContext.CreateBuilder().SessionId("1574576830").Build();
            var gradualRolloutStrategy = new GradualRolloutSessionIdStrategy();

            var parms  = BuildParams(0, "innfinn");
            var actual = gradualRolloutStrategy.IsEnabled(parms, context);

            Assert.False(actual); //"should not be enabled when 0% rollout",
        }
        public void should_be_enabled_when_using_100percent_rollout()
        {
            var context = UnleashContext.New().UserId("1574576830").Build();
            var gradualRolloutStrategy = new GradualRolloutUserIdStrategy();

            var paramseters = buildParams(100, "innfinn");
            var result      = gradualRolloutStrategy.IsEnabled(paramseters, context);

            result.Should().BeTrue();
        }
예제 #23
0
        public void should_not_match_subparts_of_ids()
        {
            var parameters = new Dictionary <string, string>();

            var context = UnleashContext.New().UserId("12").Build();

            parameters.Add(strategy.UserIdsConst, "123, 122, 121, 212");

            strategy.IsEnabled(parameters, context).Should().BeFalse();
        }
        public void should_not_be_enabled_when_0percent_rollout()
        {
            var context = UnleashContext.New().UserId("1574576830").Build();
            var gradualRolloutStrategy = new GradualRolloutUserIdStrategy();

            var paramseters = buildParams(0, "innfinn");
            var actual      = gradualRolloutStrategy.IsEnabled(paramseters, context);

            actual.Should().BeFalse("should not be enabled when 0% rollout");
        }
예제 #25
0
        public void should_match_real_ids()
        {
            var parameters = new Dictionary <string, string>();

            var context = UnleashContext.New().UserId("298261117").Build();

            parameters.Add(strategy.UserIdsConst,
                           "160118738, 1823311338, 1422637466, 2125981185, 298261117, 1829486714, 463568019, 271166598");

            strategy.IsEnabled(parameters, context).Should().BeTrue();
        }
 public static bool Validate(List <Constraint> constraints, UnleashContext context)
 {
     if (constraints?.Count > 0)
     {
         return(constraints.TrueForAll(c => ValidateConstraint(c, context)));
     }
     else
     {
         return(true);
     }
 }
예제 #27
0
        public void IsEnabled_ShouldReturnExpectedValue(string actualIp, string parameterString, bool expected)
        {
            var context    = UnleashContext.New().RemoteAddress(actualIp).Build();
            var parameters = new Dictionary <string, string>
            {
                [RemoteAddressStrategy.PARAM] = parameterString
            };

            var actual = Strategy.IsEnabled(parameters, context);

            Assert.Equal(expected, actual);
        }
        public bool IsEnabled(Dictionary <string, string> parameters, UnleashContext context = null)
        {
            if (!parameters.TryGetValue(Percentage, out var value))
            {
                return(false);
            }

            var percentage   = StrategyUtils.GetPercentage(value);
            var randomNumber = random.Next(100) + 1;

            return(percentage >= randomNumber);
        }
예제 #29
0
        private static string GetIdentifier(UnleashContext context, string stickiness)
        {
            if (stickiness != "default")
            {
                var stickinessValue = context.GetByName(stickiness);
                return(stickinessValue ?? GetRandomValue());
            }

            return(context.UserId
                   ?? context.SessionId
                   ?? context.RemoteAddress
                   ?? GetRandomValue());
        }
예제 #30
0
        public void NUM_LTE_Item_Count_Of_6_Is_Not_Less_Than_Or_Equal_To_Constraint_Value_5()
        {
            // Arrange
            var target     = new NumberConstraintOperator();
            var constraint = new Constraint("item_count", Operator.NUM_LTE, false, false, "5");
            var context    = new UnleashContext();

            context.Properties.Add("item_count", "6");
            // Act
            var result = target.Evaluate(constraint, context);

            // Assert
            result.Should().BeFalse();
        }