예제 #1
0
        public async Task be_not_active_if_user_agent_is_not_allowed()
        {
            var toggle = Build
                         .Toggle <UserAgentToggle>()
                         .AddParameter(Browsers, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36;Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Request
            .Headers
            .Add("user-agent", new StringValues("Internet Explorer 11"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new UserAgentToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeFalse();
        }
예제 #2
0
        public async Task be_active_when_session_is_on_valid_partition()
        {
            var toggle = Build
                         .Toggle <GradualRolloutSessionToggle>()
                         .AddParameter("Percentage", 100)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Session = new FakeSession();

            var partitioner = new DefaultValuePartitioner();

            var gradualRolloutSession = new GradualRolloutSessionToggle(partitioner, new FakeHttpContextAccessor(context));

            var active = await gradualRolloutSession.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeTrue();
        }
예제 #3
0
        ///<inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            if (Double.TryParse(context.Data[Percentage].ToString(), out double percentage))
            {
                string claimType = context.Data[ClaimType]?.ToString();

                if (claimType != null && percentage > 0)
                {
                    var user = _httpContextAccessor
                               .HttpContext
                               .User;

                    if (user != null && user.Identity.IsAuthenticated)
                    {
                        var value = user.FindFirst(claimType)?.Value;

                        if (value != null)
                        {
                            // this only apply when claim exist, we apply also some entropy to current claim value.
                            // adding this entropy ensure that not all features with gradual rollout for claim value are enabled/disable at the same time for the same user.

                            var assignedPartition = _partitioner
                                                    .ResolvePartition(context.FeatureName + value, partitions: 100);

                            var active = assignedPartition <= percentage;

                            return(new ValueTask <bool>(active));
                        }
                    }
                }
            }

            return(new ValueTask <bool>(false));
        }
예제 #4
0
        public async Task throw_when_session_is_not_active()
        {
            var toggle = Build
                         .Toggle <GradualRolloutSessionToggle>()
                         .AddParameter("Percentage", 100)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            var partitioner = new DefaultValuePartitioner();

            var gradualRolloutSession = new GradualRolloutSessionToggle(partitioner, new FakeHttpContextAccessor(context));

            await Assert.ThrowsAsync <InvalidOperationException>(async() =>
            {
                await gradualRolloutSession.IsActiveAsync(
                    ToggleExecutionContext.FromToggle(
                        feature.Name,
                        EsquioConstants.DEFAULT_PRODUCT_NAME,
                        EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                        toggle));
            });
        }
예제 #5
0
        public async Task be_not_active_when_headervalue__are_not_successfully_configured()
        {
            var toggle = Build
                         .Toggle <HeaderValueToggle>()
                         .AddParameter("HeaderName", "Accept")
                         .AddParameter("HeaderValues", "text/xml")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Request.Headers.Add("Accept", "application/json");

            var headerValueToggle = new HeaderValueToggle(new FakeHttpContextAccessor(context));

            var active = await headerValueToggle.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeFalse();
        }
예제 #6
0
        public async Task be_not_active_if_localip_is_empty()
        {
            var toggle = Build
                         .Toggle <ClientIpAddressToggle>()
                         .AddParameter(IpAddresses, "127.0.0.1;127.0.0.2")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Connection
            .RemoteIpAddress = null;

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new ClientIpAddressToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeFalse();
        }
예제 #7
0
        public async Task be_active_if_user_agent_is_allowed()
        {
            var toggle = Build
                         .Toggle <UserAgentToggle>()
                         .AddParameter(Browsers, "Firefox")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Request
            .Headers
            .Add("user-agent", new StringValues("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new UserAgentToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeTrue();
        }
예제 #8
0
        /// <inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            var roles = context.Data[Roles]?.ToString();

            if (roles is null)
            {
                return(new ValueTask <bool>(false));
            }

            var tokenizer = new StringTokenizer(roles, EsquioConstants.DEFAULT_SPLIT_SEPARATOR);

            foreach (var role in tokenizer)
            {
                var isActive = _httpContextAccessor
                               .HttpContext?
                               .User?
                               .IsInRole(role.Value);

                if (isActive.HasValue && isActive.Value)
                {
                    return(new ValueTask <bool>(true));
                }
            }

            return(new ValueTask <bool>(false));
        }
예제 #9
0
        public async Task be_active_when_claim_value_is_on_valid_partition()
        {
            var toggle = Build
                         .Toggle <GradualRolloutClaimValueToggle>()
                         .AddParameter("ClaimType", "some_claim_type")
                         .AddParameter("Percentage", 100)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim("some_claim_type", "some_claim_value") }, "cookies"));

            var store       = new DelegatedValueFeatureStore((_, __, ___) => feature);
            var partitioner = new DefaultValuePartitioner();

            var gradualRolloutClaimValue = new GradualRolloutClaimValueToggle(partitioner, new FakeHttpContextAccessor(context));

            var active = await gradualRolloutClaimValue.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeTrue();
        }
