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(); }
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(); }
///<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)); }
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)); }); }
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(); }
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(); }
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(); }
/// <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)); }
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(); }
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(); }
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)); }
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(); }
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(); }
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(); }
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(); }
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); }
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(); }
///<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)); }
///<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)); }
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(); }
/// <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)); }
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(); }
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(); }
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(); }
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(); }
/// <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)); }
/// <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)); }
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(); }
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(); }
/// <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)); }