Skip to content

Commit f905cc3

Browse files
Merge pull request #49 from Flagsmith/release/4.2.0
Release 4.2.0
2 parents 2e9ecc4 + ebb3a0a commit f905cc3

File tree

6 files changed

+75
-6
lines changed

6 files changed

+75
-6
lines changed

Flagsmith.Engine/Segment/Constants.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,8 @@ public static class Constants
2020
public const string NotEqual = "NOT_EQUAL";
2121
public const string Regex = "REGEX";
2222
public const string PercentageSplit = "PERCENTAGE_SPLIT";
23+
public const string IsSet = "IS_SET";
24+
public const string IsNotSet = "IS_NOT_SET";
25+
public const string Modulo = "MODULO";
2326
}
2427
}

Flagsmith.Engine/Segment/Evaluator.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,24 @@ static bool TraitsMatchSegmentCondition(List<TraitModel> identityTraits, Segment
3636
return Hashing.GetHashedPercentageForObjectIds(new List<string>() { segemntId, identityId }) <= float.Parse(condition.Value);
3737

3838
var trait = identityTraits?.FirstOrDefault(t => t.TraitKey == condition.Property);
39-
if (trait != null)
40-
return MatchesTraitValue(trait.TraitValue, condition);
41-
return false;
39+
40+
if (condition.Operator == Constants.IsSet)
41+
{
42+
return trait != null;
43+
}
44+
else if (condition.Operator == Constants.IsNotSet)
45+
{
46+
return trait == null;
47+
}
48+
49+
return trait != null && MatchesTraitValue(trait.TraitValue, condition);
4250
}
4351
public static bool MatchesTraitValue(object traitValue, SegmentConditionModel condition)
4452
{
4553
var exceptionOperatorMethods = new Dictionary<string, string>(){
4654
{Constants.NotContains, "EvaluateNotContains"},
4755
{Constants.Regex, "EvaluateRegex"},
56+
{Constants.Modulo, "EvaluateModulo"},
4857
};
4958
if (exceptionOperatorMethods.ContainsKey(condition.Operator))
5059
return (bool)typeof(SegmentConditionModel).GetMethod(exceptionOperatorMethods[condition.Operator]).Invoke(condition, new object[] { traitValue });

Flagsmith.Engine/Segment/Models/SegmentConditionModel.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Text.RegularExpressions;
2+
using System;
23
using Newtonsoft.Json;
34
namespace FlagsmithEngine.Segment.Models
45
{
@@ -13,6 +14,23 @@ public class SegmentConditionModel
1314

1415
public bool EvaluateNotContains(string traitValue) => !traitValue.Contains(Value);
1516
public bool EvaluateRegex(string traitValue) => Regex.Match(traitValue, Value).Success;
17+
public bool EvaluateModulo(object traitValue)
18+
{
19+
try
20+
{
21+
string[] parts = this.Value.Split('|');
22+
if (parts.Length != 2) { return false; }
23+
24+
double divisor = Convert.ToDouble(parts[0]);
25+
double remainder = Convert.ToDouble(parts[1]);
26+
27+
return Convert.ToDouble(traitValue) % divisor == remainder;
28+
}
29+
catch (FormatException)
30+
{
31+
return false;
32+
}
33+
}
1634

1735
}
1836
}

Flagsmith.EngineTest/Unit/Segments/SegmentEvaluatorTest.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ public static IEnumerable<object[]> TestCasesSegmentCondition() =>
9393
new object[]{Constants.LessThanInclusive, "1.0.0", "1.0.1:semver", true},
9494
new object[]{Constants.LessThanInclusive, "1.0.0", "1.0.0:semver", true},
9595
new object[]{Constants.LessThanInclusive, "1.0.1", "1.0.0:semver", false},
96+
new object[]{Constants.Modulo, 2, "2|0", true},
97+
new object[]{Constants.Modulo, 3, "2|0", false},
98+
new object[]{Constants.Modulo, 2.0, "2|0", true},
99+
new object[]{Constants.Modulo, 2.0, "2.0|0", true},
100+
new object[]{Constants.Modulo, "foo", "2|0", false},
101+
new object[]{Constants.Modulo, "foo", "foo|bar", false},
96102
};
97103
[Theory]
98104
[MemberData(nameof(TestCasesIdentityInSegment))]
@@ -142,6 +148,10 @@ public static IEnumerable<object[]> TestCasesIdentityInSegment() =>
142148
new TraitModel { TraitKey = Fixtures.TraitKey3, TraitValue = Fixtures.TraitValue3 }
143149
}, true
144150
},
151+
new object[] { Fixtures.SegmentToCheckIfTrait1IsSet, new List<TraitModel>(), false },
152+
new object[] { Fixtures.SegmentToCheckIfTrait1IsSet, new List<TraitModel>() { new TraitModel {TraitKey = Fixtures.TraitKey1, TraitValue = "foo"}}, true },
153+
new object[] { Fixtures.SegmentToCheckIfTrait1IsNotSet, new List<TraitModel>() { new TraitModel {TraitKey = Fixtures.TraitKey1, TraitValue = "foo"}}, false },
154+
new object[] { Fixtures.SegmentToCheckIfTrait1IsNotSet, new List<TraitModel>(), true },
145155
};
146156
[Theory]
147157
[InlineData(10, 1, true)]
@@ -164,6 +174,5 @@ public void TestIdentityInSegmentPercentageSplit(int segmentSplitValue, int iden
164174
var result = Evaluator.EvaluateIdentityInSegment(Unit.Fixtures.Identity(), segment, null);
165175
Assert.Equal(expectedResult, result);
166176
}
167-
168177
}
169178
}

Flagsmith.EngineTest/Unit/Segments/fixtures.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,35 @@ public class Fixtures
122122
}
123123

124124
};
125+
126+
public static SegmentModel SegmentToCheckIfTrait1IsSet => new SegmentModel()
127+
{
128+
Id = 7,
129+
Name = "segment_to_check_if_foo_is_set",
130+
Rules = new List<SegmentRuleModel> {
131+
new SegmentRuleModel {
132+
Type = Constants.AllRule,
133+
Conditions = new List<SegmentConditionModel>
134+
{
135+
new SegmentConditionModel { Operator = Constants.IsSet, Property = TraitKey1, Value = null }
136+
}
137+
}
138+
}
139+
};
140+
141+
public static SegmentModel SegmentToCheckIfTrait1IsNotSet => new SegmentModel()
142+
{
143+
Id = 8,
144+
Name = "segment_to_check_if_foo_is_not_set",
145+
Rules = new List<SegmentRuleModel> {
146+
new SegmentRuleModel {
147+
Type = Constants.AllRule,
148+
Conditions = new List<SegmentConditionModel>
149+
{
150+
new SegmentConditionModel { Operator = Constants.IsNotSet, Property = TraitKey1, Value = null }
151+
}
152+
}
153+
}
154+
};
125155
}
126156
}

Flagsmith.FlagsmithClient/Flagsmith.FlagsmithClient.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
77
<PackageId>Flagsmith</PackageId>
88
<Title>Flagsmith</Title>
9-
<Version>4.1.0</Version>
10-
<Authors>ssg-luke</Authors>
9+
<Version>4.2.0</Version>
10+
<Authors>flagsmith</Authors>
1111
<Company>Flagsmith</Company>
1212
<PackageDescription>Client SDK for Flagsmith. Ship features with confidence using feature flags and remote config. Host yourself or use our hosted version at https://flagsmith.com/</PackageDescription>
1313
<Copyright>Copyright © 2021 Bullet Train Ltd</Copyright>

0 commit comments

Comments
 (0)