예제 #10
0
        public async Task be_not_active_if_role_is_not_contained_on_roles_parameters_value()
        {
            var toggle = Build
                         .Toggle <RoleNameToggle>()
                         .AddParameter(Roles, "admin")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim(ClaimsIdentity.DefaultRoleClaimType, "userole") }, "cookies"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new RoleNameToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeFalse();
        }
예제 #11
0
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            var ipAddress = _contextAccessor.HttpContext
                            .Connection
                            .LocalIpAddress;

            if (ipAddress != null)
            {
                string allowedIpAddresses = context.Data[IpAddresses]?.ToString();

                var bytes = ipAddress.GetAddressBytes();

                var tokenizer = new StringTokenizer(allowedIpAddresses, EsquioConstants.DEFAULT_SPLIT_SEPARATOR);

                foreach (var token in tokenizer)
                {
                    if (token.HasValue &&
                        IPAddress.TryParse(token, out IPAddress address) &&
                        address.GetAddressBytes().SequenceEqual(bytes))
                    {
                        return(new ValueTask <bool>(true));
                    }
                }
            }

            return(new ValueTask <bool>(false));
        }
예제 #12
0
        public async Task be_active_if_user_is_equal_to_users_parameters_value()
        {
            var toggle = Build
                         .Toggle <UserNameToggle>()
                         .AddParameter(Users, "user1")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim(ClaimsIdentity.DefaultNameClaimType, "user1") }, "cookies"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new UserNameToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeTrue();
        }
예제 #13
0
        public async Task be_inactive_if_configured_country_is_not_the_same_as_remote_ip_address()
        {
            var toggle = Build
                         .Toggle <Ip2CountryToggle>()
                         .AddParameter(Countries, "FR")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Connection.RemoteIpAddress = IPAddress.Parse("2.142.250.6");

            var contextAccessor   = new FakeHttpContextAccessor(context);
            var httpClientFactory = new FakeHttpClientFactory();

            var active = await new Ip2CountryToggle(contextAccessor, httpClientFactory).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeFalse();
        }
예제 #14
0
        public async Task be_not_active_when_claim_type_and_value_are_successfully_configured()
        {
            var toggle = Build
                         .Toggle <ClaimValueToggle>()
                         .AddParameter("ClaimType", "some_claim_type")
                         .AddParameter("ClaimValues", "some_claim_value")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim("some_claim_type", "not_some_claim_value") }, "cookies"));

            var store            = new DelegatedValueFeatureStore((_, __, ___) => feature);
            var claimValueToggle = new ClaimValueToggle(new FakeHttpContextAccessor(context));

            var active = await claimValueToggle.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeFalse();
        }
예제 #15
0
        public async Task be_not_active_if_user_is_null()
        {
            var toggle = Build
                         .Toggle <UserNameToggle>()
                         .AddParameter(Users, "user")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity());

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new UserNameToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeFalse();
        }
예제 #16
0
        public async Task be_active_when_user_partition_is_on_percent_bucket(string username, int percentage)
        {
            var partition = new DefaultValuePartitioner().ResolvePartition(Constants.FeatureName + username, partitions: 100);
            var expected  = partition <= percentage;

            var toggle = Build
                         .Toggle <GradualRolloutUserNameToggle>()
                         .AddParameter(Percentage, percentage)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim(ClaimsIdentity.DefaultNameClaimType, username) }, "cookies"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var partitioner = new DefaultValuePartitioner();

            var active = await new GradualRolloutUserNameToggle(partitioner, contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().Be(expected);
        }
예제 #17
0
        public async Task be_no_active_when_percentage_is_zero_percent()
        {
            var toggle = Build
                         .Toggle <GradualRolloutUserNameToggle>()
                         .AddParameter(Percentage, 0)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim(ClaimsIdentity.DefaultNameClaimType, "User1") }, "cookies"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var partitioner = new DefaultValuePartitioner();

            var active = await new GradualRolloutUserNameToggle(partitioner, contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeFalse();
        }
