1
1
/****************************************************************************
2
- * Copyright 2020, Optimizely, Inc. and contributors *
2
+ * Copyright 2020-2021 , 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. *
@@ -174,15 +174,17 @@ func (s *OptimizelyUserContextTestSuite) TestDecideFeatureTest() {
174
174
s .Nil (err )
175
175
176
176
user := s .OptimizelyClient .CreateUserContext (s .userID , nil )
177
- decision := user .Decide (flagKey , nil )
177
+ decision := user .Decide (flagKey , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
178
178
179
179
s .Equal (variationKey , decision .VariationKey )
180
180
s .Equal (true , decision .Enabled )
181
181
s .Equal (variablesExpected .ToMap (), decision .Variables .ToMap ())
182
182
s .Equal (ruleKey , decision .RuleKey )
183
183
s .Equal (flagKey , decision .FlagKey )
184
184
s .Equal (user , decision .UserContext )
185
- s .Len (decision .Reasons , 0 )
185
+ reasons := decision .Reasons
186
+ s .Len (reasons , 1 )
187
+ s .Equal (`Audiences for experiment exp_no_audience collectively evaluated to true.` , reasons [0 ])
186
188
187
189
s .True (len (s .eventProcessor .Events ) == 1 )
188
190
s .Equal (s .userID , s .eventProcessor .Events [0 ].VisitorID )
@@ -205,15 +207,32 @@ func (s *OptimizelyUserContextTestSuite) TestDecideRollout() {
205
207
s .Nil (err )
206
208
207
209
user := s .OptimizelyClient .CreateUserContext (s .userID , nil )
208
- decision := user .Decide (flagKey , nil )
210
+ decision := user .Decide (flagKey , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
209
211
210
212
s .Equal (variationKey , decision .VariationKey )
211
213
s .Equal (true , decision .Enabled )
212
214
s .Equal (variablesExpected .ToMap (), decision .Variables .ToMap ())
213
215
s .Equal (ruleKey , decision .RuleKey )
214
216
s .Equal (flagKey , decision .FlagKey )
215
217
s .Equal (user , decision .UserContext )
216
- s .Len (decision .Reasons , 3 )
218
+ reasons := decision .Reasons
219
+ s .Len (reasons , 9 )
220
+
221
+ expectedLogs := []string {
222
+ `an error occurred while evaluating nested tree for audience ID "13389141123"` ,
223
+ `Audiences for experiment exp_with_audience collectively evaluated to false.` ,
224
+ `User "tester" does not meet conditions to be in experiment "exp_with_audience".` ,
225
+ `an error occurred while evaluating nested tree for audience ID "13389130056"` ,
226
+ `User "tester" does not meet conditions for targeting rule 1.` ,
227
+ `an error occurred while evaluating nested tree for audience ID "12208130097"` ,
228
+ `User "tester" does not meet conditions for targeting rule 2.` ,
229
+ `Audiences for experiment 18322080788 collectively evaluated to true.` ,
230
+ `User "tester" meets conditions for targeting rule "Everyone Else".` ,
231
+ }
232
+
233
+ for index , log := range expectedLogs {
234
+ s .Equal (log , reasons [index ])
235
+ }
217
236
218
237
s .True (len (s .eventProcessor .Events ) == 1 )
219
238
s .Equal (s .userID , s .eventProcessor .Events [0 ].VisitorID )
@@ -233,15 +252,17 @@ func (s *OptimizelyUserContextTestSuite) TestDecideNullVariation() {
233
252
variablesExpected := optimizelyjson .NewOptimizelyJSONfromMap (map [string ]interface {}{})
234
253
235
254
user := s .OptimizelyClient .CreateUserContext (s .userID , nil )
236
- decision := user .Decide (flagKey , nil )
255
+ decision := user .Decide (flagKey , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
237
256
238
257
s .Equal ("" , decision .VariationKey )
239
258
s .Equal (false , decision .Enabled )
240
259
s .Equal (variablesExpected .ToMap (), decision .Variables .ToMap ())
241
260
s .Equal ("" , decision .RuleKey )
242
261
s .Equal ("feature_3" , decision .FlagKey )
243
262
s .Equal (user , decision .UserContext )
244
- s .Len (decision .Reasons , 0 )
263
+ reasons := decision .Reasons
264
+ s .Len (reasons , 1 )
265
+ s .Equal (`Rollout with ID "" is not in the datafile.` , reasons [0 ])
245
266
246
267
s .True (len (s .eventProcessor .Events ) == 1 )
247
268
s .Equal (s .userID , s .eventProcessor .Events [0 ].VisitorID )
@@ -265,17 +286,21 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeysOneFlag() {
265
286
s .Nil (err )
266
287
267
288
user := s .OptimizelyClient .CreateUserContext (s .userID , nil )
268
- decisions := user .DecideForKeys (flagKeys , nil )
289
+ decisions := user .DecideForKeys (flagKeys , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
269
290
s .Len (decisions , 1 )
270
291
271
292
decision1 := decisions [flagKey ]
293
+
272
294
s .Equal (variationKey , decision1 .VariationKey )
273
295
s .Equal (true , decision1 .Enabled )
274
296
s .Equal (variablesExpected .ToMap (), decision1 .Variables .ToMap ())
275
297
s .Equal (ruleKey , decision1 .RuleKey )
276
298
s .Equal (flagKey , decision1 .FlagKey )
277
299
s .Equal (user , decision1 .UserContext )
278
- s .Len (decision1 .Reasons , 0 )
300
+
301
+ reasons := decision1 .Reasons
302
+ s .Len (reasons , 1 )
303
+ s .Equal (`Audiences for experiment exp_no_audience collectively evaluated to true.` , reasons [0 ])
279
304
280
305
s .True (len (s .eventProcessor .Events ) == 1 )
281
306
s .Equal (s .userID , s .eventProcessor .Events [0 ].VisitorID )
@@ -304,7 +329,7 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeysWithMultipleFlags() {
304
329
s .Nil (err )
305
330
306
331
user := s .OptimizelyClient .CreateUserContext (s .userID , map [string ]interface {}{"gender" : "f" })
307
- decisions := user .DecideForKeys (flagKeys , nil )
332
+ decisions := user .DecideForKeys (flagKeys , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
308
333
s .Len (decisions , 2 )
309
334
310
335
decision1 := decisions [flagKey1 ]
@@ -314,7 +339,9 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeysWithMultipleFlags() {
314
339
s .Equal (ruleKey1 , decision1 .RuleKey )
315
340
s .Equal (flagKey1 , decision1 .FlagKey )
316
341
s .Equal (user , decision1 .UserContext )
317
- s .Len (decision1 .Reasons , 0 )
342
+ reasons := decision1 .Reasons
343
+ s .Len (reasons , 1 )
344
+ s .Equal (`Audiences for experiment exp_with_audience collectively evaluated to true.` , reasons [0 ])
318
345
319
346
decision2 := decisions [flagKey2 ]
320
347
s .Equal (variationKey2 , decision2 .VariationKey )
@@ -323,7 +350,9 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeysWithMultipleFlags() {
323
350
s .Equal (ruleKey2 , decision2 .RuleKey )
324
351
s .Equal (flagKey2 , decision2 .FlagKey )
325
352
s .Equal (user , decision2 .UserContext )
326
- s .Len (decision2 .Reasons , 0 )
353
+ reasons = decision2 .Reasons
354
+ s .Len (reasons , 1 )
355
+ s .Equal (`Audiences for experiment exp_no_audience collectively evaluated to true.` , reasons [0 ])
327
356
328
357
s .True (len (s .eventProcessor .Events ) == 2 )
329
358
s .Equal (s .userID , s .eventProcessor .Events [0 ].VisitorID )
@@ -454,7 +483,7 @@ func (s *OptimizelyUserContextTestSuite) TestDecideAllEnabledFlagsOnly() {
454
483
s .Nil (err )
455
484
456
485
user := s .OptimizelyClient .CreateUserContext (s .userID , map [string ]interface {}{"gender" : "f" })
457
- decisions := user .DecideAll ([]decide.OptimizelyDecideOptions {decide .EnabledFlagsOnly })
486
+ decisions := user .DecideAll ([]decide.OptimizelyDecideOptions {decide .EnabledFlagsOnly , decide . IncludeReasons })
458
487
s .Len (decisions , 2 )
459
488
460
489
decision1 := decisions [flagKey1 ]
@@ -464,7 +493,9 @@ func (s *OptimizelyUserContextTestSuite) TestDecideAllEnabledFlagsOnly() {
464
493
s .Equal ("exp_with_audience" , decision1 .RuleKey )
465
494
s .Equal (flagKey1 , decision1 .FlagKey )
466
495
s .Equal (user , decision1 .UserContext )
467
- s .Len (decision1 .Reasons , 0 )
496
+ reasons := decision1 .Reasons
497
+ s .Len (reasons , 1 )
498
+ s .Equal (`Audiences for experiment exp_with_audience collectively evaluated to true.` , reasons [0 ])
468
499
}
469
500
470
501
func (s * OptimizelyUserContextTestSuite ) TestTrackEvent () {
@@ -580,6 +611,7 @@ func (s *OptimizelyUserContextTestSuite) TestDecideOptionsBypassUps() {
580
611
variationID2 := "10418510624"
581
612
variationKey1 := "variation_with_traffic"
582
613
variationKey2 := "variation_no_traffic"
614
+ options := []decide.OptimizelyDecideOptions {decide .IncludeReasons }
583
615
584
616
userProfileService := new (MockUserProfileService )
585
617
s .OptimizelyClient , _ = s .factory .Client (
@@ -596,13 +628,20 @@ func (s *OptimizelyUserContextTestSuite) TestDecideOptionsBypassUps() {
596
628
userProfileService .On ("Save" , mock .Anything )
597
629
598
630
userContext := s .OptimizelyClient .CreateUserContext (s .userID , map [string ]interface {}{})
599
- decision := userContext .Decide (flagKey , nil )
631
+ decision := userContext .Decide (flagKey , options )
632
+ reasons := decision .Reasons
633
+ s .Len (reasons , 1 )
634
+ s .Equal (`User "tester" was previously bucketed into variation "variation_no_traffic" of experiment "exp_no_audience".` , reasons [0 ])
600
635
// should return variationId2 set by UPS
601
636
s .Equal (variationKey2 , decision .VariationKey )
602
637
userProfileService .AssertCalled (s .T (), "Lookup" , s .userID )
603
638
userProfileService .AssertNotCalled (s .T (), "Save" , mock .Anything )
604
639
605
- decision = userContext .Decide (flagKey , []decide.OptimizelyDecideOptions {decide .IgnoreUserProfileService })
640
+ options = append (options , decide .IgnoreUserProfileService )
641
+ decision = userContext .Decide (flagKey , options )
642
+ reasons = decision .Reasons
643
+ s .Len (reasons , 1 )
644
+ s .Equal (`Audiences for experiment exp_no_audience collectively evaluated to true.` , reasons [0 ])
606
645
// should not lookup, ignore variationId2 set by UPS and return variationId1
607
646
s .Equal (variationKey1 , decision .VariationKey )
608
647
userProfileService .AssertNumberOfCalls (s .T (), "Lookup" , 1 )
@@ -641,8 +680,25 @@ func (s *OptimizelyUserContextTestSuite) TestDecideOptionsIncludeReasons() {
641
680
642
681
// valid flag key
643
682
flagKey = "feature_1"
644
- decision = user .Decide (flagKey , nil )
645
- s .Len (decision .Reasons , 3 )
683
+ decision = user .Decide (flagKey , options )
684
+ reasons := decision .Reasons
685
+ s .Len (reasons , 9 )
686
+
687
+ expectedLogs := []string {
688
+ `an error occurred while evaluating nested tree for audience ID "13389141123"` ,
689
+ `Audiences for experiment exp_with_audience collectively evaluated to false.` ,
690
+ `User "tester" does not meet conditions to be in experiment "exp_with_audience".` ,
691
+ `an error occurred while evaluating nested tree for audience ID "13389130056"` ,
692
+ `User "tester" does not meet conditions for targeting rule 1.` ,
693
+ `an error occurred while evaluating nested tree for audience ID "12208130097"` ,
694
+ `User "tester" does not meet conditions for targeting rule 2.` ,
695
+ `Audiences for experiment 18322080788 collectively evaluated to true.` ,
696
+ `User "tester" meets conditions for targeting rule "Everyone Else".` ,
697
+ }
698
+
699
+ for index , log := range expectedLogs {
700
+ s .Equal (log , reasons [index ])
701
+ }
646
702
}
647
703
648
704
func (s * OptimizelyUserContextTestSuite ) TestDefaultDecideOptionsExcludeVariables () {
@@ -654,14 +710,38 @@ func (s *OptimizelyUserContextTestSuite) TestDefaultDecideOptionsExcludeVariable
654
710
// should be excluded by DefaultDecideOption
655
711
decision := userContext .Decide (flagKey , nil )
656
712
s .Len (decision .Variables .ToMap (), 0 )
713
+ reasons := decision .Reasons
714
+ s .Len (reasons , 0 )
715
+
716
+ options = append (options , decide .IncludeReasons )
717
+ client , _ = s .factory .Client (WithEventProcessor (s .eventProcessor ), WithDefaultDecideOptions (options ))
718
+ userContext = client .CreateUserContext (s .userID , nil )
719
+
720
+ decision = userContext .Decide (flagKey , nil )
721
+ reasons = decision .Reasons
722
+ s .Len (reasons , 9 )
723
+
724
+ expectedLogs := []string {
725
+ `an error occurred while evaluating nested tree for audience ID "13389141123"` ,
726
+ `Audiences for experiment exp_with_audience collectively evaluated to false.` ,
727
+ `User "tester" does not meet conditions to be in experiment "exp_with_audience".` ,
728
+ `an error occurred while evaluating nested tree for audience ID "13389130056"` ,
729
+ `User "tester" does not meet conditions for targeting rule 1.` ,
730
+ `an error occurred while evaluating nested tree for audience ID "12208130097"` ,
731
+ `User "tester" does not meet conditions for targeting rule 2.` ,
732
+ `Audiences for experiment 18322080788 collectively evaluated to true.` ,
733
+ `User "tester" meets conditions for targeting rule "Everyone Else".` ,
734
+ }
657
735
658
- // @TODO: Need one more case: IncludeReasons = true and flagKey = "feature_1". Then reasons.count > 0
736
+ for index , log := range expectedLogs {
737
+ s .Equal (log , reasons [index ])
738
+ }
659
739
}
660
740
661
741
func (s * OptimizelyUserContextTestSuite ) TestDefaultDecideOptionsEnabledFlagsOnly () {
662
742
flagKey := "feature_1"
663
743
variablesExpected , _ := s .OptimizelyClient .GetAllFeatureVariables (flagKey , entities.UserContext {ID : s .userID })
664
- options := []decide.OptimizelyDecideOptions {decide .EnabledFlagsOnly }
744
+ options := []decide.OptimizelyDecideOptions {decide .EnabledFlagsOnly , decide . IncludeReasons }
665
745
client , _ := s .factory .Client (WithEventProcessor (s .eventProcessor ), WithDefaultDecideOptions (options ))
666
746
user := client .CreateUserContext (s .userID , map [string ]interface {}{"gender" : "f" })
667
747
@@ -676,7 +756,9 @@ func (s *OptimizelyUserContextTestSuite) TestDefaultDecideOptionsEnabledFlagsOnl
676
756
s .Equal ("exp_with_audience" , decision1 .RuleKey )
677
757
s .Equal (flagKey , decision1 .FlagKey )
678
758
s .Equal (user , decision1 .UserContext )
679
- s .Len (decision1 .Reasons , 0 )
759
+ reasons := decision1 .Reasons
760
+ s .Len (reasons , 1 )
761
+ s .Equal ("Audiences for experiment exp_with_audience collectively evaluated to true." , reasons [0 ])
680
762
}
681
763
682
764
func (s * OptimizelyUserContextTestSuite ) TestDefaultDecideOptionsIncludeReasons () {
@@ -714,7 +796,8 @@ func (s *OptimizelyUserContextTestSuite) TestDefaultDecideOptionsBypassUps() {
714
796
options := []decide.OptimizelyDecideOptions {decide .IgnoreUserProfileService }
715
797
client , _ := s .factory .Client (WithEventProcessor (s .eventProcessor ), WithDefaultDecideOptions (options ))
716
798
user := client .CreateUserContext (s .userID , nil )
717
- decision := user .Decide (flagKey , nil )
799
+ decision := user .Decide (flagKey , []decide.OptimizelyDecideOptions {decide .IncludeReasons })
800
+ s .Len (decision .Reasons , 1 )
718
801
719
802
// should get IgnoreUserProfileService by DefaultDecideOption
720
803
// should not lookup, ignore variationId2 set by UPS and return variationId1
@@ -763,7 +846,7 @@ func (s *OptimizelyUserContextTestSuite) TestDecideSDKNotReady() {
763
846
func (s * OptimizelyUserContextTestSuite ) TestDecideInvalidFeatureKey () {
764
847
flagKey := "invalid_key"
765
848
userContext := s .OptimizelyClient .CreateUserContext (s .userID , nil )
766
- decision := userContext .Decide (flagKey , nil )
849
+ decision := userContext .Decide (flagKey , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
767
850
768
851
s .Equal ("" , decision .VariationKey )
769
852
s .False (decision .Enabled )
@@ -779,7 +862,7 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeySDKNotReady() {
779
862
factory := OptimizelyFactory {SDKKey : "121" }
780
863
client , _ := factory .Client ()
781
864
userContext := client .CreateUserContext (s .userID , nil )
782
- decisions := userContext .DecideForKeys (flagKeys , nil )
865
+ decisions := userContext .DecideForKeys (flagKeys , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
783
866
784
867
s .Len (decisions , 0 )
785
868
}
@@ -801,7 +884,7 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeysErrorDecisionIncluded(
801
884
s .Nil (err )
802
885
803
886
user := s .OptimizelyClient .CreateUserContext (s .userID , nil )
804
- decisions := user .DecideForKeys (flagKeys , nil )
887
+ decisions := user .DecideForKeys (flagKeys , []decide. OptimizelyDecideOptions { decide . IncludeReasons } )
805
888
s .Len (decisions , 2 )
806
889
807
890
decision := decisions [flagKey1 ]
@@ -811,13 +894,16 @@ func (s *OptimizelyUserContextTestSuite) TestDecideForKeysErrorDecisionIncluded(
811
894
s .Equal ("exp_no_audience" , decision .RuleKey )
812
895
s .Equal (flagKey1 , decision .FlagKey )
813
896
s .Equal (user , decision .UserContext )
814
- s .Len (decision .Reasons , 0 )
897
+ reasons := decision .Reasons
898
+ s .Len (reasons , 1 )
899
+ s .Equal (`Audiences for experiment exp_no_audience collectively evaluated to true.` , reasons [0 ])
815
900
816
901
decision = decisions [flagKey2 ]
817
902
s .Equal (flagKey2 , decision .FlagKey )
818
903
s .Equal (user , decision .UserContext )
819
- s .Len (decision .Reasons , 1 )
820
- s .Equal (decide .GetDecideMessage (decide .FlagKeyInvalid , flagKey2 ), decision .Reasons [0 ])
904
+ reasons = decision .Reasons
905
+ s .Len (reasons , 1 )
906
+ s .Equal (decide .GetDecideMessage (decide .FlagKeyInvalid , flagKey2 ), reasons [0 ])
821
907
}
822
908
823
909
func TestOptimizelyUserContextTestSuite (t * testing.T ) {
0 commit comments