Skip to content

Commit 86c8026

Browse files
msohailhussainmikeproeng37
authored andcommitted
Feature Flag & Roll out models (#25)
1 parent 66572d7 commit 86c8026

File tree

14 files changed

+885
-180
lines changed

14 files changed

+885
-180
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
language: csharp
2+
mono:
3+
- 5.2.0
24
solution: "./OptimizelySDK.Travis.sln"
35
install:
46
- nuget restore ./OptimizelySDK.Travis.sln
57
- nuget install ./OptimizelySDK.Tests/packages.config -OutputDirectory ./packages
68
- nuget install NUnit.Runners -Version 2.6.4 -OutputDirectory ./testrunner
79
script:
810
- xbuild /p:Configuration=Release ./OptimizelySDK.Travis.sln
9-
- mono ./testrunner/NUnit.Runners.2.6.4/tools/nunit-console.exe ./OptimizelySDK.Tests/bin/Release/OptimizelySDK.Tests.dll
11+
- mono ./testrunner/NUnit.Runners.2.6.4/tools/nunit-console.exe ./OptimizelySDK.Tests/bin/Release/OptimizelySDK.Tests.dll

OptimizelySDK.Net35/OptimizelySDK.Net35.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@
162162
</Compile>
163163
<Compile Include="..\OptimizelySDK\Bucketing\UserprofileUtil.cs">
164164
<Link>Bucketing\UserProfileUtil</Link>
165+
</Compile>
166+
<Compile Include="..\OptimizelySDK\Entity\FeatureVariableUsage.cs">
167+
<Link>Entity\FeatureVariableUsage</Link>
168+
</Compile>
169+
<Compile Include="..\OptimizelySDK\Entity\FeatureFlag.cs">
170+
<Link>Entity\FeatureFlag</Link>
171+
</Compile>
172+
<Compile Include="..\OptimizelySDK\Entity\FeatureVariable.cs">
173+
<Link>Entity\FeatureVariable</Link>
174+
</Compile>
175+
<Compile Include="..\OptimizelySDK\Entity\Rollout.cs">
176+
<Link>Entity\Rollout</Link>
165177
</Compile>
166178
</ItemGroup>
167179
<ItemGroup>

OptimizelySDK.Net40/OptimizelySDK.Net40.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@
162162
</Compile>
163163
<Compile Include="..\OptimizelySDK\Bucketing\UserprofileUtil.cs">
164164
<Link>Bucketing\UserProfileUtil</Link>
165+
</Compile>
166+
<Compile Include="..\OptimizelySDK\Entity\FeatureVariableUsage.cs">
167+
<Link>Entity\FeatureVariableUsage</Link>
168+
</Compile>
169+
<Compile Include="..\OptimizelySDK\Entity\FeatureFlag.cs">
170+
<Link>Entity\FeatureFlag</Link>
171+
</Compile>
172+
<Compile Include="..\OptimizelySDK\Entity\FeatureVariable.cs">
173+
<Link>Entity\FeatureVariable</Link>
174+
</Compile>
175+
<Compile Include="..\OptimizelySDK\Entity\Rollout.cs">
176+
<Link>Entity\Rollout</Link>
165177
</Compile>
166178
</ItemGroup>
167179
<ItemGroup>

OptimizelySDK.NetStandard16/OptimizelySDK.NetStandard16.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
<Compile Include="..\OptimizelySDK\Entity\TrafficAllocation.cs" />
1818
<Compile Include="..\OptimizelySDK\Entity\UserAttributes.cs" />
1919
<Compile Include="..\OptimizelySDK\Entity\Variation.cs" />
20+
<Compile Include="..\OptimizelySDK\Entity\FeatureVariableUsage.cs" />
21+
<Compile Include="..\OptimizelySDK\Entity\FeatureFlag.cs" />
22+
<Compile Include="..\OptimizelySDK\Entity\FeatureVariable.cs" />
23+
<Compile Include="..\OptimizelySDK\Entity\Rollout.cs"/>
2024
<Compile Include="..\OptimizelySDK\ErrorHandler\DefaultErrorHandler.cs" />
2125
<Compile Include="..\OptimizelySDK\ErrorHandler\IErrorHandler.cs" />
2226
<Compile Include="..\OptimizelySDK\ErrorHandler\NoOpErrorHandler.cs" />
@@ -45,7 +49,7 @@
4549
<Compile Include="..\OptimizelySDK\Bucketing\UserProfile.cs" />
4650
<Compile Include="..\OptimizelySDK\Bucketing\UserProfileService.cs" />
4751
<Compile Include="..\OptimizelySDK\Bucketing\UserProfileUtil.cs" />
48-
<Compile Include="..\OptimizelySDK\Utils\ExperimentUtils.cs" />
52+
<Compile Include="..\OptimizelySDK\Utils\ExperimentUtils.cs" />
4953

5054
</ItemGroup>
5155
<ItemGroup>

OptimizelySDK.Tests/ProjectConfigTest.cs

Lines changed: 108 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static Dictionary<string, object> CreateDictionary(string name, object en
5151
public void TestInit()
5252
{
5353
// Check Version
54-
Assert.AreEqual(2, Config.Version);
54+
Assert.AreEqual(4, Config.Version);
5555

5656
// Check Account ID
5757
Assert.AreEqual("1592310167", Config.AccountId);
@@ -71,6 +71,10 @@ public void TestInit()
7171
{
7272
{"test_experiment",Config.GetExperimentFromKey("test_experiment") },
7373
{ "paused_experiment",Config.GetExperimentFromKey("paused_experiment") },
74+
{ "test_experiment_multivariate",Config.GetExperimentFromKey("test_experiment_multivariate") },
75+
{ "test_experiment_with_feature_rollout",Config.GetExperimentFromKey("test_experiment_with_feature_rollout") },
76+
{ "test_experiment_double_feature",Config.GetExperimentFromKey("test_experiment_double_feature") },
77+
{ "test_experiment_integer_feature",Config.GetExperimentFromKey("test_experiment_integer_feature") },
7478
{ "group_experiment_1",Config.GetExperimentFromKey("group_experiment_1") },
7579
{"group_experiment_2",Config.GetExperimentFromKey("group_experiment_2") }
7680
};
@@ -83,14 +87,17 @@ public void TestInit()
8387
{
8488
{"7716830082",Config.GetExperimentFromId("7716830082") },
8589
{"7716830585",Config.GetExperimentFromId("7716830585") },
90+
{"122230",Config.GetExperimentFromId("122230") },
91+
{"122235",Config.GetExperimentFromId("122235") },
92+
{"122238",Config.GetExperimentFromId("122238") },
93+
{"122241",Config.GetExperimentFromId("122241") },
8694
{ "7723330021",Config.GetExperimentFromId("7723330021") },
8795
{ "7718750065",Config.GetExperimentFromId("7718750065") }
8896
};
8997

90-
Assert.IsTrue(TestData.CompareObjects(experimentIdMap, Config.ExperimentIdMap));
91-
92-
// Check Event key Map
98+
Assert.IsTrue(TestData.CompareObjects(experimentIdMap, Config.ExperimentIdMap));
9399

100+
// Check Event key Map
94101
var eventKeyMap = new Dictionary<string, object> { { "purchase", Config.GetEvent("purchase") } };
95102
Assert.IsTrue(TestData.CompareObjects(eventKeyMap, Config.EventKeyMap));
96103

@@ -105,12 +112,13 @@ public void TestInit()
105112
// Check Audience ID Map
106113
var audienceIdMap = new Dictionary<string, object>
107114
{
108-
{ "7718080042", Config.GetAudience("7718080042") }
115+
{ "7718080042", Config.GetAudience("7718080042") },
116+
{ "11155", Config.GetAudience("11155") }
109117
};
110118
Assert.IsTrue(TestData.CompareObjects(audienceIdMap, Config.AudienceIdMap));
111119

112120
// Check Variation Key Map
113-
var variationKeyMap = new Dictionary<string, object>
121+
var expectedVariationKeyMap = new Dictionary<string, object>
114122
{
115123
{ "test_experiment", new Dictionary<string, object>
116124
{
@@ -130,21 +138,44 @@ public void TestInit()
130138
{ "group_exp_1_var_2", Config.GetVariationFromKey("group_experiment_1", "group_exp_1_var_2") }
131139
}
132140
},
133-
{
134-
"group_experiment_2", new Dictionary<string, object>
141+
{ "group_experiment_2", new Dictionary<string, object>
135142
{
136143
{"group_exp_2_var_1", Config.GetVariationFromKey("group_experiment_2", "group_exp_2_var_1") },
137144
{ "group_exp_2_var_2", Config.GetVariationFromKey("group_experiment_2", "group_exp_2_var_2") }
138145
}
146+
},
147+
{ "test_experiment_multivariate", new Dictionary<string, object>
148+
{
149+
{"Fred", Config.GetVariationFromKey("test_experiment_multivariate", "Fred") },
150+
{ "Feorge", Config.GetVariationFromKey("test_experiment_multivariate", "Feorge") },
151+
{ "Gred", Config.GetVariationFromKey("test_experiment_multivariate", "Gred") },
152+
{ "George", Config.GetVariationFromKey("test_experiment_multivariate", "George") }
153+
}
154+
},
155+
{ "test_experiment_with_feature_rollout", new Dictionary<string, object>
156+
{
157+
{"control", Config.GetVariationFromKey("test_experiment_with_feature_rollout", "control") },
158+
{ "variation", Config.GetVariationFromKey("test_experiment_with_feature_rollout", "variation") }
159+
}
160+
},
161+
{ "test_experiment_double_feature", new Dictionary<string, object>
162+
{
163+
{"control", Config.GetVariationFromKey("test_experiment_double_feature", "control") },
164+
{ "variation", Config.GetVariationFromKey("test_experiment_double_feature", "variation") }
165+
}
166+
},
167+
{ "test_experiment_integer_feature", new Dictionary<string, object>
168+
{
169+
{"control", Config.GetVariationFromKey("test_experiment_integer_feature", "control") },
170+
{ "variation", Config.GetVariationFromKey("test_experiment_integer_feature", "variation") }
171+
}
139172
}
140173
};
141174

142-
143-
144-
Assert.IsTrue(TestData.CompareObjects(variationKeyMap, Config.VariationKeyMap));
175+
Assert.IsTrue(TestData.CompareObjects(expectedVariationKeyMap, Config.VariationKeyMap));
145176

146177
// Check Variation ID Map
147-
var variationIdMap = new Dictionary<string, object>
178+
var expectedVariationIdMap = new Dictionary<string, object>
148179
{
149180
{ "test_experiment", new Dictionary<string, object>
150181
{
@@ -158,6 +189,32 @@ public void TestInit()
158189
{ "7721010509", Config.GetVariationFromId("paused_experiment", "7721010509") }
159190
}
160191
},
192+
{ "test_experiment_multivariate", new Dictionary<string, object>
193+
{
194+
{ "122231", Config.GetVariationFromId("test_experiment_multivariate", "122231") },
195+
{ "122232", Config.GetVariationFromId("test_experiment_multivariate", "122232") },
196+
{ "122233", Config.GetVariationFromId("test_experiment_multivariate", "122233") },
197+
{ "122234", Config.GetVariationFromId("test_experiment_multivariate", "122234") }
198+
}
199+
},
200+
{ "test_experiment_with_feature_rollout", new Dictionary<string, object>
201+
{
202+
{ "122236", Config.GetVariationFromId("test_experiment_with_feature_rollout", "122236") },
203+
{ "122237", Config.GetVariationFromId("test_experiment_with_feature_rollout", "122237") }
204+
}
205+
},
206+
{ "test_experiment_double_feature", new Dictionary<string, object>
207+
{
208+
{ "122239", Config.GetVariationFromId("test_experiment_double_feature", "122239") },
209+
{ "122240", Config.GetVariationFromId("test_experiment_double_feature", "122240") }
210+
}
211+
},
212+
{ "test_experiment_integer_feature", new Dictionary<string, object>
213+
{
214+
{ "122242", Config.GetVariationFromId("test_experiment_integer_feature", "122242") },
215+
{ "122243", Config.GetVariationFromId("test_experiment_integer_feature", "122243") }
216+
}
217+
},
161218
{ "group_experiment_1", new Dictionary<string, object>
162219
{
163220
{"7722260071", Config.GetVariationFromId("group_experiment_1", "7722260071") },
@@ -171,7 +228,45 @@ public void TestInit()
171228
}
172229
};
173230

174-
Assert.IsTrue(TestData.CompareObjects(variationIdMap, Config.VariationIdMap));
231+
Assert.IsTrue(TestData.CompareObjects(expectedVariationIdMap, Config.VariationIdMap));
232+
233+
234+
// Check Variation returns correct variable usage
235+
var featureVariableUsageInstance = new List<FeatureVariableUsage>
236+
{
237+
new FeatureVariableUsage{Id="155560", Value="F"},
238+
new FeatureVariableUsage{Id="155561", Value="red"},
239+
};
240+
var expectedVariationUsage = new Variation { Id = "122231", Key = "Fred", FeatureVariableUsageInstances = featureVariableUsageInstance};
241+
242+
var actualVariationUsage = Config.GetVariationFromKey("test_experiment_multivariate", "Fred");
243+
244+
Assert.IsTrue(TestData.CompareObjects(expectedVariationUsage, actualVariationUsage));
245+
246+
247+
// Check Feature Key map.
248+
var expectedFeatureKeyMap = new Dictionary<string, FeatureFlag>
249+
{
250+
{ "boolean_feature", Config.GetFeatureFlagFromKey("boolean_feature") },
251+
{ "double_single_variable_feature", Config.GetFeatureFlagFromKey("double_single_variable_feature") },
252+
{ "integer_single_variable_feature", Config.GetFeatureFlagFromKey("integer_single_variable_feature") },
253+
{ "boolean_single_variable_feature", Config.GetFeatureFlagFromKey("boolean_single_variable_feature") },
254+
{ "string_single_variable_feature", Config.GetFeatureFlagFromKey("string_single_variable_feature") },
255+
{ "multi_variate_feature", Config.GetFeatureFlagFromKey("multi_variate_feature") },
256+
{ "mutex_group_feature", Config.GetFeatureFlagFromKey("mutex_group_feature") },
257+
{ "empty_feature", Config.GetFeatureFlagFromKey("empty_feature") }
258+
};
259+
260+
Assert.IsTrue(TestData.CompareObjects(expectedFeatureKeyMap, Config.FeatureKeyMap));
261+
262+
// Check Feature Key map.
263+
var expectedRolloutIdMap = new Dictionary<string, Rollout>
264+
{
265+
{ "166660", Config.GetRolloutFromId("166660") },
266+
{ "166661", Config.GetRolloutFromId("166661") }
267+
};
268+
269+
Assert.IsTrue(TestData.CompareObjects(expectedRolloutIdMap, Config.RolloutIdMap));
175270
}
176271

177272
[Test]
@@ -197,8 +292,6 @@ public void TestGetGroupValidId()
197292
[Test]
198293
public void TestGetGroupInvalidId()
199294
{
200-
201-
202295
var group = Config.GetGroup("invalid_id");
203296

204297
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(1));

0 commit comments

Comments
 (0)