예제 #18
0
        ///<inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            string headerName    = context.Data[HeaderName]?.ToString();
            string allowedValues = context.Data[HeaderValues]?.ToString();

            if (headerName != null
                &&
                allowedValues != null)
            {
                var tokenizer = new StringTokenizer(allowedValues, SPLIT_SEPARATOR);

                var values = _httpContextAccessor.HttpContext
                             .Request
                             .Headers[headerName];

                foreach (var item in values)
                {
                    var active = tokenizer.Contains(item, StringSegmentComparer.OrdinalIgnoreCase);

                    return(new ValueTask <bool>(active));
                }
            }

            return(new ValueTask <bool>(false));
        }
예제 #19
0
        ///<inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            string claimType     = context.Data[ClaimType]?.ToString();
            string allowedValues = context.Data[ClaimValues]?.ToString();

            if (claimType != null
                &&
                allowedValues != null)
            {
                var user = _httpContextAccessor.HttpContext.User;
                if (user != null && user.Identity.IsAuthenticated)
                {
                    var tokenizer = new StringTokenizer(allowedValues, EsquioConstants.DEFAULT_SPLIT_SEPARATOR);

                    var claimValues = user.Claims
                                      .Where(claim => claim.Type == claimType)
                                      .Select(claim => claim.Value);

                    foreach (var item in claimValues)
                    {
                        if (item != null)
                        {
                            var active = tokenizer.Contains(item, StringSegmentComparer.OrdinalIgnoreCase);
                            return(new ValueTask <bool>(active));
                        }
                    }
                }
            }

            return(new ValueTask <bool>(false));
        }
예제 #20
0
        public async Task be_active_when_role_type_is_different_from_default_role_type()
        {
            var toggle = Build
                         .Toggle <RoleNameToggle>()
                         .AddParameter(Roles, "admin")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(
                    new Claim[] { new Claim("role", "admin") }, "cookies", nameType: "name", roleType: "role"));

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new RoleNameToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeTrue();
        }
예제 #21
0
        /// <inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            var parseExactFormats = new string[] { DEFAULT_FORMAT_DATE, SINGLE_DIGIT_FORMAT_DATE };

            var fromDate = DateTime.ParseExact(
                context.Data[From].ToString(),
                parseExactFormats,
                CultureInfo.InvariantCulture,
                DateTimeStyles.AssumeUniversal);

            var toDate = DateTime.ParseExact(
                context.Data[To].ToString(),
                parseExactFormats,
                CultureInfo.InvariantCulture,
                DateTimeStyles.AssumeUniversal);

            var now = DateTime.UtcNow;

            if (now > fromDate && now < toDate)
            {
                return(new ValueTask <bool>(true));
            }

            return(new ValueTask <bool>(false));
        }
예제 #22
0
        public async Task be_active_if_user_agent_is_allowed()
        {
            var toggle = Build
                         .Toggle <ServerIpAddressToggle>()
                         .AddParameter(IpAddresses, "127.0.0.1;127.0.0.2")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Connection
            .LocalIpAddress = IPAddress.Parse("127.0.0.1");

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new ServerIpAddressToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeTrue();
        }
예제 #23
0
        public async Task be_active_when_claim_value_is_on_valid_partition()
        {
            var toggle = Build
                         .Toggle <GradualRolloutHeaderValueToggle>()
                         .AddParameter("HeaderName", "header-name")
                         .AddParameter("Percentage", 100)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Request.Headers.Add(new KeyValuePair <string, StringValues>("header-name", "header-value"));

            var partitioner = new DefaultValuePartitioner();

            var gradualRolloutHeaderValue = new GradualRolloutHeaderValueToggle(partitioner, new FakeHttpContextAccessor(context));

            var active = await gradualRolloutHeaderValue.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeTrue();
        }
예제 #24
0
        public async Task be_active_if_hostname_is_allowed()
        {
            var toggle = Build
                         .Toggle <HostNameToggle>()
                         .AddParameter(HostNames, "localhost")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Request.Host = new HostString("localhost", 8080);

            var contextAccessor = new FakeHttpContextAccessor(context);

            var active = await new HostNameToggle(contextAccessor).IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeTrue();
        }
예제 #25
0
        public async Task be_active_if_current_environment_is_configured_with_different_case()
        {
            var toggle = Build
                         .Toggle <EnvironmentVariableToggle>()
                         .AddParameter(EnvironmentVariable, "ASPNETCORE_ENVIRONMENT")
                         .AddParameter(Values, "pRoDuCtIoN")
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Production", EnvironmentVariableTarget.Process);



            var active = await new EnvironmentVariableToggle().IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should().BeTrue();
        }
