Skip to content

Commit 53d754a

Browse files
update: add CmabService to DecisionService and its tests
1 parent fbed362 commit 53d754a

File tree

3 files changed

+36
-20
lines changed

3 files changed

+36
-20
lines changed

core-api/src/main/java/com/optimizely/ab/Optimizely.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1885,7 +1885,7 @@ public Optimizely build() {
18851885
}
18861886

18871887
if (decisionService == null) {
1888-
decisionService = new DecisionService(bucketer, errorHandler, userProfileService);
1888+
decisionService = new DecisionService(bucketer, errorHandler, userProfileService, cmabService);
18891889
}
18901890

18911891
if (projectConfig == null && datafile != null && !datafile.isEmpty()) {

core-api/src/main/java/com/optimizely/ab/bucketing/DecisionService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import javax.annotation.Nonnull;
2727
import javax.annotation.Nullable;
2828

29+
import com.optimizely.ab.cmab.service.CmabService;
2930
import org.slf4j.Logger;
3031
import org.slf4j.LoggerFactory;
3132

@@ -64,6 +65,7 @@ public class DecisionService {
6465
private final Bucketer bucketer;
6566
private final ErrorHandler errorHandler;
6667
private final UserProfileService userProfileService;
68+
private final CmabService cmabService;
6769
private static final Logger logger = LoggerFactory.getLogger(DecisionService.class);
6870

6971
/**
@@ -84,10 +86,12 @@ public class DecisionService {
8486
*/
8587
public DecisionService(@Nonnull Bucketer bucketer,
8688
@Nonnull ErrorHandler errorHandler,
87-
@Nullable UserProfileService userProfileService) {
89+
@Nullable UserProfileService userProfileService,
90+
@Nullable CmabService cmabService) {
8891
this.bucketer = bucketer;
8992
this.errorHandler = errorHandler;
9093
this.userProfileService = userProfileService;
94+
this.cmabService = cmabService;
9195
}
9296

9397
/**

core-api/src/test/java/com/optimizely/ab/bucketing/DecisionServiceTest.java

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import com.optimizely.ab.OptimizelyDecisionContext;
5656
import com.optimizely.ab.OptimizelyForcedDecision;
5757
import com.optimizely.ab.OptimizelyUserContext;
58+
import com.optimizely.ab.cmab.service.CmabService;
5859
import com.optimizely.ab.config.DatafileProjectConfigTestUtils;
5960
import static com.optimizely.ab.config.DatafileProjectConfigTestUtils.noAudienceProjectConfigV3;
6061
import static com.optimizely.ab.config.DatafileProjectConfigTestUtils.validProjectConfigV3;
@@ -109,6 +110,9 @@ public class DecisionServiceTest {
109110
@Mock
110111
private ErrorHandler mockErrorHandler;
111112

113+
@Mock
114+
private CmabService mockCmabService;
115+
112116
private ProjectConfig noAudienceProjectConfig;
113117
private ProjectConfig v4ProjectConfig;
114118
private ProjectConfig validProjectConfig;
@@ -129,7 +133,7 @@ public void setUp() throws Exception {
129133
whitelistedExperiment = validProjectConfig.getExperimentIdMapping().get("223");
130134
whitelistedVariation = whitelistedExperiment.getVariationKeyToVariationMap().get("vtag1");
131135
Bucketer bucketer = new Bucketer();
132-
decisionService = spy(new DecisionService(bucketer, mockErrorHandler, null));
136+
decisionService = spy(new DecisionService(bucketer, mockErrorHandler, null, mockCmabService));
133137
this.optimizely = Optimizely.builder().build();
134138
}
135139

@@ -224,7 +228,8 @@ public void getVariationForcedBeforeUserProfile() throws Exception {
224228
UserProfileService userProfileService = mock(UserProfileService.class);
225229
when(userProfileService.lookup(userProfileId)).thenReturn(userProfile.toMap());
226230

227-
DecisionService decisionService = spy(new DecisionService(new Bucketer(), mockErrorHandler, userProfileService));
231+
CmabService cmabService = mock(CmabService.class);
232+
DecisionService decisionService = spy(new DecisionService(new Bucketer(), mockErrorHandler, userProfileService, cmabService));
228233

229234
// ensure that normal users still get excluded from the experiment when they fail audience evaluation
230235
assertNull(decisionService.getVariation(experiment, optimizely.createUserContext(genericUserId, Collections.<String, Object>emptyMap()), validProjectConfig).getResult());
@@ -255,7 +260,8 @@ public void getVariationEvaluatesUserProfileBeforeAudienceTargeting() throws Exc
255260
UserProfileService userProfileService = mock(UserProfileService.class);
256261
when(userProfileService.lookup(userProfileId)).thenReturn(userProfile.toMap());
257262

258-
DecisionService decisionService = spy(new DecisionService(new Bucketer(), mockErrorHandler, userProfileService));
263+
CmabService cmabService = mock(CmabService.class);
264+
DecisionService decisionService = spy(new DecisionService(new Bucketer(), mockErrorHandler, userProfileService, cmabService));
259265

260266
// ensure that normal users still get excluded from the experiment when they fail audience evaluation
261267
assertNull(decisionService.getVariation(experiment, optimizely.createUserContext(genericUserId, Collections.<String, Object>emptyMap()), validProjectConfig).getResult());
@@ -550,7 +556,7 @@ public void getVariationsForFeatureListBatchesUpsLoadAndSave() throws Exception
550556
ErrorHandler mockErrorHandler = mock(ErrorHandler.class);
551557
UserProfileService mockUserProfileService = mock(UserProfileService.class);
552558

553-
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, mockUserProfileService);
559+
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, mockUserProfileService, null);
554560

555561
FeatureFlag featureFlag1 = FEATURE_FLAG_MULTI_VARIATE_FEATURE;
556562
FeatureFlag featureFlag2 = FEATURE_FLAG_MULTI_VARIATE_FUTURE_FEATURE;
@@ -609,6 +615,7 @@ public void getVariationForFeatureInRolloutReturnsNullWhenUserIsExcludedFromAllT
609615
DecisionService decisionService = new DecisionService(
610616
mockBucketer,
611617
mockErrorHandler,
618+
null,
612619
null
613620
);
614621

@@ -636,7 +643,7 @@ public void getVariationForFeatureInRolloutReturnsNullWhenUserFailsAllAudiencesA
636643
Bucketer mockBucketer = mock(Bucketer.class);
637644
when(mockBucketer.bucket(any(Experiment.class), anyString(), any(ProjectConfig.class))).thenReturn(DecisionResponse.nullNoReasons());
638645

639-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null);
646+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null, null);
640647

641648
FeatureDecision featureDecision = decisionService.getVariationForFeatureInRollout(
642649
FEATURE_FLAG_MULTI_VARIATE_FEATURE,
@@ -666,6 +673,7 @@ public void getVariationForFeatureInRolloutReturnsVariationWhenUserFailsAllAudie
666673
DecisionService decisionService = new DecisionService(
667674
mockBucketer,
668675
mockErrorHandler,
676+
null,
669677
null
670678
);
671679

@@ -707,6 +715,7 @@ public void getVariationForFeatureInRolloutReturnsVariationWhenUserFailsTrafficI
707715
DecisionService decisionService = new DecisionService(
708716
mockBucketer,
709717
mockErrorHandler,
718+
null,
710719
null
711720
);
712721

@@ -747,6 +756,7 @@ public void getVariationForFeatureInRolloutReturnsVariationWhenUserFailsTrafficI
747756
DecisionService decisionService = new DecisionService(
748757
mockBucketer,
749758
mockErrorHandler,
759+
null,
750760
null
751761
);
752762

@@ -786,7 +796,7 @@ public void getVariationForFeatureInRolloutReturnsVariationWhenUserFailsTargetin
786796
when(mockBucketer.bucket(eq(everyoneElseRule), anyString(), any(ProjectConfig.class))).thenReturn(DecisionResponse.responseNoReasons(everyoneElseVariation));
787797
when(mockBucketer.bucket(eq(englishCitizensRule), anyString(), any(ProjectConfig.class))).thenReturn(DecisionResponse.responseNoReasons(englishCitizenVariation));
788798

789-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null);
799+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null, null);
790800

791801
FeatureDecision featureDecision = decisionService.getVariationForFeatureInRollout(
792802
FEATURE_FLAG_MULTI_VARIATE_FEATURE,
@@ -939,7 +949,7 @@ public void bucketReturnsVariationStoredInUserProfile() throws Exception {
939949
when(userProfileService.lookup(userProfileId)).thenReturn(userProfile.toMap());
940950

941951
Bucketer bucketer = new Bucketer();
942-
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService);
952+
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService, null);
943953

944954
logbackVerifier.expectMessage(Level.INFO,
945955
"Returning previously activated variation \"" + variation.getKey() + "\" of experiment \"" + experiment.getKey() + "\""
@@ -965,7 +975,7 @@ public void getStoredVariationLogsWhenLookupReturnsNull() throws Exception {
965975
UserProfile userProfile = new UserProfile(userProfileId, Collections.<String, Decision>emptyMap());
966976
when(userProfileService.lookup(userProfileId)).thenReturn(userProfile.toMap());
967977

968-
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService);
978+
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService, null);
969979

970980
logbackVerifier.expectMessage(Level.INFO, "No previously activated variation of experiment " +
971981
"\"" + experiment.getKey() + "\" for user \"" + userProfileId + "\" found in user profile.");
@@ -992,7 +1002,7 @@ public void getStoredVariationReturnsNullWhenVariationIsNoLongerInConfig() throw
9921002
UserProfileService userProfileService = mock(UserProfileService.class);
9931003
when(userProfileService.lookup(userProfileId)).thenReturn(storedUserProfile.toMap());
9941004

995-
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService);
1005+
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService, null);
9961006

9971007
logbackVerifier.expectMessage(Level.INFO,
9981008
"User \"" + userProfileId + "\" was previously bucketed into variation with ID \"" + storedVariationId + "\" for " +
@@ -1023,7 +1033,7 @@ public void getVariationSavesBucketedVariationIntoUserProfile() throws Exception
10231033
Bucketer mockBucketer = mock(Bucketer.class);
10241034
when(mockBucketer.bucket(eq(experiment), eq(userProfileId), eq(noAudienceProjectConfig))).thenReturn(DecisionResponse.responseNoReasons(variation));
10251035

1026-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, userProfileService);
1036+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, userProfileService, null);
10271037

10281038
assertEquals(variation, decisionService.getVariation(
10291039
experiment, optimizely.createUserContext(userProfileId, Collections.emptyMap()), noAudienceProjectConfig).getResult()
@@ -1058,7 +1068,8 @@ public void bucketLogsCorrectlyWhenUserProfileFailsToSave() throws Exception {
10581068
UserProfile saveUserProfile = new UserProfile(userProfileId,
10591069
new HashMap<String, Decision>());
10601070

1061-
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService);
1071+
CmabService cmabService = mock(CmabService.class);
1072+
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService, cmabService);
10621073

10631074

10641075
decisionService.saveVariation(experiment, variation, saveUserProfile);
@@ -1084,7 +1095,7 @@ public void getVariationSavesANewUserProfile() throws Exception {
10841095

10851096
Bucketer bucketer = mock(Bucketer.class);
10861097
UserProfileService userProfileService = mock(UserProfileService.class);
1087-
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService);
1098+
DecisionService decisionService = new DecisionService(bucketer, mockErrorHandler, userProfileService, null);
10881099

10891100
when(bucketer.bucket(eq(experiment), eq(userProfileId), eq(noAudienceProjectConfig))).thenReturn(DecisionResponse.responseNoReasons(variation));
10901101
when(userProfileService.lookup(userProfileId)).thenReturn(null);
@@ -1096,7 +1107,7 @@ public void getVariationSavesANewUserProfile() throws Exception {
10961107
@Test
10971108
public void getVariationBucketingId() throws Exception {
10981109
Bucketer bucketer = mock(Bucketer.class);
1099-
DecisionService decisionService = spy(new DecisionService(bucketer, mockErrorHandler, null));
1110+
DecisionService decisionService = spy(new DecisionService(bucketer, mockErrorHandler, null, null));
11001111
Experiment experiment = validProjectConfig.getExperiments().get(0);
11011112
Variation expectedVariation = experiment.getVariations().get(0);
11021113

@@ -1130,6 +1141,7 @@ public void getVariationForRolloutWithBucketingId() {
11301141
DecisionService decisionService = spy(new DecisionService(
11311142
bucketer,
11321143
mockErrorHandler,
1144+
null,
11331145
null
11341146
));
11351147

@@ -1285,7 +1297,7 @@ public void getVariationForFeatureReturnHoldoutDecisionForGlobalHoldout() {
12851297

12861298
Bucketer mockBucketer = new Bucketer();
12871299

1288-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null);
1300+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null, null);
12891301

12901302
Map<String, Object> attributes = new HashMap<>();
12911303
attributes.put("$opt_bucketing_id", "ppid160000");
@@ -1307,8 +1319,8 @@ public void includedFlagsHoldoutOnlyAppliestoSpecificFlags() {
13071319
ProjectConfig holdoutProjectConfig = generateValidProjectConfigV4_holdout();
13081320

13091321
Bucketer mockBucketer = new Bucketer();
1310-
1311-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null);
1322+
CmabService cmabService = mock(CmabService.class);
1323+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null, cmabService);
13121324

13131325
Map<String, Object> attributes = new HashMap<>();
13141326
attributes.put("$opt_bucketing_id", "ppid120000");
@@ -1331,7 +1343,7 @@ public void excludedFlagsHoldoutAppliesToAllExceptSpecified() {
13311343

13321344
Bucketer mockBucketer = new Bucketer();
13331345

1334-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null);
1346+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null, null);
13351347

13361348
Map<String, Object> attributes = new HashMap<>();
13371349
attributes.put("$opt_bucketing_id", "ppid300002");
@@ -1362,7 +1374,7 @@ public void userMeetsHoldoutAudienceConditions() {
13621374

13631375
Bucketer mockBucketer = new Bucketer();
13641376

1365-
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null);
1377+
DecisionService decisionService = new DecisionService(mockBucketer, mockErrorHandler, null, null);
13661378

13671379
Map<String, Object> attributes = new HashMap<>();
13681380
attributes.put("$opt_bucketing_id", "ppid543400");

0 commit comments

Comments
 (0)