diff --git a/core-api/src/main/java/com/optimizely/ab/Optimizely.java b/core-api/src/main/java/com/optimizely/ab/Optimizely.java index 11d89c03f..f69b018c8 100644 --- a/core-api/src/main/java/com/optimizely/ab/Optimizely.java +++ b/core-api/src/main/java/com/optimizely/ab/Optimizely.java @@ -318,7 +318,7 @@ private void sendImpression(@Nonnull ProjectConfig projectConfig, * @param variation the variation that was returned from activate. * @param flagKey It can either be empty if ruleType is experiment or it's feature key in case ruleType is feature-test or rollout * @param ruleType It can either be experiment in case impression event is sent from activate or it's feature-test or rollout - * @param cmabUUID The cmabUUID if the experiment is a cmab experiment. + * @param cmabUuid The cmabUuid if the experiment is a cmab experiment. */ private boolean sendImpression(@Nonnull ProjectConfig projectConfig, @Nullable ExperimentCore experiment, @@ -328,7 +328,7 @@ private boolean sendImpression(@Nonnull ProjectConfig projectConfig, @Nonnull String flagKey, @Nonnull String ruleType, @Nonnull boolean enabled, - @Nullable String cmabUUID) { + @Nullable String cmabUuid) { UserEvent userEvent = UserEventFactory.createImpressionEvent( projectConfig, @@ -339,11 +339,12 @@ private boolean sendImpression(@Nonnull ProjectConfig projectConfig, flagKey, ruleType, enabled, - cmabUUID); + cmabUuid); if (userEvent == null) { return false; } + eventProcessor.getClass().getName(); eventProcessor.process(userEvent); if (experiment != null) { logger.info("Activating user \"{}\" in experiment \"{}\".", userId, experiment.getKey()); @@ -501,7 +502,7 @@ private Boolean isFeatureEnabled(@Nonnull ProjectConfig projectConfig, if (featureDecision.decisionSource != null) { decisionSource = featureDecision.decisionSource; } - String cmabUUID = featureDecision.cmabUUID; + String cmabUuid = featureDecision.cmabUuid; if (featureDecision.variation != null) { // This information is only necessary for feature tests. // For rollouts experiments and variations are an implementation detail only. @@ -524,7 +525,7 @@ private Boolean isFeatureEnabled(@Nonnull ProjectConfig projectConfig, featureKey, decisionSource.toString(), featureEnabled, - cmabUUID); + cmabUuid); DecisionNotification decisionNotification = DecisionNotification.newFeatureDecisionNotificationBuilder() .withUserId(userId) @@ -1339,7 +1340,7 @@ private OptimizelyDecision createOptimizelyDecision( Map attributes = user.getAttributes(); Map copiedAttributes = new HashMap<>(attributes); - String cmabUUID = flagDecision.cmabUUID; + String cmabUuid = flagDecision.cmabUuid; if (!allOptions.contains(OptimizelyDecideOption.DISABLE_DECISION_EVENT)) { decisionEventDispatched = sendImpression( @@ -1351,7 +1352,7 @@ private OptimizelyDecision createOptimizelyDecision( flagKey, decisionSource.toString(), flagEnabled, - cmabUUID); + cmabUuid); } DecisionNotification decisionNotification = DecisionNotification.newFlagDecisionNotificationBuilder() diff --git a/core-api/src/main/java/com/optimizely/ab/bucketing/DecisionService.java b/core-api/src/main/java/com/optimizely/ab/bucketing/DecisionService.java index 572d28981..6908615f0 100644 --- a/core-api/src/main/java/com/optimizely/ab/bucketing/DecisionService.java +++ b/core-api/src/main/java/com/optimizely/ab/bucketing/DecisionService.java @@ -169,7 +169,7 @@ public DecisionResponse getVariation(@Nonnull Experiment experiment, reasons.merge(decisionMeetAudience.getReasons()); if (decisionMeetAudience.getResult()) { String bucketingId = getBucketingId(user.getUserId(), user.getAttributes()); - String cmabUUID = null; + String cmabUuid = null; decisionVariation = bucketer.bucket(experiment, bucketingId, projectConfig, decisionPath); if (decisionPath == DecisionPath.WITH_CMAB && isCmabExperiment(experiment) && decisionVariation.getResult() != null) { // group-allocation and traffic-allocation checking passed for cmab @@ -184,7 +184,7 @@ public DecisionResponse getVariation(@Nonnull Experiment experiment, CmabDecision cmabResult = cmabDecision.getResult(); if (cmabResult != null) { String variationId = cmabResult.getVariationId(); - cmabUUID = cmabResult.getCmabUUID(); + cmabUuid = cmabResult.getCmabUuid(); variation = experiment.getVariationIdToVariationMap().get(variationId); } } else { @@ -201,7 +201,7 @@ public DecisionResponse getVariation(@Nonnull Experiment experiment, } } - return new DecisionResponse<>(variation, reasons, false, cmabUUID); + return new DecisionResponse<>(variation, reasons, false, cmabUuid); } String message = reasons.addInfo("User \"%s\" does not meet conditions to be in experiment \"%s\".", user.getUserId(), experiment.getKey()); @@ -336,7 +336,7 @@ public List> getVariationsForFeatureList(@Non boolean error = decisionVariationResponse.isError(); if (decision != null) { - decisions.add(new DecisionResponse(decision, reasons, error, decision.cmabUUID)); + decisions.add(new DecisionResponse(decision, reasons, error, decision.cmabUuid)); continue; } @@ -395,21 +395,21 @@ DecisionResponse getVariationFromExperiment(@Nonnull ProjectCon getVariationFromExperimentRule(projectConfig, featureFlag.getKey(), experiment, user, options, userProfileTracker, decisionPath); reasons.merge(decisionVariation.getReasons()); Variation variation = decisionVariation.getResult(); - String cmabUUID = decisionVariation.getCmabUUID(); + String cmabUuid = decisionVariation.getCmabUuid(); boolean error = decisionVariation.isError(); if (error) { return new DecisionResponse( - new FeatureDecision(experiment, variation, FeatureDecision.DecisionSource.FEATURE_TEST, cmabUUID), + new FeatureDecision(experiment, variation, FeatureDecision.DecisionSource.FEATURE_TEST, cmabUuid), reasons, decisionVariation.isError(), - cmabUUID); + cmabUuid); } if (variation != null) { return new DecisionResponse( - new FeatureDecision(experiment, variation, FeatureDecision.DecisionSource.FEATURE_TEST, cmabUUID), + new FeatureDecision(experiment, variation, FeatureDecision.DecisionSource.FEATURE_TEST, cmabUuid), reasons, decisionVariation.isError(), - cmabUUID); + cmabUuid); } } } else { @@ -844,7 +844,7 @@ private DecisionResponse getVariationFromExperimentRule(@Nonnull Proj variation = decisionResponse.getResult(); - return new DecisionResponse<>(variation, reasons, decisionResponse.isError(), decisionResponse.getCmabUUID()); + return new DecisionResponse<>(variation, reasons, decisionResponse.isError(), decisionResponse.getCmabUuid()); } /** diff --git a/core-api/src/main/java/com/optimizely/ab/bucketing/FeatureDecision.java b/core-api/src/main/java/com/optimizely/ab/bucketing/FeatureDecision.java index 35bde3d7a..ed369ee69 100644 --- a/core-api/src/main/java/com/optimizely/ab/bucketing/FeatureDecision.java +++ b/core-api/src/main/java/com/optimizely/ab/bucketing/FeatureDecision.java @@ -43,7 +43,7 @@ public class FeatureDecision { * The CMAB UUID for Contextual Multi-Armed Bandit experiments. */ @Nullable - public String cmabUUID; + public String cmabUuid; public enum DecisionSource { FEATURE_TEST("feature-test"), @@ -74,7 +74,7 @@ public FeatureDecision(@Nullable ExperimentCore experiment, @Nullable Variation this.experiment = experiment; this.variation = variation; this.decisionSource = decisionSource; - this.cmabUUID = null; + this.cmabUuid = null; } /** @@ -83,14 +83,14 @@ public FeatureDecision(@Nullable ExperimentCore experiment, @Nullable Variation * @param experiment The {@link ExperimentCore} the Feature is associated with. * @param variation The {@link Variation} the user was bucketed into. * @param decisionSource The source of the variation. - * @param cmabUUID The CMAB UUID for Contextual Multi-Armed Bandit experiments. + * @param cmabUuid The CMAB UUID for Contextual Multi-Armed Bandit experiments. */ public FeatureDecision(@Nullable ExperimentCore experiment, @Nullable Variation variation, - @Nullable DecisionSource decisionSource, @Nullable String cmabUUID) { + @Nullable DecisionSource decisionSource, @Nullable String cmabUuid) { this.experiment = experiment; this.variation = variation; this.decisionSource = decisionSource; - this.cmabUUID = cmabUUID; + this.cmabUuid = cmabUuid; } @Override @@ -103,14 +103,14 @@ public boolean equals(Object o) { if (variation != null ? !variation.equals(that.variation) : that.variation != null) return false; if (decisionSource != that.decisionSource) return false; - return cmabUUID != null ? cmabUUID.equals(that.cmabUUID) : that.cmabUUID == null; + return cmabUuid != null ? cmabUuid.equals(that.cmabUuid) : that.cmabUuid == null; } @Override public int hashCode() { int result = variation != null ? variation.hashCode() : 0; result = 31 * result + (decisionSource != null ? decisionSource.hashCode() : 0); - result = 31 * result + (cmabUUID != null ? cmabUUID.hashCode() : 0); + result = 31 * result + (cmabUuid != null ? cmabUuid.hashCode() : 0); return result; } } diff --git a/core-api/src/main/java/com/optimizely/ab/cmab/client/CmabClient.java b/core-api/src/main/java/com/optimizely/ab/cmab/client/CmabClient.java index 2deabcfb4..9e7272be4 100644 --- a/core-api/src/main/java/com/optimizely/ab/cmab/client/CmabClient.java +++ b/core-api/src/main/java/com/optimizely/ab/cmab/client/CmabClient.java @@ -24,8 +24,8 @@ public interface CmabClient { * @param ruleId The rule/experiment ID * @param userId The user ID * @param attributes User attributes - * @param cmabUUID The CMAB UUID + * @param cmabUuid The CMAB UUID * @return CompletableFuture containing the variation ID as a String */ - String fetchDecision(String ruleId, String userId, Map attributes, String cmabUUID); + String fetchDecision(String ruleId, String userId, Map attributes, String cmabUuid); } diff --git a/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabCacheValue.java b/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabCacheValue.java index aa2ba30e6..361118ab5 100644 --- a/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabCacheValue.java +++ b/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabCacheValue.java @@ -20,12 +20,12 @@ public class CmabCacheValue { private final String attributesHash; private final String variationId; - private final String cmabUUID; + private final String cmabUuid; - public CmabCacheValue(String attributesHash, String variationId, String cmabUUID) { + public CmabCacheValue(String attributesHash, String variationId, String cmabUuid) { this.attributesHash = attributesHash; this.variationId = variationId; - this.cmabUUID = cmabUUID; + this.cmabUuid = cmabUuid; } public String getAttributesHash() { @@ -37,7 +37,7 @@ public String getVariationId() { } public String getCmabUuid() { - return cmabUUID; + return cmabUuid; } @Override @@ -45,7 +45,7 @@ public String toString() { return "CmabCacheValue{" + "attributesHash='" + attributesHash + '\'' + ", variationId='" + variationId + '\'' + - ", cmabUuid='" + cmabUUID + '\'' + + ", cmabUuid='" + cmabUuid + '\'' + '}'; } @@ -56,11 +56,11 @@ public boolean equals(Object o) { CmabCacheValue that = (CmabCacheValue) o; return Objects.equals(attributesHash, that.attributesHash) && Objects.equals(variationId, that.variationId) && - Objects.equals(cmabUUID, that.cmabUUID); + Objects.equals(cmabUuid, that.cmabUuid); } @Override public int hashCode() { - return Objects.hash(attributesHash, variationId, cmabUUID); + return Objects.hash(attributesHash, variationId, cmabUuid); } } diff --git a/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabDecision.java b/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabDecision.java index e96bf303f..1dbb44ed7 100644 --- a/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabDecision.java +++ b/core-api/src/main/java/com/optimizely/ab/cmab/service/CmabDecision.java @@ -19,26 +19,26 @@ public class CmabDecision { private final String variationId; - private final String cmabUUID; + private final String cmabUuid; - public CmabDecision(String variationId, String cmabUUID) { + public CmabDecision(String variationId, String cmabUuid) { this.variationId = variationId; - this.cmabUUID = cmabUUID; + this.cmabUuid = cmabUuid; } public String getVariationId() { return variationId; } - public String getCmabUUID() { - return cmabUUID; + public String getCmabUuid() { + return cmabUuid; } @Override public String toString() { return "CmabDecision{" + "variationId='" + variationId + '\'' + - ", cmabUUID='" + cmabUUID + '\'' + + ", cmabUuid='" + cmabUuid + '\'' + '}'; } @@ -48,11 +48,11 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; CmabDecision that = (CmabDecision) o; return Objects.equals(variationId, that.variationId) && - Objects.equals(cmabUUID, that.cmabUUID); + Objects.equals(cmabUuid, that.cmabUuid); } @Override public int hashCode() { - return Objects.hash(variationId, cmabUUID); + return Objects.hash(variationId, cmabUuid); } } diff --git a/core-api/src/main/java/com/optimizely/ab/cmab/service/DefaultCmabService.java b/core-api/src/main/java/com/optimizely/ab/cmab/service/DefaultCmabService.java index 686956016..75835a9f8 100644 --- a/core-api/src/main/java/com/optimizely/ab/cmab/service/DefaultCmabService.java +++ b/core-api/src/main/java/com/optimizely/ab/cmab/service/DefaultCmabService.java @@ -22,7 +22,6 @@ import java.util.TreeMap; import java.util.concurrent.locks.ReentrantLock; -import com.optimizely.ab.event.internal.ClientEngineInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +31,7 @@ import com.optimizely.ab.config.Attribute; import com.optimizely.ab.config.Experiment; import com.optimizely.ab.config.ProjectConfig; +import com.optimizely.ab.event.internal.ClientEngineInfo; import com.optimizely.ab.internal.Cache; import com.optimizely.ab.internal.DefaultLRUCache; import com.optimizely.ab.optimizelydecision.OptimizelyDecideOption; @@ -107,7 +107,7 @@ public CmabDecision getDecision(ProjectConfig projectConfig, OptimizelyUserConte CmabDecision cmabDecision = fetchDecision(ruleId, userId, filteredAttributes); logger.debug("CMAB decision is {}", cmabDecision); - cmabCache.save(cacheKey, new CmabCacheValue(attributesHash, cmabDecision.getVariationId(), cmabDecision.getCmabUUID())); + cmabCache.save(cacheKey, new CmabCacheValue(attributesHash, cmabDecision.getVariationId(), cmabDecision.getCmabUuid())); return cmabDecision; } finally { diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/UserEventFactory.java b/core-api/src/main/java/com/optimizely/ab/event/internal/UserEventFactory.java index 93f0f1f8b..f7a121506 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/UserEventFactory.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/UserEventFactory.java @@ -42,7 +42,7 @@ public static ImpressionEvent createImpressionEvent(@Nonnull ProjectConfig proje @Nonnull String flagKey, @Nonnull String ruleType, @Nonnull boolean enabled, - @Nullable String cmabUUID) { + @Nullable String cmabUuid) { if ((FeatureDecision.DecisionSource.ROLLOUT.toString().equals(ruleType) || variation == null) && !projectConfig.getSendFlagDecisions()) { @@ -76,8 +76,8 @@ public static ImpressionEvent createImpressionEvent(@Nonnull ProjectConfig proje .setVariationKey(variationKey) .setEnabled(enabled); - if (cmabUUID != null) { - metadataBuilder.setCmabUUID(cmabUUID); + if (cmabUuid != null) { + metadataBuilder.setCmabUuid(cmabUuid); } DecisionMetadata metadata = metadataBuilder.build(); diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/DecisionMetadata.java b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/DecisionMetadata.java index 3613c979a..7abf6506e 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/payload/DecisionMetadata.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/payload/DecisionMetadata.java @@ -16,11 +16,11 @@ */ package com.optimizely.ab.event.internal.payload; +import java.util.StringJoiner; + import com.fasterxml.jackson.annotation.JsonProperty; import com.optimizely.ab.annotations.VisibleForTesting; -import java.util.StringJoiner; - public class DecisionMetadata { @JsonProperty("flag_key") @@ -34,19 +34,19 @@ public class DecisionMetadata { @JsonProperty("enabled") boolean enabled; @JsonProperty("cmab_uuid") - String cmabUUID; + String cmabUuid; @VisibleForTesting public DecisionMetadata() { } - public DecisionMetadata(String flagKey, String ruleKey, String ruleType, String variationKey, boolean enabled, String cmabUUID) { + public DecisionMetadata(String flagKey, String ruleKey, String ruleType, String variationKey, boolean enabled, String cmabUuid) { this.flagKey = flagKey; this.ruleKey = ruleKey; this.ruleType = ruleType; this.variationKey = variationKey; this.enabled = enabled; - this.cmabUUID = cmabUUID; + this.cmabUuid = cmabUuid; } public String getRuleType() { @@ -69,8 +69,8 @@ public String getVariationKey() { return variationKey; } - public String getCmabUUID() { - return cmabUUID; + public String getCmabUuid() { + return cmabUuid; } @Override @@ -84,7 +84,7 @@ public boolean equals(Object o) { if (!ruleKey.equals(that.ruleKey)) return false; if (!flagKey.equals(that.flagKey)) return false; if (enabled != that.enabled) return false; - if (!java.util.Objects.equals(cmabUUID, that.cmabUUID)) return false; + if (!java.util.Objects.equals(cmabUuid, that.cmabUuid)) return false; return variationKey.equals(that.variationKey); } @@ -94,7 +94,7 @@ public int hashCode() { result = 31 * result + flagKey.hashCode(); result = 31 * result + ruleKey.hashCode(); result = 31 * result + variationKey.hashCode(); - result = 31 * result + (cmabUUID != null ? cmabUUID.hashCode() : 0); + result = 31 * result + (cmabUuid != null ? cmabUuid.hashCode() : 0); return result; } @@ -106,7 +106,7 @@ public String toString() { .add("ruleType='" + ruleType + "'") .add("variationKey='" + variationKey + "'") .add("enabled=" + enabled) - .add("cmabUUID='" + cmabUUID + "'") + .add("cmabUuid='" + cmabUuid + "'") .toString(); } @@ -118,7 +118,7 @@ public static class Builder { private String flagKey; private String variationKey; private boolean enabled; - private String cmabUUID; + private String cmabUuid; public Builder setEnabled(boolean enabled) { this.enabled = enabled; @@ -145,13 +145,13 @@ public Builder setVariationKey(String variationKey) { return this; } - public Builder setCmabUUID(String cmabUUID){ - this.cmabUUID = cmabUUID; + public Builder setCmabUuid(String cmabUuid){ + this.cmabUuid = cmabUuid; return this; } public DecisionMetadata build() { - return new DecisionMetadata(flagKey, ruleKey, ruleType, variationKey, enabled, cmabUUID); + return new DecisionMetadata(flagKey, ruleKey, ruleType, variationKey, enabled, cmabUuid); } } } diff --git a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java index b35c74ba6..e7a5f0614 100644 --- a/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java +++ b/core-api/src/main/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializer.java @@ -16,13 +16,8 @@ */ package com.optimizely.ab.event.internal.serializer; -import com.optimizely.ab.event.internal.payload.Attribute; -import com.optimizely.ab.event.internal.payload.Decision; -import com.optimizely.ab.event.internal.payload.EventBatch; +import com.optimizely.ab.event.internal.payload.*; -import com.optimizely.ab.event.internal.payload.Event; -import com.optimizely.ab.event.internal.payload.Snapshot; -import com.optimizely.ab.event.internal.payload.Visitor; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -142,6 +137,19 @@ private JSONObject serializeDecision(Decision decision) { if (decision.getVariationId() != null) jsonObject.put("variation_id", decision.getVariationId()); jsonObject.put("is_campaign_holdback", decision.getIsCampaignHoldback()); + if (decision.getMetadata() != null) jsonObject.put("metadata", serializeDecisionMetadata(decision.getMetadata())); + + return jsonObject; + } + + private JSONObject serializeDecisionMetadata(DecisionMetadata metadata) { + JSONObject jsonObject = new JSONObject(); + if (metadata.getFlagKey() != null) jsonObject.put("flag_key", metadata.getFlagKey()); + if (metadata.getRuleKey() != null) jsonObject.put("rule_key", metadata.getRuleKey()); + if (metadata.getRuleType() != null) jsonObject.put("rule_type", metadata.getRuleType()); + if (metadata.getVariationKey() != null) jsonObject.put("variation_key", metadata.getVariationKey()); + jsonObject.put("enabled", metadata.getEnabled()); + if (metadata.getCmabUuid() != null) jsonObject.put("cmab_uuid", metadata.getCmabUuid()); return jsonObject; } diff --git a/core-api/src/main/java/com/optimizely/ab/optimizelydecision/DecisionResponse.java b/core-api/src/main/java/com/optimizely/ab/optimizelydecision/DecisionResponse.java index c67c7f95a..7f082a8a5 100644 --- a/core-api/src/main/java/com/optimizely/ab/optimizelydecision/DecisionResponse.java +++ b/core-api/src/main/java/com/optimizely/ab/optimizelydecision/DecisionResponse.java @@ -23,13 +23,13 @@ public class DecisionResponse { private T result; private DecisionReasons reasons; private boolean error; - private String cmabUUID; + private String cmabUuid; - public DecisionResponse(@Nullable T result, @Nonnull DecisionReasons reasons, @Nonnull boolean error, @Nullable String cmabUUID) { + public DecisionResponse(@Nullable T result, @Nonnull DecisionReasons reasons, @Nonnull boolean error, @Nullable String cmabUuid) { this.result = result; this.reasons = reasons; this.error = error; - this.cmabUUID = cmabUUID; + this.cmabUuid = cmabUuid; } public DecisionResponse(@Nullable T result, @Nonnull DecisionReasons reasons) { @@ -60,7 +60,7 @@ public boolean isError(){ } @Nullable - public String getCmabUUID() { - return cmabUUID; + public String getCmabUuid() { + return cmabUuid; } } diff --git a/core-api/src/test/java/com/optimizely/ab/cmab/DefaultCmabServiceTest.java b/core-api/src/test/java/com/optimizely/ab/cmab/DefaultCmabServiceTest.java index 8794788fe..671b8c1b8 100644 --- a/core-api/src/test/java/com/optimizely/ab/cmab/DefaultCmabServiceTest.java +++ b/core-api/src/test/java/com/optimizely/ab/cmab/DefaultCmabServiceTest.java @@ -18,11 +18,13 @@ import java.lang.reflect.Method; import java.util.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; - -import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; @@ -124,7 +126,7 @@ public void testReturnsDecisionFromCacheWhenValid() { CmabDecision secondDecision = cmabService.getDecision(mockProjectConfig, mockUserContext, "exp1", Collections.emptyList()); assertEquals("varA", secondDecision.getVariationId()); - assertEquals(savedValue.getCmabUuid(), secondDecision.getCmabUUID()); + assertEquals(savedValue.getCmabUuid(), secondDecision.getCmabUuid()); verify(mockCmabClient, never()).fetchDecision(any(), any(), any(), any()); } @@ -137,7 +139,7 @@ public void testIgnoresCacheWhenOptionGiven() { CmabDecision decision = cmabService.getDecision(mockProjectConfig, mockUserContext, "exp1", options); assertEquals("varB", decision.getVariationId()); - assertNotNull(decision.getCmabUUID()); + assertNotNull(decision.getCmabUuid()); Map expectedAttributes = new HashMap<>(); expectedAttributes.put("age", 25); @@ -162,7 +164,7 @@ public void testInvalidatesUserCacheWhenOptionGiven() { // Verify the decision is correct assertEquals("varC", decision.getVariationId()); - assertNotNull(decision.getCmabUUID()); + assertNotNull(decision.getCmabUuid()); } @Test @@ -176,7 +178,7 @@ public void testResetsCacheWhenOptionGiven() { verify(mockCmabCache).reset(); assertEquals("varD", decision.getVariationId()); - assertNotNull(decision.getCmabUUID()); + assertNotNull(decision.getCmabUuid()); } @Test @@ -226,7 +228,7 @@ public void testOnlyCmabAttributesPassedToClient() { verify(mockCmabClient).fetchDecision(eq("exp1"), eq("user123"), eq(expectedAttributes), anyString()); assertEquals("varF", decision.getVariationId()); - assertNotNull(decision.getCmabUUID()); + assertNotNull(decision.getCmabUuid()); } @Test @@ -261,7 +263,7 @@ public void testAttributeHashingBehavior() { // Verify cache was populated verify(mockCmabCache).save(eq(cacheKey), any(CmabCacheValue.class)); assertEquals("varA", decision1.getVariationId()); - assertNotNull(decision1.getCmabUUID()); + assertNotNull(decision1.getCmabUuid()); } @Test @@ -368,7 +370,7 @@ public void testAttributeOrderDoesNotMatterForCaching() { // Verify basic functionality assertEquals("varA", decision.getVariationId()); - assertNotNull(decision.getCmabUUID()); + assertNotNull(decision.getCmabUuid()); verify(mockCmabCache).save(eq(cacheKey), any(CmabCacheValue.class)); } @Test diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/UserEventFactoryTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/UserEventFactoryTest.java index 24c0c5c80..c27deff3b 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/UserEventFactoryTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/UserEventFactoryTest.java @@ -186,7 +186,7 @@ public void createImpressionEventWithCmabUuid() { // Verify DecisionMetadata contains cmabUUID DecisionMetadata metadata = result.getMetadata(); assertNotNull(metadata); - assertEquals(cmabUUID, metadata.getCmabUUID()); + assertEquals(cmabUUID, metadata.getCmabUuid()); assertEquals(flagKey, metadata.getFlagKey()); assertEquals("experimentKey", metadata.getRuleKey()); assertEquals(ruleType, metadata.getRuleType()); @@ -240,6 +240,6 @@ public void createImpressionEventWithNullCmabUuid() { assertNotNull(result); DecisionMetadata metadata = result.getMetadata(); assertNotNull(metadata); - assertNull(metadata.getCmabUUID()); + assertNull(metadata.getCmabUuid()); } } diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java index 05573a7d8..eaa5b0486 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/GsonSerializerTest.java @@ -20,11 +20,12 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.optimizely.ab.event.internal.payload.EventBatch; +import com.optimizely.ab.event.internal.payload.*; import org.junit.Test; import java.io.IOException; +import java.util.Collections; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversion; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversionJson; @@ -36,7 +37,7 @@ import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateImpressionWithSessionIdJson; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.*; public class GsonSerializerTest { @@ -84,4 +85,53 @@ public void serializeConversionWithSessionId() throws Exception { assertThat(actual, is(expected)); } + + @Test + public void serializeDecisionMetadataWithCmabUuid() throws IOException { + String cmabUuid = "test-cmab-uuid-12345"; + DecisionMetadata metadata = new DecisionMetadata("test_flag", "test_rule", "feature-test", "variation_a", true, cmabUuid); + + Decision decision = new Decision.Builder() + .setCampaignId("layerId") + .setExperimentId("experimentId") + .setVariationId("variationId") + .setIsCampaignHoldback(false) + .setMetadata(metadata) + .build(); + + Event event = new Event.Builder() + .setTimestamp(12345L) + .setUuid("event-uuid") + .setEntityId("entityId") + .setKey("test_event") + .setType("test_event") + .build(); + + Snapshot snapshot = new Snapshot.Builder() + .setDecisions(Collections.singletonList(decision)) + .setEvents(Collections.singletonList(event)) + .build(); + + Visitor visitor = new Visitor.Builder() + .setVisitorId("visitor123") + .setAttributes(Collections.emptyList()) + .setSnapshots(Collections.singletonList(snapshot)) + .build(); + + EventBatch eventBatch = new EventBatch.Builder() + .setClientVersion("1.0.0") + .setAccountId("accountId") + .setVisitors(Collections.singletonList(visitor)) + .setAnonymizeIp(false) + .setProjectId("projectId") + .setRevision("1") + .build(); + + String serialized = serializer.serialize(eventBatch); + + // Critical assertion: must be "cmab_uuid", NOT "cmab_u_u_i_d" + assertTrue("Serialized JSON should contain 'cmab_uuid'", serialized.contains("\"cmab_uuid\"")); + assertTrue("Serialized JSON should contain the UUID value", serialized.contains(cmabUuid)); + assertFalse("Serialized JSON must NOT contain 'cmab_u_u_i_d'", serialized.contains("\"cmab_u_u_i_d\"")); + } } diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java index fb068e3ab..8e4ac415b 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JacksonSerializerTest.java @@ -19,11 +19,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import com.optimizely.ab.event.internal.payload.EventBatch; +import com.optimizely.ab.event.internal.payload.*; import org.junit.Test; import java.io.IOException; +import java.util.Collections; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversion; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversionJson; @@ -35,7 +36,7 @@ import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateImpressionWithSessionIdJson; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.*; public class JacksonSerializerTest { @@ -84,4 +85,53 @@ public void serializeConversionWithSessionId() throws IOException { assertThat(actual, is(expected)); } + + @Test + public void serializeDecisionMetadataWithCmabUuid() throws IOException { + String cmabUuid = "test-cmab-uuid-12345"; + DecisionMetadata metadata = new DecisionMetadata("test_flag", "test_rule", "feature-test", "variation_a", true, cmabUuid); + + Decision decision = new Decision.Builder() + .setCampaignId("layerId") + .setExperimentId("experimentId") + .setVariationId("variationId") + .setIsCampaignHoldback(false) + .setMetadata(metadata) + .build(); + + Event event = new Event.Builder() + .setTimestamp(12345L) + .setUuid("event-uuid") + .setEntityId("entityId") + .setKey("test_event") + .setType("test_event") + .build(); + + Snapshot snapshot = new Snapshot.Builder() + .setDecisions(Collections.singletonList(decision)) + .setEvents(Collections.singletonList(event)) + .build(); + + Visitor visitor = new Visitor.Builder() + .setVisitorId("visitor123") + .setAttributes(Collections.emptyList()) + .setSnapshots(Collections.singletonList(snapshot)) + .build(); + + EventBatch eventBatch = new EventBatch.Builder() + .setClientVersion("1.0.0") + .setAccountId("accountId") + .setVisitors(Collections.singletonList(visitor)) + .setAnonymizeIp(false) + .setProjectId("projectId") + .setRevision("1") + .build(); + + String serialized = serializer.serialize(eventBatch); + System.out.println("serialized" + serialized); + // Critical assertion: must be "cmab_uuid", NOT "cmab_u_u_i_d" + assertTrue("Serialized JSON should contain 'cmab_uuid'", serialized.contains("\"cmab_uuid\"")); + assertTrue("Serialized JSON should contain the UUID value", serialized.contains(cmabUuid)); + assertFalse("Serialized JSON must NOT contain 'cmab_u_u_i_d'", serialized.contains("\"cmab_u_u_i_d\"")); + } } diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java index ff86538a5..c5b2d5f05 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSerializerTest.java @@ -16,13 +16,14 @@ */ package com.optimizely.ab.event.internal.serializer; -import com.optimizely.ab.event.internal.payload.EventBatch; +import com.optimizely.ab.event.internal.payload.*; import org.json.JSONObject; import org.junit.Test; import java.io.IOException; +import java.util.Collections; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversion; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversionJson; @@ -33,6 +34,7 @@ import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateImpressionWithSessionId; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateImpressionWithSessionIdJson; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class JsonSerializerTest { @@ -78,4 +80,53 @@ public void serializeConversionWithSessionId() throws IOException { assertTrue(actual.similar(expected)); } + + @Test + public void serializeDecisionMetadataWithCmabUuid() throws IOException { + String cmabUuid = "test-cmab-uuid-12345"; + DecisionMetadata metadata = new DecisionMetadata("test_flag", "test_rule", "feature-test", "variation_a", true, cmabUuid); + + Decision decision = new Decision.Builder() + .setCampaignId("layerId") + .setExperimentId("experimentId") + .setVariationId("variationId") + .setIsCampaignHoldback(false) + .setMetadata(metadata) + .build(); + + Event event = new Event.Builder() + .setTimestamp(12345L) + .setUuid("event-uuid") + .setEntityId("entityId") + .setKey("test_event") + .setType("test_event") + .build(); + + Snapshot snapshot = new Snapshot.Builder() + .setDecisions(Collections.singletonList(decision)) + .setEvents(Collections.singletonList(event)) + .build(); + + Visitor visitor = new Visitor.Builder() + .setVisitorId("visitor123") + .setAttributes(Collections.emptyList()) + .setSnapshots(Collections.singletonList(snapshot)) + .build(); + + EventBatch eventBatch = new EventBatch.Builder() + .setClientVersion("1.0.0") + .setAccountId("accountId") + .setVisitors(Collections.singletonList(visitor)) + .setAnonymizeIp(false) + .setProjectId("projectId") + .setRevision("1") + .build(); + + String serialized = serializer.serialize(eventBatch); + System.out.println("serialized"+serialized); + // Verify correct serialization + assertTrue("Serialized JSON should contain 'cmab_uuid'", serialized.contains("\"cmab_uuid\"")); + assertTrue("Serialized JSON should contain the UUID value", serialized.contains(cmabUuid)); + assertFalse("Serialized JSON must NOT contain 'cmab_u_u_i_d'", serialized.contains("\"cmab_u_u_i_d\"")); + } } diff --git a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java index e0a15ba3c..05dfddb34 100644 --- a/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java +++ b/core-api/src/test/java/com/optimizely/ab/event/internal/serializer/JsonSimpleSerializerTest.java @@ -16,7 +16,7 @@ */ package com.optimizely.ab.event.internal.serializer; -import com.optimizely.ab.event.internal.payload.EventBatch; +import com.optimizely.ab.event.internal.payload.*; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; @@ -24,6 +24,7 @@ import org.junit.Test; import java.io.IOException; +import java.util.Collections; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversion; import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateConversionJson; @@ -35,7 +36,7 @@ import static com.optimizely.ab.event.internal.serializer.SerializerTestUtils.generateImpressionWithSessionIdJson; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.*; public class JsonSimpleSerializerTest { @@ -81,4 +82,54 @@ public void serializeConversionWithSessionId() throws IOException, ParseExceptio assertThat(actual, is(expected)); } + + @Test + public void serializeDecisionMetadataWithCmabUuid() throws IOException, ParseException { + String cmabUuid = "test-cmab-uuid-12345"; + DecisionMetadata metadata = new DecisionMetadata("test_flag", "test_rule", "feature-test", "variation_a", true, cmabUuid); + + Decision decision = new Decision.Builder() + .setCampaignId("layerId") + .setExperimentId("experimentId") + .setVariationId("variationId") + .setIsCampaignHoldback(false) + .setMetadata(metadata) + .build(); + + Event event = new Event.Builder() + .setTimestamp(12345L) + .setUuid("event-uuid") + .setEntityId("entityId") + .setKey("test_event") + .setType("test_event") + .build(); + + Snapshot snapshot = new Snapshot.Builder() + .setDecisions(Collections.singletonList(decision)) + .setEvents(Collections.singletonList(event)) + .build(); + + Visitor visitor = new Visitor.Builder() + .setVisitorId("visitor123") + .setAttributes(Collections.emptyList()) + .setSnapshots(Collections.singletonList(snapshot)) + .build(); + + EventBatch eventBatch = new EventBatch.Builder() + .setClientVersion("1.0.0") + .setAccountId("accountId") + .setVisitors(Collections.singletonList(visitor)) + .setAnonymizeIp(false) + .setProjectId("projectId") + .setRevision("1") + .build(); + + String serialized = serializer.serialize(eventBatch); + System.out.println("serialized" + serialized); + + // Verify correct serialization + assertTrue("Serialized JSON should contain 'cmab_uuid'", serialized.contains("\"cmab_uuid\"")); + assertTrue("Serialized JSON should contain the UUID value", serialized.contains(cmabUuid)); + assertFalse("Serialized JSON must NOT contain 'cmab_u_u_i_d'", serialized.contains("\"cmab_u_u_i_d\"")); + } }