예제 #26
0
        /// <inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            string headerName = context.Data[HeaderName].ToString();

            if (Double.TryParse(context.Data[Percentage].ToString(), out double percentage))
            {
                if (percentage > 0d)
                {
                    var values = _httpContextAccessor.HttpContext
                                 .Request
                                 .Headers[headerName];

                    if (values != StringValues.Empty)
                    {
                        // this only apply when header exist, we apply also some entropy to header value.
                        // adding this entropy ensure that not all features with gradual rollout for claim value are enabled/disable at the same time for the same user.

                        var assignedPartition = _partitioner.ResolvePartition(context.FeatureName + values.First(), partitions: 100);
                        var active            = assignedPartition <= percentage;

                        return(new ValueTask <bool>(active));
                    }
                }
            }

            return(new ValueTask <bool>(false));
        }
예제 #27
0
        ///  <inheritdoc />
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            string environments = context.Data[Environments]?.ToString();

            if (environments != null)
            {
                var tokenizer = new StringTokenizer(environments, EsquioConstants.DEFAULT_SPLIT_SEPARATOR);
                var isActive  = tokenizer.Contains(_hostEnvironment.EnvironmentName, StringSegmentComparer.OrdinalIgnoreCase);

                return(new ValueTask <bool>(isActive));
            }

            return(new ValueTask <bool>(false));
        }
예제 #28
0
        public async Task use_partition_for_claim_value(int percentage)
        {
            var valid       = false;
            var claim_value = default(string);

            do
            {
                claim_value = Guid.NewGuid().ToString();
                var partition = new DefaultValuePartitioner().ResolvePartition(Constants.FeatureName + claim_value, partitions: 100);

                if (partition <= percentage)
                {
                    valid = true;
                }
            } while (!valid);

            var toggle = Build
                         .Toggle <GradualRolloutClaimValueToggle>()
                         .AddParameter("ClaimType", "some_claim_type")
                         .AddParameter("Percentage", percentage)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.User = new ClaimsPrincipal(
                new ClaimsIdentity(new Claim[] { new Claim("some_claim_type", claim_value) }, "cookies"));

            var partitioner = new DefaultValuePartitioner();

            var gradualRolloutClaimValue = new GradualRolloutClaimValueToggle(partitioner, new FakeHttpContextAccessor(context));

            var active = await gradualRolloutClaimValue.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeTrue();
        }
예제 #29
0
        public async Task use_partition_for_claim_value(int percentage)
        {
            var valid        = false;
            var header_value = default(string);

            do
            {
                header_value = Guid.NewGuid().ToString();
                var partition = new DefaultValuePartitioner().ResolvePartition(Constants.FeatureName + header_value, partitions: 100);

                if (partition <= percentage)
                {
                    valid = true;
                }
            } while (!valid);

            var toggle = Build
                         .Toggle <GradualRolloutHeaderValueToggle>()
                         .AddParameter("HeaderName", "header-name")
                         .AddParameter("Percentage", percentage)
                         .Build();

            var feature = Build
                          .Feature(Constants.FeatureName)
                          .AddOne(toggle)
                          .Build();

            var context = new DefaultHttpContext();

            context.Request.Headers.Add(new KeyValuePair <string, StringValues>("header-name", header_value));

            var partitioner = new DefaultValuePartitioner();

            var gradualRolloutHeaderValue = new GradualRolloutHeaderValueToggle(partitioner, new FakeHttpContextAccessor(context));

            var active = await gradualRolloutHeaderValue.IsActiveAsync(
                ToggleExecutionContext.FromToggle(
                    feature.Name,
                    EsquioConstants.DEFAULT_PRODUCT_NAME,
                    EsquioConstants.DEFAULT_DEPLOYMENT_NAME,
                    toggle));

            active.Should()
            .BeTrue();
        }
예제 #30
0
        /// <inheritdoc/>
        public ValueTask <bool> IsActiveAsync(ToggleExecutionContext context, CancellationToken cancellationToken = default)
        {
            string environmentVariable = context.Data[EnvironmentVariable]?.ToString();
            string validValues         = context.Data[Values]?.ToString();

            string environmentVariableValue = Environment
                                              .GetEnvironmentVariable(environmentVariable);

            if (environmentVariableValue != null)
            {
                var tokenizer = new StringTokenizer(validValues, EsquioConstants.DEFAULT_SPLIT_SEPARATOR);
                var active    = tokenizer.Contains(environmentVariableValue, StringSegmentComparer.OrdinalIgnoreCase);

                return(new ValueTask <bool>(active));
            }

            return(new ValueTask <bool>(false));
        }