From a7b10c52ea462fba1b5cd97f7cbdd605f901fba3 Mon Sep 17 00:00:00 2001 From: mnoman09 Date: Thu, 2 Jun 2022 20:42:25 +0500 Subject: [PATCH 1/6] Added qualified match type --- .../optimizely/ab/OptimizelyUserContext.java | 9 + .../ab/bucketing/DecisionService.java | 10 +- .../ab/config/audience/AndCondition.java | 4 +- .../config/audience/AudienceIdCondition.java | 5 +- .../ab/config/audience/Condition.java | 3 +- .../ab/config/audience/EmptyCondition.java | 3 +- .../ab/config/audience/NotCondition.java | 5 +- .../ab/config/audience/NullCondition.java | 3 +- .../ab/config/audience/OrCondition.java | 6 +- .../ab/config/audience/UserAttribute.java | 17 +- .../config/audience/match/MatchRegistry.java | 2 + .../config/audience/match/QualifiedMatch.java | 23 + .../ab/internal/ExperimentUtils.java | 39 +- .../AudienceConditionEvaluationTest.java | 442 +++++++++--------- 14 files changed, 321 insertions(+), 250 deletions(-) create mode 100644 core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java diff --git a/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java b/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java index d05df3bbb..33d63a6f3 100644 --- a/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java +++ b/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java @@ -36,6 +36,9 @@ public class OptimizelyUserContext { @Nonnull private final Map attributes; + @Nonnull + private List qualifiedSegments; + @Nonnull private final Optimizely optimizely; @@ -51,6 +54,7 @@ public OptimizelyUserContext(@Nonnull Optimizely optimizely, } else { this.attributes = Collections.synchronizedMap(new HashMap<>()); } + this.qualifiedSegments = Collections.synchronizedList(new ArrayList<>()); } public OptimizelyUserContext(@Nonnull Optimizely optimizely, @@ -67,6 +71,7 @@ public OptimizelyUserContext(@Nonnull Optimizely optimizely, if (forcedDecisionsMap != null) { this.forcedDecisionsMap = new ConcurrentHashMap<>(forcedDecisionsMap); } + this.qualifiedSegments = Collections.synchronizedList(new ArrayList<>()); } public OptimizelyUserContext(@Nonnull Optimizely optimizely, @Nonnull String userId) { @@ -85,6 +90,10 @@ public Optimizely getOptimizely() { return optimizely; } + public List getQualifiedSegments() { + return qualifiedSegments; + } + public OptimizelyUserContext copy() { return new OptimizelyUserContext(optimizely, userId, attributes, forcedDecisionsMap); } 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 c7ee0b3f3..db097e245 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 @@ -152,7 +152,12 @@ public DecisionResponse getVariation(@Nonnull Experiment experiment, } } - DecisionResponse decisionMeetAudience = ExperimentUtils.doesUserMeetAudienceConditions(projectConfig, experiment, user.getAttributes(), EXPERIMENT, experiment.getKey()); + DecisionResponse decisionMeetAudience = ExperimentUtils.doesUserMeetAudienceConditions(projectConfig, + experiment, + user.getAttributes(), + EXPERIMENT, + experiment.getKey(), + user.getQualifiedSegments()); reasons.merge(decisionMeetAudience.getReasons()); if (decisionMeetAudience.getResult()) { String bucketingId = getBucketingId(user.getUserId(), user.getAttributes()); @@ -695,7 +700,8 @@ DecisionResponse getVariationFromDeliveryRule(@Nonnull rule, user.getAttributes(), RULE, - String.valueOf(ruleIndex + 1) + String.valueOf(ruleIndex + 1), + user.getQualifiedSegments() ); reasons.merge(audienceDecisionResponse.getReasons()); diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java index f6561a65c..a8f5e1257 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/AndCondition.java @@ -42,7 +42,7 @@ public List getConditions() { } @Nullable - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { if (conditions == null) return null; boolean foundNull = false; // According to the matrix where: @@ -53,7 +53,7 @@ public Boolean evaluate(ProjectConfig config, Map attributes) { // true and true is true // null and null is null for (Condition condition : conditions) { - Boolean conditionEval = condition.evaluate(config, attributes); + Boolean conditionEval = condition.evaluate(config, attributes, qualifiedSegments); if (conditionEval == null) { foundNull = true; } else if (!conditionEval) { // false with nulls or trues is false. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java index e07757016..916eb487b 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java @@ -26,6 +26,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -71,7 +72,7 @@ public String getOperandOrId() { @Nullable @Override - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { if (config != null) { audience = config.getAudienceIdMapping().get(audienceId); } @@ -80,7 +81,7 @@ public Boolean evaluate(ProjectConfig config, Map attributes) { return null; } logger.debug("Starting to evaluate audience \"{}\" with conditions: {}.", audience.getId(), audience.getConditions()); - Boolean result = audience.getConditions().evaluate(config, attributes); + Boolean result = audience.getConditions().evaluate(config, attributes, qualifiedSegments); logger.debug("Audience \"{}\" evaluated to {}.", audience.getId(), result); return result; } diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java index 11b7165b9..8c37b3b71 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java @@ -19,6 +19,7 @@ import com.optimizely.ab.config.ProjectConfig; import javax.annotation.Nullable; +import java.util.List; import java.util.Map; /** @@ -27,7 +28,7 @@ public interface Condition { @Nullable - Boolean evaluate(ProjectConfig config, Map attributes); + Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments); String toJson(); diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java index 9bb355a13..737a9bbf7 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java @@ -18,12 +18,13 @@ import com.optimizely.ab.config.ProjectConfig; import javax.annotation.Nullable; +import java.util.List; import java.util.Map; public class EmptyCondition implements Condition { @Nullable @Override - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { return true; } diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java index cabc07812..0d1af0d9a 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java @@ -22,6 +22,7 @@ import javax.annotation.concurrent.Immutable; import javax.annotation.Nonnull; +import java.util.List; import java.util.Map; import java.util.StringJoiner; @@ -43,9 +44,9 @@ public Condition getCondition() { } @Nullable - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { - Boolean conditionEval = condition == null ? null : condition.evaluate(config, attributes); + Boolean conditionEval = condition == null ? null : condition.evaluate(config, attributes, qualifiedSegments); return (conditionEval == null ? null : !conditionEval); } diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java index 10633aed9..1b59dba35 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java @@ -18,12 +18,13 @@ import com.optimizely.ab.config.ProjectConfig; import javax.annotation.Nullable; +import java.util.List; import java.util.Map; public class NullCondition implements Condition { @Nullable @Override - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { return null; } diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java index 293687f66..8d6cc25ba 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java @@ -47,12 +47,12 @@ public List getConditions() { // false or false is false // null or null is null @Nullable - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { if (conditions == null) return null; boolean foundNull = false; for (Condition condition : conditions) { - Boolean conditionEval = condition.evaluate(config, attributes); - if (conditionEval == null) { // true with falses and nulls is still true + Boolean conditionEval = condition.evaluate(config, attributes, qualifiedSegments); + if (conditionEval == null) { // true with false and nulls is still true foundNull = true; } else if (conditionEval) { return true; diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java index ed029f89c..a32490083 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java @@ -28,6 +28,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import java.util.Collections; +import java.util.List; import java.util.Map; /** @@ -71,21 +72,27 @@ public Object getValue() { } @Nullable - public Boolean evaluate(ProjectConfig config, Map attributes) { + public Boolean evaluate(ProjectConfig config, Map attributes, List qualifiedSegments) { if (attributes == null) { attributes = Collections.emptyMap(); } - // Valid for primitive types, but needs to change when a value is an object or an array - Object userAttributeValue = attributes.get(name); - if (!"custom_attribute".equals(type)) { + if (!"custom_attribute".equals(type) && !"third_party_dimension".equals(type)) { logger.warn("Audience condition \"{}\" uses an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK.", this); return null; // unknown type } + // Valid for primitive types, but needs to change when a value is an object or an array + Object userAttributeValue = attributes.get(name); + // check user attribute value is equal try { Match matcher = MatchRegistry.getMatch(match); - Boolean result = matcher.eval(value, userAttributeValue); + Boolean result; + if ("qualified".equals(match)) { + result = matcher.eval(value, qualifiedSegments); + } else { + result = matcher.eval(value, userAttributeValue); + } if (result == null) { throw new UnknownValueTypeException(); } diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java b/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java index f78c35c8d..467751e2d 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java @@ -41,6 +41,7 @@ public class MatchRegistry { public static final String SEMVER_LE = "semver_le"; public static final String SEMVER_LT = "semver_lt"; public static final String SUBSTRING = "substring"; + public static final String QUALIFIED = "qualified"; static { register(EXACT, new ExactMatch()); @@ -56,6 +57,7 @@ public class MatchRegistry { register(SEMVER_LE, new SemanticVersionLEMatch()); register(SEMVER_LT, new SemanticVersionLTMatch()); register(SUBSTRING, new SubstringMatch()); + register(QUALIFIED, new QualifiedMatch()); } // TODO rename Match to Matcher diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java b/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java new file mode 100644 index 000000000..95d823d47 --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java @@ -0,0 +1,23 @@ +package com.optimizely.ab.config.audience.match; + +import javax.annotation.Nullable; +import java.util.List; + +public class QualifiedMatch implements Match { + @Nullable + public Boolean eval(Object conditionValue, Object attributeValue) throws UnexpectedValueTypeException { + if (!(conditionValue instanceof String)) { + throw new UnexpectedValueTypeException(); + } + + if (!(attributeValue instanceof List)) { + return null; + } + + try { + return ((List)attributeValue).contains(conditionValue.toString()); + } catch (Exception e) { + return null; + } + } +} diff --git a/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java b/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java index c1494bbda..59741f12f 100644 --- a/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java +++ b/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java @@ -28,9 +28,7 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; public final class ExperimentUtils { @@ -48,7 +46,6 @@ private ExperimentUtils() { public static boolean isExperimentActive(@Nonnull Experiment experiment) { return experiment.isActive(); } - /** * Determines whether a user satisfies audience conditions for the experiment. * @@ -65,14 +62,34 @@ public static DecisionResponse doesUserMeetAudienceConditions(@Nonnull @Nonnull Map attributes, @Nonnull String loggingEntityType, @Nonnull String loggingKey) { + return doesUserMeetAudienceConditions(projectConfig, experiment, attributes, loggingEntityType, loggingKey, Collections.synchronizedList(new ArrayList<>())); + } + + /** + * Determines whether a user satisfies audience conditions for the experiment. + * + * @param projectConfig the current projectConfig + * @param experiment the experiment we are evaluating audiences for + * @param attributes the attributes of the user + * @param loggingEntityType It can be either experiment or rule. + * @param loggingKey In case of loggingEntityType is experiment it will be experiment key or else it will be rule number. + * @return whether the user meets the criteria for the experiment + */ + @Nonnull + public static DecisionResponse doesUserMeetAudienceConditions(@Nonnull ProjectConfig projectConfig, + @Nonnull Experiment experiment, + @Nonnull Map attributes, + @Nonnull String loggingEntityType, + @Nonnull String loggingKey, + @Nonnull List qualifiedSegments) { DecisionReasons reasons = DefaultDecisionReasons.newInstance(); DecisionResponse decisionResponse; if (experiment.getAudienceConditions() != null) { logger.debug("Evaluating audiences for {} \"{}\": {}.", loggingEntityType, loggingKey, experiment.getAudienceConditions()); - decisionResponse = evaluateAudienceConditions(projectConfig, experiment, attributes, loggingEntityType, loggingKey); + decisionResponse = evaluateAudienceConditions(projectConfig, experiment, attributes, loggingEntityType, loggingKey, qualifiedSegments); } else { - decisionResponse = evaluateAudience(projectConfig, experiment, attributes, loggingEntityType, loggingKey); + decisionResponse = evaluateAudience(projectConfig, experiment, attributes, loggingEntityType, loggingKey, qualifiedSegments); } Boolean resolveReturn = decisionResponse.getResult(); @@ -88,7 +105,8 @@ public static DecisionResponse evaluateAudience(@Nonnull ProjectConfig @Nonnull Experiment experiment, @Nonnull Map attributes, @Nonnull String loggingEntityType, - @Nonnull String loggingKey) { + @Nonnull String loggingKey, + @Nonnull List qualifiedSegments) { DecisionReasons reasons = DefaultDecisionReasons.newInstance(); List experimentAudienceIds = experiment.getAudienceIds(); @@ -108,7 +126,7 @@ public static DecisionResponse evaluateAudience(@Nonnull ProjectConfig logger.debug("Evaluating audiences for {} \"{}\": {}.", loggingEntityType, loggingKey, conditions); - Boolean result = implicitOr.evaluate(projectConfig, attributes); + Boolean result = implicitOr.evaluate(projectConfig, attributes, qualifiedSegments); String message = reasons.addInfo("Audiences for %s \"%s\" collectively evaluated to %s.", loggingEntityType, loggingKey, result); logger.info(message); @@ -120,7 +138,8 @@ public static DecisionResponse evaluateAudienceConditions(@Nonnull Proj @Nonnull Experiment experiment, @Nonnull Map attributes, @Nonnull String loggingEntityType, - @Nonnull String loggingKey) { + @Nonnull String loggingKey, + @Nonnull List qualifiedSegments) { DecisionReasons reasons = DefaultDecisionReasons.newInstance(); Condition conditions = experiment.getAudienceConditions(); @@ -128,7 +147,7 @@ public static DecisionResponse evaluateAudienceConditions(@Nonnull Proj Boolean result = null; try { - result = conditions.evaluate(projectConfig, attributes); + result = conditions.evaluate(projectConfig, attributes, qualifiedSegments); String message = reasons.addInfo("Audiences for %s \"%s\" collectively evaluated to %s.", loggingEntityType, loggingKey, result); logger.info(message); } catch (Exception e) { diff --git a/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java b/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java index 07a0c1ad1..7477c3933 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java @@ -70,7 +70,7 @@ public void emptyConditionTest() throws Exception { EmptyCondition emptyCondition = new EmptyCondition(); assertEquals(null, emptyCondition.toJson()); assertEquals(null, emptyCondition.getOperandOrId()); - assertEquals(true, emptyCondition.evaluate(null, null)); + assertEquals(true, emptyCondition.evaluate(null, null, null)); } /** @@ -129,7 +129,7 @@ public void userAttributeEvaluateTrue() throws Exception { assertNull(testInstance.getMatch()); assertEquals(testInstance.getName(), "browser_type"); assertEquals(testInstance.getType(), "custom_attribute"); - assertTrue(testInstance.evaluate(null, testUserAttributes)); + assertTrue(testInstance.evaluate(null, testUserAttributes, null)); } /** @@ -138,7 +138,7 @@ public void userAttributeEvaluateTrue() throws Exception { @Test public void userAttributeEvaluateFalse() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", null, "firefox"); - assertFalse(testInstance.evaluate(null, testUserAttributes)); + assertFalse(testInstance.evaluate(null, testUserAttributes, null)); } /** @@ -147,7 +147,7 @@ public void userAttributeEvaluateFalse() throws Exception { @Test public void userAttributeUnknownAttribute() throws Exception { UserAttribute testInstance = new UserAttribute("unknown_dim", "custom_attribute", null, "unknown"); - assertFalse(testInstance.evaluate(null, testUserAttributes)); + assertFalse(testInstance.evaluate(null, testUserAttributes, null)); } /** @@ -156,7 +156,7 @@ public void userAttributeUnknownAttribute() throws Exception { @Test public void invalidMatchCondition() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "unknown_dimension", null, "chrome"); - assertNull(testInstance.evaluate(null, testUserAttributes)); + assertNull(testInstance.evaluate(null, testUserAttributes, null)); } /** @@ -165,7 +165,7 @@ public void invalidMatchCondition() throws Exception { @Test public void invalidMatch() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", "blah", "chrome"); - assertNull(testInstance.evaluate(null, testUserAttributes)); + assertNull(testInstance.evaluate(null, testUserAttributes, null)); logbackVerifier.expectMessage(Level.WARN, "Audience condition \"{name='browser_type', type='custom_attribute', match='blah', value='chrome'}\" uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK"); } @@ -176,7 +176,7 @@ public void invalidMatch() throws Exception { @Test public void unexpectedAttributeType() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", "gt", 20); - assertNull(testInstance.evaluate(null, testUserAttributes)); + assertNull(testInstance.evaluate(null, testUserAttributes, null)); logbackVerifier.expectMessage(Level.WARN, "Audience condition \"{name='browser_type', type='custom_attribute', match='gt', value=20}\" evaluated to UNKNOWN because a value of type \"java.lang.String\" was passed for user attribute \"browser_type\""); } @@ -187,7 +187,7 @@ public void unexpectedAttributeType() throws Exception { @Test public void unexpectedAttributeTypeNull() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", "gt", 20); - assertNull(testInstance.evaluate(null, Collections.singletonMap("browser_type", null))); + assertNull(testInstance.evaluate(null, Collections.singletonMap("browser_type", null), null)); logbackVerifier.expectMessage(Level.DEBUG, "Audience condition \"{name='browser_type', type='custom_attribute', match='gt', value=20}\" evaluated to UNKNOWN because a null value was passed for user attribute \"browser_type\""); } @@ -215,7 +215,7 @@ public void missingAttribute_returnsNullAndLogDebugMessage() throws Exception { for (Map.Entry entry : items.entrySet()) { for (Object value : entry.getValue()) { UserAttribute testInstance = new UserAttribute("n", "custom_attribute", entry.getKey(), value); - assertNull(testInstance.evaluate(null, Collections.EMPTY_MAP)); + assertNull(testInstance.evaluate(null, Collections.EMPTY_MAP, null)); String valueStr = (value instanceof String) ? ("'" + value + "'") : value.toString(); logbackVerifier.expectMessage(Level.DEBUG, "Audience condition \"{name='n', type='custom_attribute', match='" + entry.getKey() + "', value=" + valueStr + "}\" evaluated to UNKNOWN because no value was passed for user attribute \"n\""); @@ -229,7 +229,7 @@ public void missingAttribute_returnsNullAndLogDebugMessage() throws Exception { @Test public void nullAttribute() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", "gt", 20); - assertNull(testInstance.evaluate(null, null)); + assertNull(testInstance.evaluate(null, null, null)); logbackVerifier.expectMessage(Level.DEBUG, "Audience condition \"{name='browser_type', type='custom_attribute', match='gt', value=20}\" evaluated to UNKNOWN because no value was passed for user attribute \"browser_type\""); } @@ -240,7 +240,7 @@ public void nullAttribute() throws Exception { @Test public void unknownConditionType() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "blah", "exists", "firefox"); - assertNull(testInstance.evaluate(null, testUserAttributes)); + assertNull(testInstance.evaluate(null, testUserAttributes, null)); logbackVerifier.expectMessage(Level.WARN, "Audience condition \"{name='browser_type', type='blah', match='exists', value='firefox'}\" uses an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK."); } @@ -254,9 +254,9 @@ public void existsMatchConditionEmptyStringEvaluatesTrue() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", "exists", "firefox"); Map attributes = new HashMap<>(); attributes.put("browser_type", ""); - assertTrue(testInstance.evaluate(null, attributes)); + assertTrue(testInstance.evaluate(null, attributes, null)); attributes.put("browser_type", null); - assertFalse(testInstance.evaluate(null, attributes)); + assertFalse(testInstance.evaluate(null, attributes, null)); } /** @@ -266,16 +266,16 @@ public void existsMatchConditionEmptyStringEvaluatesTrue() throws Exception { @Test public void existsMatchConditionEvaluatesTrue() throws Exception { UserAttribute testInstance = new UserAttribute("browser_type", "custom_attribute", "exists", "firefox"); - assertTrue(testInstance.evaluate(null, testUserAttributes)); + assertTrue(testInstance.evaluate(null, testUserAttributes, null)); UserAttribute testInstanceBoolean = new UserAttribute("is_firefox", "custom_attribute", "exists", false); UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "exists", 5); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "exists", 4.55); UserAttribute testInstanceObject = new UserAttribute("meta_data", "custom_attribute", "exists", testUserAttributes); - assertTrue(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceObject.evaluate(null, testTypedUserAttributes)); + assertTrue(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); } /** @@ -286,8 +286,8 @@ public void existsMatchConditionEvaluatesTrue() throws Exception { public void existsMatchConditionEvaluatesFalse() throws Exception { UserAttribute testInstance = new UserAttribute("bad_var", "custom_attribute", "exists", "chrome"); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "exists", "chrome"); - assertFalse(testInstance.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertFalse(testInstance.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); } /** @@ -302,11 +302,11 @@ public void exactMatchConditionEvaluatesTrue() { UserAttribute testInstanceFloat = new UserAttribute("num_size", "custom_attribute", "exact", (float) 3); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "exact", 3.55); - assertTrue(testInstanceString.evaluate(null, testUserAttributes)); - assertTrue(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceFloat.evaluate(null, Collections.singletonMap("num_size", (float) 3))); - assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertTrue(testInstanceString.evaluate(null, testUserAttributes, null)); + assertTrue(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceFloat.evaluate(null, Collections.singletonMap("num_size", (float) 3), null)); + assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -339,22 +339,22 @@ public void exactMatchConditionEvaluatesNullWithInvalidUserAttr() { assertNull(testInstanceInteger.evaluate( null, - Collections.singletonMap("num_size", bigInteger))); + Collections.singletonMap("num_size", bigInteger), null)); assertNull(testInstanceFloat.evaluate( null, - Collections.singletonMap("num_size", invalidFloatValue))); + Collections.singletonMap("num_size", invalidFloatValue), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble))); + Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble))); + Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", infiniteNANDouble)))); + Collections.singletonMap("num_counts", infiniteNANDouble)), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", largeDouble)))); + Collections.singletonMap("num_counts", largeDouble)), null)); } /** @@ -372,10 +372,10 @@ public void invalidExactMatchConditionEvaluatesNull() { UserAttribute testInstanceNegativeInfiniteDouble = new UserAttribute("num_counts", "custom_attribute", "exact", infiniteNegativeInfiniteDouble); UserAttribute testInstanceNANDouble = new UserAttribute("num_counts", "custom_attribute", "exact", infiniteNANDouble); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -389,10 +389,10 @@ public void exactMatchConditionEvaluatesFalse() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "exact", 5); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "exact", 5.55); - assertFalse(testInstanceString.evaluate(null, testUserAttributes)); - assertFalse(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertFalse(testInstanceString.evaluate(null, testUserAttributes, null)); + assertFalse(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -408,15 +408,15 @@ public void exactMatchConditionEvaluatesNull() { UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "exact", "3.55"); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "exact", "null_val"); - assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceString.evaluate(null, testUserAttributes)); - assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceString.evaluate(null, testUserAttributes, null)); + assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); Map attr = new HashMap<>(); attr.put("browser_type", "true"); - assertNull(testInstanceString.evaluate(null, attr)); + assertNull(testInstanceString.evaluate(null, attr, null)); } /** @@ -430,13 +430,13 @@ public void gtMatchConditionEvaluatesTrue() { UserAttribute testInstanceFloat = new UserAttribute("num_size", "custom_attribute", "gt", (float) 2); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "gt", 2.55); - assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceFloat.evaluate(null, Collections.singletonMap("num_size", (float) 3))); - assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceFloat.evaluate(null, Collections.singletonMap("num_size", (float) 3), null)); + assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); Map badAttributes = new HashMap<>(); badAttributes.put("num_size", "bobs burgers"); - assertNull(testInstanceInteger.evaluate(null, badAttributes)); + assertNull(testInstanceInteger.evaluate(null, badAttributes, null)); } /** @@ -470,22 +470,22 @@ public void gtMatchConditionEvaluatesNullWithInvalidUserAttr() { assertNull(testInstanceInteger.evaluate( null, - Collections.singletonMap("num_size", bigInteger))); + Collections.singletonMap("num_size", bigInteger), null)); assertNull(testInstanceFloat.evaluate( null, - Collections.singletonMap("num_size", invalidFloatValue))); + Collections.singletonMap("num_size", invalidFloatValue), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble))); + Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble))); + Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", infiniteNANDouble)))); + Collections.singletonMap("num_counts", infiniteNANDouble)), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", largeDouble)))); + Collections.singletonMap("num_counts", largeDouble)), null)); } /** @@ -503,10 +503,10 @@ public void gtMatchConditionEvaluatesNullWithInvalidAttr() { UserAttribute testInstanceNegativeInfiniteDouble = new UserAttribute("num_counts", "custom_attribute", "gt", infiniteNegativeInfiniteDouble); UserAttribute testInstanceNANDouble = new UserAttribute("num_counts", "custom_attribute", "gt", infiniteNANDouble); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -519,8 +519,8 @@ public void gtMatchConditionEvaluatesFalse() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "gt", 5); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "gt", 5.55); - assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -534,10 +534,10 @@ public void gtMatchConditionEvaluatesNull() { UserAttribute testInstanceObject = new UserAttribute("meta_data", "custom_attribute", "gt", 3.5); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "gt", 3.5); - assertNull(testInstanceString.evaluate(null, testUserAttributes)); - assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceString.evaluate(null, testUserAttributes, null)); + assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); } @@ -552,13 +552,13 @@ public void geMatchConditionEvaluatesTrue() { UserAttribute testInstanceFloat = new UserAttribute("num_size", "custom_attribute", "ge", (float) 2); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "ge", 2.55); - assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceFloat.evaluate(null, Collections.singletonMap("num_size", (float) 2))); - assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceFloat.evaluate(null, Collections.singletonMap("num_size", (float) 2), null)); + assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); Map badAttributes = new HashMap<>(); badAttributes.put("num_size", "bobs burgers"); - assertNull(testInstanceInteger.evaluate(null, badAttributes)); + assertNull(testInstanceInteger.evaluate(null, badAttributes, null)); } /** @@ -592,22 +592,22 @@ public void geMatchConditionEvaluatesNullWithInvalidUserAttr() { assertNull(testInstanceInteger.evaluate( null, - Collections.singletonMap("num_size", bigInteger))); + Collections.singletonMap("num_size", bigInteger), null)); assertNull(testInstanceFloat.evaluate( null, - Collections.singletonMap("num_size", invalidFloatValue))); + Collections.singletonMap("num_size", invalidFloatValue), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble))); + Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble))); + Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", infiniteNANDouble)))); + Collections.singletonMap("num_counts", infiniteNANDouble)), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", largeDouble)))); + Collections.singletonMap("num_counts", largeDouble)), null)); } /** @@ -625,10 +625,10 @@ public void geMatchConditionEvaluatesNullWithInvalidAttr() { UserAttribute testInstanceNegativeInfiniteDouble = new UserAttribute("num_counts", "custom_attribute", "ge", infiniteNegativeInfiniteDouble); UserAttribute testInstanceNANDouble = new UserAttribute("num_counts", "custom_attribute", "ge", infiniteNANDouble); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -641,8 +641,8 @@ public void geMatchConditionEvaluatesFalse() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "ge", 5); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "ge", 5.55); - assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -656,10 +656,10 @@ public void geMatchConditionEvaluatesNull() { UserAttribute testInstanceObject = new UserAttribute("meta_data", "custom_attribute", "ge", 3.5); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "ge", 3.5); - assertNull(testInstanceString.evaluate(null, testUserAttributes)); - assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceString.evaluate(null, testUserAttributes, null)); + assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); } @@ -673,8 +673,8 @@ public void ltMatchConditionEvaluatesTrue() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "lt", 5); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "lt", 5.55); - assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -687,8 +687,8 @@ public void ltMatchConditionEvaluatesFalse() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "lt", 2); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "lt", 2.55); - assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -702,10 +702,10 @@ public void ltMatchConditionEvaluatesNull() { UserAttribute testInstanceObject = new UserAttribute("meta_data", "custom_attribute", "lt", 3.5); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "lt", 3.5); - assertNull(testInstanceString.evaluate(null, testUserAttributes)); - assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceString.evaluate(null, testUserAttributes, null)); + assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); } /** @@ -739,22 +739,22 @@ public void ltMatchConditionEvaluatesNullWithInvalidUserAttr() { assertNull(testInstanceInteger.evaluate( null, - Collections.singletonMap("num_size", bigInteger))); + Collections.singletonMap("num_size", bigInteger), null)); assertNull(testInstanceFloat.evaluate( null, - Collections.singletonMap("num_size", invalidFloatValue))); + Collections.singletonMap("num_size", invalidFloatValue), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble))); + Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble))); + Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", infiniteNANDouble)))); + Collections.singletonMap("num_counts", infiniteNANDouble)), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", largeDouble)))); + Collections.singletonMap("num_counts", largeDouble)), null)); } /** @@ -772,10 +772,10 @@ public void ltMatchConditionEvaluatesNullWithInvalidAttributes() { UserAttribute testInstanceNegativeInfiniteDouble = new UserAttribute("num_counts", "custom_attribute", "lt", infiniteNegativeInfiniteDouble); UserAttribute testInstanceNANDouble = new UserAttribute("num_counts", "custom_attribute", "lt", infiniteNANDouble); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes, null)); } @@ -789,8 +789,8 @@ public void leMatchConditionEvaluatesTrue() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "le", 5); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "le", 5.55); - assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertTrue(testInstanceDouble.evaluate(null, Collections.singletonMap("num_counts", 5.55))); + assertTrue(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertTrue(testInstanceDouble.evaluate(null, Collections.singletonMap("num_counts", 5.55), null)); } /** @@ -803,8 +803,8 @@ public void leMatchConditionEvaluatesFalse() { UserAttribute testInstanceInteger = new UserAttribute("num_size", "custom_attribute", "le", 2); UserAttribute testInstanceDouble = new UserAttribute("num_counts", "custom_attribute", "le", 2.55); - assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes)); + assertFalse(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertFalse(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -818,10 +818,10 @@ public void leMatchConditionEvaluatesNull() { UserAttribute testInstanceObject = new UserAttribute("meta_data", "custom_attribute", "le", 3.5); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "le", 3.5); - assertNull(testInstanceString.evaluate(null, testUserAttributes)); - assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceString.evaluate(null, testUserAttributes, null)); + assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); } /** @@ -855,22 +855,22 @@ public void leMatchConditionEvaluatesNullWithInvalidUserAttr() { assertNull(testInstanceInteger.evaluate( null, - Collections.singletonMap("num_size", bigInteger))); + Collections.singletonMap("num_size", bigInteger), null)); assertNull(testInstanceFloat.evaluate( null, - Collections.singletonMap("num_size", invalidFloatValue))); + Collections.singletonMap("num_size", invalidFloatValue), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble))); + Collections.singletonMap("num_counts", infinitePositiveInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, - Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble))); + Collections.singletonMap("num_counts", infiniteNegativeInfiniteDouble), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", infiniteNANDouble)))); + Collections.singletonMap("num_counts", infiniteNANDouble)), null)); assertNull(testInstanceDouble.evaluate( null, Collections.singletonMap("num_counts", - Collections.singletonMap("num_counts", largeDouble)))); + Collections.singletonMap("num_counts", largeDouble)), null)); } /** @@ -888,10 +888,10 @@ public void leMatchConditionEvaluatesNullWithInvalidAttributes() { UserAttribute testInstanceNegativeInfiniteDouble = new UserAttribute("num_counts", "custom_attribute", "le", infiniteNegativeInfiniteDouble); UserAttribute testInstanceNANDouble = new UserAttribute("num_counts", "custom_attribute", "le", infiniteNANDouble); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstancePositiveInfinite.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNegativeInfiniteDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNANDouble.evaluate(null, testTypedUserAttributes, null)); } /** @@ -901,7 +901,7 @@ public void leMatchConditionEvaluatesNullWithInvalidAttributes() { @Test public void substringMatchConditionEvaluatesTrue() { UserAttribute testInstanceString = new UserAttribute("browser_type", "custom_attribute", "substring", "chrome"); - assertTrue(testInstanceString.evaluate(null, testUserAttributes)); + assertTrue(testInstanceString.evaluate(null, testUserAttributes, null)); } /** @@ -911,7 +911,7 @@ public void substringMatchConditionEvaluatesTrue() { @Test public void substringMatchConditionPartialMatchEvaluatesTrue() { UserAttribute testInstanceString = new UserAttribute("browser_type", "custom_attribute", "substring", "chro"); - assertTrue(testInstanceString.evaluate(null, testUserAttributes)); + assertTrue(testInstanceString.evaluate(null, testUserAttributes, null)); } /** @@ -921,7 +921,7 @@ public void substringMatchConditionPartialMatchEvaluatesTrue() { @Test public void substringMatchConditionEvaluatesFalse() { UserAttribute testInstanceString = new UserAttribute("browser_type", "custom_attribute", "substring", "chr0me"); - assertFalse(testInstanceString.evaluate(null, testUserAttributes)); + assertFalse(testInstanceString.evaluate(null, testUserAttributes, null)); } /** @@ -936,11 +936,11 @@ public void substringMatchConditionEvaluatesNull() { UserAttribute testInstanceObject = new UserAttribute("meta_data", "custom_attribute", "substring", "chrome1"); UserAttribute testInstanceNull = new UserAttribute("null_val", "custom_attribute", "substring", "chrome1"); - assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceDouble.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes)); - assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes)); + assertNull(testInstanceBoolean.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceInteger.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceDouble.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceObject.evaluate(null, testTypedUserAttributes, null)); + assertNull(testInstanceNull.evaluate(null, testTypedUserAttributes, null)); } //======== Semantic version evaluation tests ========// @@ -951,7 +951,7 @@ public void testSemanticVersionEqualsMatchInvalidInput() { Map testAttributes = new HashMap(); testAttributes.put("version", 2.0); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } @Test @@ -959,7 +959,7 @@ public void semanticVersionInvalidMajorShouldBeNumberOnly() { Map testAttributes = new HashMap(); testAttributes.put("version", "a.1.2"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } @Test @@ -967,7 +967,7 @@ public void semanticVersionInvalidMinorShouldBeNumberOnly() { Map testAttributes = new HashMap(); testAttributes.put("version", "1.b.2"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } @Test @@ -975,7 +975,7 @@ public void semanticVersionInvalidPatchShouldBeNumberOnly() { Map testAttributes = new HashMap(); testAttributes.put("version", "1.2.c"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } // Test SemanticVersionEqualsMatch returns null if given invalid UserCondition Variable type @@ -984,7 +984,7 @@ public void testSemanticVersionEqualsMatchInvalidUserConditionVariable() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.0"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", 2.0); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } // Test SemanticVersionGTMatch returns null if given invalid value type @@ -993,7 +993,7 @@ public void testSemanticVersionGTMatchInvalidInput() { Map testAttributes = new HashMap(); testAttributes.put("version", false); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } // Test SemanticVersionGEMatch returns null if given invalid value type @@ -1002,7 +1002,7 @@ public void testSemanticVersionGEMatchInvalidInput() { Map testAttributes = new HashMap(); testAttributes.put("version", 2); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_ge", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } // Test SemanticVersionLTMatch returns null if given invalid value type @@ -1011,7 +1011,7 @@ public void testSemanticVersionLTMatchInvalidInput() { Map testAttributes = new HashMap(); testAttributes.put("version", 2); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_lt", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } // Test SemanticVersionLEMatch returns null if given invalid value type @@ -1020,7 +1020,7 @@ public void testSemanticVersionLEMatchInvalidInput() { Map testAttributes = new HashMap(); testAttributes.put("version", 2); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_le", "2.0.0"); - assertNull(testInstanceString.evaluate(null, testAttributes)); + assertNull(testInstanceString.evaluate(null, testAttributes, null)); } // Test if not same when targetVersion is only major.minor.patch and version is major.minor @@ -1029,7 +1029,7 @@ public void testIsSemanticNotSameConditionValueMajorMinorPatch() { Map testAttributes = new HashMap(); testAttributes.put("version", "1.2"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "1.2.0"); - assertFalse(testInstanceString.evaluate(null, testAttributes)); + assertFalse(testInstanceString.evaluate(null, testAttributes, null)); } // Test if same when target is only major but user condition checks only major.minor,patch @@ -1038,7 +1038,7 @@ public void testIsSemanticSameSingleDigit() { Map testAttributes = new HashMap(); testAttributes.put("version", "3.0.0"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "3"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test if greater when User value patch is greater even when its beta @@ -1047,7 +1047,7 @@ public void testIsSemanticGreaterWhenUserConditionComparesMajorMinorAndPatchVers Map testAttributes = new HashMap(); testAttributes.put("version", "3.1.1-beta"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "3.1.0"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test if greater when preRelease is greater alphabetically @@ -1056,7 +1056,7 @@ public void testIsSemanticGreaterWhenMajorMinorPatchReleaseVersionCharacter() { Map testAttributes = new HashMap(); testAttributes.put("version", "3.1.1-beta.y.1+1.1"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "3.1.1-beta.x.1+1.1"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test if greater when preRelease version number is greater @@ -1065,7 +1065,7 @@ public void testIsSemanticGreaterWhenMajorMinorPatchPreReleaseVersionNum() { Map testAttributes = new HashMap(); testAttributes.put("version", "3.1.1-beta.x.2+1.1"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "3.1.1-beta.x.1+1.1"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test if equals semantic version even when only same preRelease is passed in user attribute and no build meta @@ -1074,7 +1074,7 @@ public void testIsSemanticEqualWhenMajorMinorPatchPreReleaseVersionNum() { Map testAttributes = new HashMap(); testAttributes.put("version", "3.1.1-beta.x.1"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "3.1.1-beta.x.1"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test if not same @@ -1083,7 +1083,7 @@ public void testIsSemanticNotSameReturnsFalse() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.2"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "2.1.1"); - assertFalse(testInstanceString.evaluate(null, testAttributes)); + assertFalse(testInstanceString.evaluate(null, testAttributes, null)); } // Test when target is full semantic version major.minor.patch @@ -1092,7 +1092,7 @@ public void testIsSemanticSameFull() { Map testAttributes = new HashMap(); testAttributes.put("version", "3.0.1"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "3.0.1"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare less when user condition checks only major.minor @@ -1101,7 +1101,7 @@ public void testIsSemanticLess() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.6"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_lt", "2.2"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // When user condition checks major.minor but target is major.minor.patch then its equals @@ -1110,7 +1110,7 @@ public void testIsSemanticLessFalse() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.0"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_lt", "2.1"); - assertFalse(testInstanceString.evaluate(null, testAttributes)); + assertFalse(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare less when target is full major.minor.patch @@ -1119,7 +1119,7 @@ public void testIsSemanticFullLess() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.6"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_lt", "2.1.9"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare greater when user condition checks only major.minor @@ -1128,7 +1128,7 @@ public void testIsSemanticMore() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.3.6"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.2"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare greater when both are major.minor.patch-beta but target is greater than user condition @@ -1137,7 +1137,7 @@ public void testIsSemanticMoreWhenBeta() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.3.6-beta"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.3.5-beta"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare greater when target is major.minor.patch @@ -1146,7 +1146,7 @@ public void testIsSemanticFullMore() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.7"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.1.6"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare greater when target is major.minor.patch is smaller then it returns false @@ -1155,7 +1155,7 @@ public void testSemanticVersionGTFullMoreReturnsFalse() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.9"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.1.10"); - assertFalse(testInstanceString.evaluate(null, testAttributes)); + assertFalse(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare equal when both are exactly same - major.minor.patch-beta @@ -1164,7 +1164,7 @@ public void testIsSemanticFullEqual() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.9-beta"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_eq", "2.1.9-beta"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare equal when both major.minor.patch is same, but due to beta user condition is smaller @@ -1173,7 +1173,7 @@ public void testIsSemanticLessWhenBeta() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.9"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.1.9-beta"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare greater when target is major.minor.patch-beta and user condition only compares major.minor.patch @@ -1182,7 +1182,7 @@ public void testIsSemanticGreaterBeta() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.9"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_gt", "2.1.9-beta"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare equal when target is major.minor.patch @@ -1191,7 +1191,7 @@ public void testIsSemanticLessEqualsWhenEqualsReturnsTrue() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.9"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_le", "2.1.9"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare less when target is major.minor.patch @@ -1200,7 +1200,7 @@ public void testIsSemanticLessEqualsWhenLessReturnsTrue() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.132.9"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_le", "2.233.91"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare less when target is major.minor.patch @@ -1209,7 +1209,7 @@ public void testIsSemanticLessEqualsWhenGreaterReturnsFalse() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.233.91"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_le", "2.132.009"); - assertFalse(testInstanceString.evaluate(null, testAttributes)); + assertFalse(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare equal when target is major.minor.patch @@ -1218,7 +1218,7 @@ public void testIsSemanticGreaterEqualsWhenEqualsReturnsTrue() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.1.9"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_ge", "2.1.9"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare less when target is major.minor.patch @@ -1227,7 +1227,7 @@ public void testIsSemanticGreaterEqualsWhenLessReturnsTrue() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.233.91"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_ge", "2.132.9"); - assertTrue(testInstanceString.evaluate(null, testAttributes)); + assertTrue(testInstanceString.evaluate(null, testAttributes, null)); } // Test compare less when target is major.minor.patch @@ -1236,7 +1236,7 @@ public void testIsSemanticGreaterEqualsWhenLessReturnsFalse() { Map testAttributes = new HashMap(); testAttributes.put("version", "2.132.009"); UserAttribute testInstanceString = new UserAttribute("version", "custom_attribute", "semver_ge", "2.233.91"); - assertFalse(testInstanceString.evaluate(null, testAttributes)); + assertFalse(testInstanceString.evaluate(null, testAttributes, null)); } /** @@ -1245,7 +1245,7 @@ public void testIsSemanticGreaterEqualsWhenLessReturnsFalse() { @Test public void notConditionEvaluateNull() { NotCondition notCondition = new NotCondition(new NullCondition()); - assertNull(notCondition.evaluate(null, testUserAttributes)); + assertNull(notCondition.evaluate(null, testUserAttributes, null)); } /** @@ -1254,11 +1254,11 @@ public void notConditionEvaluateNull() { @Test public void notConditionEvaluateTrue() { UserAttribute userAttribute = mock(UserAttribute.class); - when(userAttribute.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute.evaluate(null, testUserAttributes, null)).thenReturn(false); NotCondition notCondition = new NotCondition(userAttribute); - assertTrue(notCondition.evaluate(null, testUserAttributes)); - verify(userAttribute, times(1)).evaluate(null, testUserAttributes); + assertTrue(notCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1267,11 +1267,11 @@ public void notConditionEvaluateTrue() { @Test public void notConditionEvaluateFalse() { UserAttribute userAttribute = mock(UserAttribute.class); - when(userAttribute.evaluate(null, testUserAttributes)).thenReturn(true); + when(userAttribute.evaluate(null, testUserAttributes, null)).thenReturn(true); NotCondition notCondition = new NotCondition(userAttribute); - assertFalse(notCondition.evaluate(null, testUserAttributes)); - verify(userAttribute, times(1)).evaluate(null, testUserAttributes); + assertFalse(notCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1280,20 +1280,20 @@ public void notConditionEvaluateFalse() { @Test public void orConditionEvaluateTrue() { UserAttribute userAttribute1 = mock(UserAttribute.class); - when(userAttribute1.evaluate(null, testUserAttributes)).thenReturn(true); + when(userAttribute1.evaluate(null, testUserAttributes, null)).thenReturn(true); UserAttribute userAttribute2 = mock(UserAttribute.class); - when(userAttribute2.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute2.evaluate(null, testUserAttributes, null)).thenReturn(false); List conditions = new ArrayList(); conditions.add(userAttribute1); conditions.add(userAttribute2); OrCondition orCondition = new OrCondition(conditions); - assertTrue(orCondition.evaluate(null, testUserAttributes)); - verify(userAttribute1, times(1)).evaluate(null, testUserAttributes); + assertTrue(orCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute1, times(1)).evaluate(null, testUserAttributes, null); // shouldn't be called due to short-circuiting in 'Or' evaluation - verify(userAttribute2, times(0)).evaluate(null, testUserAttributes); + verify(userAttribute2, times(0)).evaluate(null, testUserAttributes, null); } /** @@ -1302,20 +1302,20 @@ public void orConditionEvaluateTrue() { @Test public void orConditionEvaluateTrueWithNullAndTrue() { UserAttribute userAttribute1 = mock(UserAttribute.class); - when(userAttribute1.evaluate(null, testUserAttributes)).thenReturn(null); + when(userAttribute1.evaluate(null, testUserAttributes, null)).thenReturn(null); UserAttribute userAttribute2 = mock(UserAttribute.class); - when(userAttribute2.evaluate(null, testUserAttributes)).thenReturn(true); + when(userAttribute2.evaluate(null, testUserAttributes, null)).thenReturn(true); List conditions = new ArrayList(); conditions.add(userAttribute1); conditions.add(userAttribute2); OrCondition orCondition = new OrCondition(conditions); - assertTrue(orCondition.evaluate(null, testUserAttributes)); - verify(userAttribute1, times(1)).evaluate(null, testUserAttributes); + assertTrue(orCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute1, times(1)).evaluate(null, testUserAttributes, null); // shouldn't be called due to short-circuiting in 'Or' evaluation - verify(userAttribute2, times(1)).evaluate(null, testUserAttributes); + verify(userAttribute2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1324,20 +1324,20 @@ public void orConditionEvaluateTrueWithNullAndTrue() { @Test public void orConditionEvaluateNullWithNullAndFalse() { UserAttribute userAttribute1 = mock(UserAttribute.class); - when(userAttribute1.evaluate(null, testUserAttributes)).thenReturn(null); + when(userAttribute1.evaluate(null, testUserAttributes, null)).thenReturn(null); UserAttribute userAttribute2 = mock(UserAttribute.class); - when(userAttribute2.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute2.evaluate(null, testUserAttributes, null)).thenReturn(false); List conditions = new ArrayList(); conditions.add(userAttribute1); conditions.add(userAttribute2); OrCondition orCondition = new OrCondition(conditions); - assertNull(orCondition.evaluate(null, testUserAttributes)); - verify(userAttribute1, times(1)).evaluate(null, testUserAttributes); + assertNull(orCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute1, times(1)).evaluate(null, testUserAttributes, null); // shouldn't be called due to short-circuiting in 'Or' evaluation - verify(userAttribute2, times(1)).evaluate(null, testUserAttributes); + verify(userAttribute2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1346,20 +1346,20 @@ public void orConditionEvaluateNullWithNullAndFalse() { @Test public void orConditionEvaluateFalseWithFalseAndFalse() { UserAttribute userAttribute1 = mock(UserAttribute.class); - when(userAttribute1.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute1.evaluate(null, testUserAttributes, null)).thenReturn(false); UserAttribute userAttribute2 = mock(UserAttribute.class); - when(userAttribute2.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute2.evaluate(null, testUserAttributes, null)).thenReturn(false); List conditions = new ArrayList(); conditions.add(userAttribute1); conditions.add(userAttribute2); OrCondition orCondition = new OrCondition(conditions); - assertFalse(orCondition.evaluate(null, testUserAttributes)); - verify(userAttribute1, times(1)).evaluate(null, testUserAttributes); + assertFalse(orCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute1, times(1)).evaluate(null, testUserAttributes, null); // shouldn't be called due to short-circuiting in 'Or' evaluation - verify(userAttribute2, times(1)).evaluate(null, testUserAttributes); + verify(userAttribute2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1368,19 +1368,19 @@ public void orConditionEvaluateFalseWithFalseAndFalse() { @Test public void orConditionEvaluateFalse() { UserAttribute userAttribute1 = mock(UserAttribute.class); - when(userAttribute1.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute1.evaluate(null, testUserAttributes, null)).thenReturn(false); UserAttribute userAttribute2 = mock(UserAttribute.class); - when(userAttribute2.evaluate(null, testUserAttributes)).thenReturn(false); + when(userAttribute2.evaluate(null, testUserAttributes, null)).thenReturn(false); List conditions = new ArrayList(); conditions.add(userAttribute1); conditions.add(userAttribute2); OrCondition orCondition = new OrCondition(conditions); - assertFalse(orCondition.evaluate(null, testUserAttributes)); - verify(userAttribute1, times(1)).evaluate(null, testUserAttributes); - verify(userAttribute2, times(1)).evaluate(null, testUserAttributes); + assertFalse(orCondition.evaluate(null, testUserAttributes, null)); + verify(userAttribute1, times(1)).evaluate(null, testUserAttributes, null); + verify(userAttribute2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1389,19 +1389,19 @@ public void orConditionEvaluateFalse() { @Test public void andConditionEvaluateTrue() { OrCondition orCondition1 = mock(OrCondition.class); - when(orCondition1.evaluate(null, testUserAttributes)).thenReturn(true); + when(orCondition1.evaluate(null, testUserAttributes, null)).thenReturn(true); OrCondition orCondition2 = mock(OrCondition.class); - when(orCondition2.evaluate(null, testUserAttributes)).thenReturn(true); + when(orCondition2.evaluate(null, testUserAttributes, null)).thenReturn(true); List conditions = new ArrayList(); conditions.add(orCondition1); conditions.add(orCondition2); AndCondition andCondition = new AndCondition(conditions); - assertTrue(andCondition.evaluate(null, testUserAttributes)); - verify(orCondition1, times(1)).evaluate(null, testUserAttributes); - verify(orCondition2, times(1)).evaluate(null, testUserAttributes); + assertTrue(andCondition.evaluate(null, testUserAttributes, null)); + verify(orCondition1, times(1)).evaluate(null, testUserAttributes, null); + verify(orCondition2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1410,19 +1410,19 @@ public void andConditionEvaluateTrue() { @Test public void andConditionEvaluateFalseWithNullAndFalse() { OrCondition orCondition1 = mock(OrCondition.class); - when(orCondition1.evaluate(null, testUserAttributes)).thenReturn(null); + when(orCondition1.evaluate(null, testUserAttributes, null)).thenReturn(null); OrCondition orCondition2 = mock(OrCondition.class); - when(orCondition2.evaluate(null, testUserAttributes)).thenReturn(false); + when(orCondition2.evaluate(null, testUserAttributes, null)).thenReturn(false); List conditions = new ArrayList(); conditions.add(orCondition1); conditions.add(orCondition2); AndCondition andCondition = new AndCondition(conditions); - assertFalse(andCondition.evaluate(null, testUserAttributes)); - verify(orCondition1, times(1)).evaluate(null, testUserAttributes); - verify(orCondition2, times(1)).evaluate(null, testUserAttributes); + assertFalse(andCondition.evaluate(null, testUserAttributes, null)); + verify(orCondition1, times(1)).evaluate(null, testUserAttributes, null); + verify(orCondition2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1431,19 +1431,19 @@ public void andConditionEvaluateFalseWithNullAndFalse() { @Test public void andConditionEvaluateNullWithNullAndTrue() { OrCondition orCondition1 = mock(OrCondition.class); - when(orCondition1.evaluate(null, testUserAttributes)).thenReturn(null); + when(orCondition1.evaluate(null, testUserAttributes, null)).thenReturn(null); OrCondition orCondition2 = mock(OrCondition.class); - when(orCondition2.evaluate(null, testUserAttributes)).thenReturn(true); + when(orCondition2.evaluate(null, testUserAttributes, null)).thenReturn(true); List conditions = new ArrayList(); conditions.add(orCondition1); conditions.add(orCondition2); AndCondition andCondition = new AndCondition(conditions); - assertNull(andCondition.evaluate(null, testUserAttributes)); - verify(orCondition1, times(1)).evaluate(null, testUserAttributes); - verify(orCondition2, times(1)).evaluate(null, testUserAttributes); + assertNull(andCondition.evaluate(null, testUserAttributes, null)); + verify(orCondition1, times(1)).evaluate(null, testUserAttributes, null); + verify(orCondition2, times(1)).evaluate(null, testUserAttributes, null); } /** @@ -1452,10 +1452,10 @@ public void andConditionEvaluateNullWithNullAndTrue() { @Test public void andConditionEvaluateFalse() { OrCondition orCondition1 = mock(OrCondition.class); - when(orCondition1.evaluate(null, testUserAttributes)).thenReturn(false); + when(orCondition1.evaluate(null, testUserAttributes, null)).thenReturn(false); OrCondition orCondition2 = mock(OrCondition.class); - when(orCondition2.evaluate(null, testUserAttributes)).thenReturn(true); + when(orCondition2.evaluate(null, testUserAttributes, null)).thenReturn(true); // and[false, true] List conditions = new ArrayList(); @@ -1463,13 +1463,13 @@ public void andConditionEvaluateFalse() { conditions.add(orCondition2); AndCondition andCondition = new AndCondition(conditions); - assertFalse(andCondition.evaluate(null, testUserAttributes)); - verify(orCondition1, times(1)).evaluate(null, testUserAttributes); + assertFalse(andCondition.evaluate(null, testUserAttributes, null)); + verify(orCondition1, times(1)).evaluate(null, testUserAttributes, null); // shouldn't be called due to short-circuiting in 'And' evaluation - verify(orCondition2, times(0)).evaluate(null, testUserAttributes); + verify(orCondition2, times(0)).evaluate(null, testUserAttributes, null); OrCondition orCondition3 = mock(OrCondition.class); - when(orCondition3.evaluate(null, testUserAttributes)).thenReturn(null); + when(orCondition3.evaluate(null, testUserAttributes, null)).thenReturn(null); // and[null, false] List conditions2 = new ArrayList(); @@ -1477,7 +1477,7 @@ public void andConditionEvaluateFalse() { conditions2.add(orCondition1); AndCondition andCondition2 = new AndCondition(conditions2); - assertFalse(andCondition2.evaluate(null, testUserAttributes)); + assertFalse(andCondition2.evaluate(null, testUserAttributes, null)); // and[true, false, null] List conditions3 = new ArrayList(); @@ -1486,7 +1486,7 @@ public void andConditionEvaluateFalse() { conditions3.add(orCondition1); AndCondition andCondition3 = new AndCondition(conditions3); - assertFalse(andCondition3.evaluate(null, testUserAttributes)); + assertFalse(andCondition3.evaluate(null, testUserAttributes, null)); } /** @@ -1518,8 +1518,8 @@ public void nullValueEvaluate() { attributeValue ); - assertNull(nullValueAttribute.evaluate(null, Collections.emptyMap())); - assertNull(nullValueAttribute.evaluate(null, Collections.singletonMap(attributeName, attributeValue))); - assertNull(nullValueAttribute.evaluate(null, (Collections.singletonMap(attributeName, "")))); + assertNull(nullValueAttribute.evaluate(null, Collections.emptyMap(), null)); + assertNull(nullValueAttribute.evaluate(null, Collections.singletonMap(attributeName, attributeValue), null)); + assertNull(nullValueAttribute.evaluate(null, (Collections.singletonMap(attributeName, "")), null)); } } From f3ae197dbe05dd9fa018d17c15db2e481e5d6a12 Mon Sep 17 00:00:00 2001 From: mnoman09 Date: Tue, 7 Jun 2022 00:08:27 +0500 Subject: [PATCH 2/6] Added unit tests --- .../config/audience/match/QualifiedMatch.java | 22 +- .../AudienceConditionEvaluationTest.java | 263 ++++++++++++++++++ .../audience/match/QualifiedMatchTest.java | 68 +++++ 3 files changed, 348 insertions(+), 5 deletions(-) create mode 100644 core-api/src/test/java/com/optimizely/ab/config/audience/match/QualifiedMatchTest.java diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java b/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java index 95d823d47..13b7ef62b 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/match/QualifiedMatch.java @@ -1,3 +1,19 @@ +/** + * + * Copyright 2022, Optimizely and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.optimizely.ab.config.audience.match; import javax.annotation.Nullable; @@ -14,10 +30,6 @@ public Boolean eval(Object conditionValue, Object attributeValue) throws Unexpec return null; } - try { - return ((List)attributeValue).contains(conditionValue.toString()); - } catch (Exception e) { - return null; - } + return ((List)attributeValue).contains(conditionValue.toString()); } } diff --git a/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java b/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java index 7477c3933..3cc94ef91 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/audience/AudienceConditionEvaluationTest.java @@ -1522,4 +1522,267 @@ public void nullValueEvaluate() { assertNull(nullValueAttribute.evaluate(null, Collections.singletonMap(attributeName, attributeValue), null)); assertNull(nullValueAttribute.evaluate(null, (Collections.singletonMap(attributeName, "")), null)); } + + /** + * Verify that with odp segment evaluator single ODP audience evaluates true + */ + @Test + public void singleODPAudienceEvaluateTrueIfSegmentExist() throws Exception { + + UserAttribute testInstanceSingleAudience = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-1"); + List userConditions = new ArrayList<>(); + userConditions.add(testInstanceSingleAudience); + AndCondition andCondition = new AndCondition(userConditions); + + // Should evaluate true if qualified segment exist + List qualifiedSegments = Collections.singletonList("odp-segment-1"); + assertTrue(andCondition.evaluate(null, null, qualifiedSegments)); + } + + /** + * Verify that with odp segment evaluator single ODP audience evaluates false + */ + @Test + public void singleODPAudienceEvaluateFalseIfSegmentNotExist() throws Exception { + + UserAttribute testInstanceSingleAudience = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-1"); + List userConditions = new ArrayList<>(); + userConditions.add(testInstanceSingleAudience); + AndCondition andCondition = new AndCondition(userConditions); + + // Should evaluate false if qualified segment does not exist + List qualifiedSegments = Collections.singletonList("odp-segment-2"); + assertFalse(andCondition.evaluate(null, null, qualifiedSegments)); + } + + /** + * Verify that with odp segment evaluator single ODP audience evaluates false when segments not provided + */ + @Test + public void singleODPAudienceEvaluateFalseIfSegmentNotProvided() throws Exception { + + UserAttribute testInstanceSingleAudience = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-1"); + List userConditions = new ArrayList<>(); + userConditions.add(testInstanceSingleAudience); + AndCondition andCondition = new AndCondition(userConditions); + + // Should evaluate false if qualified segment does not exist + List qualifiedSegments = Collections.emptyList(); + assertFalse(andCondition.evaluate(null, null, qualifiedSegments)); + } + + /** + * Verify that with odp segment evaluator evaluates multiple ODP audience true when segment provided exist + */ + @Test + public void singleODPAudienceEvaluateMultipleOdpConditions() { + Condition andCondition = createMultipleConditionAudienceAndOrODP(); + // Should evaluate correctly based on the given segments + List qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + + assertTrue(andCondition.evaluate(null, null, qualifiedSegments)); + + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-4"); + + assertTrue(andCondition.evaluate(null, null, qualifiedSegments)); + + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + + assertTrue(andCondition.evaluate(null, null, qualifiedSegments)); + } + + /** + * Verify that with odp segment evaluator evaluates multiple ODP audience true when segment provided exist + */ + @Test + public void singleODPAudienceEvaluateMultipleOdpConditionsEvaluateFalse() { + Condition andCondition = createMultipleConditionAudienceAndOrODP(); + // Should evaluate correctly based on the given segments + List qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + + assertFalse(andCondition.evaluate(null, null, qualifiedSegments)); + + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + + assertFalse(andCondition.evaluate(null, null, qualifiedSegments)); + } + + /** + * Verify that with odp segment evaluator evaluates multiple ODP audience with multiple conditions true or false when segment conditions meet + */ + @Test + public void multipleAudienceEvaluateMultipleOdpConditionsEvaluate() { + // ["and", "1", "2"] + List audience1And2 = new ArrayList<>(); + audience1And2.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-1")); + audience1And2.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-2")); + AndCondition audienceCondition1 = new AndCondition(audience1And2); + + // ["and", "3", "4"] + List audience3And4 = new ArrayList<>(); + audience3And4.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-3")); + audience3And4.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-4")); + AndCondition audienceCondition2 = new AndCondition(audience3And4); + + // ["or", "5", "6"] + List audience5And6 = new ArrayList<>(); + audience5And6.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-5")); + audience5And6.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-6")); + OrCondition audienceCondition3 = new OrCondition(audience5And6); + + + //Scenario 1- ['or', '1', '2', '3'] + List conditions = new ArrayList<>(); + conditions.add(audienceCondition1); + conditions.add(audienceCondition2); + conditions.add(audienceCondition3); + + OrCondition implicitOr = new OrCondition(conditions); + // Should evaluate correctly based on the given segments + List qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + assertTrue(implicitOr.evaluate(null, null, qualifiedSegments)); + + + //Scenario 2- ['and', '1', '2', '3'] + AndCondition implicitAnd = new AndCondition(conditions); + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + assertFalse(implicitAnd.evaluate(null, null, qualifiedSegments)); + + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + qualifiedSegments.add("odp-segment-6"); + assertTrue(implicitAnd.evaluate(null, null, qualifiedSegments)); + + + ////Scenario 3- ['and', '1', '2',['not', '3']] + conditions = new ArrayList<>(); + conditions.add(audienceCondition1); + conditions.add(audienceCondition2); + conditions.add(new NotCondition(audienceCondition3)); + implicitAnd = new AndCondition(conditions); + + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + assertTrue(implicitAnd.evaluate(null, null, qualifiedSegments)); + + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + qualifiedSegments.add("odp-segment-5"); + assertFalse(implicitAnd.evaluate(null, null, qualifiedSegments)); + } + + /** + * Verify that with odp segment evaluator evaluates multiple ODP audience with multiple type of evaluators + */ + @Test + public void multipleAudienceEvaluateMultipleOdpConditionsEvaluateWithMultipleTypeOfEvaluator() { + // ["and", "1", "2"] + List audience1And2 = new ArrayList<>(); + audience1And2.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-1")); + audience1And2.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-2")); + AndCondition audienceCondition1 = new AndCondition(audience1And2); + + // ["and", "3", "4"] + List audience3And4 = new ArrayList<>(); + audience3And4.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-3")); + audience3And4.add(new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-4")); + AndCondition audienceCondition2 = new AndCondition(audience3And4); + + // ["or", "chrome", "safari"] + List chromeUserAudience = new ArrayList<>(); + chromeUserAudience.add(new UserAttribute("browser_type", "custom_attribute", "exact", "chrome")); + chromeUserAudience.add(new UserAttribute("browser_type", "custom_attribute", "exact", "safari")); + OrCondition audienceCondition3 = new OrCondition(chromeUserAudience); + + + //Scenario 1- ['or', '1', '2', '3'] + List conditions = new ArrayList<>(); + conditions.add(audienceCondition1); + conditions.add(audienceCondition2); + conditions.add(audienceCondition3); + + OrCondition implicitOr = new OrCondition(conditions); + // Should evaluate correctly based on the given segments + List qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + assertTrue(implicitOr.evaluate(null, null, qualifiedSegments)); + + + //Scenario 2- ['and', '1', '2', '3'] + AndCondition implicitAnd = new AndCondition(conditions); + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + assertFalse(implicitAnd.evaluate(null, Collections.singletonMap("browser_type", "chrome"), qualifiedSegments)); + + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + assertTrue(implicitAnd.evaluate(null, Collections.singletonMap("browser_type", "chrome"), qualifiedSegments)); + + // Should evaluate correctly based on the given segments + qualifiedSegments = new ArrayList<>(); + qualifiedSegments.add("odp-segment-1"); + qualifiedSegments.add("odp-segment-2"); + qualifiedSegments.add("odp-segment-3"); + qualifiedSegments.add("odp-segment-4"); + assertFalse(implicitAnd.evaluate(null, Collections.singletonMap("browser_type", "not_chrome"), qualifiedSegments)); + } + + public Condition createMultipleConditionAudienceAndOrODP() { + UserAttribute testInstanceSingleAudience1 = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-1"); + UserAttribute testInstanceSingleAudience2 = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-2"); + UserAttribute testInstanceSingleAudience3 = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-3"); + UserAttribute testInstanceSingleAudience4 = new UserAttribute("odp.audiences", "third_party_dimension", "qualified", "odp-segment-4"); + + List userConditionsOR = new ArrayList<>(); + userConditionsOR.add(testInstanceSingleAudience3); + userConditionsOR.add(testInstanceSingleAudience4); + OrCondition orCondition = new OrCondition(userConditionsOR); + List userConditionsAnd = new ArrayList<>(); + userConditionsAnd.add(testInstanceSingleAudience1); + userConditionsAnd.add(testInstanceSingleAudience2); + userConditionsAnd.add(orCondition); + AndCondition andCondition = new AndCondition(userConditionsAnd); + + return andCondition; + } } diff --git a/core-api/src/test/java/com/optimizely/ab/config/audience/match/QualifiedMatchTest.java b/core-api/src/test/java/com/optimizely/ab/config/audience/match/QualifiedMatchTest.java new file mode 100644 index 000000000..6f72345aa --- /dev/null +++ b/core-api/src/test/java/com/optimizely/ab/config/audience/match/QualifiedMatchTest.java @@ -0,0 +1,68 @@ +/** + * + * Copyright 2022, Optimizely and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.optimizely.ab.config.audience.match; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; + +public class QualifiedMatchTest { + + private QualifiedMatch match; + private static final List INVALIDS = Collections.unmodifiableList(Arrays.asList(new byte[0], new Object(), null)); + + @Before + public void setUp() { + match = new QualifiedMatch(); + } + + @Test + public void testInvalidConditionValues() { + for (Object invalid : INVALIDS) { + try { + match.eval(invalid, "valid"); + fail("should have raised exception"); + } catch (UnexpectedValueTypeException e) { + //pass + } + } + } + + @Test + public void testMismatchClasses() throws Exception { + assertNull(match.eval("odp-segment-1", "false")); + assertNull(match.eval("odp-segment-1", null)); + } + + @Test + public void testValueContains() throws Exception { + assertTrue(match.eval("odp-segment-1", Collections.singletonList("odp-segment-1"))); + assertFalse(match.eval("odp-segment-1", Collections.singletonList("odp-segment-2"))); + } + + @Test(expected = UnexpectedValueTypeException.class) + public void testUnknownValueType() throws UnexpectedValueTypeException { + match.eval(1, Collections.singletonList("odp-segment-1")); + } + +} From e25a99980abe649e5586f3e3abc1a7552f8e1fee Mon Sep 17 00:00:00 2001 From: mnoman09 Date: Tue, 7 Jun 2022 00:16:33 +0500 Subject: [PATCH 3/6] Updated headers --- .../src/main/java/com/optimizely/ab/OptimizelyUserContext.java | 3 +-- .../com/optimizely/ab/config/audience/AudienceIdCondition.java | 2 +- .../main/java/com/optimizely/ab/config/audience/Condition.java | 2 +- .../java/com/optimizely/ab/config/audience/EmptyCondition.java | 2 +- .../java/com/optimizely/ab/config/audience/NotCondition.java | 2 +- .../java/com/optimizely/ab/config/audience/NullCondition.java | 2 +- .../java/com/optimizely/ab/config/audience/OrCondition.java | 2 +- .../java/com/optimizely/ab/config/audience/UserAttribute.java | 2 +- .../com/optimizely/ab/config/audience/match/MatchRegistry.java | 2 +- .../main/java/com/optimizely/ab/internal/ExperimentUtils.java | 2 +- 10 files changed, 10 insertions(+), 11 deletions(-) diff --git a/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java b/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java index 33d63a6f3..f264c412c 100644 --- a/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java +++ b/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java @@ -16,7 +16,6 @@ */ package com.optimizely.ab; -import com.optimizely.ab.config.Variation; import com.optimizely.ab.optimizelydecision.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +36,7 @@ public class OptimizelyUserContext { private final Map attributes; @Nonnull - private List qualifiedSegments; + private final List qualifiedSegments; @Nonnull private final Optimizely optimizely; diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java index 916eb487b..57e665ae7 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/AudienceIdCondition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2018-2021, Optimizely and contributors + * Copyright 2018-2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java index 8c37b3b71..d9e6d1cbf 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/Condition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2018, Optimizely and contributors + * Copyright 2016-2018, 2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java index 737a9bbf7..3f4a70026 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/EmptyCondition.java @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely Inc. and contributors + * Copyright 2019, 2022, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java index 0d1af0d9a..a4b5addf3 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/NotCondition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2019, Optimizely and contributors + * Copyright 2016-2019, 2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java index 1b59dba35..06d6481e3 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/NullCondition.java @@ -1,5 +1,5 @@ /** - * Copyright 2019, Optimizely Inc. and contributors + * Copyright 2019, 2022, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java b/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java index 8d6cc25ba..ccd991fad 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/OrCondition.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2019, Optimizely and contributors + * Copyright 2016-2019, 2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java index a32490083..89ed776f9 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2020, Optimizely and contributors + * Copyright 2016-2020, 2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java b/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java index 467751e2d..5f8525a9e 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/match/MatchRegistry.java @@ -1,6 +1,6 @@ /** * - * Copyright 2020-2021, Optimizely and contributors + * Copyright 2020-2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java b/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java index 59741f12f..2bc7179f9 100644 --- a/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java +++ b/core-api/src/main/java/com/optimizely/ab/internal/ExperimentUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017-2021, Optimizely and contributors + * Copyright 2017-2022, Optimizely and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 49bc6370810da9a8d5d59dc191bf5ed0ed365b68 Mon Sep 17 00:00:00 2001 From: mnoman09 Date: Wed, 8 Jun 2022 20:08:18 +0500 Subject: [PATCH 4/6] refactored optimizelyUsercontext constructor resolved issue with assert --- .../optimizely/ab/OptimizelyUserContext.java | 9 +---- .../ab/config/audience/AttributeType.java | 33 +++++++++++++++++++ .../ab/config/audience/UserAttribute.java | 12 ++++++- .../DatafileProjectConfigTestUtils.java | 3 +- 4 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 core-api/src/main/java/com/optimizely/ab/config/audience/AttributeType.java diff --git a/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java b/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java index f264c412c..e4a85d3b6 100644 --- a/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java +++ b/core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java @@ -46,14 +46,7 @@ public class OptimizelyUserContext { public OptimizelyUserContext(@Nonnull Optimizely optimizely, @Nonnull String userId, @Nonnull Map attributes) { - this.optimizely = optimizely; - this.userId = userId; - if (attributes != null) { - this.attributes = Collections.synchronizedMap(new HashMap<>(attributes)); - } else { - this.attributes = Collections.synchronizedMap(new HashMap<>()); - } - this.qualifiedSegments = Collections.synchronizedList(new ArrayList<>()); + this(optimizely, userId, attributes, Collections.EMPTY_MAP); } public OptimizelyUserContext(@Nonnull Optimizely optimizely, diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/AttributeType.java b/core-api/src/main/java/com/optimizely/ab/config/audience/AttributeType.java new file mode 100644 index 000000000..926e5cca4 --- /dev/null +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/AttributeType.java @@ -0,0 +1,33 @@ +/** + * + * Copyright 2022, Optimizely and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.optimizely.ab.config.audience; + +public enum AttributeType { + CUSTOM_ATTRIBUTE("custom_attribute"), + THIRD_PARTY_DIMENSION("third_party_dimension"); + + private final String key; + + AttributeType(String key) { + this.key = key; + } + + @Override + public String toString() { + return key; + } +} diff --git a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java index 89ed776f9..527ecd5eb 100644 --- a/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java +++ b/core-api/src/main/java/com/optimizely/ab/config/audience/UserAttribute.java @@ -31,6 +31,9 @@ import java.util.List; import java.util.Map; +import static com.optimizely.ab.config.audience.AttributeType.CUSTOM_ATTRIBUTE; +import static com.optimizely.ab.config.audience.AttributeType.THIRD_PARTY_DIMENSION; + /** * Represents a user attribute instance within an audience's conditions. */ @@ -77,7 +80,7 @@ public Boolean evaluate(ProjectConfig config, Map attributes, List attributes, List actual, List assertThat(actualExperiment.getGroupId(), is(expectedExperiment.getGroupId())); assertThat(actualExperiment.getStatus(), is(expectedExperiment.getStatus())); assertThat(actualExperiment.getAudienceIds(), is(expectedExperiment.getAudienceIds())); - assertThat(actualExperiment.getAudienceConditions(), is(expectedExperiment.getAudienceConditions())); + Assert.assertEquals(actualExperiment.getAudienceConditions(), expectedExperiment.getAudienceConditions()); assertThat(actualExperiment.getUserIdToVariationKeyMap(), is(expectedExperiment.getUserIdToVariationKeyMap())); From 794e0822fe5cbf33f465999a6ec9eb3e5a233740 Mon Sep 17 00:00:00 2001 From: mnoman09 Date: Wed, 8 Jun 2022 20:23:47 +0500 Subject: [PATCH 5/6] test --- .../ab/config/DatafileProjectConfigTest.java | 9 +-- .../DatafileProjectConfigTestUtils.java | 70 +++++++++---------- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java index 41b02ea91..0f38af868 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java @@ -33,6 +33,7 @@ import com.optimizely.ab.internal.LogbackVerifier; import com.optimizely.ab.internal.ControlAttribute; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -74,11 +75,11 @@ public void verifyGetExperimentsForValidEvent() throws Exception { Experiment experiment118 = projectConfig.getExperimentIdMapping().get("118"); List expectedSingleExperiment = asList(experiment223); List actualSingleExperiment = projectConfig.getExperimentsForEventKey("clicked_cart"); - assertThat(actualSingleExperiment, is(expectedSingleExperiment)); + Assert.assertEquals(actualSingleExperiment, expectedSingleExperiment); List expectedMultipleExperiments = asList(experiment118, experiment223); List actualMultipleExperiments = projectConfig.getExperimentsForEventKey("clicked_purchase"); - assertThat(actualMultipleExperiments, is(expectedMultipleExperiments)); + Assert.assertEquals(actualMultipleExperiments, expectedMultipleExperiments); } /** @@ -89,7 +90,7 @@ public void verifyGetExperimentsForValidEvent() throws Exception { public void verifyGetExperimentsForInvalidEvent() throws Exception { List expectedExperiments = Collections.emptyList(); List actualExperiments = projectConfig.getExperimentsForEventKey("a_fake_event"); - assertThat(actualExperiments, is(expectedExperiments)); + Assert.assertEquals(actualExperiments, expectedExperiments); } /** @@ -113,7 +114,7 @@ public void verifyGetAudienceConditionsFromValidId() throws Exception { Condition expectedConditions = new AndCondition(andList); Condition actualConditions = projectConfig.getAudience("100").getConditions(); - assertThat(actualConditions, is(expectedConditions)); + Assert.assertEquals(actualConditions, expectedConditions); } /** diff --git a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java index 39470dc41..354777ba7 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java +++ b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java @@ -462,10 +462,10 @@ public static void verifyProjectConfig(@CheckForNull ProjectConfig actual, @Nonn assertNotNull(actual); // verify the project-level values - assertThat(actual.getAccountId(), is(expected.getAccountId())); - assertThat(actual.getProjectId(), is(expected.getProjectId())); - assertThat(actual.getVersion(), is(expected.getVersion())); - assertThat(actual.getRevision(), is(expected.getRevision())); + Assert.assertEquals(actual.getAccountId(), expected.getAccountId()); + Assert.assertEquals(actual.getProjectId(), expected.getProjectId()); + Assert.assertEquals(actual.getVersion(), expected.getVersion()); + Assert.assertEquals(actual.getRevision(), expected.getRevision()); verifyAttributes(actual.getAttributes(), expected.getAttributes()); verifyAudiences(actual.getAudiences(), expected.getAudiences()); @@ -481,20 +481,20 @@ public static void verifyProjectConfig(@CheckForNull ProjectConfig actual, @Nonn * Asserts that the provided experiment configs are equivalent. */ private static void verifyExperiments(List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { Experiment actualExperiment = actual.get(i); Experiment expectedExperiment = expected.get(i); - assertThat(actualExperiment.getId(), is(expectedExperiment.getId())); - assertThat(actualExperiment.getKey(), is(expectedExperiment.getKey())); - assertThat(actualExperiment.getGroupId(), is(expectedExperiment.getGroupId())); - assertThat(actualExperiment.getStatus(), is(expectedExperiment.getStatus())); - assertThat(actualExperiment.getAudienceIds(), is(expectedExperiment.getAudienceIds())); + Assert.assertEquals(actualExperiment.getId(), expectedExperiment.getId()); + Assert.assertEquals(actualExperiment.getKey(), expectedExperiment.getKey()); + Assert.assertEquals(actualExperiment.getGroupId(), expectedExperiment.getGroupId()); + Assert.assertEquals(actualExperiment.getStatus(), expectedExperiment.getStatus()); + Assert.assertEquals(actualExperiment.getAudienceIds(), expectedExperiment.getAudienceIds()); Assert.assertEquals(actualExperiment.getAudienceConditions(), expectedExperiment.getAudienceConditions()); - assertThat(actualExperiment.getUserIdToVariationKeyMap(), - is(expectedExperiment.getUserIdToVariationKeyMap())); + Assert.assertEquals(actualExperiment.getUserIdToVariationKeyMap(), + expectedExperiment.getUserIdToVariationKeyMap()); verifyVariations(actualExperiment.getVariations(), expectedExperiment.getVariations()); verifyTrafficAllocations(actualExperiment.getTrafficAllocation(), @@ -516,14 +516,14 @@ private static void verifyFeatureFlags(List actual, List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { Variation actualVariation = actual.get(i); Variation expectedVariation = expected.get(i); - assertThat(actualVariation.getId(), is(expectedVariation.getId())); - assertThat(actualVariation.getKey(), is(expectedVariation.getKey())); + Assert.assertEquals(actualVariation.getId(), expectedVariation.getId()); + Assert.assertEquals(actualVariation.getKey(), expectedVariation.getKey()); verifyFeatureVariableInstances(actualVariation.getFeatureVariableUsageInstances(), expectedVariation.getFeatureVariableUsageInstances()); } @@ -534,13 +534,13 @@ private static void verifyVariations(List actual, List exp */ private static void verifyTrafficAllocations(List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { TrafficAllocation actualDistribution = actual.get(i); TrafficAllocation expectedDistribution = expected.get(i); - assertThat(actualDistribution.getEntityId(), is(expectedDistribution.getEntityId())); + Assert.assertEquals(actualDistribution.getEntityId(), expectedDistribution.getEntityId()); assertEquals("expectedDistribution: " + expectedDistribution.toString() + "is not equal to the actualDistribution: " + actualDistribution.toString(), expectedDistribution.getEndOfRange(), actualDistribution.getEndOfRange()); @@ -551,15 +551,15 @@ private static void verifyTrafficAllocations(List actual, * Asserts that the provided attributes configs are equivalent. */ private static void verifyAttributes(List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { Attribute actualAttribute = actual.get(i); Attribute expectedAttribute = expected.get(i); - assertThat(actualAttribute.getId(), is(expectedAttribute.getId())); - assertThat(actualAttribute.getKey(), is(expectedAttribute.getKey())); - assertThat(actualAttribute.getSegmentId(), is(expectedAttribute.getSegmentId())); + Assert.assertEquals(actualAttribute.getId(), expectedAttribute.getId()); + Assert.assertEquals(actualAttribute.getKey(), expectedAttribute.getKey()); + Assert.assertEquals(actualAttribute.getSegmentId(), expectedAttribute.getSegmentId()); } } @@ -567,15 +567,15 @@ private static void verifyAttributes(List actual, List exp * Asserts that the provided event configs are equivalent. */ private static void verifyEvents(List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { EventType actualEvent = actual.get(i); EventType expectedEvent = expected.get(i); - assertThat(actualEvent.getExperimentIds(), is(expectedEvent.getExperimentIds())); - assertThat(actualEvent.getId(), is(expectedEvent.getId())); - assertThat(actualEvent.getKey(), is(expectedEvent.getKey())); + Assert.assertEquals(actualEvent.getExperimentIds(), expectedEvent.getExperimentIds()); + Assert.assertEquals(actualEvent.getId(), expectedEvent.getId()); + Assert.assertEquals(actualEvent.getKey(), expectedEvent.getKey()); } } @@ -583,15 +583,15 @@ private static void verifyEvents(List actual, List expecte * Asserts that the provided audience configs are equivalent. */ private static void verifyAudiences(List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { Audience actualAudience = actual.get(i); Audience expectedAudience = expected.get(i); - assertThat(actualAudience.getId(), is(expectedAudience.getId())); - assertThat(actualAudience.getKey(), is(expectedAudience.getKey())); - assertThat(actualAudience.getConditions(), is(expectedAudience.getConditions())); + Assert.assertEquals(actualAudience.getId(), expectedAudience.getId()); + Assert.assertEquals(actualAudience.getKey(), expectedAudience.getKey()); + Assert.assertEquals(actualAudience.getConditions(), expectedAudience.getConditions()); } } @@ -599,14 +599,14 @@ private static void verifyAudiences(List actual, List expect * Assert that the provided group configs are equivalent. */ private static void verifyGroups(List actual, List expected) { - assertThat(actual.size(), is(expected.size())); + Assert.assertEquals(actual.size(), expected.size()); for (int i = 0; i < actual.size(); i++) { Group actualGroup = actual.get(i); Group expectedGroup = expected.get(i); - assertThat(actualGroup.getId(), is(expectedGroup.getId())); - assertThat(actualGroup.getPolicy(), is(expectedGroup.getPolicy())); + Assert.assertEquals(actualGroup.getId(), expectedGroup.getId()); + Assert.assertEquals(actualGroup.getPolicy(), expectedGroup.getPolicy()); verifyTrafficAllocations(actualGroup.getTrafficAllocation(), expectedGroup.getTrafficAllocation()); verifyExperiments(actualGroup.getExperiments(), expectedGroup.getExperiments()); } @@ -637,14 +637,14 @@ private static void verifyFeatureVariableInstances(List Date: Wed, 8 Jun 2022 20:49:12 +0500 Subject: [PATCH 6/6] Revert "test" This reverts commit 794e0822fe5cbf33f465999a6ec9eb3e5a233740. --- .../ab/config/DatafileProjectConfigTest.java | 9 ++- .../DatafileProjectConfigTestUtils.java | 70 +++++++++---------- 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java index 0f38af868..41b02ea91 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java +++ b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTest.java @@ -33,7 +33,6 @@ import com.optimizely.ab.internal.LogbackVerifier; import com.optimizely.ab.internal.ControlAttribute; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -75,11 +74,11 @@ public void verifyGetExperimentsForValidEvent() throws Exception { Experiment experiment118 = projectConfig.getExperimentIdMapping().get("118"); List expectedSingleExperiment = asList(experiment223); List actualSingleExperiment = projectConfig.getExperimentsForEventKey("clicked_cart"); - Assert.assertEquals(actualSingleExperiment, expectedSingleExperiment); + assertThat(actualSingleExperiment, is(expectedSingleExperiment)); List expectedMultipleExperiments = asList(experiment118, experiment223); List actualMultipleExperiments = projectConfig.getExperimentsForEventKey("clicked_purchase"); - Assert.assertEquals(actualMultipleExperiments, expectedMultipleExperiments); + assertThat(actualMultipleExperiments, is(expectedMultipleExperiments)); } /** @@ -90,7 +89,7 @@ public void verifyGetExperimentsForValidEvent() throws Exception { public void verifyGetExperimentsForInvalidEvent() throws Exception { List expectedExperiments = Collections.emptyList(); List actualExperiments = projectConfig.getExperimentsForEventKey("a_fake_event"); - Assert.assertEquals(actualExperiments, expectedExperiments); + assertThat(actualExperiments, is(expectedExperiments)); } /** @@ -114,7 +113,7 @@ public void verifyGetAudienceConditionsFromValidId() throws Exception { Condition expectedConditions = new AndCondition(andList); Condition actualConditions = projectConfig.getAudience("100").getConditions(); - Assert.assertEquals(actualConditions, expectedConditions); + assertThat(actualConditions, is(expectedConditions)); } /** diff --git a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java index 354777ba7..39470dc41 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java +++ b/core-api/src/test/java/com/optimizely/ab/config/DatafileProjectConfigTestUtils.java @@ -462,10 +462,10 @@ public static void verifyProjectConfig(@CheckForNull ProjectConfig actual, @Nonn assertNotNull(actual); // verify the project-level values - Assert.assertEquals(actual.getAccountId(), expected.getAccountId()); - Assert.assertEquals(actual.getProjectId(), expected.getProjectId()); - Assert.assertEquals(actual.getVersion(), expected.getVersion()); - Assert.assertEquals(actual.getRevision(), expected.getRevision()); + assertThat(actual.getAccountId(), is(expected.getAccountId())); + assertThat(actual.getProjectId(), is(expected.getProjectId())); + assertThat(actual.getVersion(), is(expected.getVersion())); + assertThat(actual.getRevision(), is(expected.getRevision())); verifyAttributes(actual.getAttributes(), expected.getAttributes()); verifyAudiences(actual.getAudiences(), expected.getAudiences()); @@ -481,20 +481,20 @@ public static void verifyProjectConfig(@CheckForNull ProjectConfig actual, @Nonn * Asserts that the provided experiment configs are equivalent. */ private static void verifyExperiments(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { Experiment actualExperiment = actual.get(i); Experiment expectedExperiment = expected.get(i); - Assert.assertEquals(actualExperiment.getId(), expectedExperiment.getId()); - Assert.assertEquals(actualExperiment.getKey(), expectedExperiment.getKey()); - Assert.assertEquals(actualExperiment.getGroupId(), expectedExperiment.getGroupId()); - Assert.assertEquals(actualExperiment.getStatus(), expectedExperiment.getStatus()); - Assert.assertEquals(actualExperiment.getAudienceIds(), expectedExperiment.getAudienceIds()); + assertThat(actualExperiment.getId(), is(expectedExperiment.getId())); + assertThat(actualExperiment.getKey(), is(expectedExperiment.getKey())); + assertThat(actualExperiment.getGroupId(), is(expectedExperiment.getGroupId())); + assertThat(actualExperiment.getStatus(), is(expectedExperiment.getStatus())); + assertThat(actualExperiment.getAudienceIds(), is(expectedExperiment.getAudienceIds())); Assert.assertEquals(actualExperiment.getAudienceConditions(), expectedExperiment.getAudienceConditions()); - Assert.assertEquals(actualExperiment.getUserIdToVariationKeyMap(), - expectedExperiment.getUserIdToVariationKeyMap()); + assertThat(actualExperiment.getUserIdToVariationKeyMap(), + is(expectedExperiment.getUserIdToVariationKeyMap())); verifyVariations(actualExperiment.getVariations(), expectedExperiment.getVariations()); verifyTrafficAllocations(actualExperiment.getTrafficAllocation(), @@ -516,14 +516,14 @@ private static void verifyFeatureFlags(List actual, List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { Variation actualVariation = actual.get(i); Variation expectedVariation = expected.get(i); - Assert.assertEquals(actualVariation.getId(), expectedVariation.getId()); - Assert.assertEquals(actualVariation.getKey(), expectedVariation.getKey()); + assertThat(actualVariation.getId(), is(expectedVariation.getId())); + assertThat(actualVariation.getKey(), is(expectedVariation.getKey())); verifyFeatureVariableInstances(actualVariation.getFeatureVariableUsageInstances(), expectedVariation.getFeatureVariableUsageInstances()); } @@ -534,13 +534,13 @@ private static void verifyVariations(List actual, List exp */ private static void verifyTrafficAllocations(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { TrafficAllocation actualDistribution = actual.get(i); TrafficAllocation expectedDistribution = expected.get(i); - Assert.assertEquals(actualDistribution.getEntityId(), expectedDistribution.getEntityId()); + assertThat(actualDistribution.getEntityId(), is(expectedDistribution.getEntityId())); assertEquals("expectedDistribution: " + expectedDistribution.toString() + "is not equal to the actualDistribution: " + actualDistribution.toString(), expectedDistribution.getEndOfRange(), actualDistribution.getEndOfRange()); @@ -551,15 +551,15 @@ private static void verifyTrafficAllocations(List actual, * Asserts that the provided attributes configs are equivalent. */ private static void verifyAttributes(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { Attribute actualAttribute = actual.get(i); Attribute expectedAttribute = expected.get(i); - Assert.assertEquals(actualAttribute.getId(), expectedAttribute.getId()); - Assert.assertEquals(actualAttribute.getKey(), expectedAttribute.getKey()); - Assert.assertEquals(actualAttribute.getSegmentId(), expectedAttribute.getSegmentId()); + assertThat(actualAttribute.getId(), is(expectedAttribute.getId())); + assertThat(actualAttribute.getKey(), is(expectedAttribute.getKey())); + assertThat(actualAttribute.getSegmentId(), is(expectedAttribute.getSegmentId())); } } @@ -567,15 +567,15 @@ private static void verifyAttributes(List actual, List exp * Asserts that the provided event configs are equivalent. */ private static void verifyEvents(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { EventType actualEvent = actual.get(i); EventType expectedEvent = expected.get(i); - Assert.assertEquals(actualEvent.getExperimentIds(), expectedEvent.getExperimentIds()); - Assert.assertEquals(actualEvent.getId(), expectedEvent.getId()); - Assert.assertEquals(actualEvent.getKey(), expectedEvent.getKey()); + assertThat(actualEvent.getExperimentIds(), is(expectedEvent.getExperimentIds())); + assertThat(actualEvent.getId(), is(expectedEvent.getId())); + assertThat(actualEvent.getKey(), is(expectedEvent.getKey())); } } @@ -583,15 +583,15 @@ private static void verifyEvents(List actual, List expecte * Asserts that the provided audience configs are equivalent. */ private static void verifyAudiences(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { Audience actualAudience = actual.get(i); Audience expectedAudience = expected.get(i); - Assert.assertEquals(actualAudience.getId(), expectedAudience.getId()); - Assert.assertEquals(actualAudience.getKey(), expectedAudience.getKey()); - Assert.assertEquals(actualAudience.getConditions(), expectedAudience.getConditions()); + assertThat(actualAudience.getId(), is(expectedAudience.getId())); + assertThat(actualAudience.getKey(), is(expectedAudience.getKey())); + assertThat(actualAudience.getConditions(), is(expectedAudience.getConditions())); } } @@ -599,14 +599,14 @@ private static void verifyAudiences(List actual, List expect * Assert that the provided group configs are equivalent. */ private static void verifyGroups(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); + assertThat(actual.size(), is(expected.size())); for (int i = 0; i < actual.size(); i++) { Group actualGroup = actual.get(i); Group expectedGroup = expected.get(i); - Assert.assertEquals(actualGroup.getId(), expectedGroup.getId()); - Assert.assertEquals(actualGroup.getPolicy(), expectedGroup.getPolicy()); + assertThat(actualGroup.getId(), is(expectedGroup.getId())); + assertThat(actualGroup.getPolicy(), is(expectedGroup.getPolicy())); verifyTrafficAllocations(actualGroup.getTrafficAllocation(), expectedGroup.getTrafficAllocation()); verifyExperiments(actualGroup.getExperiments(), expectedGroup.getExperiments()); } @@ -637,14 +637,14 @@ private static void verifyFeatureVariableInstances(List