From 4af6f4f57c187d482b546de0963256f7f8d02b09 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 8 Sep 2025 14:07:52 -0700 Subject: [PATCH 1/5] Update client class --- .../java/io/split/client/SplitClientImpl.java | 44 +- .../io/split/client/SplitFactoryImpl.java | 22 +- .../split/engine/evaluator/EvaluatorImp.java | 38 +- .../io/split/client/SplitClientImplTest.java | 528 ++++++++++++++++-- .../evaluator/EvaluatorIntegrationTest.java | 4 +- .../split/engine/evaluator/EvaluatorTest.java | 2 +- 6 files changed, 548 insertions(+), 90 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientImpl.java b/client/src/main/java/io/split/client/SplitClientImpl.java index 9f4b8ff9e..30bbea529 100644 --- a/client/src/main/java/io/split/client/SplitClientImpl.java +++ b/client/src/main/java/io/split/client/SplitClientImpl.java @@ -3,9 +3,7 @@ import com.google.gson.GsonBuilder; import io.split.client.api.Key; import io.split.client.api.SplitResult; -import io.split.client.dtos.DecoratedImpression; -import io.split.client.dtos.EvaluationOptions; -import io.split.client.dtos.Event; +import io.split.client.dtos.*; import io.split.client.events.EventsStorageProducer; import io.split.client.impressions.Impression; import io.split.client.impressions.ImpressionsManager; @@ -14,7 +12,6 @@ import io.split.engine.evaluator.Evaluator; import io.split.engine.evaluator.EvaluatorImp; import io.split.engine.evaluator.Labels; -import io.split.grammar.Treatments; import io.split.inputValidation.EventsValidator; import io.split.inputValidation.KeyValidator; import io.split.inputValidation.SplitNameValidator; @@ -49,7 +46,7 @@ * @author adil */ public final class SplitClientImpl implements SplitClient { - public static final SplitResult SPLIT_RESULT_CONTROL = new SplitResult(Treatments.CONTROL, null); +// public static final SplitResult SPLIT_RESULT_CONTROL = new SplitResult(Treatments.CONTROL, null); private static final String CLIENT_DESTROY = "Client has already been destroyed - no calls possible"; private static final String CATCHALL_EXCEPTION = "CatchAll Exception"; private static final String MATCHING_KEY = "matchingKey"; @@ -66,6 +63,7 @@ public final class SplitClientImpl implements SplitClient { private final TelemetryEvaluationProducer _telemetryEvaluationProducer; private final TelemetryConfigProducer _telemetryConfigProducer; private final FlagSetsFilter _flagSetsFilter; + private final FallbackTreatmentCalculator _fallbackTreatmentCalculator; public SplitClientImpl(SplitFactory container, SplitCacheConsumer splitCacheConsumer, @@ -76,7 +74,8 @@ public SplitClientImpl(SplitFactory container, Evaluator evaluator, TelemetryEvaluationProducer telemetryEvaluationProducer, TelemetryConfigProducer telemetryConfigProducer, - FlagSetsFilter flagSetsFilter) { + FlagSetsFilter flagSetsFilter, + FallbackTreatmentCalculator fallbackTreatmentCalculator) { _container = container; _splitCacheConsumer = checkNotNull(splitCacheConsumer); _impressionManager = checkNotNull(impressionManager); @@ -87,6 +86,7 @@ public SplitClientImpl(SplitFactory container, _telemetryEvaluationProducer = checkNotNull(telemetryEvaluationProducer); _telemetryConfigProducer = checkNotNull(telemetryConfigProducer); _flagSetsFilter = flagSetsFilter; + _fallbackTreatmentCalculator = fallbackTreatmentCalculator; } @Override @@ -492,31 +492,31 @@ private SplitResult getTreatmentWithConfigInternal(String matchingKey, String bu if (_container.isDestroyed()) { _log.error(CLIENT_DESTROY); - return SPLIT_RESULT_CONTROL; + return checkFallbackTreatment(featureFlag); } if (!KeyValidator.isValid(matchingKey, MATCHING_KEY, _config.maxStringLength(), methodEnum.getMethod())) { - return SPLIT_RESULT_CONTROL; + return checkFallbackTreatment(featureFlag); } if (!KeyValidator.bucketingKeyIsValid(bucketingKey, _config.maxStringLength(), methodEnum.getMethod())) { - return SPLIT_RESULT_CONTROL; + return checkFallbackTreatment(featureFlag); } Optional splitNameResult = SplitNameValidator.isValid(featureFlag, methodEnum.getMethod()); if (!splitNameResult.isPresent()) { - return SPLIT_RESULT_CONTROL; + return checkFallbackTreatment(featureFlag); } featureFlag = splitNameResult.get(); long start = System.currentTimeMillis(); EvaluatorImp.TreatmentLabelAndChangeNumber result = _evaluator.evaluateFeature(matchingKey, bucketingKey, featureFlag, attributes); - if (result.treatment.equals(Treatments.CONTROL) && result.label.equals(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) { + if (result.label != null && result.label.contains(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) { _log.warn(String.format( "%s: you passed \"%s\" that does not exist in this environment, " + "please double check what feature flags exist in the Split user interface.", methodEnum.getMethod(), featureFlag)); - return SPLIT_RESULT_CONTROL; + return checkFallbackTreatment(featureFlag); } recordStats( @@ -541,10 +541,19 @@ private SplitResult getTreatmentWithConfigInternal(String matchingKey, String bu } catch (Exception e1) { // ignore } - return SPLIT_RESULT_CONTROL; + return checkFallbackTreatment(featureFlag); } } + private SplitResult checkFallbackTreatment(String featureName) { + FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, ""); + String config = null; + if (fallbackTreatment.getConfig() != null) { + config = fallbackTreatment.getConfig().toString(); + } + return new SplitResult(fallbackTreatment.getTreatment(), config); + } + private String validateProperties(Map properties) { if (properties == null){ return null; @@ -563,6 +572,7 @@ private Map getTreatmentsWithConfigInternal(String matching _log.error(String.format("%s: featureFlagNames must be a non-empty array", methodEnum.getMethod())); return new HashMap<>(); } + try { checkSDKReady(methodEnum, featureFlagNames); Map result = validateBeforeEvaluate(featureFlagNames, matchingKey, methodEnum, bucketingKey); @@ -623,17 +633,17 @@ private Map getTreatmentsBySetsWithConfigInternal(String ma return createMapControl(featureFlagNames); } } + private Map processEvaluatorResult(Map evaluatorResult, MethodEnum methodEnum, String matchingKey, String bucketingKey, Map attributes, long initTime, String properties){ List decoratedImpressions = new ArrayList<>(); Map result = new HashMap<>(); evaluatorResult.keySet().forEach(t -> { - if (evaluatorResult.get(t).treatment.equals(Treatments.CONTROL) && evaluatorResult.get(t).label. - equals(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) { + if (evaluatorResult.get(t).label != null && evaluatorResult.get(t).label.contains(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) { _log.warn(String.format("%s: you passed \"%s\" that does not exist in this environment please double check " + "what feature flags exist in the Split user interface.", methodEnum.getMethod(), t)); - result.put(t, SPLIT_RESULT_CONTROL); + result.put(t, checkFallbackTreatment(t)); } else { result.put(t, new SplitResult(evaluatorResult.get(t).treatment, evaluatorResult.get(t).configurations)); decoratedImpressions.add( @@ -735,7 +745,7 @@ private void checkSDKReady(MethodEnum methodEnum) { private Map createMapControl(List featureFlags) { Map result = new HashMap<>(); - featureFlags.forEach(s -> result.put(s, SPLIT_RESULT_CONTROL)); + featureFlags.forEach(s -> result.put(s, checkFallbackTreatment(s))); return result; } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index bcc1a9679..5d868f3ce 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -2,6 +2,7 @@ import com.google.common.io.Files; import io.split.client.dtos.BearerCredentialsProvider; +import io.split.client.dtos.FallbackTreatmentCalculatorImp; import io.split.client.dtos.Metadata; import io.split.client.events.EventsSender; import io.split.client.events.EventsStorage; @@ -256,8 +257,9 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn _telemetrySyncTask = new TelemetrySyncTask(config.getTelemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); // Evaluator - _evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, null); + _evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, fallbackTreatmentCalculatorImp); // SplitClient _client = new SplitClientImpl(this, @@ -269,7 +271,9 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn _evaluator, _telemetryStorageProducer, // TelemetryEvaluation instance _telemetryStorageProducer, // TelemetryConfiguration instance - flagSetsFilter); + flagSetsFilter, + fallbackTreatmentCalculatorImp + ); // SplitManager _manager = new SplitManagerImpl(splitCache, config, _gates, _telemetryStorageProducer); @@ -348,8 +352,9 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _telemetrySynchronizer = new TelemetryConsumerSubmitter(customStorageWrapper, _sdkMetadata); UserCustomRuleBasedSegmentAdapterConsumer userCustomRuleBasedSegmentAdapterConsumer = new UserCustomRuleBasedSegmentAdapterConsumer(customStorageWrapper); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); _evaluator = new EvaluatorImp(userCustomSplitAdapterConsumer, userCustomSegmentAdapterConsumer, - userCustomRuleBasedSegmentAdapterConsumer, null); + userCustomRuleBasedSegmentAdapterConsumer, fallbackTreatmentCalculatorImp); _impressionsSender = PluggableImpressionSender.create(customStorageWrapper); _uniqueKeysTracker = createUniqueKeysTracker(config); _impressionsManager = buildImpressionsManager(config, userCustomImpressionAdapterConsumer, @@ -378,7 +383,9 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _evaluator, _telemetryStorageProducer, // TelemetryEvaluation instance _telemetryStorageProducer, // TelemetryConfiguration instance - flagSetsFilter); + flagSetsFilter, + fallbackTreatmentCalculatorImp + ); // SyncManager _syncManager = new ConsumerSyncManager(synchronizer); @@ -446,8 +453,9 @@ protected SplitFactoryImpl(SplitClientConfig config) { SplitTasks splitTasks = SplitTasks.build(_splitSynchronizationTask, _segmentSynchronizationTaskImp, _impressionsManager, null, null, null); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); // Evaluator - _evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, null); + _evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, fallbackTreatmentCalculatorImp); EventsStorage eventsStorage = new NoopEventsStorageImp(); @@ -461,7 +469,9 @@ protected SplitFactoryImpl(SplitClientConfig config) { _evaluator, _telemetryStorageProducer, // TelemetryEvaluation instance _telemetryStorageProducer, // TelemetryConfiguration instance - flagSetsFilter); + flagSetsFilter, + fallbackTreatmentCalculatorImp + ); // Synchronizer Synchronizer synchronizer = new LocalhostSynchronizer(splitTasks, _splitFetcher, diff --git a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java index 773413b2b..282db10f7 100644 --- a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java +++ b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java @@ -3,12 +3,10 @@ import io.split.client.dtos.ConditionType; import io.split.client.dtos.FallbackTreatment; import io.split.client.dtos.FallbackTreatmentCalculator; -import io.split.client.dtos.FallbackTreatmentsConfiguration; import io.split.client.exceptions.ChangeNumberExceptionWrapper; import io.split.engine.experiments.ParsedCondition; import io.split.engine.experiments.ParsedSplit; import io.split.engine.splitter.Splitter; -import io.split.grammar.Treatments; import io.split.storages.RuleBasedSegmentCacheConsumer; import io.split.storages.SegmentCacheConsumer; import io.split.storages.SplitCacheConsumer; @@ -63,7 +61,27 @@ public Map evaluateFeatures(String matchi public Map evaluateFeaturesByFlagSets(String key, String bucketingKey, List flagSets, Map attributes) { List flagSetsWithNames = getFeatureFlagNamesByFlagSets(flagSets); - return evaluateFeatures(key, bucketingKey, flagSetsWithNames, attributes); + try { + return evaluateFeatures(key, bucketingKey, flagSetsWithNames, attributes); + } catch (Exception e) { + _log.error("Evaluator Exception", e); + return createMapControl(flagSetsWithNames, "exception"); + } + } + + private Map createMapControl(List featureFlags, String label) { + Map result = new HashMap<>(); + featureFlags.forEach(s -> result.put(s, checkFallbackTreatment(s, label))); + return result; + } + + private EvaluatorImp.TreatmentLabelAndChangeNumber checkFallbackTreatment(String featureName, String label) { + FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, label); + return new EvaluatorImp.TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(), + fallbackTreatment.getLabel(), + null, + getFallbackConfig(fallbackTreatment), + false); } private List getFeatureFlagNamesByFlagSets(List flagSets) { @@ -177,13 +195,25 @@ private String getConfig(ParsedSplit parsedSplit, String returnedTreatment) { return parsedSplit.configurations() != null ? parsedSplit.configurations().get(returnedTreatment) : null; } + private String getFallbackConfig(FallbackTreatment fallbackTreatment) { + if (fallbackTreatment.getConfig() != null) { + return fallbackTreatment.getConfig().toString(); + } + + return null; + } + private TreatmentLabelAndChangeNumber evaluateParsedSplit(String matchingKey, String bucketingKey, Map attributes, ParsedSplit parsedSplit, String featureName) { try { if (parsedSplit == null) { FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, Labels.DEFINITION_NOT_FOUND); - return new TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(), fallbackTreatment.getLabel()); + return new TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(), + fallbackTreatment.getLabel(), + null, + getFallbackConfig(fallbackTreatment), + true); } return getTreatment(matchingKey, bucketingKey, parsedSplit, attributes); } catch (ChangeNumberExceptionWrapper e) { diff --git a/client/src/test/java/io/split/client/SplitClientImplTest.java b/client/src/test/java/io/split/client/SplitClientImplTest.java index a5b55ed78..9db75c0cc 100644 --- a/client/src/test/java/io/split/client/SplitClientImplTest.java +++ b/client/src/test/java/io/split/client/SplitClientImplTest.java @@ -100,7 +100,8 @@ public void nullKeyResultsInControl() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.CONTROL, client.getTreatment(null, "test1")); @@ -130,7 +131,8 @@ public void nullTestResultsInControl() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.CONTROL, client.getTreatment("adil@relateiq.com", null)); @@ -153,7 +155,8 @@ public void exceptionsResultInControl() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.CONTROL, client.getTreatment("adil@relateiq.com", "test1")); @@ -185,7 +188,8 @@ public void works() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; @@ -223,7 +227,8 @@ public void worksNullConfig() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); String randomKey = RandomStringUtils.random(10); SplitResult result = client.getTreatmentWithConfig(randomKey, test); @@ -259,7 +264,8 @@ public void worksAndHasConfig() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; @@ -296,7 +302,8 @@ public void lastConditionIsAlwaysDefault() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.OFF, client.getTreatment("pato@codigo.com", test)); @@ -336,7 +343,8 @@ public void lastConditionIsAlwaysDefaultButWithTreatment() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); SplitResult result = client.getTreatmentWithConfig("pato@codigo.com", test); @@ -372,7 +380,8 @@ public void multipleConditionsWork() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals("on", client.getTreatment("adil@codigo.com", test)); @@ -406,7 +415,8 @@ public void killedTestAlwaysGoesToDefault() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.OFF, client.getTreatment("adil@codigo.com", test)); @@ -446,7 +456,8 @@ public void killedTestAlwaysGoesToDefaultHasConfig() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); SplitResult result = client.getTreatmentWithConfig("adil@codigo.com", test); @@ -484,7 +495,8 @@ public void dependencyMatcherOn() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.ON, client.getTreatment("key", parent)); @@ -510,7 +522,7 @@ public void dependencyMatcherOff() { RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); when(splitCacheConsumer.get(parent)).thenReturn(parentSplit); when(splitCacheConsumer.get(dependent)).thenReturn(dependentSplit); - + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), splitCacheConsumer, @@ -518,8 +530,9 @@ public void dependencyMatcherOff() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); assertEquals(Treatments.ON, client.getTreatment("key", parent)); @@ -539,6 +552,7 @@ public void dependencyMatcherControl() { SegmentCacheConsumer segmentCacheConsumer = mock(SegmentCacheConsumer.class); RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); when(splitCacheConsumer.get(dependent)).thenReturn(dependentSplit); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), @@ -547,8 +561,9 @@ public void dependencyMatcherControl() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); assertEquals(Treatments.ON, client.getTreatment("key", dependent)); @@ -578,7 +593,8 @@ public void attributesWork() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals("on", client.getTreatment("adil@codigo.com", test)); @@ -613,7 +629,8 @@ public void attributesWork2() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals("off", client.getTreatment("adil@codigo.com", test)); @@ -649,7 +666,8 @@ public void attributesGreaterThanNegativeNumber() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals("off", client.getTreatment("adil@codigo.com", test)); @@ -687,7 +705,8 @@ public void attributesForSets() { config, gates, new EvaluatorImp(splitCacheConsumer ,segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals("off", client.getTreatment("adil@codigo.com", test)); @@ -732,7 +751,8 @@ public void labelsArePopulated() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Map attributes = ImmutableMap.of("age", -20, "acv", "1000000"); @@ -835,7 +855,8 @@ private void trafficAllocation(String key, int trafficAllocation, int trafficAll config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(expected_treatment_on_or_off, client.getTreatment(key, test)); @@ -889,7 +910,8 @@ public void notInTrafficAllocationDefaultConfig() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.OFF, client.getTreatment("pato@split.io", test)); @@ -933,7 +955,8 @@ public void matchingBucketingKeysWork() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Key bad_key = new Key("adil", "aijaz"); @@ -976,7 +999,8 @@ public void matchingBucketingKeysByFlagSetWork() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Key bad_key = new Key("adil", "aijaz"); @@ -1017,7 +1041,8 @@ public void matchingBucketingKeysByFlagSetsWork() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Key bad_key = new Key("adil", "aijaz"); @@ -1055,7 +1080,8 @@ public void impressionMetadataIsPropagated() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Map attributes = ImmutableMap.of("age", -20, "acv", "1000000"); @@ -1098,7 +1124,8 @@ public void blockUntilReadyDoesNotTimeWhenSdkIsReady() throws TimeoutException, config, ready, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); client.blockUntilReady(); @@ -1120,7 +1147,8 @@ public void blockUntilReadyTimesWhenSdkIsNotReady() throws TimeoutException, Int config, ready, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); client.blockUntilReady(); @@ -1141,7 +1169,8 @@ public void trackWithValidParameters() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertTrue(client.track("validKey", "valid_traffic_type", "valid_event")); @@ -1167,7 +1196,8 @@ public void trackWithInvalidEventTypeIds() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Assert.assertFalse(client.track("validKey", "valid_traffic_type", "")); Assert.assertFalse(client.track("validKey", "valid_traffic_type", null)); @@ -1192,7 +1222,8 @@ public void trackWithInvalidTrafficTypeNames() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Assert.assertFalse(client.track("validKey", "", "valid")); @@ -1214,7 +1245,8 @@ public void trackWithInvalidKeys() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Assert.assertFalse(client.track("", "valid_traffic_type", "valid")); @@ -1246,7 +1278,8 @@ public void getTreatmentWithInvalidKeys() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Assert.assertNotEquals(Treatments.CONTROL, client.getTreatment("valid", "split")); assertEquals(Treatments.CONTROL, client.getTreatment("", "split")); @@ -1297,7 +1330,8 @@ public void trackWithProperties() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); HashMap properties = new HashMap<>(); @@ -1421,7 +1455,8 @@ public void clientCannotPerformActionsWhenDestroyed() throws InterruptedExceptio config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.ON, client.getTreatment("valid", "split")); @@ -1462,7 +1497,8 @@ public void worksAndHasConfigTryKetTreatmentWithKey() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; @@ -1513,7 +1549,8 @@ public void worksAndHasConfigByFlagSetTryKetTreatmentWithKey() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; @@ -1562,7 +1599,8 @@ public void worksAndHasConfigByFlagSetsTryKetTreatmentWithKey() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; @@ -1600,7 +1638,8 @@ public void blockUntilReadyException() throws TimeoutException, InterruptedExcep config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); client.blockUntilReady(); @@ -1630,7 +1669,8 @@ public void nullKeyResultsInControlGetTreatments() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(Treatments.CONTROL, client.getTreatments(null, Collections.singletonList("test1")).get("test1")); @@ -1661,7 +1701,8 @@ public void nullSplitsResultsInEmptyGetTreatments() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertEquals(0, client.getTreatments("key", null).size()); @@ -1684,7 +1725,8 @@ public void exceptionsResultInControlGetTreatments() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Map result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1", "test2")); assertEquals(2, result.values().size()); @@ -1709,6 +1751,7 @@ public void getTreatmentsWorks() { RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); when(splitCacheConsumer.fetchMany(anyList())).thenReturn(splits); when(gates.isSDKReady()).thenReturn(true); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), @@ -1717,8 +1760,9 @@ public void getTreatmentsWorks() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); Map result = client.getTreatments("randomKey", Arrays.asList(test, "test2")); assertEquals("on", result.get(test)); @@ -1749,7 +1793,8 @@ public void emptySplitsResultsInNullGetTreatments() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Map result = client.getTreatments("key", new ArrayList<>()); assertNotNull(result); @@ -1774,7 +1819,8 @@ public void exceptionsResultInControlTreatments() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Map result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1")); assertEquals(1, result.size()); @@ -1812,7 +1858,8 @@ public void worksTreatments() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); Map result = client.getTreatments("anyKey", Arrays.asList(test, test2)); assertNotNull(result); @@ -1841,6 +1888,7 @@ public void worksOneControlTreatments() { RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); when(splitCacheConsumer.fetchMany(anyList())).thenReturn(parsedSplits); when(gates.isSDKReady()).thenReturn(true); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), @@ -1849,8 +1897,9 @@ public void worksOneControlTreatments() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); Map result = client.getTreatments("anyKey", Arrays.asList(test, test2)); @@ -1886,6 +1935,7 @@ public void treatmentsWorksAndHasConfig() { SegmentCacheConsumer segmentCacheConsumer = mock(SegmentCacheConsumer.class); RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); when(splitCacheConsumer.fetchMany(anyList())).thenReturn(parsedSplits); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), @@ -1894,8 +1944,9 @@ public void treatmentsWorksAndHasConfig() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); Map attributes = new HashMap<>(); Map result = client.getTreatmentsWithConfig("randomKey", Arrays.asList(test, test2, "", null), attributes); @@ -1938,7 +1989,8 @@ public void testTreatmentsByFlagSet() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; @@ -1979,7 +2031,8 @@ public void testTreatmentsByFlagSetInvalid() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); assertTrue(client.getTreatmentsByFlagSet(RandomStringUtils.random(10), "", new HashMap<>()).isEmpty()); } @@ -2023,7 +2076,8 @@ public void testTreatmentsByFlagSets() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + flagSetsFilter, + new FallbackTreatmentCalculatorImp(null) ); int numKeys = 5; Map getTreatmentResult; @@ -2070,6 +2124,7 @@ public void treatmentsWorksAndHasConfigFlagSet() { when(splitCacheConsumer.getNamesByFlagSets(sets)).thenReturn(flagsBySets); SDKReadinessGates gates = mock(SDKReadinessGates.class); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), @@ -2078,8 +2133,9 @@ public void treatmentsWorksAndHasConfigFlagSet() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); Map attributes = new HashMap<>(); Map result = client.getTreatmentsWithConfigByFlagSet("randomKey", "set1", attributes); @@ -2127,6 +2183,7 @@ public void treatmentsWorksAndHasConfigFlagSets() { when(splitCacheConsumer.getNamesByFlagSets(sets)).thenReturn(flagsBySets); SDKReadinessGates gates = mock(SDKReadinessGates.class); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); SplitClientImpl client = new SplitClientImpl( mock(SplitFactory.class), @@ -2135,8 +2192,9 @@ public void treatmentsWorksAndHasConfigFlagSets() { NoopEventsStorageImp.create(), config, gates, - new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - flagSetsFilter + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculatorImp), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + flagSetsFilter, + fallbackTreatmentCalculatorImp ); Map attributes = new HashMap<>(); Map result = client.getTreatmentsWithConfigByFlagSets("randomKey", new ArrayList<>(Arrays.asList("set1")), attributes); @@ -2182,7 +2240,9 @@ public void impressionPropertiesTest() { config, gates, new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, null), TELEMETRY_STORAGE, TELEMETRY_STORAGE, - new FlagSetsFilterImpl(new HashSet<>()) + new FlagSetsFilterImpl(new HashSet<>()), + new FallbackTreatmentCalculatorImp(null) + ); Map attributes = ImmutableMap.of("age", -20, "acv", "1000000"); EvaluationOptions properties = new EvaluationOptions(new HashMap() @@ -2233,4 +2293,350 @@ public void impressionPropertiesTest() { assertEquals("{\"prop2\":\"val2\",\"prop1\":\"val1\"}", impression.impression().properties()); } } + + @Test + public void fallbackTreatmentWithExceptionsResult() { + SDKReadinessGates gates = mock(SDKReadinessGates.class); + SplitCacheConsumer splitCacheConsumer = mock(SplitCacheConsumer.class); + SegmentCacheConsumer segmentCacheConsumer = mock(SegmentCacheConsumer.class); + RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); + when(splitCacheConsumer.get(anyString())).thenThrow(RuntimeException.class); + when(splitCacheConsumer.fetchMany(anyList())).thenThrow(RuntimeException.class); + HashMap> features = new HashMap<>(); + features.put("flag", new HashSet<>(Arrays.asList("test1"))); + when(splitCacheConsumer.getNamesByFlagSets(anyList())).thenReturn(features); + + Map fallbcakConfigGlobal = new HashMap() {{ put("prop1", "val1"); }}; + FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration( + new FallbackTreatment("on", fallbcakConfigGlobal), + null); + FallbackTreatmentCalculator fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration); + + SplitClientImpl client = new SplitClientImpl( + mock(SplitFactory.class), + splitCacheConsumer, + new ImpressionsManager.NoOpImpressionsManager(), + NoopEventsStorageImp.create(), + config, + gates, + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculator), + TELEMETRY_STORAGE, TELEMETRY_STORAGE, + new FlagSetsFilterImpl(new HashSet<>()), + fallbackTreatmentCalculator + ); + assertEquals("on", client.getTreatment("adil@relateiq.com", "test1")); + assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals("on", client.getTreatments("adil@relateiq.com", Arrays.asList("test1")).get("test1")); + assertEquals("on", client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1")).get("test1").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1")).get("test1").config()); + + assertEquals("on", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("test1")); + assertEquals("on", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1")); + assertEquals("on", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test1").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test1").config()); + assertEquals("on", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1").config()); + + Map fallbcakConfigByFlag = new HashMap() {{ put("prop2", "val2"); }}; + fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on", fallbcakConfigGlobal), + new HashMap() {{ put("feature", new FallbackTreatment("off", fallbcakConfigByFlag)); }}); + + features = new HashMap<>(); + features.put("flag", new HashSet<>(Arrays.asList("test", "feature"))); + when(splitCacheConsumer.getNamesByFlagSets(anyList())).thenReturn(features); + + fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration); + + client = new SplitClientImpl( + mock(SplitFactory.class), + splitCacheConsumer, + new ImpressionsManager.NoOpImpressionsManager(), + NoopEventsStorageImp.create(), + config, + gates, + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculator), + TELEMETRY_STORAGE, TELEMETRY_STORAGE, + new FlagSetsFilterImpl(new HashSet<>()), + fallbackTreatmentCalculator + ); + assertEquals("on", client.getTreatment("adil@relateiq.com", "test")); + assertEquals("off", client.getTreatment("adil@relateiq.com", "feature")); + assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "feature").config()); + Map result = client.getTreatments("adil@relateiq.com", Arrays.asList("feature", "test")); + assertEquals("off", result.get("feature")); + assertEquals("on", result.get("test")); + Map results = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("feature", "test")); + assertEquals("off", results.get("feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("feature").config()); + assertEquals("on", results.get("test").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), results.get("test").config()); + + assertEquals("on", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("test")); + assertEquals("off", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("feature")); + assertEquals("on", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test")); + assertEquals("off", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature")); + assertEquals("on", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").config()); + assertEquals("off", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").config()); + assertEquals("on", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").config()); + assertEquals("off", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").config()); + + fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null, + new HashMap() {{ put("feature", new FallbackTreatment("off", fallbcakConfigByFlag)); }}); + + fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration); + + client = new SplitClientImpl( + mock(SplitFactory.class), + splitCacheConsumer, + new ImpressionsManager.NoOpImpressionsManager(), + NoopEventsStorageImp.create(), + config, + gates, + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculator), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + new FlagSetsFilterImpl(new HashSet<>()), + fallbackTreatmentCalculator + ); + assertEquals(Treatments.CONTROL, client.getTreatment("adil@relateiq.com", "test")); + assertEquals("off", client.getTreatment("adil@relateiq.com", "feature")); + assertEquals(Treatments.CONTROL, client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); + assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "feature").config()); + result = client.getTreatments("adil@relateiq.com", Arrays.asList("feature", "test")); + assertEquals("off", result.get("feature")); + assertEquals(Treatments.CONTROL, result.get("test")); + results = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("feature", "test")); + assertEquals("off", results.get("feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("feature").config()); + assertEquals(Treatments.CONTROL, results.get("test").treatment()); + assertEquals(null, results.get("test").config()); + + assertEquals(Treatments.CONTROL, client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("test")); + assertEquals("off", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("feature")); + assertEquals(Treatments.CONTROL, client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test")); + assertEquals("off", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature")); + assertEquals(Treatments.CONTROL, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").treatment()); + assertEquals(null, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").config()); + assertEquals("off", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").config()); + assertEquals(Treatments.CONTROL, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").treatment()); + assertEquals(null, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").config()); + assertEquals("off", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").config()); + } + + @Test + public void fallbackTreatmentWithSplitNotFoundResult() { + SDKReadinessGates gates = mock(SDKReadinessGates.class); + SplitCacheConsumer splitCacheConsumer = mock(SplitCacheConsumer.class); + SegmentCacheConsumer segmentCacheConsumer = mock(SegmentCacheConsumer.class); + RuleBasedSegmentCacheConsumer ruleBasedSegmentCacheConsumer = mock(RuleBasedSegmentCacheConsumer.class); + ParsedCondition rollOutToEveryone = ParsedCondition.createParsedConditionForTests(CombiningMatcher.of(new WhitelistMatcher(Lists.newArrayList("adil@codigo.com"))), Lists.newArrayList(partition("on", 100))); + List conditions = Lists.newArrayList(rollOutToEveryone); + ParsedSplit parsedSplit = ParsedSplit.createParsedSplitForTests("test", 123, false, Treatments.OFF, conditions, + null, 1, 1, new HashSet<>(), false, new PrerequisitesMatcher(null)); + + when(splitCacheConsumer.get("test1")).thenReturn(parsedSplit); + when(splitCacheConsumer.get("test2")).thenReturn(null); + when(splitCacheConsumer.get("test3")).thenReturn(null); + HashMap features = new HashMap<>(); + features.put("test1", parsedSplit); + features.put("test2", null); + features.put("test3", null); + when(splitCacheConsumer.fetchMany(anyList())).thenReturn(features); + HashMap> flagFeatures = new HashMap<>(); + flagFeatures.put("flag", new HashSet<>(Arrays.asList("test1", "test2", "test3"))); + when(splitCacheConsumer.getNamesByFlagSets(anyList())).thenReturn(flagFeatures); + + Map fallbcakConfigGlobal = new HashMap() {{ put("prop1", "val1"); }}; + FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration( + new FallbackTreatment("on", fallbcakConfigGlobal), + null); + FallbackTreatmentCalculator fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration); + + SplitClientImpl client = new SplitClientImpl( + mock(SplitFactory.class), + splitCacheConsumer, + new ImpressionsManager.NoOpImpressionsManager(), + NoopEventsStorageImp.create(), + config, + gates, + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculator), + TELEMETRY_STORAGE, TELEMETRY_STORAGE, + new FlagSetsFilterImpl(new HashSet<>()), + fallbackTreatmentCalculator + ); + assertEquals("off", client.getTreatment("adil@relateiq.com", "test1")); + assertEquals("on", client.getTreatment("adil@relateiq.com", "test2")); + assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test2").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); + + Map result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1", "test2")); + assertEquals("off", result.get("test1")); + assertEquals("on", result.get("test2")); + Map resultWithConfig = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1", "test2")); + assertEquals("off", resultWithConfig.get("test1").treatment()); + assertEquals(null, resultWithConfig.get("test1").config()); + assertEquals("on", resultWithConfig.get("test2").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), resultWithConfig.get("test2").config()); + + result = client.getTreatmentsByFlagSet("adil@relateiq.com", "flag"); + assertEquals("off", result.get("test1")); + assertEquals("on", result.get("test2")); + result = client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")); + assertEquals("off", result.get("test1")); + assertEquals("on", result.get("test2")); + resultWithConfig = client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag"); + assertEquals("off", resultWithConfig.get("test1").treatment()); + assertEquals(null, resultWithConfig.get("test1").config()); + assertEquals("on", resultWithConfig.get("test2").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), resultWithConfig.get("test2").config()); + resultWithConfig = client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")); + assertEquals("off", resultWithConfig.get("test1").treatment()); + assertEquals(null, resultWithConfig.get("test1").config()); + assertEquals("on", resultWithConfig.get("test2").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), resultWithConfig.get("test2").config()); + + Map fallbcakConfigByFlag = new HashMap() {{ put("prop2", "val2"); }}; + fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on", fallbcakConfigGlobal), + new HashMap() {{ put("test2", new FallbackTreatment("off-fallback", fallbcakConfigByFlag)); }}); + + fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration); + + client = new SplitClientImpl( + mock(SplitFactory.class), + splitCacheConsumer, + new ImpressionsManager.NoOpImpressionsManager(), + NoopEventsStorageImp.create(), + config, + gates, + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculator), + TELEMETRY_STORAGE, TELEMETRY_STORAGE, + new FlagSetsFilterImpl(new HashSet<>()), + fallbackTreatmentCalculator + ); + assertEquals("off", client.getTreatment("adil@relateiq.com", "test1")); + assertEquals("off-fallback", client.getTreatment("adil@relateiq.com", "test2")); + assertEquals("on", client.getTreatment("adil@relateiq.com", "test3")); + + assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); + assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals("off-fallback", client.getTreatmentWithConfig("adil@relateiq.com", "test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); + assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test3").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test3").config()); + + result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1", "test2", "test3")); + assertEquals("off", result.get("test1")); + assertEquals("off-fallback", result.get("test2")); + assertEquals("on", result.get("test3")); + + Map results = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1", "test2", "test3")); + assertEquals("off", results.get("test1").treatment()); + assertEquals(null, results.get("test1").config()); + assertEquals("off-fallback", results.get("test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals("on", results.get("test3").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), results.get("test3").config()); + + result = client.getTreatmentsByFlagSet("adil@relateiq.com", "flag"); + assertEquals("off", result.get("test1")); + assertEquals("off-fallback", result.get("test2")); + assertEquals("on", result.get("test3")); + + result = client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")); + assertEquals("off", result.get("test1")); + assertEquals("off-fallback", result.get("test2")); + assertEquals("on", result.get("test3")); + + results = client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag"); + assertEquals("off", results.get("test1").treatment()); + assertEquals(null, results.get("test1").config()); + assertEquals("off-fallback", results.get("test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals("on", results.get("test3").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), results.get("test3").config()); + + results = client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")); + assertEquals("off", results.get("test1").treatment()); + assertEquals(null, results.get("test1").config()); + assertEquals("off-fallback", results.get("test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals("on", results.get("test3").treatment()); + assertEquals(fallbcakConfigGlobal.toString(), results.get("test3").config()); + + fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null, + new HashMap() {{ put("test2", new FallbackTreatment("off-fallback", fallbcakConfigByFlag)); }}); + + fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration); + + client = new SplitClientImpl( + mock(SplitFactory.class), + splitCacheConsumer, + new ImpressionsManager.NoOpImpressionsManager(), + NoopEventsStorageImp.create(), + config, + gates, + new EvaluatorImp(splitCacheConsumer, segmentCacheConsumer, ruleBasedSegmentCacheConsumer, fallbackTreatmentCalculator), TELEMETRY_STORAGE, TELEMETRY_STORAGE, + new FlagSetsFilterImpl(new HashSet<>()), + fallbackTreatmentCalculator + ); + assertEquals("off", client.getTreatment("adil@relateiq.com", "test1")); + assertEquals("off-fallback", client.getTreatment("adil@relateiq.com", "test2")); + assertEquals(Treatments.CONTROL, client.getTreatment("adil@relateiq.com", "test3")); + + assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); + assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals("off-fallback", client.getTreatmentWithConfig("adil@relateiq.com", "test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); + assertEquals(Treatments.CONTROL, client.getTreatmentWithConfig("adil@relateiq.com", "test3").treatment()); + assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test3").config()); + + result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1", "test2", "test3")); + assertEquals("off", result.get("test1")); + assertEquals("off-fallback", result.get("test2")); + assertEquals(Treatments.CONTROL, result.get("test3")); + + results = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1", "test2", "test3")); + assertEquals("off", results.get("test1").treatment()); + assertEquals(null, results.get("test1").config()); + assertEquals("off-fallback", results.get("test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(Treatments.CONTROL, results.get("test3").treatment()); + assertEquals(null, results.get("test3").config()); + + result = client.getTreatmentsByFlagSet("adil@relateiq.com", "flag"); + assertEquals("off", result.get("test1")); + assertEquals("off-fallback", result.get("test2")); + assertEquals(Treatments.CONTROL, result.get("test3")); + + result = client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")); + assertEquals("off", result.get("test1")); + assertEquals("off-fallback", result.get("test2")); + assertEquals(Treatments.CONTROL, result.get("test3")); + + results = client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag"); + assertEquals("off", results.get("test1").treatment()); + assertEquals(null, results.get("test1").config()); + assertEquals("off-fallback", results.get("test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(Treatments.CONTROL, results.get("test3").treatment()); + assertEquals(null, results.get("test3").config()); + + results = client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")); + assertEquals("off", results.get("test1").treatment()); + assertEquals(null, results.get("test1").config()); + assertEquals("off-fallback", results.get("test2").treatment()); + assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(Treatments.CONTROL, results.get("test3").treatment()); + assertEquals(null, results.get("test3").config()); + } } \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/evaluator/EvaluatorIntegrationTest.java b/client/src/test/java/io/split/engine/evaluator/EvaluatorIntegrationTest.java index e686f5308..5b0a024a6 100644 --- a/client/src/test/java/io/split/engine/evaluator/EvaluatorIntegrationTest.java +++ b/client/src/test/java/io/split/engine/evaluator/EvaluatorIntegrationTest.java @@ -2,6 +2,7 @@ import com.google.common.collect.Lists; import io.split.client.dtos.ConditionType; +import io.split.client.dtos.FallbackTreatmentCalculatorImp; import io.split.client.dtos.MatcherCombiner; import io.split.client.dtos.Partition; import io.split.client.interceptors.FlagSetsFilter; @@ -174,7 +175,8 @@ private Evaluator buildEvaluatorAndLoadCache(boolean killed, int trafficAllocati SplitCache splitCache = new InMemoryCacheImp(flagSetsFilter); SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); RuleBasedSegmentCache ruleBasedSegmentCache = new RuleBasedSegmentCacheInMemoryImp(); - Evaluator evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, null); + FallbackTreatmentCalculatorImp fallbackTreatmentCalculatorImp = new FallbackTreatmentCalculatorImp(null); + Evaluator evaluator = new EvaluatorImp(splitCache, segmentCache, ruleBasedSegmentCache, fallbackTreatmentCalculatorImp); Partition partition = new Partition(); partition.treatment = ON_TREATMENT; diff --git a/client/src/test/java/io/split/engine/evaluator/EvaluatorTest.java b/client/src/test/java/io/split/engine/evaluator/EvaluatorTest.java index 9ef7343aa..05a87a611 100644 --- a/client/src/test/java/io/split/engine/evaluator/EvaluatorTest.java +++ b/client/src/test/java/io/split/engine/evaluator/EvaluatorTest.java @@ -48,7 +48,7 @@ public void before() { _splitCacheConsumer = Mockito.mock(SplitCacheConsumer.class); _segmentCacheConsumer = Mockito.mock(SegmentCacheConsumer.class); _ruleBasedSegmentCacheConsumer = Mockito.mock(RuleBasedSegmentCacheConsumer.class); - _evaluator = new EvaluatorImp(_splitCacheConsumer, _segmentCacheConsumer, _ruleBasedSegmentCacheConsumer, null); + _evaluator = new EvaluatorImp(_splitCacheConsumer, _segmentCacheConsumer, _ruleBasedSegmentCacheConsumer, new FallbackTreatmentCalculatorImp(null)); _matcher = Mockito.mock(CombiningMatcher.class); _evaluationContext = Mockito.mock(EvaluationContext.class); From c26b3fa3e664e8e7a84d9d13a16331df92a53fdb Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 8 Sep 2025 14:19:49 -0700 Subject: [PATCH 2/5] polish --- client/src/main/java/io/split/client/SplitClientImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/main/java/io/split/client/SplitClientImpl.java b/client/src/main/java/io/split/client/SplitClientImpl.java index 30bbea529..0953bc710 100644 --- a/client/src/main/java/io/split/client/SplitClientImpl.java +++ b/client/src/main/java/io/split/client/SplitClientImpl.java @@ -46,7 +46,6 @@ * @author adil */ public final class SplitClientImpl implements SplitClient { -// public static final SplitResult SPLIT_RESULT_CONTROL = new SplitResult(Treatments.CONTROL, null); private static final String CLIENT_DESTROY = "Client has already been destroyed - no calls possible"; private static final String CATCHALL_EXCEPTION = "CatchAll Exception"; private static final String MATCHING_KEY = "matchingKey"; From a639d54f341758d3e7de60311c1dfedb6199fc5c Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 9 Sep 2025 10:01:23 -0700 Subject: [PATCH 3/5] polishing --- .../java/io/split/client/SplitClientImpl.java | 49 +++++++++---------- .../split/engine/evaluator/EvaluatorImp.java | 2 +- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientImpl.java b/client/src/main/java/io/split/client/SplitClientImpl.java index 0953bc710..084baca0a 100644 --- a/client/src/main/java/io/split/client/SplitClientImpl.java +++ b/client/src/main/java/io/split/client/SplitClientImpl.java @@ -610,27 +610,22 @@ private Map getTreatmentsBySetsWithConfigInternal(String ma if (cleanFlagSets.isEmpty()) { return new HashMap<>(); } - List featureFlagNames = new ArrayList<>(); - try { - checkSDKReady(methodEnum); - Map result = validateBeforeEvaluateByFlagSets(matchingKey, methodEnum,bucketingKey); - if(result != null) { - return result; - } - Map evaluatorResult = _evaluator.evaluateFeaturesByFlagSets(matchingKey, - bucketingKey, new ArrayList<>(cleanFlagSets), attributes); + checkSDKReady(methodEnum); + Map result = validateBeforeEvaluateByFlagSets(matchingKey, methodEnum,bucketingKey); + if(result != null) { + return result; + } + Map evaluatorResult = _evaluator.evaluateFeaturesByFlagSets(matchingKey, + bucketingKey, new ArrayList<>(cleanFlagSets), attributes); - return processEvaluatorResult(evaluatorResult, methodEnum, matchingKey, bucketingKey, attributes, initTime, - validateProperties(evaluationOptions.getProperties())); - } catch (Exception e) { - try { + evaluatorResult.entrySet().forEach(flag -> { + if (flag.getValue().label != null && + flag.getValue().label.contains(io.split.engine.evaluator.Labels.EXCEPTION)) { _telemetryEvaluationProducer.recordException(methodEnum); - _log.error(CATCHALL_EXCEPTION, e); - } catch (Exception e1) { - // ignore } - return createMapControl(featureFlagNames); - } + }); + return processEvaluatorResult(evaluatorResult, methodEnum, matchingKey, bucketingKey, attributes, initTime, + validateProperties(evaluationOptions.getProperties())); } private Map processEvaluatorResult(Map evaluatorResult, @@ -638,18 +633,20 @@ private Map processEvaluatorResult(Map attributes, long initTime, String properties){ List decoratedImpressions = new ArrayList<>(); Map result = new HashMap<>(); - evaluatorResult.keySet().forEach(t -> { - if (evaluatorResult.get(t).label != null && evaluatorResult.get(t).label.contains(Labels.DEFINITION_NOT_FOUND) && _gates.isSDKReady()) { + evaluatorResult.keySet().forEach(flag -> { + if (evaluatorResult.get(flag).label != null && + evaluatorResult.get(flag).label.contains(Labels.DEFINITION_NOT_FOUND) && + _gates.isSDKReady()) { _log.warn(String.format("%s: you passed \"%s\" that does not exist in this environment please double check " + - "what feature flags exist in the Split user interface.", methodEnum.getMethod(), t)); - result.put(t, checkFallbackTreatment(t)); + "what feature flags exist in the Split user interface.", methodEnum.getMethod(), flag)); + result.put(flag, checkFallbackTreatment(flag)); } else { - result.put(t, new SplitResult(evaluatorResult.get(t).treatment, evaluatorResult.get(t).configurations)); + result.put(flag, new SplitResult(evaluatorResult.get(flag).treatment, evaluatorResult.get(flag).configurations)); decoratedImpressions.add( new DecoratedImpression( - new Impression(matchingKey, bucketingKey, t, evaluatorResult.get(t).treatment, System.currentTimeMillis(), - evaluatorResult.get(t).label, evaluatorResult.get(t).changeNumber, attributes, properties), - evaluatorResult.get(t).track)); + new Impression(matchingKey, bucketingKey, flag, evaluatorResult.get(flag).treatment, System.currentTimeMillis(), + evaluatorResult.get(flag).label, evaluatorResult.get(flag).changeNumber, attributes, properties), + evaluatorResult.get(flag).track)); } }); _telemetryEvaluationProducer.recordLatency(methodEnum, System.currentTimeMillis() - initTime); diff --git a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java index 282db10f7..167d8c621 100644 --- a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java +++ b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java @@ -65,7 +65,7 @@ public Map evaluateFeaturesB return evaluateFeatures(key, bucketingKey, flagSetsWithNames, attributes); } catch (Exception e) { _log.error("Evaluator Exception", e); - return createMapControl(flagSetsWithNames, "exception"); + return createMapControl(flagSetsWithNames, io.split.engine.evaluator.Labels.EXCEPTION); } } From 480d1f31322230bf1f1adb7aff712c41bf3d0f77 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 9 Sep 2025 10:01:55 -0700 Subject: [PATCH 4/5] polishing --- .../src/main/java/io/split/engine/evaluator/EvaluatorImp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java index 167d8c621..e74ea67fa 100644 --- a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java +++ b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java @@ -213,7 +213,7 @@ private TreatmentLabelAndChangeNumber evaluateParsedSplit(String matchingKey, St fallbackTreatment.getLabel(), null, getFallbackConfig(fallbackTreatment), - true); + false); } return getTreatment(matchingKey, bucketingKey, parsedSplit, attributes); } catch (ChangeNumberExceptionWrapper e) { From 076a850625e16d571888a55879d02f46b86a3c30 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 9 Sep 2025 10:37:55 -0700 Subject: [PATCH 5/5] Convert fallback config to String --- .../java/io/split/client/SplitClientImpl.java | 2 +- .../split/client/dtos/FallbackTreatment.java | 10 ++- .../split/engine/evaluator/EvaluatorImp.java | 3 +- .../io/split/client/SplitClientImplTest.java | 72 +++++++++---------- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientImpl.java b/client/src/main/java/io/split/client/SplitClientImpl.java index 084baca0a..32b68b092 100644 --- a/client/src/main/java/io/split/client/SplitClientImpl.java +++ b/client/src/main/java/io/split/client/SplitClientImpl.java @@ -548,7 +548,7 @@ private SplitResult checkFallbackTreatment(String featureName) { FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, ""); String config = null; if (fallbackTreatment.getConfig() != null) { - config = fallbackTreatment.getConfig().toString(); + config = fallbackTreatment.getConfig(); } return new SplitResult(fallbackTreatment.getTreatment(), config); } diff --git a/client/src/main/java/io/split/client/dtos/FallbackTreatment.java b/client/src/main/java/io/split/client/dtos/FallbackTreatment.java index 542f90157..291db4f48 100644 --- a/client/src/main/java/io/split/client/dtos/FallbackTreatment.java +++ b/client/src/main/java/io/split/client/dtos/FallbackTreatment.java @@ -1,13 +1,11 @@ package io.split.client.dtos; -import java.util.Map; - public class FallbackTreatment { - private final Map _config; + private final String _config; private final String _treatment; private final String _label; - public FallbackTreatment(String treatment, Map config) { + public FallbackTreatment(String treatment, String config) { _treatment = treatment; _config = config; _label = null; @@ -19,13 +17,13 @@ public FallbackTreatment(String treatment) { _label = null; } - public FallbackTreatment(String treatment, Map config, String label) { + public FallbackTreatment(String treatment, String config, String label) { _treatment = treatment; _config = config; _label = label; } - public Map getConfig() { + public String getConfig() { return _config; } diff --git a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java index e74ea67fa..f3b06f8fa 100644 --- a/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java +++ b/client/src/main/java/io/split/engine/evaluator/EvaluatorImp.java @@ -197,7 +197,7 @@ private String getConfig(ParsedSplit parsedSplit, String returnedTreatment) { private String getFallbackConfig(FallbackTreatment fallbackTreatment) { if (fallbackTreatment.getConfig() != null) { - return fallbackTreatment.getConfig().toString(); + return fallbackTreatment.getConfig(); } return null; @@ -206,7 +206,6 @@ private String getFallbackConfig(FallbackTreatment fallbackTreatment) { private TreatmentLabelAndChangeNumber evaluateParsedSplit(String matchingKey, String bucketingKey, Map attributes, ParsedSplit parsedSplit, String featureName) { try { - if (parsedSplit == null) { FallbackTreatment fallbackTreatment = _fallbackTreatmentCalculator.resolve(featureName, Labels.DEFINITION_NOT_FOUND); return new TreatmentLabelAndChangeNumber(fallbackTreatment.getTreatment(), diff --git a/client/src/test/java/io/split/client/SplitClientImplTest.java b/client/src/test/java/io/split/client/SplitClientImplTest.java index 9db75c0cc..2556508c6 100644 --- a/client/src/test/java/io/split/client/SplitClientImplTest.java +++ b/client/src/test/java/io/split/client/SplitClientImplTest.java @@ -2306,7 +2306,7 @@ public void fallbackTreatmentWithExceptionsResult() { features.put("flag", new HashSet<>(Arrays.asList("test1"))); when(splitCacheConsumer.getNamesByFlagSets(anyList())).thenReturn(features); - Map fallbcakConfigGlobal = new HashMap() {{ put("prop1", "val1"); }}; + String fallbcakConfigGlobal = "{\"prop1\", \"val1\"}"; FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration( new FallbackTreatment("on", fallbcakConfigGlobal), null); @@ -2326,19 +2326,19 @@ public void fallbackTreatmentWithExceptionsResult() { ); assertEquals("on", client.getTreatment("adil@relateiq.com", "test1")); assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); assertEquals("on", client.getTreatments("adil@relateiq.com", Arrays.asList("test1")).get("test1")); assertEquals("on", client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1")).get("test1").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1")).get("test1").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("test1")).get("test1").config()); assertEquals("on", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("test1")); assertEquals("on", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1")); assertEquals("on", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test1").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test1").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test1").config()); assertEquals("on", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test1").config()); - Map fallbcakConfigByFlag = new HashMap() {{ put("prop2", "val2"); }}; + String fallbcakConfigByFlag = "{\"prop2\", \"val2\"}"; fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on", fallbcakConfigGlobal), new HashMap() {{ put("feature", new FallbackTreatment("off", fallbcakConfigByFlag)); }}); @@ -2363,30 +2363,30 @@ public void fallbackTreatmentWithExceptionsResult() { assertEquals("on", client.getTreatment("adil@relateiq.com", "test")); assertEquals("off", client.getTreatment("adil@relateiq.com", "feature")); assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "feature").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentWithConfig("adil@relateiq.com", "feature").config()); Map result = client.getTreatments("adil@relateiq.com", Arrays.asList("feature", "test")); assertEquals("off", result.get("feature")); assertEquals("on", result.get("test")); Map results = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("feature", "test")); assertEquals("off", results.get("feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("feature").config()); + assertEquals(fallbcakConfigByFlag, results.get("feature").config()); assertEquals("on", results.get("test").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), results.get("test").config()); + assertEquals(fallbcakConfigGlobal, results.get("test").config()); assertEquals("on", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("test")); assertEquals("off", client.getTreatmentsByFlagSet("adil@relateiq.com", "flag").get("feature")); assertEquals("on", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test")); assertEquals("off", client.getTreatmentsByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature")); assertEquals("on", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").config()); assertEquals("off", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").config()); assertEquals("on", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").config()); assertEquals("off", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").config()); fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null, new HashMap() {{ put("feature", new FallbackTreatment("off", fallbcakConfigByFlag)); }}); @@ -2409,13 +2409,13 @@ public void fallbackTreatmentWithExceptionsResult() { assertEquals(Treatments.CONTROL, client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "feature").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentWithConfig("adil@relateiq.com", "feature").config()); result = client.getTreatments("adil@relateiq.com", Arrays.asList("feature", "test")); assertEquals("off", result.get("feature")); assertEquals(Treatments.CONTROL, result.get("test")); results = client.getTreatmentsWithConfig("adil@relateiq.com", Arrays.asList("feature", "test")); assertEquals("off", results.get("feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("feature").config()); + assertEquals(fallbcakConfigByFlag, results.get("feature").config()); assertEquals(Treatments.CONTROL, results.get("test").treatment()); assertEquals(null, results.get("test").config()); @@ -2426,11 +2426,11 @@ public void fallbackTreatmentWithExceptionsResult() { assertEquals(Treatments.CONTROL, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").treatment()); assertEquals(null, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("test").config()); assertEquals("off", client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentsWithConfigByFlagSet("adil@relateiq.com", "flag").get("feature").config()); assertEquals(Treatments.CONTROL, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").treatment()); assertEquals(null, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("test").config()); assertEquals("off", client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")).get("feature").config()); } @Test @@ -2456,7 +2456,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { flagFeatures.put("flag", new HashSet<>(Arrays.asList("test1", "test2", "test3"))); when(splitCacheConsumer.getNamesByFlagSets(anyList())).thenReturn(flagFeatures); - Map fallbcakConfigGlobal = new HashMap() {{ put("prop1", "val1"); }}; + String fallbcakConfigGlobal = "{\"prop1\", \"val1\"}"; FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration( new FallbackTreatment("on", fallbcakConfigGlobal), null); @@ -2477,7 +2477,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", client.getTreatment("adil@relateiq.com", "test1")); assertEquals("on", client.getTreatment("adil@relateiq.com", "test2")); assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test2").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); Map result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1", "test2")); assertEquals("off", result.get("test1")); @@ -2486,7 +2486,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", resultWithConfig.get("test1").treatment()); assertEquals(null, resultWithConfig.get("test1").config()); assertEquals("on", resultWithConfig.get("test2").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), resultWithConfig.get("test2").config()); + assertEquals(fallbcakConfigGlobal, resultWithConfig.get("test2").config()); result = client.getTreatmentsByFlagSet("adil@relateiq.com", "flag"); assertEquals("off", result.get("test1")); @@ -2498,14 +2498,14 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", resultWithConfig.get("test1").treatment()); assertEquals(null, resultWithConfig.get("test1").config()); assertEquals("on", resultWithConfig.get("test2").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), resultWithConfig.get("test2").config()); + assertEquals(fallbcakConfigGlobal, resultWithConfig.get("test2").config()); resultWithConfig = client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")); assertEquals("off", resultWithConfig.get("test1").treatment()); assertEquals(null, resultWithConfig.get("test1").config()); assertEquals("on", resultWithConfig.get("test2").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), resultWithConfig.get("test2").config()); + assertEquals(fallbcakConfigGlobal, resultWithConfig.get("test2").config()); - Map fallbcakConfigByFlag = new HashMap() {{ put("prop2", "val2"); }}; + String fallbcakConfigByFlag = "{\"prop2\", \"val2\"}"; fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on", fallbcakConfigGlobal), new HashMap() {{ put("test2", new FallbackTreatment("off-fallback", fallbcakConfigByFlag)); }}); @@ -2530,9 +2530,9 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); assertEquals("off-fallback", client.getTreatmentWithConfig("adil@relateiq.com", "test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); assertEquals("on", client.getTreatmentWithConfig("adil@relateiq.com", "test3").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test3").config()); + assertEquals(fallbcakConfigGlobal, client.getTreatmentWithConfig("adil@relateiq.com", "test3").config()); result = client.getTreatments("adil@relateiq.com", Arrays.asList("test1", "test2", "test3")); assertEquals("off", result.get("test1")); @@ -2543,9 +2543,9 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", results.get("test1").treatment()); assertEquals(null, results.get("test1").config()); assertEquals("off-fallback", results.get("test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(fallbcakConfigByFlag, results.get("test2").config()); assertEquals("on", results.get("test3").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), results.get("test3").config()); + assertEquals(fallbcakConfigGlobal, results.get("test3").config()); result = client.getTreatmentsByFlagSet("adil@relateiq.com", "flag"); assertEquals("off", result.get("test1")); @@ -2561,17 +2561,17 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", results.get("test1").treatment()); assertEquals(null, results.get("test1").config()); assertEquals("off-fallback", results.get("test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(fallbcakConfigByFlag, results.get("test2").config()); assertEquals("on", results.get("test3").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), results.get("test3").config()); + assertEquals(fallbcakConfigGlobal, results.get("test3").config()); results = client.getTreatmentsWithConfigByFlagSets("adil@relateiq.com", Arrays.asList("flag")); assertEquals("off", results.get("test1").treatment()); assertEquals(null, results.get("test1").config()); assertEquals("off-fallback", results.get("test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(fallbcakConfigByFlag, results.get("test2").config()); assertEquals("on", results.get("test3").treatment()); - assertEquals(fallbcakConfigGlobal.toString(), results.get("test3").config()); + assertEquals(fallbcakConfigGlobal, results.get("test3").config()); fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null, new HashMap() {{ put("test2", new FallbackTreatment("off-fallback", fallbcakConfigByFlag)); }}); @@ -2596,7 +2596,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", client.getTreatmentWithConfig("adil@relateiq.com", "test1").treatment()); assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test1").config()); assertEquals("off-fallback", client.getTreatmentWithConfig("adil@relateiq.com", "test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); + assertEquals(fallbcakConfigByFlag, client.getTreatmentWithConfig("adil@relateiq.com", "test2").config()); assertEquals(Treatments.CONTROL, client.getTreatmentWithConfig("adil@relateiq.com", "test3").treatment()); assertEquals(null, client.getTreatmentWithConfig("adil@relateiq.com", "test3").config()); @@ -2609,7 +2609,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", results.get("test1").treatment()); assertEquals(null, results.get("test1").config()); assertEquals("off-fallback", results.get("test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(fallbcakConfigByFlag, results.get("test2").config()); assertEquals(Treatments.CONTROL, results.get("test3").treatment()); assertEquals(null, results.get("test3").config()); @@ -2627,7 +2627,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", results.get("test1").treatment()); assertEquals(null, results.get("test1").config()); assertEquals("off-fallback", results.get("test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(fallbcakConfigByFlag, results.get("test2").config()); assertEquals(Treatments.CONTROL, results.get("test3").treatment()); assertEquals(null, results.get("test3").config()); @@ -2635,7 +2635,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() { assertEquals("off", results.get("test1").treatment()); assertEquals(null, results.get("test1").config()); assertEquals("off-fallback", results.get("test2").treatment()); - assertEquals(fallbcakConfigByFlag.toString(), results.get("test2").config()); + assertEquals(fallbcakConfigByFlag, results.get("test2").config()); assertEquals(Treatments.CONTROL, results.get("test3").treatment()); assertEquals(null, results.get("test3").config()); }