Skip to content

Commit 30ccea9

Browse files
[AI-FSSDK] [FSSDK-12369] Add local holdouts support to C# SDK (#408)
* [AI-FSSDK] [FSSDK-12369] Add local holdouts support to C# SDK * [FSSDK-12369] Add mandatory enforcement test: forced decision beats 100% local holdout * [FSSDK-12369] file format fix * [FSSDK-12369] improvements --------- Co-authored-by: Md Junaed Hossain <169046794+junaed-optimizely@users.noreply.github.com>
1 parent fbf6901 commit 30ccea9

8 files changed

Lines changed: 919 additions & 8 deletions

File tree

‎OptimizelySDK.Tests/DecisionServiceHoldoutTest.cs‎

Lines changed: 312 additions & 0 deletions
Large diffs are not rendered by default.

‎OptimizelySDK.Tests/TestData/HoldoutTestData.json‎

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,5 +210,280 @@
210210
"excludedFlags": []
211211
}
212212
]
213+
},
214+
"datafileWithLocalHoldouts": {
215+
"version": "4",
216+
"rollouts": [
217+
{
218+
"id": "rollout_1",
219+
"experiments": [
220+
{
221+
"id": "rule_id_1",
222+
"key": "delivery_rule_1",
223+
"status": "Running",
224+
"layerId": "rollout_layer_1",
225+
"variations": [
226+
{
227+
"id": "rule1_var_1",
228+
"key": "enabled",
229+
"featureEnabled": true,
230+
"variables": []
231+
}
232+
],
233+
"trafficAllocation": [
234+
{
235+
"entityId": "rule1_var_1",
236+
"endOfRange": 10000
237+
}
238+
],
239+
"audienceIds": [],
240+
"audienceConditions": [],
241+
"forcedVariations": {}
242+
},
243+
{
244+
"id": "rule_id_2",
245+
"key": "delivery_rule_2",
246+
"status": "Running",
247+
"layerId": "rollout_layer_1",
248+
"variations": [
249+
{
250+
"id": "rule2_var_1",
251+
"key": "enabled",
252+
"featureEnabled": true,
253+
"variables": []
254+
}
255+
],
256+
"trafficAllocation": [
257+
{
258+
"entityId": "rule2_var_1",
259+
"endOfRange": 10000
260+
}
261+
],
262+
"audienceIds": [],
263+
"audienceConditions": [],
264+
"forcedVariations": {}
265+
},
266+
{
267+
"id": "rule_id_everyone_else",
268+
"key": "everyone_else_rule",
269+
"status": "Running",
270+
"layerId": "rollout_layer_1",
271+
"variations": [
272+
{
273+
"id": "everyone_var_1",
274+
"key": "enabled",
275+
"featureEnabled": true,
276+
"variables": []
277+
}
278+
],
279+
"trafficAllocation": [
280+
{
281+
"entityId": "everyone_var_1",
282+
"endOfRange": 10000
283+
}
284+
],
285+
"audienceIds": [],
286+
"audienceConditions": [],
287+
"forcedVariations": {}
288+
}
289+
]
290+
}
291+
],
292+
"projectId": "test_project",
293+
"experiments": [
294+
{
295+
"id": "exp_rule_id_1",
296+
"key": "experiment_rule_1",
297+
"status": "Running",
298+
"layerId": "exp_layer_1",
299+
"variations": [
300+
{
301+
"id": "exp1_var_1",
302+
"key": "variation_a",
303+
"featureEnabled": true,
304+
"variables": []
305+
}
306+
],
307+
"trafficAllocation": [
308+
{
309+
"entityId": "exp1_var_1",
310+
"endOfRange": 10000
311+
}
312+
],
313+
"audienceIds": [],
314+
"audienceConditions": [],
315+
"forcedVariations": {}
316+
},
317+
{
318+
"id": "exp_rule_id_2",
319+
"key": "experiment_rule_2",
320+
"status": "Running",
321+
"layerId": "exp_layer_2",
322+
"variations": [
323+
{
324+
"id": "exp2_var_1",
325+
"key": "variation_b",
326+
"featureEnabled": true,
327+
"variables": []
328+
}
329+
],
330+
"trafficAllocation": [
331+
{
332+
"entityId": "exp2_var_1",
333+
"endOfRange": 10000
334+
}
335+
],
336+
"audienceIds": [],
337+
"audienceConditions": [],
338+
"forcedVariations": {}
339+
}
340+
],
341+
"groups": [],
342+
"attributes": [],
343+
"audiences": [],
344+
"layers": [],
345+
"events": [],
346+
"revision": "2",
347+
"accountId": "12345",
348+
"anonymizeIP": false,
349+
"featureFlags": [
350+
{
351+
"id": "flag_1",
352+
"key": "test_flag_1",
353+
"experimentIds": [],
354+
"rolloutId": "rollout_1",
355+
"variables": []
356+
},
357+
{
358+
"id": "flag_2",
359+
"key": "test_flag_2",
360+
"experimentIds": ["exp_rule_id_1", "exp_rule_id_2"],
361+
"rolloutId": "",
362+
"variables": []
363+
},
364+
{
365+
"id": "flag_3",
366+
"key": "test_flag_3",
367+
"experimentIds": [],
368+
"rolloutId": "",
369+
"variables": []
370+
}
371+
],
372+
"holdouts": [
373+
{
374+
"id": "holdout_global_2",
375+
"key": "global_holdout_2",
376+
"status": "Running",
377+
"layerId": "layer_g2",
378+
"variations": [
379+
{
380+
"id": "gvar_1",
381+
"key": "holdout_off",
382+
"featureEnabled": false,
383+
"variables": []
384+
}
385+
],
386+
"trafficAllocation": [
387+
{
388+
"entityId": "gvar_1",
389+
"endOfRange": 10000
390+
}
391+
],
392+
"audienceIds": [],
393+
"audienceConditions": []
394+
},
395+
{
396+
"id": "holdout_local_rule1",
397+
"key": "local_holdout_rule1",
398+
"status": "Running",
399+
"layerId": "layer_local_1",
400+
"variations": [
401+
{
402+
"id": "lvar_1",
403+
"key": "local_holdout_off",
404+
"featureEnabled": false,
405+
"variables": []
406+
}
407+
],
408+
"trafficAllocation": [
409+
{
410+
"entityId": "lvar_1",
411+
"endOfRange": 10000
412+
}
413+
],
414+
"audienceIds": [],
415+
"audienceConditions": [],
416+
"includedRules": ["rule_id_1"]
417+
},
418+
{
419+
"id": "holdout_local_rule2",
420+
"key": "local_holdout_rule2",
421+
"status": "Running",
422+
"layerId": "layer_local_2",
423+
"variations": [
424+
{
425+
"id": "lvar_2",
426+
"key": "local_holdout_off_2",
427+
"featureEnabled": false,
428+
"variables": []
429+
}
430+
],
431+
"trafficAllocation": [
432+
{
433+
"entityId": "lvar_2",
434+
"endOfRange": 10000
435+
}
436+
],
437+
"audienceIds": [],
438+
"audienceConditions": [],
439+
"includedRules": ["rule_id_2"]
440+
},
441+
{
442+
"id": "holdout_local_empty_rules",
443+
"key": "local_holdout_empty_rules",
444+
"status": "Running",
445+
"layerId": "layer_local_empty",
446+
"variations": [
447+
{
448+
"id": "lvar_empty",
449+
"key": "local_empty_off",
450+
"featureEnabled": false,
451+
"variables": []
452+
}
453+
],
454+
"trafficAllocation": [
455+
{
456+
"entityId": "lvar_empty",
457+
"endOfRange": 10000
458+
}
459+
],
460+
"audienceIds": [],
461+
"audienceConditions": [],
462+
"includedRules": []
463+
},
464+
{
465+
"id": "holdout_local_exp_rule1",
466+
"key": "local_holdout_exp_rule1",
467+
"status": "Running",
468+
"layerId": "layer_local_exp1",
469+
"variations": [
470+
{
471+
"id": "exp_lvar_1",
472+
"key": "local_exp_holdout_off",
473+
"featureEnabled": false,
474+
"variables": []
475+
}
476+
],
477+
"trafficAllocation": [
478+
{
479+
"entityId": "exp_lvar_1",
480+
"endOfRange": 10000
481+
}
482+
],
483+
"audienceIds": [],
484+
"audienceConditions": [],
485+
"includedRules": ["exp_rule_id_1"]
486+
}
487+
]
213488
}
214489
}

0 commit comments

Comments
 (0)