1
1
/****************************************************************************
2
- * Copyright 2019, Optimizely, Inc. and contributors *
2
+ * Copyright 2019-2020 , Optimizely, Inc. and contributors *
3
3
* *
4
4
* Licensed under the Apache License, Version 2.0 (the "License"); *
5
5
* you may not use this file except in compliance with the License. *
@@ -27,7 +27,9 @@ class DecisionServiceTests_Features: XCTestCase {
27
27
var kExperimentId = " country11 "
28
28
var kRolloutId = " rollout11 "
29
29
var kRolloutExperimentId = " rolloutExp11 "
30
-
30
+ var kRolloutExperimentId2 = " rolloutExp12 "
31
+ var kRolloutExperimentId3 = " rolloutExp13 "
32
+
31
33
var kVariationKeyA = " a "
32
34
var kVariationKeyB = " b "
33
35
var kVariationKeyC = " c "
@@ -37,11 +39,21 @@ class DecisionServiceTests_Features: XCTestCase {
37
39
var kAudienceIdAge = " 20 "
38
40
var kAudienceIdInvalid = " 9999999 "
39
41
42
+ var kRolloutVariationKeyA = " rolloutA "
43
+ var kRolloutVariationKeyB = " rolloutB "
44
+ var kRolloutVariationKeyC = " rolloutC "
45
+
46
+ var kRolloutAudienceIdAge1 = " 30 "
47
+ var kRolloutAudienceIdAge2 = " 40 "
48
+
40
49
var kAttributesCountryMatch : [ String : Any ] = [ " country " : " us " ]
41
50
var kAttributesCountryNotMatch : [ String : Any ] = [ " country " : " ca " ]
42
51
var kAttributesAgeMatch : [ String : Any ] = [ " age " : 30 ]
43
52
var kAttributesAgeNotMatch : [ String : Any ] = [ " age " : 10 ]
44
53
var kAttributesEmpty : [ String : Any ] = [ : ]
54
+ var kAttributesRolloutAge1Match : [ String : Any ] = [ " age " : 20 ]
55
+ var kAttributesRolloutAge2Match : [ String : Any ] = [ " age " : 30 ]
56
+ var kAttributesRolloutNotMatch : [ String : Any ] = [ " age " : 40 ]
45
57
46
58
var experiment : Experiment !
47
59
var variation : Variation !
@@ -127,32 +139,93 @@ class DecisionServiceTests_Features: XCTestCase {
127
139
var sampleRolloutData : [ String : Any ] { return
128
140
[
129
141
" id " : kRolloutId,
130
- " experiments " : [ sampleRolloutExperimentData]
142
+ " experiments " : sampleRolloutExperimentData
131
143
]
132
144
}
133
145
134
- var sampleRolloutExperimentData : [ String : Any ] { return
146
+ var sampleRolloutExperimentData : [ [ String : Any ] ] { return
135
147
[
136
- " status " : " Running " ,
137
- " id " : kRolloutExperimentId,
138
- " key " : " rolloutExp " ,
139
- " layerId " : " 10420273888 " ,
140
- " trafficAllocation " : [
141
- [
142
- " entityId " : " 10389700000 " ,
143
- " endOfRange " : 10000
144
- ]
148
+ [
149
+ " status " : " Running " ,
150
+ " id " : kRolloutExperimentId,
151
+ " key " : " rolloutExp " ,
152
+ " layerId " : " 10420273888 " ,
153
+ " trafficAllocation " : [
154
+ [
155
+ " entityId " : " 10389700000 " ,
156
+ " endOfRange " : 10000
157
+ ]
158
+ ] ,
159
+ " audienceIds " : [ kRolloutAudienceIdAge1] ,
160
+ " variations " : [
161
+ [
162
+ " variables " : [ ] ,
163
+ " id " : " 10389700000 " ,
164
+ " key " : kRolloutVariationKeyA,
165
+ " featureEnabled " : true
166
+ ]
167
+ ] ,
168
+ " forcedVariations " : [ : ]
145
169
] ,
146
- " audienceIds " : [ ] ,
147
- " variations " : [
148
- [
149
- " variables " : [ ] ,
150
- " id " : " 10389700000 " ,
151
- " key " : kVariationKeyA,
152
- " featureEnabled " : true
153
- ]
170
+ [
171
+ " status " : " Running " ,
172
+ " id " : kRolloutExperimentId2,
173
+ " key " : " rolloutExp1 " ,
174
+ " layerId " : " 10420273889 " ,
175
+ " trafficAllocation " : [
176
+ [
177
+ " entityId " : " 10389700000 " ,
178
+ " endOfRange " : 10000
179
+ ]
180
+ ] ,
181
+ " audienceIds " : [ kRolloutAudienceIdAge2] ,
182
+ " variations " : [
183
+ [
184
+ " variables " : [ ] ,
185
+ " id " : " 10389700000 " ,
186
+ " key " : kRolloutVariationKeyB,
187
+ " featureEnabled " : true
188
+ ]
189
+ ] ,
190
+ " forcedVariations " : [ : ]
154
191
] ,
155
- " forcedVariations " : [ : ]
192
+ [
193
+ " status " : " Running " ,
194
+ " id " : kRolloutExperimentId3,
195
+ " key " : " rolloutExp2 " ,
196
+ " layerId " : " 10420273890 " ,
197
+ " trafficAllocation " : [
198
+ [
199
+ " entityId " : " 10389700000 " ,
200
+ " endOfRange " : 10000
201
+ ]
202
+ ] ,
203
+ " audienceIds " : [ ] ,
204
+ " variations " : [
205
+ [
206
+ " variables " : [ ] ,
207
+ " id " : " 10389700000 " ,
208
+ " key " : kRolloutVariationKeyC,
209
+ " featureEnabled " : true
210
+ ]
211
+ ] ,
212
+ " forcedVariations " : [ : ]
213
+ ]
214
+ ]
215
+ }
216
+
217
+ var sampleRolloutTypedAudiencesData : [ [ String : Any ] ] { return
218
+ [
219
+ [
220
+ " id " : kRolloutAudienceIdAge1,
221
+ " conditions " : [ " type " : " custom_attribute " , " name " : " age " , " match " : " lt " , " value " : 30 ] ,
222
+ " name " : " age "
223
+ ] ,
224
+ [
225
+ " id " : kRolloutAudienceIdAge2,
226
+ " conditions " : [ " type " : " custom_attribute " , " name " : " age " , " match " : " lt " , " value " : 40 ] ,
227
+ " name " : " age "
228
+ ]
156
229
]
157
230
}
158
231
@@ -222,14 +295,15 @@ extension DecisionServiceTests_Features {
222
295
func testGetVariationForFeatureRollout( ) {
223
296
// rollout set
224
297
self . config. project. rollouts = [ try ! OTUtils . model ( from: sampleRolloutData) ]
298
+ self . config. project. typedAudiences = try ! OTUtils . model ( from: sampleRolloutTypedAudiencesData)
225
299
featureFlag. rolloutId = kRolloutId
226
300
self . config. project. featureFlags = [ featureFlag]
227
301
228
302
let variation = self . decisionService. getVariationForFeatureRollout ( config: config,
229
303
featureFlag: featureFlag,
230
304
userId: kUserId,
231
- attributes: kAttributesEmpty )
232
- XCTAssert ( variation!. key == kVariationKeyA )
305
+ attributes: kAttributesRolloutAge1Match )
306
+ XCTAssert ( variation!. key == kRolloutVariationKeyA )
233
307
}
234
308
235
309
func testGetVariationForFeatureRolloutEmpty( ) {
@@ -253,10 +327,63 @@ extension DecisionServiceTests_Features {
253
327
XCTAssertNil ( variation)
254
328
}
255
329
256
- func testGetVariationForFeatureRolloutMultiple( ) {
257
- // add tests for last rollout handling
330
+ func testGetVariationForFeatureRolloutFallbackRule( ) {
331
+ self . config. project. rollouts = [ try ! OTUtils . model ( from: sampleRolloutData) ]
332
+ self . config. project. typedAudiences = try ! OTUtils . model ( from: sampleRolloutTypedAudiencesData)
333
+ self . config. project. rollouts [ 0 ] . experiments [ 0 ] . trafficAllocation [ 0 ] . endOfRange = 0
334
+ featureFlag. rolloutId = kRolloutId
335
+ self . config. project. featureFlags = [ featureFlag]
336
+
337
+ let variation = self . decisionService. getVariationForFeatureRollout ( config: config,
338
+ featureFlag: featureFlag,
339
+ userId: kUserId,
340
+ attributes: kAttributesRolloutAge1Match)
341
+ XCTAssert ( variation!. key == kRolloutVariationKeyC)
342
+ }
343
+
344
+ func testGetVariationForFeatureRolloutEvaluatesNextIfAudienceEvaluationFails( ) {
345
+ self . config. project. rollouts = [ try ! OTUtils . model ( from: sampleRolloutData) ]
346
+ self . config. project. typedAudiences = try ! OTUtils . model ( from: sampleRolloutTypedAudiencesData)
347
+ featureFlag. rolloutId = kRolloutId
348
+ self . config. project. featureFlags = [ featureFlag]
349
+
350
+ let variation = self . decisionService. getVariationForFeatureRollout ( config: config,
351
+ featureFlag: featureFlag,
352
+ userId: kUserId,
353
+ attributes: kAttributesRolloutAge2Match)
354
+ XCTAssert ( variation!. key == kRolloutVariationKeyB)
258
355
}
259
356
357
+ func testGetVariationForFeatureRolloutReturnsNilIfAudienceEvaluationFailsForFallback( ) {
358
+ self . config. project. rollouts = [ try ! OTUtils . model ( from: sampleRolloutData) ]
359
+ self . config. project. typedAudiences = try ! OTUtils . model ( from: sampleRolloutTypedAudiencesData)
360
+ featureFlag. rolloutId = kRolloutId
361
+ self . config. project. featureFlags = [ featureFlag]
362
+
363
+ self . config. project. rollouts [ 0 ] . experiments [ 0 ] . audienceIds = [ kRolloutAudienceIdAge2]
364
+ self . config. project. rollouts [ 0 ] . experiments [ 0 ] . trafficAllocation [ 0 ] . endOfRange = 0
365
+ self . config. project. rollouts [ 0 ] . experiments [ 2 ] . audienceIds = [ kRolloutAudienceIdAge1]
366
+ let variation = self . decisionService. getVariationForFeatureRollout ( config: config,
367
+ featureFlag: featureFlag,
368
+ userId: kUserId,
369
+ attributes: kAttributesRolloutAge2Match)
370
+ XCTAssertNil ( variation)
371
+ }
372
+
373
+ func testGetVariationForFeatureRolloutReturnsNilIfBucketingFailsForFallback( ) {
374
+ self . config. project. rollouts = [ try ! OTUtils . model ( from: sampleRolloutData) ]
375
+ self . config. project. typedAudiences = try ! OTUtils . model ( from: sampleRolloutTypedAudiencesData)
376
+ featureFlag. rolloutId = kRolloutId
377
+ self . config. project. featureFlags = [ featureFlag]
378
+
379
+ self . config. project. rollouts [ 0 ] . experiments [ 0 ] . trafficAllocation [ 0 ] . endOfRange = 0
380
+ self . config. project. rollouts [ 0 ] . experiments [ 2 ] . trafficAllocation [ 0 ] . endOfRange = 0
381
+ let variation = self . decisionService. getVariationForFeatureRollout ( config: config,
382
+ featureFlag: featureFlag,
383
+ userId: kUserId,
384
+ attributes: kAttributesRolloutAge1Match)
385
+ XCTAssertNil ( variation)
386
+ }
260
387
}
261
388
262
389
// MARK: - Test getVariationForFeatureERollout()
@@ -293,7 +420,7 @@ extension DecisionServiceTests_Features {
293
420
attributes: kAttributesCountryNotMatch)
294
421
XCTAssertNotNil ( pair)
295
422
XCTAssertNil ( pair!. experiment)
296
- XCTAssert ( pair!. variation!. key == kVariationKeyA )
423
+ XCTAssert ( pair!. variation!. key == kRolloutVariationKeyC )
297
424
}
298
425
299
426
}
0 commit comments