From 9ece1c469b091df8fabb0a3e8da774976902915b Mon Sep 17 00:00:00 2001 From: Mauro Sanz <51236193+sanzmauro@users.noreply.github.com> Date: Wed, 8 Nov 2023 14:55:22 -0300 Subject: [PATCH 01/88] Update CHANGES.txt --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 5a060d81e..72201bdb4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -4.10.1 (Nov 9, 2023) +4.10.1 (Nov 8, 2023) - Fixed handler for response http headers. 4.10.0 (Nov 2, 2023) From 8cd72f352d9209938cb3f992e6c1141778a888d0 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 5 Jan 2024 14:02:39 -0300 Subject: [PATCH 02/88] [SDKS-7890] Add java conventions and remove imports not using --- .../io/split/client/SplitClientConfig.java | 2 +- .../io/split/client/SplitFactoryImpl.java | 4 +- .../io/split/engine/SDKReadinessGates.java | 3 - .../io/split/engine/common/SplitTasks.java | 3 - .../split/engine/matchers/AllKeysMatcher.java | 1 - .../engine/matchers/AttributeMatcher.java | 1 - .../split/engine/matchers/BetweenMatcher.java | 1 - .../split/engine/matchers/BooleanMatcher.java | 1 - .../engine/matchers/CombiningMatcher.java | 2 - .../split/engine/matchers/EqualToMatcher.java | 1 - .../matchers/GreaterThanOrEqualToMatcher.java | 1 - .../matchers/LessThanOrEqualToMatcher.java | 1 - .../collections/ContainsAllOfSetMatcher.java | 1 - .../collections/ContainsAnyOfSetMatcher.java | 1 - .../collections/EqualToSetMatcher.java | 1 - .../collections/PartOfSetMatcher.java | 1 - .../strings/ContainsAnyOfMatcher.java | 1 - .../strings/EndsWithAnyOfMatcher.java | 1 - .../strings/RegularExpressionMatcher.java | 1 - .../strings/StartsWithAnyOfMatcher.java | 1 - .../matchers/strings/WhitelistMatcher.java | 1 - .../io/split/engine/splitter/Splitter.java | 8 +- .../sse/dtos/RawMessageNotification.java | 2 - .../pluggable/domain/UserPipelineWrapper.java | 1 - .../io/split/telemetry/domain/HTTPErrors.java | 30 ++--- .../split/telemetry/domain/HTTPLatencies.java | 30 ++--- .../telemetry/domain/LastSynchronization.java | 30 ++--- .../java/io/split/telemetry/domain/Rates.java | 22 ++-- .../java/io/split/telemetry/domain/Stats.java | 2 +- .../telemetry/domain/StreamingEvent.java | 10 +- .../split/telemetry/domain/URLOverrides.java | 22 ++-- .../storage/InMemoryTelemetryStorage.java | 42 +++--- .../TelemetryInMemorySubmitter.java | 24 ++-- .../synchronizer/TelemetrySyncTask.java | 1 - .../io/split/client/SplitManagerImplTest.java | 4 +- .../client/dtos/ImpressionCountTest.java | 1 - .../engine/experiments/SplitParserTest.java | 120 ++++++------------ .../engine/matchers/AttributeMatcherTest.java | 116 ++++++++--------- .../engine/matchers/BetweenMatcherTest.java | 30 ++--- .../engine/matchers/BooleanMatcherTest.java | 4 +- .../engine/matchers/CombiningMatcherTest.java | 15 +-- .../engine/matchers/EqualToMatcherTest.java | 52 ++++---- .../GreaterThanOrEqualToMatcherTest.java | 54 ++++---- .../LessThanOrEqualToMatcherTest.java | 54 ++++---- .../engine/matchers/NegatableMatcherTest.java | 15 +-- .../ContainsAllOfSetMatcherTest.java | 41 +++--- .../ContainsAnyOfSetMatcherTest.java | 42 +++--- .../collections/EqualToSetMatcherTest.java | 52 ++++---- .../collections/PartOfSetMatcherTest.java | 40 +++--- .../segments/SegmentFetcherImpTest.java | 13 +- .../engine/splitter/HashConsistencyTest.java | 5 +- .../io/split/service/HttpPostImpTest.java | 6 +- .../pluggable/CustomStorageWrapperImp.java | 2 +- .../storage/InMemoryTelemetryStorageTest.java | 60 ++++----- .../TelemetryInMemorySubmitterTest.java | 46 +++---- 55 files changed, 464 insertions(+), 562 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 11e2ec2bc..4e344444e 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -355,7 +355,7 @@ public String telemetryURL() { return _telemetryURL; } - public int get_telemetryRefreshRate() { + public int getTelemetryRefreshRate() { return _telemetryRefreshRate; } public int streamingRetryDelay() {return _onDemandFetchRetryDelayMs;} diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index aab089b69..49c257882 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -227,7 +227,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn EventsSender eventsSender = EventsSender.create(_httpclient, _eventsRootTarget, _telemetryStorageProducer); _eventsTask = EventsTask.create(config.eventSendIntervalInMillis(), eventsStorage, eventsSender, config.getThreadFactory()); - _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); + _telemetrySyncTask = new TelemetrySyncTask(config.getTelemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); // Evaluator _evaluator = new EvaluatorImp(splitCache, segmentCache); @@ -313,7 +313,7 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _impressionsSender = PluggableImpressionSender.create(customStorageWrapper); _uniqueKeysTracker = createUniqueKeysTracker(config); _impressionsManager = buildImpressionsManager(config, userCustomImpressionAdapterConsumer, userCustomImpressionAdapterProducer); - _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); + _telemetrySyncTask = new TelemetrySyncTask(config.getTelemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); SplitTasks splitTasks = SplitTasks.build(null, null, _impressionsManager, null, _telemetrySyncTask, _uniqueKeysTracker); diff --git a/client/src/main/java/io/split/engine/SDKReadinessGates.java b/client/src/main/java/io/split/engine/SDKReadinessGates.java index b4fd99fe6..c5ca5dbc8 100644 --- a/client/src/main/java/io/split/engine/SDKReadinessGates.java +++ b/client/src/main/java/io/split/engine/SDKReadinessGates.java @@ -3,9 +3,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; diff --git a/client/src/main/java/io/split/engine/common/SplitTasks.java b/client/src/main/java/io/split/engine/common/SplitTasks.java index 6045e826e..d2960d824 100644 --- a/client/src/main/java/io/split/engine/common/SplitTasks.java +++ b/client/src/main/java/io/split/engine/common/SplitTasks.java @@ -5,11 +5,8 @@ import io.split.client.impressions.UniqueKeysTracker; import io.split.engine.experiments.SplitSynchronizationTask; import io.split.engine.segments.SegmentSynchronizationTask; -import io.split.engine.segments.SegmentSynchronizationTaskImp; import io.split.telemetry.synchronizer.TelemetrySyncTask; -import static com.google.common.base.Preconditions.checkNotNull; - public class SplitTasks { private final SplitSynchronizationTask _splitSynchronizationTask; private final SegmentSynchronizationTask _segmentSynchronizationTask; diff --git a/client/src/main/java/io/split/engine/matchers/AllKeysMatcher.java b/client/src/main/java/io/split/engine/matchers/AllKeysMatcher.java index 54de94ce0..790224ab1 100644 --- a/client/src/main/java/io/split/engine/matchers/AllKeysMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/AllKeysMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/AttributeMatcher.java b/client/src/main/java/io/split/engine/matchers/AttributeMatcher.java index 487a5d3de..92deb0140 100644 --- a/client/src/main/java/io/split/engine/matchers/AttributeMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/AttributeMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; import java.util.Objects; diff --git a/client/src/main/java/io/split/engine/matchers/BetweenMatcher.java b/client/src/main/java/io/split/engine/matchers/BetweenMatcher.java index 79ccd676c..a0ccfc1b7 100644 --- a/client/src/main/java/io/split/engine/matchers/BetweenMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/BetweenMatcher.java @@ -2,7 +2,6 @@ import io.split.client.dtos.DataType; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/BooleanMatcher.java b/client/src/main/java/io/split/engine/matchers/BooleanMatcher.java index 0a7418bb7..79d5a303f 100644 --- a/client/src/main/java/io/split/engine/matchers/BooleanMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/BooleanMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/CombiningMatcher.java b/client/src/main/java/io/split/engine/matchers/CombiningMatcher.java index da75c53f3..4097ef851 100644 --- a/client/src/main/java/io/split/engine/matchers/CombiningMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/CombiningMatcher.java @@ -2,10 +2,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import io.split.client.SplitClientImpl; import io.split.client.dtos.MatcherCombiner; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.List; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/EqualToMatcher.java b/client/src/main/java/io/split/engine/matchers/EqualToMatcher.java index dece1e539..9a1e32f37 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToMatcher.java @@ -2,7 +2,6 @@ import io.split.client.dtos.DataType; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToMatcher.java index 21620b920..1b83dc2c3 100644 --- a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToMatcher.java @@ -2,7 +2,6 @@ import io.split.client.dtos.DataType; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToMatcher.java index bd4e779f2..24a74aaba 100644 --- a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToMatcher.java @@ -2,7 +2,6 @@ import io.split.client.dtos.DataType; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcher.java b/client/src/main/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcher.java index a2e477df7..5f4f9433a 100644 --- a/client/src/main/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.collections; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcher.java b/client/src/main/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcher.java index 93c7c2815..3a2514401 100644 --- a/client/src/main/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.collections; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/collections/EqualToSetMatcher.java b/client/src/main/java/io/split/engine/matchers/collections/EqualToSetMatcher.java index bf811c70a..4a09c9efc 100644 --- a/client/src/main/java/io/split/engine/matchers/collections/EqualToSetMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/collections/EqualToSetMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.collections; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/collections/PartOfSetMatcher.java b/client/src/main/java/io/split/engine/matchers/collections/PartOfSetMatcher.java index 88974cb58..8bb5f1399 100644 --- a/client/src/main/java/io/split/engine/matchers/collections/PartOfSetMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/collections/PartOfSetMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.collections; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/strings/ContainsAnyOfMatcher.java b/client/src/main/java/io/split/engine/matchers/strings/ContainsAnyOfMatcher.java index 40f950cbe..b8cbe8fca 100644 --- a/client/src/main/java/io/split/engine/matchers/strings/ContainsAnyOfMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/strings/ContainsAnyOfMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.strings; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/strings/EndsWithAnyOfMatcher.java b/client/src/main/java/io/split/engine/matchers/strings/EndsWithAnyOfMatcher.java index 971fe01cc..32ac9f7f3 100644 --- a/client/src/main/java/io/split/engine/matchers/strings/EndsWithAnyOfMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/strings/EndsWithAnyOfMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.strings; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/strings/RegularExpressionMatcher.java b/client/src/main/java/io/split/engine/matchers/strings/RegularExpressionMatcher.java index f63dbcca8..f64b3264b 100644 --- a/client/src/main/java/io/split/engine/matchers/strings/RegularExpressionMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/strings/RegularExpressionMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.strings; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Map; diff --git a/client/src/main/java/io/split/engine/matchers/strings/StartsWithAnyOfMatcher.java b/client/src/main/java/io/split/engine/matchers/strings/StartsWithAnyOfMatcher.java index bb74ee185..7f1ed2cad 100644 --- a/client/src/main/java/io/split/engine/matchers/strings/StartsWithAnyOfMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/strings/StartsWithAnyOfMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.strings; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/matchers/strings/WhitelistMatcher.java b/client/src/main/java/io/split/engine/matchers/strings/WhitelistMatcher.java index d41123e53..5068c1437 100644 --- a/client/src/main/java/io/split/engine/matchers/strings/WhitelistMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/strings/WhitelistMatcher.java @@ -1,7 +1,6 @@ package io.split.engine.matchers.strings; import io.split.engine.evaluator.EvaluationContext; -import io.split.engine.evaluator.Evaluator; import io.split.engine.matchers.Matcher; import java.util.Collection; diff --git a/client/src/main/java/io/split/engine/splitter/Splitter.java b/client/src/main/java/io/split/engine/splitter/Splitter.java index 60bb6d740..c867a81db 100644 --- a/client/src/main/java/io/split/engine/splitter/Splitter.java +++ b/client/src/main/java/io/split/engine/splitter/Splitter.java @@ -33,15 +33,15 @@ public static String getTreatment(String key, int seed, List partitio static long hash(String key, int seed, int algo) { switch (algo) { case ALGO_MURMUR: - return murmur_hash(key, seed); + return murmurHash(key, seed); case ALGO_LEGACY: default: - return legacy_hash(key, seed); + return legacyHash(key, seed); } } /*package private*/ - static long murmur_hash(String key, int seed) { + static long murmurHash(String key, int seed) { return MurmurHash3.murmurhash3_x86_32(key, 0, key.length(), seed); } @@ -56,7 +56,7 @@ public static int getBucket(String key, int seed, int algo) { } /*package private*/ - static int legacy_hash(String key, int seed) { + static int legacyHash(String key, int seed) { int h = 0; for (int i = 0; i < key.length(); i++) { h = 31 * h + key.charAt(i); diff --git a/client/src/main/java/io/split/engine/sse/dtos/RawMessageNotification.java b/client/src/main/java/io/split/engine/sse/dtos/RawMessageNotification.java index f39bc8b20..9fc5ad6cd 100644 --- a/client/src/main/java/io/split/engine/sse/dtos/RawMessageNotification.java +++ b/client/src/main/java/io/split/engine/sse/dtos/RawMessageNotification.java @@ -1,7 +1,5 @@ package io.split.engine.sse.dtos; -import java.util.Map; - public class RawMessageNotification { private String id; private String clientId; diff --git a/client/src/main/java/io/split/storages/pluggable/domain/UserPipelineWrapper.java b/client/src/main/java/io/split/storages/pluggable/domain/UserPipelineWrapper.java index 505fe11c6..81ddc691a 100644 --- a/client/src/main/java/io/split/storages/pluggable/domain/UserPipelineWrapper.java +++ b/client/src/main/java/io/split/storages/pluggable/domain/UserPipelineWrapper.java @@ -5,7 +5,6 @@ import pluggable.Pipeline; import pluggable.Result; -import java.util.ArrayList; import java.util.List; public class UserPipelineWrapper implements Pipeline{ diff --git a/client/src/main/java/io/split/telemetry/domain/HTTPErrors.java b/client/src/main/java/io/split/telemetry/domain/HTTPErrors.java index dac746117..69c85ad85 100644 --- a/client/src/main/java/io/split/telemetry/domain/HTTPErrors.java +++ b/client/src/main/java/io/split/telemetry/domain/HTTPErrors.java @@ -39,59 +39,59 @@ public HTTPErrors() { _telemetry = new ConcurrentHashMap<>(); } - public Map get_splits() { + public Map getSplits() { return _splits; } - public void set_splits(Map _splits) { + public void setSplits(Map _splits) { this._splits = _splits; } - public Map get_segments() { + public Map getSegments() { return _segments; } - public void set_segments(Map _segments) { + public void setSegments(Map _segments) { this._segments = _segments; } - public Map get_impressions() { + public Map getImpressions() { return _impressions; } - public void set_impressions(Map _impressions) { + public void setImpressions(Map _impressions) { this._impressions = _impressions; } - public Map get_events() { + public Map getEvents() { return _events; } - public void set_events(Map _events) { + public void setEvents(Map _events) { this._events = _events; } - public Map get_token() { + public Map getToken() { return _token; } - public void set_token(Map _token) { + public void setToken(Map _token) { this._token = _token; } - public Map get_telemetry() { + public Map getTelemetry() { return _telemetry; } - public void set_telemetry(Map _telemetry) { + public void setTelemetry(Map _telemetry) { this._telemetry = _telemetry; } - public Map get_impressionsCount() { + public Map getImpressionsCount() { return _impressionsCount; } - public void set_impressionsCount(Map _impressionsCount) { + public void setImpressionsCount(Map _impressionsCount) { this._impressionsCount = _impressionsCount; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/domain/HTTPLatencies.java b/client/src/main/java/io/split/telemetry/domain/HTTPLatencies.java index 0e0791ed9..1b7ec2f8e 100644 --- a/client/src/main/java/io/split/telemetry/domain/HTTPLatencies.java +++ b/client/src/main/java/io/split/telemetry/domain/HTTPLatencies.java @@ -39,59 +39,59 @@ public HTTPLatencies() { _telemetry = new ArrayList<>(); } - public List get_splits() { + public List getSplits() { return _splits; } - public void set_splits(List _splits) { + public void setSplits(List _splits) { this._splits = _splits; } - public List get_segments() { + public List getSegments() { return _segments; } - public void set_segments(List _segments) { + public void setSegments(List _segments) { this._segments = _segments; } - public List get_impressions() { + public List getImpressions() { return _impressions; } - public void set_impressions(List _impressions) { + public void setImpressions(List _impressions) { this._impressions = _impressions; } - public List get_events() { + public List getEvents() { return _events; } - public void set_events(List _events) { + public void setEvents(List _events) { this._events = _events; } - public List get_token() { + public List getToken() { return _token; } - public void set_token(List _token) { + public void setToken(List _token) { this._token = _token; } - public List get_telemetry() { + public List getTelemetry() { return _telemetry; } - public void set_telemetry(List _telemetry) { + public void setTelemetry(List _telemetry) { this._telemetry = _telemetry; } - public List get_impressionsCount() { + public List getImpressionsCount() { return _impressionsCount; } - public void set_impressionsCount(List _impressionsCount) { + public void setImpressionsCount(List _impressionsCount) { this._impressionsCount = _impressionsCount; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/domain/LastSynchronization.java b/client/src/main/java/io/split/telemetry/domain/LastSynchronization.java index 59586562e..74889e1f9 100644 --- a/client/src/main/java/io/split/telemetry/domain/LastSynchronization.java +++ b/client/src/main/java/io/split/telemetry/domain/LastSynchronization.java @@ -26,59 +26,59 @@ public class LastSynchronization { @SerializedName(FIELD_TELEMETRY) private long _telemetry; - public long get_splits() { + public long getSplits() { return _splits; } - public void set_splits(long _splits) { + public void setSplits(long _splits) { this._splits = _splits; } - public long get_segments() { + public long getSegments() { return _segments; } - public void set_segments(long _segments) { + public void setSegments(long _segments) { this._segments = _segments; } - public long get_impressions() { + public long getImpressions() { return _impressions; } - public void set_impressions(long _impressions) { + public void setImpressions(long _impressions) { this._impressions = _impressions; } - public long get_events() { + public long getEvents() { return _events; } - public void set_events(long _events) { + public void setEvents(long _events) { this._events = _events; } - public long get_token() { + public long getToken() { return _token; } - public void set_token(long _token) { + public void setToken(long _token) { this._token = _token; } - public long get_telemetry() { + public long getTelemetry() { return _telemetry; } - public void set_telemetry(long _telemetry) { + public void setTelemetry(long _telemetry) { this._telemetry = _telemetry; } - public long get_impressionsCount() { + public long getImpressionsCount() { return _impressionsCount; } - public void set_impressionsCount(long _impressionsCount) { + public void setImpressionsCount(long _impressionsCount) { this._impressionsCount = _impressionsCount; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/domain/Rates.java b/client/src/main/java/io/split/telemetry/domain/Rates.java index e80d26079..0ae5efdac 100644 --- a/client/src/main/java/io/split/telemetry/domain/Rates.java +++ b/client/src/main/java/io/split/telemetry/domain/Rates.java @@ -20,43 +20,43 @@ public class Rates { @SerializedName(FIELD_TELEMETRY) private long _telemetry; - public long get_splits() { + public long getSplits() { return _splits; } - public void set_splits(long _splits) { + public void setSplits(long _splits) { this._splits = _splits; } - public long get_segments() { + public long getSegments() { return _segments; } - public void set_segments(long _segments) { + public void setSegments(long _segments) { this._segments = _segments; } - public long get_impressions() { + public long getImpressions() { return _impressions; } - public void set_impressions(long _impressions) { + public void setImpressions(long _impressions) { this._impressions = _impressions; } - public long get_events() { + public long getEvents() { return _events; } - public void set_events(long _events) { + public void setEvents(long _events) { this._events = _events; } - public long get_telemetry() { + public long getTelemetry() { return _telemetry; } - public void set_telemetry(long _telemetry) { + public void setTelemetry(long _telemetry) { this._telemetry = _telemetry; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/domain/Stats.java b/client/src/main/java/io/split/telemetry/domain/Stats.java index 7d271969f..55882cdc9 100644 --- a/client/src/main/java/io/split/telemetry/domain/Stats.java +++ b/client/src/main/java/io/split/telemetry/domain/Stats.java @@ -215,4 +215,4 @@ public UpdatesFromSSE getUpdatesFromSSE() { public void setUpdatesFromSSE(UpdatesFromSSE updatesFromSSE) { this._updatesFromSSE = updatesFromSSE; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/domain/StreamingEvent.java b/client/src/main/java/io/split/telemetry/domain/StreamingEvent.java index 161b29762..9fd3ae568 100644 --- a/client/src/main/java/io/split/telemetry/domain/StreamingEvent.java +++ b/client/src/main/java/io/split/telemetry/domain/StreamingEvent.java @@ -20,19 +20,19 @@ public StreamingEvent(int _type, long _data, long _timestamp) { this._timestamp = _timestamp; } - public int get_type() { + public int getType() { return _type; } - public void set_type(int _type) { + public void setType(int _type) { this._type = _type; } - public long get_data() { + public long getData() { return _data; } - public void set_data(long _data) { + public void setData(long _data) { this._data = _data; } @@ -43,4 +43,4 @@ public long getTimestamp() { public void setTimestamp(long timestamp) { this._timestamp = timestamp; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/domain/URLOverrides.java b/client/src/main/java/io/split/telemetry/domain/URLOverrides.java index 5813f1d6c..587fdf3dd 100644 --- a/client/src/main/java/io/split/telemetry/domain/URLOverrides.java +++ b/client/src/main/java/io/split/telemetry/domain/URLOverrides.java @@ -20,43 +20,43 @@ public class URLOverrides { @SerializedName(FIELD_TELEMETRY) private boolean _telemetry; - public boolean is_sdk() { + public boolean isSdk() { return _sdk; } - public void set_sdk(boolean _sdk) { + public void setSdk(boolean _sdk) { this._sdk = _sdk; } - public boolean is_events() { + public boolean isEvents() { return _events; } - public void set_events(boolean _events) { + public void setEvents(boolean _events) { this._events = _events; } - public boolean is_auth() { + public boolean isAuth() { return _auth; } - public void set_auth(boolean _auth) { + public void setAuth(boolean _auth) { this._auth = _auth; } - public boolean is_stream() { + public boolean isStream() { return _stream; } - public void set_stream(boolean _stream) { + public void setStream(boolean _stream) { this._stream = _stream; } - public boolean is_telemetry() { + public boolean isTelemetry() { return _telemetry; } - public void set_telemetry(boolean _telemetry) { + public void setTelemetry(boolean _telemetry) { this._telemetry = _telemetry; } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/telemetry/storage/InMemoryTelemetryStorage.java b/client/src/main/java/io/split/telemetry/storage/InMemoryTelemetryStorage.java index 94246fa7f..6958f110a 100644 --- a/client/src/main/java/io/split/telemetry/storage/InMemoryTelemetryStorage.java +++ b/client/src/main/java/io/split/telemetry/storage/InMemoryTelemetryStorage.java @@ -152,13 +152,13 @@ public long getEventStats(EventsDataRecordsEnum dataType) { @Override public LastSynchronization getLastSynchronization() { LastSynchronization lastSynchronization = new LastSynchronization(); - lastSynchronization.set_splits(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.SPLITS).get()); - lastSynchronization.set_segments(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.SEGMENTS).get()); - lastSynchronization.set_impressions(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.IMPRESSIONS).get()); - lastSynchronization.set_impressionsCount(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT).get()); - lastSynchronization.set_events(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.EVENTS).get()); - lastSynchronization.set_telemetry(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.TELEMETRY).get()); - lastSynchronization.set_token(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.TOKEN).get()); + lastSynchronization.setSplits(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.SPLITS).get()); + lastSynchronization.setSegments(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.SEGMENTS).get()); + lastSynchronization.setImpressions(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.IMPRESSIONS).get()); + lastSynchronization.setImpressionsCount(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT).get()); + lastSynchronization.setEvents(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.EVENTS).get()); + lastSynchronization.setTelemetry(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.TELEMETRY).get()); + lastSynchronization.setToken(_lastSynchronizationRecords.get(LastSynchronizationRecordsEnum.TOKEN).get()); return lastSynchronization; } @@ -166,13 +166,13 @@ public LastSynchronization getLastSynchronization() { @Override public HTTPErrors popHTTPErrors() { HTTPErrors errors = new HTTPErrors(); - errors.set_splits(_httpErrors.get(ResourceEnum.SPLIT_SYNC)); - errors.set_segments(_httpErrors.get(ResourceEnum.SEGMENT_SYNC)); - errors.set_impressions(_httpErrors.get(ResourceEnum.IMPRESSION_SYNC)); - errors.set_impressionsCount(_httpErrors.get(ResourceEnum.IMPRESSION_COUNT_SYNC)); - errors.set_events(_httpErrors.get(ResourceEnum.EVENT_SYNC)); - errors.set_telemetry(_httpErrors.get(ResourceEnum.TELEMETRY_SYNC)); - errors.set_token(_httpErrors.get(ResourceEnum.TOKEN_SYNC)); + errors.setSplits(_httpErrors.get(ResourceEnum.SPLIT_SYNC)); + errors.setSegments(_httpErrors.get(ResourceEnum.SEGMENT_SYNC)); + errors.setImpressions(_httpErrors.get(ResourceEnum.IMPRESSION_SYNC)); + errors.setImpressionsCount(_httpErrors.get(ResourceEnum.IMPRESSION_COUNT_SYNC)); + errors.setEvents(_httpErrors.get(ResourceEnum.EVENT_SYNC)); + errors.setTelemetry(_httpErrors.get(ResourceEnum.TELEMETRY_SYNC)); + errors.setToken(_httpErrors.get(ResourceEnum.TOKEN_SYNC)); _httpErrors.clear(); initHttpErrors(); @@ -183,13 +183,13 @@ public HTTPErrors popHTTPErrors() { @Override public HTTPLatencies popHTTPLatencies(){ HTTPLatencies latencies = new HTTPLatencies(); - latencies.set_splits(_httpLatencies.get(HTTPLatenciesEnum.SPLITS).fetchAndClearAll()); - latencies.set_segments(_httpLatencies.get(HTTPLatenciesEnum.SEGMENTS).fetchAndClearAll()); - latencies.set_impressions(_httpLatencies.get(HTTPLatenciesEnum.IMPRESSIONS).fetchAndClearAll()); - latencies.set_impressionsCount(_httpLatencies.get(HTTPLatenciesEnum.IMPRESSIONS_COUNT).fetchAndClearAll()); - latencies.set_events(_httpLatencies.get(HTTPLatenciesEnum.EVENTS).fetchAndClearAll()); - latencies.set_telemetry(_httpLatencies.get(HTTPLatenciesEnum.TELEMETRY).fetchAndClearAll()); - latencies.set_token(_httpLatencies.get(HTTPLatenciesEnum.TOKEN).fetchAndClearAll()); + latencies.setSplits(_httpLatencies.get(HTTPLatenciesEnum.SPLITS).fetchAndClearAll()); + latencies.setSegments(_httpLatencies.get(HTTPLatenciesEnum.SEGMENTS).fetchAndClearAll()); + latencies.setImpressions(_httpLatencies.get(HTTPLatenciesEnum.IMPRESSIONS).fetchAndClearAll()); + latencies.setImpressionsCount(_httpLatencies.get(HTTPLatenciesEnum.IMPRESSIONS_COUNT).fetchAndClearAll()); + latencies.setEvents(_httpLatencies.get(HTTPLatenciesEnum.EVENTS).fetchAndClearAll()); + latencies.setTelemetry(_httpLatencies.get(HTTPLatenciesEnum.TELEMETRY).fetchAndClearAll()); + latencies.setToken(_httpLatencies.get(HTTPLatenciesEnum.TOKEN).fetchAndClearAll()); return latencies; } diff --git a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java index 4f52bcdf1..b736ada52 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java @@ -109,17 +109,17 @@ Config generateConfig(SplitClientConfig splitClientConfig, long readyTimestamp, } List impressions = getImpressions(impressionsListeners); - rates.set_telemetry(splitClientConfig.get_telemetryRefreshRate()); - rates.set_events(splitClientConfig.eventSendIntervalInMillis()); - rates.set_impressions(splitClientConfig.impressionsRefreshRate()); - rates.set_segments(splitClientConfig.segmentsRefreshRate()); - rates.set_splits(splitClientConfig.featuresRefreshRate()); - - urlOverrides.set_auth(!SplitClientConfig.AUTH_ENDPOINT.equals(splitClientConfig.authServiceURL())); - urlOverrides.set_stream(!SplitClientConfig.STREAMING_ENDPOINT.equals(splitClientConfig.streamingServiceURL())); - urlOverrides.set_sdk(!SplitClientConfig.SDK_ENDPOINT.equals(splitClientConfig.endpoint())); - urlOverrides.set_events(!SplitClientConfig.EVENTS_ENDPOINT.equals(splitClientConfig.eventsEndpoint())); - urlOverrides.set_telemetry(!SplitClientConfig.TELEMETRY_ENDPOINT.equals(splitClientConfig.telemetryURL())); + rates.setTelemetry(splitClientConfig.getTelemetryRefreshRate()); + rates.setEvents(splitClientConfig.eventSendIntervalInMillis()); + rates.setImpressions(splitClientConfig.impressionsRefreshRate()); + rates.setSegments(splitClientConfig.segmentsRefreshRate()); + rates.setSplits(splitClientConfig.featuresRefreshRate()); + + urlOverrides.setAuth(!SplitClientConfig.AUTH_ENDPOINT.equals(splitClientConfig.authServiceURL())); + urlOverrides.setStream(!SplitClientConfig.STREAMING_ENDPOINT.equals(splitClientConfig.streamingServiceURL())); + urlOverrides.setSdk(!SplitClientConfig.SDK_ENDPOINT.equals(splitClientConfig.endpoint())); + urlOverrides.setEvents(!SplitClientConfig.EVENTS_ENDPOINT.equals(splitClientConfig.eventsEndpoint())); + urlOverrides.setTelemetry(!SplitClientConfig.TELEMETRY_ENDPOINT.equals(splitClientConfig.telemetryURL())); config.setBurTimeouts(_telemetryStorageConsumer.getBURTimeouts()); config.setNonReadyUsages(_telemetryStorageConsumer.getNonReadyUsages()); @@ -170,4 +170,4 @@ private List getImpressions(List(), 1L); segmentCache.updateSegment(SALES_PEOPLE, Stream.of("kunal").collect(Collectors.toList()), new ArrayList<>(), 1L); @@ -87,12 +86,11 @@ public void works() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test public void worksWithConfig() { - SDKReadinessGates gates = new SDKReadinessGates(); SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); segmentCache.updateSegment(EMPLOYEES, Stream.of("adil", "pato", "trevor").collect(Collectors.toList()), new ArrayList<>(), 1L); segmentCache.updateSegment(SALES_PEOPLE, Stream.of("kunal").collect(Collectors.toList()), new ArrayList<>(), 1L); @@ -129,12 +127,12 @@ public void worksWithConfig() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, configurations, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); - assertThat(actual.configurations().get("on"), is(equalTo(configurations.get("on")))); + Assert.assertEquals(actual, expected); + Assert.assertEquals(actual.configurations().get("on"), configurations.get("on")); } @Test - public void works_for_two_conditions() { + public void worksForTwoConditions() { SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); segmentCache.updateSegment(EMPLOYEES, Stream.of("adil", "pato", "trevor").collect(Collectors.toList()), new ArrayList<>(), 1L); segmentCache.updateSegment(SALES_PEOPLE, Stream.of("kunal").collect(Collectors.toList()), new ArrayList<>(), 1L); @@ -168,12 +166,11 @@ public void works_for_two_conditions() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfParsedConditions, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test - public void success_for_long_conditions() { - SDKReadinessGates gates = new SDKReadinessGates(); + public void successForLongConditions() { SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); segmentCache.updateSegment(EMPLOYEES, Stream.of("adil", "pato", "trevor").collect(Collectors.toList()), new ArrayList<>(), 1L); segmentCache.updateSegment(SALES_PEOPLE, Stream.of("kunal").collect(Collectors.toList()), new ArrayList<>(), 1L); @@ -200,8 +197,7 @@ public void success_for_long_conditions() { @Test - public void works_with_attributes() { - SDKReadinessGates gates = new SDKReadinessGates(); + public void worksWithAttributes() { SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); segmentCache.updateSegment(EMPLOYEES, Stream.of("adil", "pato", "trevor").collect(Collectors.toList()), new ArrayList<>(), 1L); segmentCache.updateSegment(SALES_PEOPLE, Stream.of("kunal").collect(Collectors.toList()), new ArrayList<>(), 1L); @@ -239,17 +235,11 @@ public void works_with_attributes() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test - public void less_than_or_equal_to() { - - -// SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); -// SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); - SDKReadinessGates gates = new SDKReadinessGates(); - SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); + public void lessThanOrEqualTo() { SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); SegmentChange segmentChangeEmployee = getSegmentChange(-1L, -1L, EMPLOYEES); SegmentChange segmentChangeSalesPeople = getSegmentChange(-1L, -1L, SALES_PEOPLE); @@ -278,16 +268,11 @@ public void less_than_or_equal_to() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test - public void equal_to() { - -// SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); -// SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); - SDKReadinessGates gates = new SDKReadinessGates(); - SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); + public void equalTo() { SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); SegmentChange segmentChangeEmployee = getSegmentChange(-1L, -1L, EMPLOYEES); SegmentChange segmentChangeSalesPeople = getSegmentChange(-1L, -1L, SALES_PEOPLE); @@ -315,16 +300,11 @@ public void equal_to() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test - public void equal_to_negative_number() { - -// SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); -// SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); - SDKReadinessGates gates = new SDKReadinessGates(); - SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); + public void equalToNegativeNumber() { SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); SegmentChange segmentChangeEmployee = getSegmentChange(-1L, -1L, EMPLOYEES); SegmentChange segmentChangeSalesPeople = getSegmentChange(-1L, -1L, SALES_PEOPLE); @@ -351,16 +331,11 @@ public void equal_to_negative_number() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test public void between() { - -// SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); -// SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); - SDKReadinessGates gates = new SDKReadinessGates(); - SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); SegmentChange segmentChangeEmployee = getSegmentChange(-1L, -1L, EMPLOYEES); SegmentChange segmentChangeSalesPeople = getSegmentChange(-1L, -1L, SALES_PEOPLE); @@ -392,12 +367,11 @@ public void between() { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("first.name", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } @Test - public void contains_any_of_set() { - + public void containsAnyOfSet() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -411,12 +385,11 @@ public void contains_any_of_set() { ContainsAnyOfSetMatcher m = new ContainsAnyOfSetMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } @Test - public void contains_all_of_set() { - + public void containsAllOfSet() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -430,12 +403,11 @@ public void contains_all_of_set() { ContainsAllOfSetMatcher m = new ContainsAllOfSetMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } @Test - public void equal_to_set() { - + public void equalToSet() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -449,12 +421,11 @@ public void equal_to_set() { EqualToSetMatcher m = new EqualToSetMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } @Test - public void is_part_of_set() { - + public void isPartOfSet() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -468,12 +439,11 @@ public void is_part_of_set() { PartOfSetMatcher m = new PartOfSetMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } @Test - public void starts_with_string() { - + public void startsWithString() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -487,12 +457,11 @@ public void starts_with_string() { StartsWithAnyOfMatcher m = new StartsWithAnyOfMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } @Test - public void ends_with_string() { - + public void endsWithString() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -506,13 +475,12 @@ public void ends_with_string() { EndsWithAnyOfMatcher m = new EndsWithAnyOfMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } @Test - public void contains_string() { - + public void containsString() { ArrayList set = Lists.newArrayList("sms", "voice"); List partitions = Lists.newArrayList(ConditionsTestUtil.partition("on", 100)); @@ -526,15 +494,10 @@ public void contains_string() { ContainsAnyOfMatcher m = new ContainsAnyOfMatcher(set); - set_matcher_test(c, m); + setMatcherTest(c, m); } - public void set_matcher_test(Condition c, io.split.engine.matchers.Matcher m) { - -// SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); -// SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); - SDKReadinessGates gates = new SDKReadinessGates(); - SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); + public void setMatcherTest(Condition c, io.split.engine.matchers.Matcher m) { SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); SegmentChange segmentChangeEmployee = getSegmentChange(-1L, -1L, EMPLOYEES); SegmentChange segmentChangeSalesPeople = getSegmentChange(-1L, -1L, SALES_PEOPLE); @@ -560,7 +523,7 @@ public void set_matcher_test(Condition c, io.split.engine.matchers.Matcher m) { ParsedSplit expected = ParsedSplit.createParsedSplitForTests("splitName", 123, false, Treatments.OFF, listOfMatcherAndSplits, "user", 1, 1, new HashSet<>()); - assertThat(actual, is(equalTo(expected))); + Assert.assertEquals(actual, expected); } private Split makeSplit(String name, int seed, List conditions, long changeNumber) { @@ -592,5 +555,4 @@ private SegmentChange getSegmentChange(long since, long till, String segmentName segmentChange.removed = new ArrayList<>(); return segmentChange; } - -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/AttributeMatcherTest.java b/client/src/test/java/io/split/engine/matchers/AttributeMatcherTest.java index 7c723adb6..9f535790d 100644 --- a/client/src/test/java/io/split/engine/matchers/AttributeMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/AttributeMatcherTest.java @@ -5,6 +5,7 @@ import com.google.common.collect.Maps; import io.split.client.dtos.DataType; import io.split.engine.matchers.strings.WhitelistMatcher; +import org.junit.Assert; import org.junit.Test; import java.util.Calendar; @@ -12,9 +13,6 @@ import java.util.Date; import java.util.Map; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests for AllKeysMatcher */ @@ -23,60 +21,62 @@ public class AttributeMatcherTest { @Test public void works() { AttributeMatcher matcher = new AttributeMatcher("creation_date", new GreaterThanOrEqualToMatcher(100L, DataType.NUMBER), false); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 100L), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", Calendar.getInstance()), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", new Date()), null), is(false)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 100L), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", Calendar.getInstance()), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", new Date()), null)); } @Test - public void works_negation() { + public void worksNegation() { AttributeMatcher matcher = new AttributeMatcher("creation_date", new GreaterThanOrEqualToMatcher(100L, DataType.NUMBER), true); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 100L), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", Calendar.getInstance()), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", new Date()), null), is(true)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 100L), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", Calendar.getInstance()), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", new Date()), null)); } @Test - public void works_less_than_or_equal_to() { + public void worksLessThanOrEqualTo() { AttributeMatcher matcher = new AttributeMatcher("creation_date", new LessThanOrEqualToMatcher(100L, DataType.NUMBER), false); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 100L), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", Calendar.getInstance()), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", new Date()), null), is(false)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 99L), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 100L), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 101.3), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", Calendar.getInstance()), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", new Date()), null)); } @Test - public void works_boolean() { + public void worksBoolean() { AttributeMatcher matcher = new AttributeMatcher("value", new BooleanMatcher(true), false); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", true), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "true"), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "True"), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "TrUe"), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "TRUE"), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", false), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "false"), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "False"), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "FALSE"), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", "faLSE"), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", ""), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", 0), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("value", 1), null), is(false)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("value", true), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("value", "true"), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("value", "True"), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("value", "TrUe"), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("value", "TRUE"), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", false), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", "false"), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", "False"), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", "FALSE"), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", "faLSE"), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", ""), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", 0), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("value", 1), null)); } @Test - public void error_conditions() { + public void errorConditions() { AttributeMatcher matcher = new AttributeMatcher("creation_date", new GreaterThanOrEqualToMatcher(100L, DataType.NUMBER), false); - assertThat(matcher.match("ignore", null, null, null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("foo", 101), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", "101"), null), is(false)); + Assert.assertFalse(matcher.match("ignore", null, null, null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("foo", 101), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", "101"), null)); } @Test @@ -85,38 +85,38 @@ public void dates() { Calendar c = Calendar.getInstance(); c.add(Calendar.YEAR, -1); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", c.getTimeInMillis()), null), is(false)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", c.getTimeInMillis()), null)); c.add(Calendar.YEAR, 2); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", c.getTimeInMillis()), null), is(true)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", c.getTimeInMillis()), null)); } @Test public void between() { AttributeMatcher matcher = new AttributeMatcher("creation_date", new BetweenMatcher(10, 12, DataType.NUMBER), false); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 9), null), is(false)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 10), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 11), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 12), null), is(true)); - assertThat(matcher.match("ignore", null, ImmutableMap.of("creation_date", 13), null), is(false)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 9), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 10), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 11), null)); + Assert.assertTrue(matcher.match("ignore", null, ImmutableMap.of("creation_date", 12), null)); + Assert.assertFalse(matcher.match("ignore", null, ImmutableMap.of("creation_date", 13), null)); } @Test - public void when_no_attribute_we_use_the_key() { + public void whenNoAttributeWeUseTheKey() { AttributeMatcher matcher = new AttributeMatcher(null, new WhitelistMatcher(Lists.newArrayList("trial")), false); Map nullMap = Maps.newHashMap(); nullMap.put("planType", null); - assertThat(matcher.match("trial", null, ImmutableMap.of("planType", "trial"), null), is(true)); - assertThat(matcher.match("trial", null, ImmutableMap.of("planType", "Trial"), null), is(true)); - assertThat(matcher.match("trial", null, nullMap, null), is(true)); - assertThat(matcher.match("trial", null, ImmutableMap.of("planType", "premium"), null), is(true)); - assertThat(matcher.match("trial", null, ImmutableMap.of("planType", 10), null), is(true)); - assertThat(matcher.match("trial", null, Collections.emptyMap(), null), is(true)); - assertThat(matcher.match("trial", null, null, null), is(true)); - assertThat(matcher.match("premium", null, null, null), is(false)); + Assert.assertTrue(matcher.match("trial", null, ImmutableMap.of("planType", "trial"), null)); + Assert.assertTrue(matcher.match("trial", null, ImmutableMap.of("planType", "Trial"), null)); + Assert.assertTrue(matcher.match("trial", null, nullMap, null)); + Assert.assertTrue(matcher.match("trial", null, ImmutableMap.of("planType", "premium"), null)); + Assert.assertTrue(matcher.match("trial", null, ImmutableMap.of("planType", 10), null)); + Assert.assertTrue(matcher.match("trial", null, Collections.emptyMap(), null)); + Assert.assertTrue(matcher.match("trial", null, null, null)); + Assert.assertFalse(matcher.match("premium", null, null, null)); } -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/BetweenMatcherTest.java b/client/src/test/java/io/split/engine/matchers/BetweenMatcherTest.java index 410977699..22bc3b449 100644 --- a/client/src/test/java/io/split/engine/matchers/BetweenMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/BetweenMatcherTest.java @@ -1,11 +1,9 @@ package io.split.engine.matchers; import io.split.client.dtos.DataType; +import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests for BetweenMatcherTest */ @@ -18,18 +16,18 @@ public void works() { BetweenMatcher matcher = new BetweenMatcher(start, end, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); for (int i = start; i <= end; i++) { - assertThat(matcher.match(i, null, null, null), is(true)); + Assert.assertTrue(matcher.match(i, null, null, null)); } - assertThat(matcher.match(new Long(start - 1), null, null, null), is(false)); - assertThat(matcher.match(end + 1, null, null, null), is(false)); + Assert.assertFalse(matcher.match(new Long(start - 1), null, null, null)); + Assert.assertFalse(matcher.match(end + 1, null, null, null)); } @Test - public void works_dates() { + public void worksDates() { long april11_2016_23_59 = 1460419199000L; long april12_2016_midnight_19 = 1460420360000L; long april12_2016_midnight_20 = 1460420421903L; @@ -39,14 +37,10 @@ public void works_dates() { BetweenMatcher matcher = new BetweenMatcher(april12_2016_midnight_19, april12_2016_midnight_20_59, DataType.DATETIME); - assertThat(matcher.match(april11_2016_23_59, null, null, null), is(false)); - assertThat(matcher.match(april12_2016_midnight_19, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_20, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_20_59, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_1_20, null, null, null), is(false)); - - + Assert.assertFalse(matcher.match(april11_2016_23_59, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_19, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20_59, null, null, null)); + Assert.assertFalse(matcher.match(april12_2016_1_20, null, null, null)); } - - -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/BooleanMatcherTest.java b/client/src/test/java/io/split/engine/matchers/BooleanMatcherTest.java index cb466bc0b..14889af68 100644 --- a/client/src/test/java/io/split/engine/matchers/BooleanMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/BooleanMatcherTest.java @@ -8,7 +8,7 @@ public class BooleanMatcherTest { @Test - public void works_true() { + public void worksTrue() { BooleanMatcher matcher = new BooleanMatcher(true); assertThat(matcher.match(null, null, null, null), is(false)); assertThat(matcher.match(true, null, null, null), is(true)); @@ -23,7 +23,7 @@ public void works_true() { } @Test - public void works_false() { + public void worksFalse() { BooleanMatcher matcher = new BooleanMatcher(false); assertThat(matcher.match(null, null, null, null), is(false)); assertThat(matcher.match(true, null, null, null), is(false)); diff --git a/client/src/test/java/io/split/engine/matchers/CombiningMatcherTest.java b/client/src/test/java/io/split/engine/matchers/CombiningMatcherTest.java index ee58a18a2..3946aed50 100644 --- a/client/src/test/java/io/split/engine/matchers/CombiningMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/CombiningMatcherTest.java @@ -3,13 +3,11 @@ import com.google.common.collect.Lists; import io.split.client.dtos.MatcherCombiner; import io.split.engine.matchers.strings.WhitelistMatcher; +import org.junit.Assert; import org.junit.Test; import java.util.Collections; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests CombiningMatcher * @@ -18,15 +16,14 @@ public class CombiningMatcherTest { @Test - public void works_and() { + public void worksAnd() { AttributeMatcher matcher1 = AttributeMatcher.vanilla(new AllKeysMatcher()); AttributeMatcher matcher2 = AttributeMatcher.vanilla(new WhitelistMatcher(Lists.newArrayList("a", "b"))); CombiningMatcher combiner = new CombiningMatcher(MatcherCombiner.AND, Lists.newArrayList(matcher1, matcher2)); - assertThat(combiner.match("a", null, null, null), is(true)); - assertThat(combiner.match("b", null, Collections.emptyMap(), null), is(true)); - assertThat(combiner.match("c", null, null, null), is(false)); + Assert.assertTrue(combiner.match("a", null, null, null)); + Assert.assertTrue(combiner.match("b", null, Collections.emptyMap(), null)); + Assert.assertFalse(combiner.match("c", null, null, null)); } - -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/EqualToMatcherTest.java b/client/src/test/java/io/split/engine/matchers/EqualToMatcherTest.java index aeb887f9c..f8320e511 100644 --- a/client/src/test/java/io/split/engine/matchers/EqualToMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/EqualToMatcherTest.java @@ -1,11 +1,9 @@ package io.split.engine.matchers; import io.split.client.dtos.DataType; +import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests for AllKeysMatcher */ @@ -14,30 +12,30 @@ public class EqualToMatcherTest { @Test public void works() { EqualToMatcher matcher = new EqualToMatcher(10, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); - assertThat(matcher.match(1, null, null, null), is(false)); - assertThat(matcher.match(new Long(-1), null, null, null), is(false)); - assertThat(matcher.match(9, null, null, null), is(false)); - assertThat(matcher.match(new Long(10), null, null, null), is(true)); - assertThat(matcher.match(11, null, null, null), is(false)); - assertThat(matcher.match(100, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); + Assert.assertFalse(matcher.match(1, null, null, null)); + Assert.assertFalse(matcher.match(new Long(-1), null, null, null)); + Assert.assertFalse(matcher.match(9, null, null, null)); + Assert.assertTrue(matcher.match(new Long(10), null, null, null)); + Assert.assertFalse(matcher.match(11, null, null, null)); + Assert.assertFalse(matcher.match(100, null, null, null)); } @Test - public void works_negative() { + public void worksNegative() { EqualToMatcher matcher = new EqualToMatcher(-10, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); - assertThat(matcher.match(1, null, null, null), is(false)); - assertThat(matcher.match(new Long(-1), null, null, null), is(false)); - assertThat(matcher.match(9, null, null, null), is(false)); - assertThat(matcher.match(new Long(10), null, null, null), is(false)); - assertThat(matcher.match(11, null, null, null), is(false)); - assertThat(matcher.match(-10, null, null, null), is(true)); - assertThat(matcher.match(-11, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); + Assert.assertFalse(matcher.match(1, null, null, null)); + Assert.assertFalse(matcher.match(new Long(-1), null, null, null)); + Assert.assertFalse(matcher.match(9, null, null, null)); + Assert.assertFalse(matcher.match(new Long(10), null, null, null)); + Assert.assertFalse(matcher.match(11, null, null, null)); + Assert.assertTrue(matcher.match(-10, null, null, null)); + Assert.assertFalse(matcher.match(-11, null, null, null)); } @Test - public void works_dates() { + public void worksDates() { long april11_2016_23_59_59 = 1460419199000L; long april12_2016_midnight_19 = 1460420360000L; long april12_2016_midnight_20 = 1460420421903L; @@ -45,12 +43,10 @@ public void works_dates() { long april13_2016_00_00_00 = 1460505600000L; EqualToMatcher matcher = new EqualToMatcher(april12_2016_midnight_20, DataType.DATETIME); - assertThat(matcher.match(april11_2016_23_59_59, null, null, null), is(false)); - assertThat(matcher.match(april12_2016_midnight_19, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_20, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_1_20, null, null, null), is(true)); - assertThat(matcher.match(april13_2016_00_00_00, null, null, null), is(false)); - + Assert.assertFalse(matcher.match(april11_2016_23_59_59, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_19, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_1_20, null, null, null)); + Assert.assertFalse(matcher.match(april13_2016_00_00_00, null, null, null)); } - -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToMatcherTest.java b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToMatcherTest.java index 566f53623..bbe37fdd7 100644 --- a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToMatcherTest.java @@ -1,11 +1,9 @@ package io.split.engine.matchers; import io.split.client.dtos.DataType; +import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests for AllKeysMatcher */ @@ -14,31 +12,31 @@ public class GreaterThanOrEqualToMatcherTest { @Test public void works() { GreaterThanOrEqualToMatcher matcher = new GreaterThanOrEqualToMatcher(10, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); - assertThat(matcher.match(1, null, null, null), is(false)); - assertThat(matcher.match(new Long(-1), null, null, null), is(false)); - assertThat(matcher.match(9, null, null, null), is(false)); - assertThat(matcher.match(new Long(10), null, null, null), is(true)); - assertThat(matcher.match(11, null, null, null), is(true)); - assertThat(matcher.match(100, null, null, null), is(true)); + Assert.assertFalse(matcher.match(null, null, null, null)); + Assert.assertFalse(matcher.match(1, null, null, null)); + Assert.assertFalse(matcher.match(new Long(-1), null, null, null)); + Assert.assertFalse(matcher.match(9, null, null, null)); + Assert.assertTrue(matcher.match(new Long(10), null, null, null)); + Assert.assertTrue(matcher.match(11, null, null, null)); + Assert.assertTrue(matcher.match(100, null, null, null)); } @Test - public void works_negative() { + public void worksNegative() { GreaterThanOrEqualToMatcher matcher = new GreaterThanOrEqualToMatcher(-10, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); - assertThat(matcher.match(1, null, null, null), is(true)); - assertThat(matcher.match(new Long(-1), null, null, null), is(true)); - assertThat(matcher.match(9, null, null, null), is(true)); - assertThat(matcher.match(new Long(10), null, null, null), is(true)); - assertThat(matcher.match(11, null, null, null), is(true)); - assertThat(matcher.match(100, null, null, null), is(true)); - assertThat(matcher.match(-10, null, null, null), is(true)); - assertThat(matcher.match(-11, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); + Assert.assertTrue(matcher.match(1, null, null, null)); + Assert.assertTrue(matcher.match(new Long(-1), null, null, null)); + Assert.assertTrue(matcher.match(9, null, null, null)); + Assert.assertTrue(matcher.match(new Long(10), null, null, null)); + Assert.assertTrue(matcher.match(11, null, null, null)); + Assert.assertTrue(matcher.match(100, null, null, null)); + Assert.assertTrue(matcher.match(-10, null, null, null)); + Assert.assertFalse(matcher.match(-11, null, null, null)); } @Test - public void works_dates() { + public void worksDates() { long april12_2016_midnight_19 = 1460420360000L; long april12_2016_midnight_20 = 1460420421903L; long april12_2016_midnight_20_59 = 1460420459000L; @@ -46,11 +44,11 @@ public void works_dates() { long april12_2016_18_20 = 1460485239000L; GreaterThanOrEqualToMatcher matcher = new GreaterThanOrEqualToMatcher(april12_2016_midnight_20, DataType.DATETIME); - assertThat(matcher.match(april12_2016_midnight_19, null, null, null), is(false)); - assertThat(matcher.match(april12_2016_midnight_20_59, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_20, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_1_20, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_18_20, null, null, null), is(true)); + Assert.assertFalse(matcher.match(april12_2016_midnight_19, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20_59, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20_59, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_1_20, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_18_20, null, null, null)); } - -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToMatcherTest.java b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToMatcherTest.java index 1663a6085..47853ed4c 100644 --- a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToMatcherTest.java @@ -1,11 +1,9 @@ package io.split.engine.matchers; import io.split.client.dtos.DataType; +import org.junit.Assert; import org.junit.Test; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests for AllKeysMatcher */ @@ -14,31 +12,31 @@ public class LessThanOrEqualToMatcherTest { @Test public void works() { LessThanOrEqualToMatcher matcher = new LessThanOrEqualToMatcher(10, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); - assertThat(matcher.match(1, null, null, null), is(true)); - assertThat(matcher.match(new Long(-1), null, null, null), is(true)); - assertThat(matcher.match(9, null, null, null), is(true)); - assertThat(matcher.match(new Long(10), null, null, null), is(true)); - assertThat(matcher.match(11, null, null, null), is(false)); - assertThat(matcher.match(100, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); + Assert.assertTrue(matcher.match(1, null, null, null)); + Assert.assertTrue(matcher.match(new Long(-1), null, null, null)); + Assert.assertTrue(matcher.match(9, null, null, null)); + Assert.assertTrue(matcher.match(new Long(10), null, null, null)); + Assert.assertFalse(matcher.match(11, null, null, null)); + Assert.assertFalse(matcher.match(100, null, null, null)); } @Test - public void works_negative() { + public void worksNegative() { LessThanOrEqualToMatcher matcher = new LessThanOrEqualToMatcher(-10, DataType.NUMBER); - assertThat(matcher.match(null, null, null, null), is(false)); - assertThat(matcher.match(1, null, null, null), is(false)); - assertThat(matcher.match(new Long(-1), null, null, null), is(false)); - assertThat(matcher.match(9, null, null, null), is(false)); - assertThat(matcher.match(new Long(10), null, null, null), is(false)); - assertThat(matcher.match(11, null, null, null), is(false)); - assertThat(matcher.match(-9, null, null, null), is(false)); - assertThat(matcher.match(-10, null, null, null), is(true)); - assertThat(matcher.match(-11, null, null, null), is(true)); + Assert.assertFalse(matcher.match(null, null, null, null)); + Assert.assertFalse(matcher.match(1, null, null, null)); + Assert.assertFalse(matcher.match(new Long(-1), null, null, null)); + Assert.assertFalse(matcher.match(9, null, null, null)); + Assert.assertFalse(matcher.match(new Long(10), null, null, null)); + Assert.assertFalse(matcher.match(11, null, null, null)); + Assert.assertFalse(matcher.match(-9, null, null, null)); + Assert.assertTrue(matcher.match(-10, null, null, null)); + Assert.assertTrue(matcher.match(-11, null, null, null)); } @Test - public void works_dates() { + public void worksDates() { long april11_2016_23_59 = 1460419199000L; long april12_2016_midnight_19 = 1460420360000L; long april12_2016_midnight_20 = 1460420421903L; @@ -46,12 +44,10 @@ public void works_dates() { long april12_2016_1_20 = 1460424039000L; LessThanOrEqualToMatcher matcher = new LessThanOrEqualToMatcher(april12_2016_midnight_20, DataType.DATETIME); - assertThat(matcher.match(april11_2016_23_59, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_19, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_20, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_midnight_20_59, null, null, null), is(true)); - assertThat(matcher.match(april12_2016_1_20, null, null, null), is(false)); + Assert.assertTrue(matcher.match(april11_2016_23_59, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_19, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20, null, null, null)); + Assert.assertTrue(matcher.match(april12_2016_midnight_20_59, null, null, null)); + Assert.assertFalse(matcher.match(april12_2016_1_20, null, null, null)); } - - -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/NegatableMatcherTest.java b/client/src/test/java/io/split/engine/matchers/NegatableMatcherTest.java index 3aec5ab0d..97e4aebe2 100644 --- a/client/src/test/java/io/split/engine/matchers/NegatableMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/NegatableMatcherTest.java @@ -6,6 +6,7 @@ import io.split.engine.matchers.strings.WhitelistMatcher; import io.split.storages.SegmentCache; import io.split.storages.memory.SegmentCacheInMemoryImpl; +import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; @@ -13,9 +14,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Tests for NegatableMatcher. * @@ -24,7 +22,7 @@ public class NegatableMatcherTest { @Test - public void works_all_keys() { + public void worksAllKeys() { AllKeysMatcher delegate = new AllKeysMatcher(); AttributeMatcher.NegatableMatcher matcher = new AttributeMatcher.NegatableMatcher(delegate, true); @@ -32,7 +30,7 @@ public void works_all_keys() { } @Test - public void works_segment() { + public void worksSegment() { SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); segmentCache.updateSegment("foo", Stream.of("a","b").collect(Collectors.toList()), new ArrayList<>(), 1L); UserDefinedSegmentMatcher delegate = new UserDefinedSegmentMatcher("foo"); @@ -44,7 +42,7 @@ public void works_segment() { } @Test - public void works_whitelist() { + public void worksWhitelist() { WhitelistMatcher delegate = new WhitelistMatcher(Lists.newArrayList("a", "b")); AttributeMatcher.NegatableMatcher matcher = new AttributeMatcher.NegatableMatcher(delegate, true); @@ -54,9 +52,8 @@ public void works_whitelist() { } private void test(AttributeMatcher.NegatableMatcher negationMatcher, String key, boolean expected, SegmentCache segmentCache) { - assertThat(negationMatcher.match(key, null, null, new EvaluationContext(Mockito.mock(Evaluator.class), segmentCache)), is(expected)); - assertThat(negationMatcher.delegate().match(key, null, null, new EvaluationContext(Mockito.mock(Evaluator.class), segmentCache)), is(!expected)); - + Assert.assertEquals(expected, negationMatcher.match(key, null, null, new EvaluationContext(Mockito.mock(Evaluator.class), segmentCache))); + Assert.assertNotEquals(expected, negationMatcher.delegate().match(key, null, null, new EvaluationContext(Mockito.mock(Evaluator.class), segmentCache))); } diff --git a/client/src/test/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcherTest.java b/client/src/test/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcherTest.java index caa7b40da..1c84cf2e6 100644 --- a/client/src/test/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/collections/ContainsAllOfSetMatcherTest.java @@ -1,5 +1,6 @@ package io.split.engine.matchers.collections; +import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; @@ -7,77 +8,75 @@ import java.util.List; import java.util.Set; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Created by adilaijaz on 4/18/17. */ public class ContainsAllOfSetMatcherTest { @Test - public void works_for_sets() { + public void worksForSets() { Set set = new HashSet<>(); set.add("first"); set.add("second"); ContainsAllOfSetMatcher matcher = new ContainsAllOfSetMatcher(set); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); Set argument = new HashSet<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); } @Test - public void works_for_lists() { + public void worksForLists() { List list = new ArrayList<>(); list.add("first"); list.add("second"); ContainsAllOfSetMatcher matcher = new ContainsAllOfSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); } @Test - public void works_for_empty_paramter() { + public void worksForEmptyParamter() { List list = new ArrayList<>(); ContainsAllOfSetMatcher matcher = new ContainsAllOfSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcherTest.java b/client/src/test/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcherTest.java index 2b54dcbaf..520959aee 100644 --- a/client/src/test/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/collections/ContainsAnyOfSetMatcherTest.java @@ -1,5 +1,6 @@ package io.split.engine.matchers.collections; +import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; @@ -7,77 +8,74 @@ import java.util.List; import java.util.Set; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Created by adilaijaz on 4/18/17. */ public class ContainsAnyOfSetMatcherTest { @Test - public void works_for_sets() { + public void worksForSets() { Set set = new HashSet<>(); set.add("first"); set.add("second"); ContainsAnyOfSetMatcher matcher = new ContainsAnyOfSetMatcher(set); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); Set argument = new HashSet<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); } @Test - public void works_for_lists() { + public void worksForLists() { List list = new ArrayList<>(); list.add("first"); list.add("second"); ContainsAnyOfSetMatcher matcher = new ContainsAnyOfSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); } @Test - public void works_for_empty_paramter() { + public void worksForEmptyParamter() { List list = new ArrayList<>(); ContainsAnyOfSetMatcher matcher = new ContainsAnyOfSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/matchers/collections/EqualToSetMatcherTest.java b/client/src/test/java/io/split/engine/matchers/collections/EqualToSetMatcherTest.java index 24c783c59..ceb3b4b11 100644 --- a/client/src/test/java/io/split/engine/matchers/collections/EqualToSetMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/collections/EqualToSetMatcherTest.java @@ -1,5 +1,6 @@ package io.split.engine.matchers.collections; +import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; @@ -7,100 +8,97 @@ import java.util.List; import java.util.Set; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Created by adilaijaz on 4/18/17. */ public class EqualToSetMatcherTest { @Test - public void works_for_sets() { + public void worksForSets() { Set set = new HashSet<>(); set.add("first"); set.add("second"); EqualToSetMatcher matcher = new EqualToSetMatcher(set); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); Set argument = new HashSet<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } @Test - public void works_for_sets_same_order() { + public void worksForSetsSameOrder() { Set set = new HashSet<>(); set.add("first"); set.add("second"); EqualToSetMatcher matcher = new EqualToSetMatcher(set); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); Set argument = new HashSet<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } @Test - public void works_for_lists() { + public void worksForLists() { List list = new ArrayList<>(); list.add("first"); list.add("second"); EqualToSetMatcher matcher = new EqualToSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } @Test - public void works_for_empty_paramter() { + public void worksForEmptyParamter() { List list = new ArrayList<>(); EqualToSetMatcher matcher = new EqualToSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/matchers/collections/PartOfSetMatcherTest.java b/client/src/test/java/io/split/engine/matchers/collections/PartOfSetMatcherTest.java index ff75dc9fb..0a734e884 100644 --- a/client/src/test/java/io/split/engine/matchers/collections/PartOfSetMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/collections/PartOfSetMatcherTest.java @@ -1,5 +1,6 @@ package io.split.engine.matchers.collections; +import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; @@ -7,77 +8,74 @@ import java.util.List; import java.util.Set; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Created by adilaijaz on 4/18/17. */ public class PartOfSetMatcherTest { @Test - public void works_for_sets() { + public void worksForSets() { Set set = new HashSet<>(); set.add("first"); set.add("second"); PartOfSetMatcher matcher = new PartOfSetMatcher(set); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); Set argument = new HashSet<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } @Test - public void works_for_lists() { + public void worksForLists() { List list = new ArrayList<>(); list.add("first"); list.add("second"); PartOfSetMatcher matcher = new PartOfSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(true)); + Assert.assertTrue(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } @Test - public void works_for_empty_paramter() { + public void worksForEmptyParamter() { List list = new ArrayList<>(); PartOfSetMatcher matcher = new PartOfSetMatcher(list); - assertThat(matcher.match(null, null, null, null), is(false)); + Assert.assertFalse(matcher.match(null, null, null, null)); List argument = new ArrayList<>(); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("second"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("first"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); argument.add("third"); - assertThat(matcher.match(argument, null, null, null), is(false)); + Assert.assertFalse(matcher.match(argument, null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/segments/SegmentFetcherImpTest.java b/client/src/test/java/io/split/engine/segments/SegmentFetcherImpTest.java index ce263bfe4..0872fb45b 100644 --- a/client/src/test/java/io/split/engine/segments/SegmentFetcherImpTest.java +++ b/client/src/test/java/io/split/engine/segments/SegmentFetcherImpTest.java @@ -36,18 +36,17 @@ public class SegmentFetcherImpTest { private static final TelemetryStorage TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); @Test - public void works_when_we_start_without_state() throws InterruptedException { + public void worksWhenWeStartWithoutState() throws InterruptedException { works(-1L); } @Test - public void works_when_we_start_with_state() throws InterruptedException { + public void worksWhenWeStartWithState() throws InterruptedException { works(20L); } @Test - public void works_when_there_are_no_changes() throws InterruptedException { - long startingChangeNumber = -1L; + public void worksWhenThereAreNoChanges() throws InterruptedException { SegmentCache segmentCache = new SegmentCacheInMemoryImpl(); SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); @@ -112,13 +111,13 @@ private void works(long startingChangeNumber) throws InterruptedException { @Test(expected = NullPointerException.class) - public void does_not_work_if_segment_change_fetcher_is_null() { + public void doesNotWorkIfSegmentChangeFetcherIsNull() { SegmentCacheProducer segmentCacheProducer = Mockito.mock(SegmentCacheProducer.class); SegmentFetcher fetcher = new SegmentFetcherImp(SEGMENT_NAME, null, segmentCacheProducer, TELEMETRY_STORAGE); } @Test(expected = NullPointerException.class) - public void does_not_work_if_segment_name_is_null() { + public void doesNotWorkIfSegmentNameIsNull() { SegmentCacheProducer segmentCacheProducer = Mockito.mock(SegmentCacheProducer.class); SegmentChangeFetcher segmentChangeFetcher = Mockito.mock(SegmentChangeFetcher.class); SegmentFetcher fetcher = new SegmentFetcherImp(null, segmentChangeFetcher, segmentCacheProducer, TELEMETRY_STORAGE); @@ -176,4 +175,4 @@ private SegmentChange getSegmentChange(long since, long till){ segmentChange.removed = new ArrayList<>(); return segmentChange; } -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/engine/splitter/HashConsistencyTest.java b/client/src/test/java/io/split/engine/splitter/HashConsistencyTest.java index 34b0e557d..cb2200294 100644 --- a/client/src/test/java/io/split/engine/splitter/HashConsistencyTest.java +++ b/client/src/test/java/io/split/engine/splitter/HashConsistencyTest.java @@ -12,7 +12,6 @@ import java.io.FileReader; import java.io.IOException; import java.net.URL; -import java.nio.charset.Charset; public class HashConsistencyTest { @Test @@ -77,7 +76,7 @@ private void validateFileLegacyHash(File file) throws IOException { int expected_hash = Integer.parseInt(parts[2]); int expected_bucket = Integer.parseInt(parts[3]); - int hash = Splitter.legacy_hash(key, seed); + int hash = Splitter.legacyHash(key, seed); int bucket = Splitter.bucket(hash); Assert.assertEquals(expected_hash, hash); @@ -98,7 +97,7 @@ private void validateFileMurmur3Hash(File file) throws IOException { long expected_hash = Long.parseLong(parts[2]); int expected_bucket = Integer.parseInt(parts[3]); - long hash = Splitter.murmur_hash(key, seed); + long hash = Splitter.murmurHash(key, seed); int bucket = Splitter.bucket(hash); Assert.assertEquals(expected_hash, hash); diff --git a/client/src/test/java/io/split/service/HttpPostImpTest.java b/client/src/test/java/io/split/service/HttpPostImpTest.java index b6b422d89..c618ed042 100644 --- a/client/src/test/java/io/split/service/HttpPostImpTest.java +++ b/client/src/test/java/io/split/service/HttpPostImpTest.java @@ -25,8 +25,8 @@ public void testPostWith200() throws InvocationTargetException, NoSuchMethodExce HttpPostImp httpPostImp = new HttpPostImp(client, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); - Assert.assertNotEquals(0, telemetryStorage.getLastSynchronization().get_telemetry()); - Assert.assertEquals(1, telemetryStorage.popHTTPLatencies().get_telemetry().stream().mapToInt(Long::intValue).sum()); + Assert.assertNotEquals(0, telemetryStorage.getLastSynchronization().getTelemetry()); + Assert.assertEquals(1, telemetryStorage.popHTTPLatencies().getTelemetry().stream().mapToInt(Long::intValue).sum()); } @Test @@ -37,6 +37,6 @@ public void testPostWith400() throws InvocationTargetException, NoSuchMethodExce httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); - Assert.assertEquals(1, telemetryStorage.popHTTPErrors().get_telemetry().get(Long.valueOf(HttpStatus.SC_CLIENT_ERROR)).intValue()); + Assert.assertEquals(1, telemetryStorage.popHTTPErrors().getTelemetry().get(Long.valueOf(HttpStatus.SC_CLIENT_ERROR)).intValue()); } } \ No newline at end of file diff --git a/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java b/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java index 6b936254e..65ca18b06 100644 --- a/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java +++ b/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java @@ -285,7 +285,7 @@ public ConcurrentMap getLatencies() { return _latencies; } - public ConcurrentMap get_impressionsCount() { + public ConcurrentMap getImpressionsCount() { return _impressionsCount; } diff --git a/client/src/test/java/io/split/telemetry/storage/InMemoryTelemetryStorageTest.java b/client/src/test/java/io/split/telemetry/storage/InMemoryTelemetryStorageTest.java index 3b8a0941c..a74ee03ac 100644 --- a/client/src/test/java/io/split/telemetry/storage/InMemoryTelemetryStorageTest.java +++ b/client/src/test/java/io/split/telemetry/storage/InMemoryTelemetryStorageTest.java @@ -71,22 +71,22 @@ public void testInMemoryTelemetryStorage() { HTTPLatencies httpLatencies = telemetryStorage.popHTTPLatencies(); - Assert.assertEquals(3, httpLatencies.get_splits().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(2, httpLatencies.get_telemetry().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(2, httpLatencies.get_events().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, httpLatencies.get_segments().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, httpLatencies.get_impressions().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, httpLatencies.get_impressionsCount().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_token().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(3, httpLatencies.getSplits().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(2, httpLatencies.getTelemetry().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(2, httpLatencies.getEvents().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, httpLatencies.getSegments().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, httpLatencies.getImpressions().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, httpLatencies.getImpressionsCount().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getToken().stream().mapToInt(Long::intValue).sum()); httpLatencies = telemetryStorage.popHTTPLatencies(); - Assert.assertEquals(0, httpLatencies.get_splits().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_telemetry().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_events().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_segments().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_impressions().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_impressionsCount().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, httpLatencies.get_token().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getSplits().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getTelemetry().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getEvents().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getSegments().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getImpressions().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getImpressionsCount().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, httpLatencies.getToken().stream().mapToInt(Long::intValue).sum()); //Exceptions @@ -191,13 +191,13 @@ public void testInMemoryTelemetryStorage() { telemetryStorage.recordSuccessfulSync(LastSynchronizationRecordsEnum.TOKEN, 129); LastSynchronization lastSynchronization = telemetryStorage.getLastSynchronization(); - Assert.assertEquals(800, lastSynchronization.get_events()); - Assert.assertEquals(129, lastSynchronization.get_token()); - Assert.assertEquals(1580, lastSynchronization.get_segments()); - Assert.assertEquals(0, lastSynchronization.get_splits()); - Assert.assertEquals(10500, lastSynchronization.get_impressions()); - Assert.assertEquals(1500, lastSynchronization.get_impressionsCount()); - Assert.assertEquals(265, lastSynchronization.get_telemetry()); + Assert.assertEquals(800, lastSynchronization.getEvents()); + Assert.assertEquals(129, lastSynchronization.getToken()); + Assert.assertEquals(1580, lastSynchronization.getSegments()); + Assert.assertEquals(0, lastSynchronization.getSplits()); + Assert.assertEquals(10500, lastSynchronization.getImpressions()); + Assert.assertEquals(1500, lastSynchronization.getImpressionsCount()); + Assert.assertEquals(265, lastSynchronization.getTelemetry()); //Session length telemetryStorage.recordSessionLength(91218); @@ -216,21 +216,21 @@ public void testInMemoryTelemetryStorage() { telemetryStorage.recordSyncError(ResourceEnum.TOKEN_SYNC, 403); HTTPErrors httpErrors = telemetryStorage.popHTTPErrors(); - Assert.assertEquals(2, httpErrors.get_telemetry().get(400l).intValue()); - Assert.assertEquals(1, httpErrors.get_segments().get(501l).intValue()); - Assert.assertEquals(2, httpErrors.get_impressions().get(403l).intValue()); - Assert.assertEquals(1, httpErrors.get_impressionsCount().get(403l).intValue()); - Assert.assertEquals(1, httpErrors.get_events().get(503l).intValue()); - Assert.assertEquals(1, httpErrors.get_splits().get(403l).intValue()); - Assert.assertEquals(1, httpErrors.get_token().get(403l).intValue()); + Assert.assertEquals(2, httpErrors.getTelemetry().get(400l).intValue()); + Assert.assertEquals(1, httpErrors.getSegments().get(501l).intValue()); + Assert.assertEquals(2, httpErrors.getImpressions().get(403l).intValue()); + Assert.assertEquals(1, httpErrors.getImpressionsCount().get(403l).intValue()); + Assert.assertEquals(1, httpErrors.getEvents().get(503l).intValue()); + Assert.assertEquals(1, httpErrors.getSplits().get(403l).intValue()); + Assert.assertEquals(1, httpErrors.getToken().get(403l).intValue()); //Streaming events StreamingEvent streamingEvent = new StreamingEvent(1, 290, 91218); telemetryStorage.recordStreamingEvents(streamingEvent); List streamingEvents = telemetryStorage.popStreamingEvents(); - Assert.assertEquals(290, streamingEvents.get(0).get_data()); - Assert.assertEquals(1, streamingEvents.get(0).get_type()); + Assert.assertEquals(290, streamingEvents.get(0).getData()); + Assert.assertEquals(1, streamingEvents.get(0).getType()); Assert.assertEquals(91218, streamingEvents.get(0).getTimestamp()); //Check list has been cleared diff --git a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java index 10aa46298..991f8af9f 100644 --- a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java +++ b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java @@ -129,13 +129,13 @@ public void testStats() throws Exception { Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentWithConfigByFlagSet().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentWithConfigByFlagSets().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(0, stats.getMethodLatencies().getTrack().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(3, stats.getHttpLatencies().get_splits().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(2, stats.getHttpLatencies().get_telemetry().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(2, stats.getHttpLatencies().get_events().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getHttpLatencies().get_segments().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getHttpLatencies().get_impressions().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getHttpLatencies().get_impressionsCount().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(0, stats.getHttpLatencies().get_token().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(3, stats.getHttpLatencies().getSplits().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(2, stats.getHttpLatencies().getTelemetry().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(2, stats.getHttpLatencies().getEvents().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, stats.getHttpLatencies().getSegments().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, stats.getHttpLatencies().getImpressions().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, stats.getHttpLatencies().getImpressionsCount().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(0, stats.getHttpLatencies().getToken().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(2, stats.getMethodExceptions().getTreatment()); Assert.assertEquals(2, stats.getMethodExceptions().getTreatments()); Assert.assertEquals(1, stats.getMethodExceptions().getTreatmentsWithConfig()); @@ -153,24 +153,24 @@ public void testStats() throws Exception { Assert.assertEquals(0, stats.getImpressionsQueued()); Assert.assertEquals(10, stats.getEventsDropped()); Assert.assertEquals(3, stats.getEventsQueued()); - Assert.assertEquals(800, stats.getLastSynchronization().get_events()); - Assert.assertEquals(129, stats.getLastSynchronization().get_token()); - Assert.assertEquals(1580, stats.getLastSynchronization().get_segments()); - Assert.assertEquals(0, stats.getLastSynchronization().get_splits()); - Assert.assertEquals(10500, stats.getLastSynchronization().get_impressions()); - Assert.assertEquals(1500, stats.getLastSynchronization().get_impressionsCount()); - Assert.assertEquals(265, stats.getLastSynchronization().get_telemetry()); + Assert.assertEquals(800, stats.getLastSynchronization().getEvents()); + Assert.assertEquals(129, stats.getLastSynchronization().getToken()); + Assert.assertEquals(1580, stats.getLastSynchronization().getSegments()); + Assert.assertEquals(0, stats.getLastSynchronization().getSplits()); + Assert.assertEquals(10500, stats.getLastSynchronization().getImpressions()); + Assert.assertEquals(1500, stats.getLastSynchronization().getImpressionsCount()); + Assert.assertEquals(265, stats.getLastSynchronization().getTelemetry()); Assert.assertEquals(91218, stats.getSessionLengthMs()); - Assert.assertEquals(2, stats.getHttpErrors().get_telemetry().get(400l).intValue()); - Assert.assertEquals(1, stats.getHttpErrors().get_segments().get(501l).intValue()); - Assert.assertEquals(2, stats.getHttpErrors().get_impressions().get(403l).intValue()); - Assert.assertEquals(1, stats.getHttpErrors().get_impressionsCount().get(403l).intValue()); - Assert.assertEquals(1, stats.getHttpErrors().get_events().get(503l).intValue()); - Assert.assertEquals(1, stats.getHttpErrors().get_splits().get(403l).intValue()); - Assert.assertEquals(1, stats.getHttpErrors().get_token().get(403l).intValue()); + Assert.assertEquals(2, stats.getHttpErrors().getTelemetry().get(400l).intValue()); + Assert.assertEquals(1, stats.getHttpErrors().getSegments().get(501l).intValue()); + Assert.assertEquals(2, stats.getHttpErrors().getImpressions().get(403l).intValue()); + Assert.assertEquals(1, stats.getHttpErrors().getImpressionsCount().get(403l).intValue()); + Assert.assertEquals(1, stats.getHttpErrors().getEvents().get(503l).intValue()); + Assert.assertEquals(1, stats.getHttpErrors().getSplits().get(403l).intValue()); + Assert.assertEquals(1, stats.getHttpErrors().getToken().get(403l).intValue()); List streamingEvents = stats.getStreamingEvents(); - Assert.assertEquals(290, streamingEvents.get(0).get_data()); - Assert.assertEquals(1, streamingEvents.get(0).get_type()); + Assert.assertEquals(290, streamingEvents.get(0).getData()); + Assert.assertEquals(1, streamingEvents.get(0).getType()); Assert.assertEquals(91218, streamingEvents.get(0).getTimestamp()); Assert.assertEquals(1, stats.getUpdatesFromSSE().getSplits()); } From 4908571c8193207406ea6a3883f62e3c6b30f3de Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 11 Jan 2024 10:39:50 -0300 Subject: [PATCH 03/88] Deprecate get_telemetryRefreshRate method --- .../src/main/java/io/split/client/SplitClientConfig.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 4e344444e..36ce55fb7 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -355,6 +355,14 @@ public String telemetryURL() { return _telemetryURL; } + /** + * @deprecated As of release 4.X.X, replaced by {@link #getTelemetryRefreshRate()} } //todo update version + **/ + @Deprecated + public int get_telemetryRefreshRate() { + return _telemetryRefreshRate; + } + public int getTelemetryRefreshRate() { return _telemetryRefreshRate; } From 9d58e0079a6acb664417c013689499a5c2821ff6 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 11 Mar 2024 20:27:56 -0700 Subject: [PATCH 04/88] added request decorator class --- .../io/split/client/RequestDecorator.java | 63 ++++++++++++ .../io/split/client/RequestDecoratorTest.java | 95 +++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 client/src/main/java/io/split/client/RequestDecorator.java create mode 100644 client/src/test/java/io/split/client/RequestDecoratorTest.java diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java new file mode 100644 index 000000000..6cbd54fcf --- /dev/null +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -0,0 +1,63 @@ +package io.split.client; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; + +import java.util.*; + +interface UserCustomHeaderDecorator +{ + Map getHeaderOverrides(); +} + +class NoOpHeaderDecorator implements UserCustomHeaderDecorator { + public NoOpHeaderDecorator() {} + @Override + public Map getHeaderOverrides() { + return new HashMap(); + } +} + +class RequestDecorator { + UserCustomHeaderDecorator _headerDecorator; + + private static final Set forbiddenHeaders = new HashSet<>(Arrays.asList( + "SplitSDKVersion", + "SplitMachineIp", + "SplitMachineName", + "SplitImpressionsMode", + "Host", + "Referrer", + "Content-Type", + "Content-Length", + "Content-Encoding", + "Accept", + "Keep-Alive", + "X-Fastly-Debug" + )); + + public RequestDecorator(UserCustomHeaderDecorator headerDecorator) { + _headerDecorator = (headerDecorator == null) + ? new NoOpHeaderDecorator() + : headerDecorator; + } + + public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { + try { + Map headers = _headerDecorator.getHeaderOverrides(); + for (Map.Entry entry : headers.entrySet()) { + if (isHeaderAllowed(entry.getKey().toString())) { + request.addHeader(entry.getKey().toString(), entry.getValue()); + } + } + } catch (Exception e) { + throw new IllegalArgumentException(String.format("Problem adding custom headers to request decorator: %s", e), e); + } + + return request; + } + + private boolean isHeaderAllowed(String headerName) { + return !forbiddenHeaders.contains(headerName); + } +} diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java new file mode 100644 index 000000000..a3dfbaa8a --- /dev/null +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -0,0 +1,95 @@ +package io.split.client; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.ProtocolException; +import org.junit.Assert; +import org.junit.Test; +import io.split.client.RequestDecorator; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +public class RequestDecoratorTest { + + @Test + public void testNoOp() { + RequestDecorator decorator = new RequestDecorator(null); + HttpGet request = new HttpGet("http://anyhost"); + request = (HttpGet) decorator.decorateHeaders((HttpUriRequestBase) request); + Assert.assertEquals(0, request.getHeaders().length); + request.addHeader("myheader", "value"); + request = (HttpGet) decorator.decorateHeaders(request); + Assert.assertEquals(1, request.getHeaders().length); + } + + @Test + public void testAddCustomHeaders() throws ProtocolException { + class MyCustomHeaders implements UserCustomHeaderDecorator { + public MyCustomHeaders() {} + @Override + public Map getHeaderOverrides() { + return new HashMap() + {{ + put("first", "1"); + put("second", "2"); + put("third", "3"); + }}; + } + } + MyCustomHeaders myHeaders = new MyCustomHeaders(); + RequestDecorator decorator = new RequestDecorator(myHeaders); + HttpGet request = new HttpGet("http://anyhost"); + request = (HttpGet) decorator.decorateHeaders(request); + Assert.assertEquals(3, request.getHeaders().length); + Assert.assertEquals("1", request.getHeader("first").getValue()); + Assert.assertEquals("2", request.getHeader("second").getValue()); + Assert.assertEquals("3", request.getHeader("third").getValue()); + + HttpPost request2 = new HttpPost("http://anyhost"); + request2.addHeader("myheader", "value"); + request2 = (HttpPost) decorator.decorateHeaders(request2); + Assert.assertEquals(4, request2.getHeaders().length); + } + + @Test + public void testAddBlockedHeaders() throws ProtocolException { + class MyCustomHeaders implements UserCustomHeaderDecorator { + public MyCustomHeaders() {} + @Override + public Map getHeaderOverrides() { + return new HashMap() + {{ + put("first", "1"); + put("SplitSDKVersion", "2.4"); + }}; + } + } + MyCustomHeaders myHeaders = new MyCustomHeaders(); + RequestDecorator decorator = new RequestDecorator(myHeaders); + HttpGet request = new HttpGet("http://anyhost"); + request = (HttpGet) decorator.decorateHeaders(request); + Assert.assertEquals(1, request.getHeaders().length); + Assert.assertEquals(null, request.getHeader("SplitSDKVersion")); + } + + @Test(expected = IllegalArgumentException.class) + public void customDecoratorError() { + class MyCustomHeaders implements UserCustomHeaderDecorator { + public MyCustomHeaders() {} + @Override + public Map getHeaderOverrides() { + throw new RuntimeException(); + } + } + MyCustomHeaders myHeaders = new MyCustomHeaders(); + RequestDecorator decorator = new RequestDecorator(myHeaders); + HttpGet request = new HttpGet("http://anyhost"); + request = (HttpGet) decorator.decorateHeaders(request); + } +} \ No newline at end of file From 0d41c4fbfdd5ac14fc3b0ececfdb25716ddcdbd6 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 11 Mar 2024 20:34:56 -0700 Subject: [PATCH 05/88] polish --- .../src/main/java/io/split/client/RequestDecorator.java | 2 -- .../test/java/io/split/client/RequestDecoratorTest.java | 8 +------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 6cbd54fcf..de4695544 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -1,8 +1,6 @@ package io.split.client; -import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; - import java.util.*; interface UserCustomHeaderDecorator diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index a3dfbaa8a..b7c5e500f 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -2,26 +2,20 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import org.apache.hc.core5.http.ProtocolException; import org.junit.Assert; import org.junit.Test; -import io.split.client.RequestDecorator; import java.util.HashMap; import java.util.Map; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; - public class RequestDecoratorTest { @Test public void testNoOp() { RequestDecorator decorator = new RequestDecorator(null); HttpGet request = new HttpGet("http://anyhost"); - request = (HttpGet) decorator.decorateHeaders((HttpUriRequestBase) request); + request = (HttpGet) decorator.decorateHeaders(request); Assert.assertEquals(0, request.getHeaders().length); request.addHeader("myheader", "value"); request = (HttpGet) decorator.decorateHeaders(request); From cf1bd48625392871c93214d3c3e98ab98115bda4 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 12 Mar 2024 13:32:40 -0700 Subject: [PATCH 06/88] added httpclient wrapper --- .../java/io/split/client/SplitHttpClient.java | 113 ++++++++++++++ .../io/split/client/HttpSplitClientTest.java | 140 ++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 client/src/main/java/io/split/client/SplitHttpClient.java create mode 100644 client/src/test/java/io/split/client/HttpSplitClientTest.java diff --git a/client/src/main/java/io/split/client/SplitHttpClient.java b/client/src/main/java/io/split/client/SplitHttpClient.java new file mode 100644 index 000000000..758817f29 --- /dev/null +++ b/client/src/main/java/io/split/client/SplitHttpClient.java @@ -0,0 +1,113 @@ +package io.split.client; + +import io.split.client.exceptions.UriTooLongException; +import io.split.client.utils.Utils; +import io.split.engine.common.FetchOptions; +import io.split.telemetry.domain.enums.HttpParamsWrapper; +import io.split.telemetry.storage.TelemetryRuntimeProducer; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class SplitHttpClient { + private static final Logger _log = LoggerFactory.getLogger(SplitHttpClient.class); + private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; + private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; + private final CloseableHttpClient _client; + private final RequestDecorator _requestDecorator; + private final TelemetryRuntimeProducer _telemetryRuntimeProducer; + + public static SplitHttpClient create(CloseableHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer, RequestDecorator requestDecorator) + throws URISyntaxException { + return new SplitHttpClient(client, telemetryRuntimeProducer, requestDecorator); + } + + private SplitHttpClient(CloseableHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer, RequestDecorator requestDecorator) { + _client = client; + _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); + _requestDecorator = requestDecorator; + } + + public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryParamsWrapper) { + long start = System.currentTimeMillis(); + + CloseableHttpResponse response = null; + + try { + HttpGet request = new HttpGet(uri); + if(options.cacheControlHeadersEnabled()) { + request.setHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE); + } + request = (HttpGet) _requestDecorator.decorateHeaders(request); + + response = _client.execute(request); + + int statusCode = response.getCode(); + + if (_log.isDebugEnabled()) { + _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); + } + + if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), statusCode); + if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { + _log.error("The amount of flag sets provided are big causing uri length error."); + throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); + } + _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); + throw new IllegalStateException(String.format("Http get received non-successful return code %s", statusCode)); + } + + return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } catch (Exception e) { + throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); + } finally { + _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis()-start); + Utils.forceClose(response); + } + } + + public void post(URI uri, HttpEntity entity, Map additionalHeaders, HttpParamsWrapper telemetryParamsWrapper) throws IOException { + CloseableHttpResponse response = null; + long initTime = System.currentTimeMillis(); + try { + HttpPost request = new HttpPost(uri); + if (additionalHeaders != null) { + for (Map.Entry entry : additionalHeaders.entrySet()) { + request.addHeader(entry.getKey().toString(), entry.getValue()); + } + } + request.setEntity(entity); + request = (HttpPost) _requestDecorator.decorateHeaders(request); + + response = _client.execute(request); + + int status = response.getCode(); + + if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), status); + _log.warn(String.format("Response status was: %s. Reason: %s", status, response.getReasonPhrase())); + } + _telemetryRuntimeProducer.recordSuccessfulSync(telemetryParamsWrapper.getLastSynchronizationRecordsEnum(), System.currentTimeMillis()); + } catch (Exception e) { + throw new IOException(String.format("Problem in http post operation: %s", e), e); + } finally { + _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); + Utils.forceClose(response); + } + } +} diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/client/HttpSplitClientTest.java new file mode 100644 index 000000000..ecfb92ebf --- /dev/null +++ b/client/src/test/java/io/split/client/HttpSplitClientTest.java @@ -0,0 +1,140 @@ +package io.split.client; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import io.split.TestHelper; +import io.split.client.dtos.KeyImpression; +import io.split.client.dtos.Split; +import io.split.client.dtos.SplitChange; +import io.split.client.dtos.TestImpressions; +import io.split.client.impressions.Impression; +import io.split.client.utils.Json; +import io.split.client.utils.Utils; +import io.split.engine.common.FetchOptions; +import io.split.telemetry.storage.InMemoryTelemetryStorage; +import io.split.telemetry.storage.TelemetryStorage; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpUriRequest; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import io.split.telemetry.domain.enums.HttpParamsWrapper; +import org.apache.hc.core5.http.*; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.mockito.Mockito.verify; + +public class HttpSplitClientTest { + private static final TelemetryStorage TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); + + @Test + public void testGetWithSpecialCharacters() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_OK); + RequestDecorator decorator = new RequestDecorator(null); + + SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, decorator); + String change_raw = splitHtpClient.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build(), + HttpParamsWrapper.SPLITS + ); + SplitChange change = Json.fromJson(change_raw, SplitChange.class); + + Assert.assertNotNull(change); + Assert.assertEquals(1, change.splits.size()); + Assert.assertNotNull(change.splits.get(0)); + + Split split = change.splits.get(0); + Map configs = split.configurations; + Assert.assertEquals(2, configs.size()); + Assert.assertEquals("{\"test\": \"blue\",\"grüne Straße\": 13}", configs.get("on")); + Assert.assertEquals("{\"test\": \"blue\",\"size\": 15}", configs.get("off")); + Assert.assertEquals(2, split.sets.size()); + } + + @Test(expected = IllegalStateException.class) + public void testGetError() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + RequestDecorator decorator = new RequestDecorator(null); + + SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, decorator); + String change_raw = splitHtpClient.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build(), + HttpParamsWrapper.SPLITS + ); + } + + @Test + public void testPost() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + URI rootTarget = URI.create("https://kubernetesturl.com/split"); + + // Setup response mock + CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); + RequestDecorator decorator = new RequestDecorator(null); + + SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClient, TELEMETRY_STORAGE, decorator); + + // Send impressions + List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( + KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)) + )), new TestImpressions("t2", Arrays.asList( + KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null)) + ))); + Map additionalHeaders = new HashMap<>(); + additionalHeaders.put("SplitSDKImpressionsMode", "any"); + splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders, HttpParamsWrapper.IMPRESSIONS); + + // Capture outgoing request and validate it + ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); + verify(httpClient).execute(captor.capture()); + HttpUriRequest request = captor.getValue(); + assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); + assertThat(request.getHeaders().length, is(1)); + assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("OPTIMIZED"))); + assertThat(request, instanceOf(HttpPost.class)); + HttpPost asPostRequest = (HttpPost) request; + InputStreamReader reader = new InputStreamReader(asPostRequest.getEntity().getContent()); + Gson gson = new Gson(); + List payload = gson.fromJson(reader, new TypeToken>() { }.getType()); + assertThat(payload.size(), is(equalTo(2))); + } + + @Test + public void testPosttNoExceptionOnHttpErrorCode() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + RequestDecorator decorator = new RequestDecorator(null); + + SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, decorator); + splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null, HttpParamsWrapper.IMPRESSIONS); + } + + @Test(expected = IOException.class) + public void testPosttException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + + SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, null); + splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null, HttpParamsWrapper.IMPRESSIONS); + } +} \ No newline at end of file From a372032d86a84d249bbb57b0c02f114bfe81fd6f Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 12 Mar 2024 13:45:17 -0700 Subject: [PATCH 07/88] polish --- .../java/io/split/client/SplitHttpClient.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitHttpClient.java b/client/src/main/java/io/split/client/SplitHttpClient.java index 758817f29..71c88d1ad 100644 --- a/client/src/main/java/io/split/client/SplitHttpClient.java +++ b/client/src/main/java/io/split/client/SplitHttpClient.java @@ -31,12 +31,18 @@ public final class SplitHttpClient { private final RequestDecorator _requestDecorator; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public static SplitHttpClient create(CloseableHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer, RequestDecorator requestDecorator) - throws URISyntaxException { + public static SplitHttpClient create( + CloseableHttpClient client, + TelemetryRuntimeProducer telemetryRuntimeProducer, + RequestDecorator requestDecorator + ) throws URISyntaxException { return new SplitHttpClient(client, telemetryRuntimeProducer, requestDecorator); } - private SplitHttpClient(CloseableHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer, RequestDecorator requestDecorator) { + private SplitHttpClient + (CloseableHttpClient client, + TelemetryRuntimeProducer telemetryRuntimeProducer, + RequestDecorator requestDecorator) { _client = client; _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); _requestDecorator = requestDecorator; @@ -81,7 +87,11 @@ public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryPara } } - public void post(URI uri, HttpEntity entity, Map additionalHeaders, HttpParamsWrapper telemetryParamsWrapper) throws IOException { + public void post + (URI uri, + HttpEntity entity, + Map additionalHeaders, + HttpParamsWrapper telemetryParamsWrapper) throws IOException { CloseableHttpResponse response = null; long initTime = System.currentTimeMillis(); try { From 5ae5405e96cb9315a75ab69c66679d91cf110b2c Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 12 Mar 2024 14:20:44 -0700 Subject: [PATCH 08/88] fixed tests and added splithttpclient interface --- .../java/io/split/client/SplitHttpClient.java | 113 +--------------- .../io/split/client/SplitHttpClientImpl.java | 123 ++++++++++++++++++ .../io/split/client/HttpSplitClientTest.java | 14 +- 3 files changed, 134 insertions(+), 116 deletions(-) create mode 100644 client/src/main/java/io/split/client/SplitHttpClientImpl.java diff --git a/client/src/main/java/io/split/client/SplitHttpClient.java b/client/src/main/java/io/split/client/SplitHttpClient.java index 71c88d1ad..2ab1a38e0 100644 --- a/client/src/main/java/io/split/client/SplitHttpClient.java +++ b/client/src/main/java/io/split/client/SplitHttpClient.java @@ -1,123 +1,18 @@ package io.split.client; -import io.split.client.exceptions.UriTooLongException; -import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; import io.split.telemetry.domain.enums.HttpParamsWrapper; -import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.hc.core5.http.HttpEntity; import java.io.IOException; import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; - -public final class SplitHttpClient { - private static final Logger _log = LoggerFactory.getLogger(SplitHttpClient.class); - private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; - private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; - private final CloseableHttpClient _client; - private final RequestDecorator _requestDecorator; - private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - - public static SplitHttpClient create( - CloseableHttpClient client, - TelemetryRuntimeProducer telemetryRuntimeProducer, - RequestDecorator requestDecorator - ) throws URISyntaxException { - return new SplitHttpClient(client, telemetryRuntimeProducer, requestDecorator); - } - - private SplitHttpClient - (CloseableHttpClient client, - TelemetryRuntimeProducer telemetryRuntimeProducer, - RequestDecorator requestDecorator) { - _client = client; - _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); - _requestDecorator = requestDecorator; - } - - public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryParamsWrapper) { - long start = System.currentTimeMillis(); - - CloseableHttpResponse response = null; - - try { - HttpGet request = new HttpGet(uri); - if(options.cacheControlHeadersEnabled()) { - request.setHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE); - } - request = (HttpGet) _requestDecorator.decorateHeaders(request); - - response = _client.execute(request); - - int statusCode = response.getCode(); - - if (_log.isDebugEnabled()) { - _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); - } - - if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), statusCode); - if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { - _log.error("The amount of flag sets provided are big causing uri length error."); - throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); - } - _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); - throw new IllegalStateException(String.format("Http get received non-successful return code %s", statusCode)); - } - - return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - } catch (Exception e) { - throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); - } finally { - _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis()-start); - Utils.forceClose(response); - } - } - +public interface SplitHttpClient { + public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryParamsWrapper); public void post (URI uri, HttpEntity entity, Map additionalHeaders, - HttpParamsWrapper telemetryParamsWrapper) throws IOException { - CloseableHttpResponse response = null; - long initTime = System.currentTimeMillis(); - try { - HttpPost request = new HttpPost(uri); - if (additionalHeaders != null) { - for (Map.Entry entry : additionalHeaders.entrySet()) { - request.addHeader(entry.getKey().toString(), entry.getValue()); - } - } - request.setEntity(entity); - request = (HttpPost) _requestDecorator.decorateHeaders(request); - - response = _client.execute(request); - - int status = response.getCode(); - - if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), status); - _log.warn(String.format("Response status was: %s. Reason: %s", status, response.getReasonPhrase())); - } - _telemetryRuntimeProducer.recordSuccessfulSync(telemetryParamsWrapper.getLastSynchronizationRecordsEnum(), System.currentTimeMillis()); - } catch (Exception e) { - throw new IOException(String.format("Problem in http post operation: %s", e), e); - } finally { - _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); - Utils.forceClose(response); - } - } + HttpParamsWrapper telemetryParamsWrapper) throws IOException; } diff --git a/client/src/main/java/io/split/client/SplitHttpClientImpl.java b/client/src/main/java/io/split/client/SplitHttpClientImpl.java new file mode 100644 index 000000000..ee1dc36ae --- /dev/null +++ b/client/src/main/java/io/split/client/SplitHttpClientImpl.java @@ -0,0 +1,123 @@ +package io.split.client; + +import io.split.client.exceptions.UriTooLongException; +import io.split.client.utils.Utils; +import io.split.engine.common.FetchOptions; +import io.split.telemetry.domain.enums.HttpParamsWrapper; +import io.split.telemetry.storage.TelemetryRuntimeProducer; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class SplitHttpClientImpl implements SplitHttpClient { + private static final Logger _log = LoggerFactory.getLogger(SplitHttpClient.class); + private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; + private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; + private final CloseableHttpClient _client; + private final RequestDecorator _requestDecorator; + private final TelemetryRuntimeProducer _telemetryRuntimeProducer; + + public static SplitHttpClientImpl create( + CloseableHttpClient client, + TelemetryRuntimeProducer telemetryRuntimeProducer, + RequestDecorator requestDecorator + ) throws URISyntaxException { + return new SplitHttpClientImpl(client, telemetryRuntimeProducer, requestDecorator); + } + + private SplitHttpClientImpl + (CloseableHttpClient client, + TelemetryRuntimeProducer telemetryRuntimeProducer, + RequestDecorator requestDecorator) { + _client = client; + _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); + _requestDecorator = requestDecorator; + } + + public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryParamsWrapper) { + long start = System.currentTimeMillis(); + + CloseableHttpResponse response = null; + + try { + HttpGet request = new HttpGet(uri); + if(options.cacheControlHeadersEnabled()) { + request.setHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE); + } + request = (HttpGet) _requestDecorator.decorateHeaders(request); + + response = _client.execute(request); + + int statusCode = response.getCode(); + + if (_log.isDebugEnabled()) { + _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); + } + + if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), statusCode); + if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { + _log.error("The amount of flag sets provided are big causing uri length error."); + throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); + } + _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); + throw new IllegalStateException(String.format("Http get received non-successful return code %s", statusCode)); + } + + return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } catch (Exception e) { + throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); + } finally { + _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis()-start); + Utils.forceClose(response); + } + } + + public void post + (URI uri, + HttpEntity entity, + Map additionalHeaders, + HttpParamsWrapper telemetryParamsWrapper) throws IOException { + CloseableHttpResponse response = null; + long initTime = System.currentTimeMillis(); + try { + HttpPost request = new HttpPost(uri); + if (additionalHeaders != null) { + for (Map.Entry entry : additionalHeaders.entrySet()) { + request.addHeader(entry.getKey().toString(), entry.getValue()); + } + } + request.setEntity(entity); + request = (HttpPost) _requestDecorator.decorateHeaders(request); + + response = _client.execute(request); + + int status = response.getCode(); + + if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), status); + _log.warn(String.format("Response status was: %s. Reason: %s", status, response.getReasonPhrase())); + } + _telemetryRuntimeProducer.recordSuccessfulSync(telemetryParamsWrapper.getLastSynchronizationRecordsEnum(), System.currentTimeMillis()); + } catch (Exception e) { + throw new IOException(String.format("Problem in http post operation: %s", e), e); + } finally { + _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); + Utils.forceClose(response); + } + } +} diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/client/HttpSplitClientTest.java index ecfb92ebf..5a9baea23 100644 --- a/client/src/test/java/io/split/client/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/client/HttpSplitClientTest.java @@ -48,7 +48,7 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_OK); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, decorator); String change_raw = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), HttpParamsWrapper.SPLITS @@ -73,7 +73,7 @@ public void testGetError() throws URISyntaxException, InvocationTargetException, CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, decorator); String change_raw = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), HttpParamsWrapper.SPLITS @@ -82,13 +82,13 @@ public void testGetError() throws URISyntaxException, InvocationTargetException, @Test public void testPost() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { - URI rootTarget = URI.create("https://kubernetesturl.com/split"); + URI rootTarget = URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk"); // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClient, TELEMETRY_STORAGE, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, TELEMETRY_STORAGE, decorator); // Send impressions List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( @@ -101,7 +101,7 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null)) ))); Map additionalHeaders = new HashMap<>(); - additionalHeaders.put("SplitSDKImpressionsMode", "any"); + additionalHeaders.put("SplitSDKImpressionsMode", "OPTIMIZED"); splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders, HttpParamsWrapper.IMPRESSIONS); // Capture outgoing request and validate it @@ -125,7 +125,7 @@ public void testPosttNoExceptionOnHttpErrorCode() throws URISyntaxException, Inv CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, decorator); splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null, HttpParamsWrapper.IMPRESSIONS); } @@ -134,7 +134,7 @@ public void testPosttException() throws URISyntaxException, InvocationTargetExce URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); - SplitHttpClient splitHtpClient = SplitHttpClient.create(httpClientMock, TELEMETRY_STORAGE, null); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, null); splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null, HttpParamsWrapper.IMPRESSIONS); } } \ No newline at end of file From 1958b82be63548eadbfb38892ba172d37d2d26e9 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 12 Mar 2024 19:42:27 -0700 Subject: [PATCH 09/88] added splithttpresponse dto --- .../java/io/split/client/SplitHttpClient.java | 8 ++-- .../io/split/client/SplitHttpClientImpl.java | 40 ++++++++--------- .../split/client/dtos/SplitHttpResponse.java | 10 +++++ .../io/split/client/HttpSplitClientTest.java | 45 ++++++++----------- 4 files changed, 51 insertions(+), 52 deletions(-) create mode 100644 client/src/main/java/io/split/client/dtos/SplitHttpResponse.java diff --git a/client/src/main/java/io/split/client/SplitHttpClient.java b/client/src/main/java/io/split/client/SplitHttpClient.java index 2ab1a38e0..6d54d768f 100644 --- a/client/src/main/java/io/split/client/SplitHttpClient.java +++ b/client/src/main/java/io/split/client/SplitHttpClient.java @@ -2,6 +2,7 @@ import io.split.engine.common.FetchOptions; import io.split.telemetry.domain.enums.HttpParamsWrapper; +import io.split.client.dtos.SplitHttpResponse; import org.apache.hc.core5.http.HttpEntity; import java.io.IOException; @@ -9,10 +10,9 @@ import java.util.Map; public interface SplitHttpClient { - public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryParamsWrapper); - public void post + public SplitHttpResponse get(URI uri, FetchOptions options); + public SplitHttpResponse post (URI uri, HttpEntity entity, - Map additionalHeaders, - HttpParamsWrapper telemetryParamsWrapper) throws IOException; + Map additionalHeaders) throws IOException; } diff --git a/client/src/main/java/io/split/client/SplitHttpClientImpl.java b/client/src/main/java/io/split/client/SplitHttpClientImpl.java index ee1dc36ae..b38562971 100644 --- a/client/src/main/java/io/split/client/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/client/SplitHttpClientImpl.java @@ -1,10 +1,10 @@ package io.split.client; import io.split.client.exceptions.UriTooLongException; +import io.split.client.utils.Json; import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; -import io.split.telemetry.domain.enums.HttpParamsWrapper; -import io.split.telemetry.storage.TelemetryRuntimeProducer; +import io.split.client.dtos.SplitHttpResponse; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; @@ -21,36 +21,28 @@ import java.nio.charset.StandardCharsets; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; - public final class SplitHttpClientImpl implements SplitHttpClient { private static final Logger _log = LoggerFactory.getLogger(SplitHttpClient.class); private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; private final CloseableHttpClient _client; private final RequestDecorator _requestDecorator; - private final TelemetryRuntimeProducer _telemetryRuntimeProducer; public static SplitHttpClientImpl create( CloseableHttpClient client, - TelemetryRuntimeProducer telemetryRuntimeProducer, RequestDecorator requestDecorator ) throws URISyntaxException { - return new SplitHttpClientImpl(client, telemetryRuntimeProducer, requestDecorator); + return new SplitHttpClientImpl(client, requestDecorator); } private SplitHttpClientImpl (CloseableHttpClient client, - TelemetryRuntimeProducer telemetryRuntimeProducer, RequestDecorator requestDecorator) { _client = client; - _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); _requestDecorator = requestDecorator; } - public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryParamsWrapper) { - long start = System.currentTimeMillis(); - + public SplitHttpResponse get(URI uri, FetchOptions options) { CloseableHttpResponse response = null; try { @@ -69,7 +61,6 @@ public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryPara } if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), statusCode); if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { _log.error("The amount of flag sets provided are big causing uri length error."); throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); @@ -77,21 +68,22 @@ public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryPara _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); throw new IllegalStateException(String.format("Http get received non-successful return code %s", statusCode)); } - - return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + SplitHttpResponse httpResponse = new SplitHttpResponse(); + httpResponse.statusCode = statusCode; + httpResponse.body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + httpResponse.statusMessage = ""; + return httpResponse; } catch (Exception e) { throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); } finally { - _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis()-start); Utils.forceClose(response); } } - public void post + public SplitHttpResponse post (URI uri, HttpEntity entity, - Map additionalHeaders, - HttpParamsWrapper telemetryParamsWrapper) throws IOException { + Map additionalHeaders) throws IOException { CloseableHttpResponse response = null; long initTime = System.currentTimeMillis(); try { @@ -108,15 +100,19 @@ public String get(URI uri, FetchOptions options, HttpParamsWrapper telemetryPara int status = response.getCode(); + String statusMessage = new String(""); if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(telemetryParamsWrapper.getResourceEnum(), status); + statusMessage = response.getReasonPhrase(); _log.warn(String.format("Response status was: %s. Reason: %s", status, response.getReasonPhrase())); } - _telemetryRuntimeProducer.recordSuccessfulSync(telemetryParamsWrapper.getLastSynchronizationRecordsEnum(), System.currentTimeMillis()); + SplitHttpResponse httpResponse = new SplitHttpResponse(); + httpResponse.statusCode = status; + httpResponse.body = ""; + httpResponse.statusMessage = statusMessage; + return httpResponse; } catch (Exception e) { throw new IOException(String.format("Problem in http post operation: %s", e), e); } finally { - _telemetryRuntimeProducer.recordSyncLatency(telemetryParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); Utils.forceClose(response); } } diff --git a/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java b/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java new file mode 100644 index 000000000..a708a4648 --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java @@ -0,0 +1,10 @@ +package io.split.client.dtos; + +/** + * A structure for returning http call results information + */ +public class SplitHttpResponse { + public Integer statusCode; + public String statusMessage; + public String body; +} diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/client/HttpSplitClientTest.java index 5a9baea23..91c946cac 100644 --- a/client/src/test/java/io/split/client/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/client/HttpSplitClientTest.java @@ -3,10 +3,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import io.split.TestHelper; -import io.split.client.dtos.KeyImpression; -import io.split.client.dtos.Split; -import io.split.client.dtos.SplitChange; -import io.split.client.dtos.TestImpressions; +import io.split.client.dtos.*; import io.split.client.impressions.Impression; import io.split.client.utils.Json; import io.split.client.utils.Utils; @@ -28,10 +25,7 @@ import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; @@ -40,7 +34,6 @@ import static org.mockito.Mockito.verify; public class HttpSplitClientTest { - private static final TelemetryStorage TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); @Test public void testGetWithSpecialCharacters() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { @@ -48,12 +41,11 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_OK); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, decorator); - String change_raw = splitHtpClient.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build(), - HttpParamsWrapper.SPLITS - ); - SplitChange change = Json.fromJson(change_raw, SplitChange.class); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + + SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build()); + SplitChange change = Json.fromJson(splitHttpResponse.body, SplitChange.class); Assert.assertNotNull(change); Assert.assertEquals(1, change.splits.size()); @@ -73,11 +65,9 @@ public void testGetError() throws URISyntaxException, InvocationTargetException, CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, decorator); - String change_raw = splitHtpClient.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build(), - HttpParamsWrapper.SPLITS - ); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + splitHtpClient.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build()); } @Test @@ -88,7 +78,7 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, TELEMETRY_STORAGE, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, decorator); // Send impressions List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( @@ -102,7 +92,7 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce ))); Map additionalHeaders = new HashMap<>(); additionalHeaders.put("SplitSDKImpressionsMode", "OPTIMIZED"); - splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders, HttpParamsWrapper.IMPRESSIONS); + SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders); // Capture outgoing request and validate it ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); @@ -117,6 +107,7 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce Gson gson = new Gson(); List payload = gson.fromJson(reader, new TypeToken>() { }.getType()); assertThat(payload.size(), is(equalTo(2))); + Assert.assertEquals(200,(long) splitHttpResponse.statusCode); } @Test @@ -125,8 +116,10 @@ public void testPosttNoExceptionOnHttpErrorCode() throws URISyntaxException, Inv CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, decorator); - splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null, HttpParamsWrapper.IMPRESSIONS); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null); + Assert.assertEquals(500, (long) splitHttpResponse.statusCode); + } @Test(expected = IOException.class) @@ -134,7 +127,7 @@ public void testPosttException() throws URISyntaxException, InvocationTargetExce URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, TELEMETRY_STORAGE, null); - splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null, HttpParamsWrapper.IMPRESSIONS); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, null); + splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null); } } \ No newline at end of file From 33e0454fad492611b617e8d09b776d6037f25cd0 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 13 Mar 2024 09:42:46 -0700 Subject: [PATCH 10/88] removed exception when status is not 200 --- .../src/main/java/io/split/client/SplitHttpClientImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitHttpClientImpl.java b/client/src/main/java/io/split/client/SplitHttpClientImpl.java index b38562971..a578b1913 100644 --- a/client/src/main/java/io/split/client/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/client/SplitHttpClientImpl.java @@ -60,18 +60,18 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); } + SplitHttpResponse httpResponse = new SplitHttpResponse(); + httpResponse.statusMessage = ""; if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { _log.error("The amount of flag sets provided are big causing uri length error."); throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); } _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); - throw new IllegalStateException(String.format("Http get received non-successful return code %s", statusCode)); + httpResponse.statusMessage = response.getReasonPhrase(); } - SplitHttpResponse httpResponse = new SplitHttpResponse(); httpResponse.statusCode = statusCode; httpResponse.body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - httpResponse.statusMessage = ""; return httpResponse; } catch (Exception e) { throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); From f9a6e9473acda48af89df6ebe6f92761edbf4143 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 13 Mar 2024 10:31:24 -0700 Subject: [PATCH 11/88] fixed test --- .../java/io/split/client/HttpSplitClientTest.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/client/HttpSplitClientTest.java index 91c946cac..6a2fd010a 100644 --- a/client/src/test/java/io/split/client/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/client/HttpSplitClientTest.java @@ -59,12 +59,24 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation Assert.assertEquals(2, split.sets.size()); } - @Test(expected = IllegalStateException.class) + @Test public void testGetError() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build()); + Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (long) splitHttpResponse.statusCode); + } + + @Test(expected = IllegalStateException.class) + public void testException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + RequestDecorator decorator = null; + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build()); From a9c3eab558239d21a20db2d510f08a464e8acf15 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 13 Mar 2024 10:40:36 -0700 Subject: [PATCH 12/88] updated split change fetcher --- .../split/client/HttpSplitChangeFetcher.java | 39 +++++-------------- .../io/split/client/SplitHttpClientImpl.java | 6 +-- .../client/HttpSplitChangeFetcherTest.java | 23 +++++++---- .../io/split/client/HttpSplitClientTest.java | 14 ++++++- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index 65d37d144..8419c76f4 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -2,6 +2,7 @@ import com.google.common.annotations.VisibleForTesting; import io.split.client.dtos.SplitChange; +import io.split.client.dtos.SplitHttpResponse; import io.split.client.exceptions.UriTooLongException; import io.split.client.utils.Json; import io.split.client.utils.Utils; @@ -10,18 +11,13 @@ import io.split.telemetry.domain.enums.HTTPLatenciesEnum; import io.split.telemetry.domain.enums.ResourceEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.net.URIBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import static com.google.common.base.Preconditions.checkNotNull; @@ -38,16 +34,16 @@ public final class HttpSplitChangeFetcher implements SplitChangeFetcher { private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; - private final CloseableHttpClient _client; + private final SplitHttpClient _client; private final URI _target; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public static HttpSplitChangeFetcher create(CloseableHttpClient client, URI root, TelemetryRuntimeProducer telemetryRuntimeProducer) + public static HttpSplitChangeFetcher create(SplitHttpClient client, URI root, TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { return new HttpSplitChangeFetcher(client, Utils.appendPath(root, "api/splitChanges"), telemetryRuntimeProducer); } - private HttpSplitChangeFetcher(CloseableHttpClient client, URI uri, TelemetryRuntimeProducer telemetryRuntimeProducer) { + private HttpSplitChangeFetcher(SplitHttpClient client, URI uri, TelemetryRuntimeProducer telemetryRuntimeProducer) { _client = client; _target = uri; checkNotNull(_target); @@ -64,7 +60,7 @@ public SplitChange fetch(long since, FetchOptions options) { long start = System.currentTimeMillis(); - CloseableHttpResponse response = null; + SplitHttpResponse response = null; try { URIBuilder uriBuilder = new URIBuilder(_target).addParameter(SINCE, "" + since); @@ -75,38 +71,21 @@ public SplitChange fetch(long since, FetchOptions options) { uriBuilder.addParameter(SETS, "" + options.flagSetsFilter()); } URI uri = uriBuilder.build(); + response = _client.get(uri, options); - HttpGet request = new HttpGet(uri); - if(options.cacheControlHeadersEnabled()) { - request.setHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE); - } - - response = _client.execute(request); - - int statusCode = response.getCode(); - - if (_log.isDebugEnabled()) { - _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); - } + int statusCode = response.statusCode; if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.statusMessage)); _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, statusCode); - if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { - _log.error("The amount of flag sets provided are big causing uri length error."); - throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); - } - _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); throw new IllegalStateException(String.format("Could not retrieve splitChanges since %s; http return code %s", since, statusCode)); } - String json = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - - return Json.fromJson(json, SplitChange.class); + return Json.fromJson(response.body, SplitChange.class); } catch (Exception e) { throw new IllegalStateException(String.format("Problem fetching splitChanges since %s: %s", since, e), e); } finally { _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.SPLITS, System.currentTimeMillis()-start); - Utils.forceClose(response); } } diff --git a/client/src/main/java/io/split/client/SplitHttpClientImpl.java b/client/src/main/java/io/split/client/SplitHttpClientImpl.java index b38562971..a578b1913 100644 --- a/client/src/main/java/io/split/client/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/client/SplitHttpClientImpl.java @@ -60,18 +60,18 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); } + SplitHttpResponse httpResponse = new SplitHttpResponse(); + httpResponse.statusMessage = ""; if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { _log.error("The amount of flag sets provided are big causing uri length error."); throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); } _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); - throw new IllegalStateException(String.format("Http get received non-successful return code %s", statusCode)); + httpResponse.statusMessage = response.getReasonPhrase(); } - SplitHttpResponse httpResponse = new SplitHttpResponse(); httpResponse.statusCode = statusCode; httpResponse.body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - httpResponse.statusMessage = ""; return httpResponse; } catch (Exception e) { throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); diff --git a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java index 1784c44ed..e5a70198c 100644 --- a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java @@ -40,7 +40,9 @@ public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://api.split.io/api/splitChanges", fetcher.getTarget().toString()); } @@ -48,7 +50,9 @@ public void testDefaultURL() throws URISyntaxException { public void testCustomURLNoPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://kubernetesturl.com/split/api/splitChanges", fetcher.getTarget().toString()); } @@ -56,7 +60,8 @@ public void testCustomURLNoPathNoBackslash() throws URISyntaxException { public void testCustomURLAppendingPath() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split/"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://kubernetesturl.com/split/api/splitChanges", fetcher.getTarget().toString()); } @@ -64,7 +69,8 @@ public void testCustomURLAppendingPath() throws URISyntaxException { public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://kubernetesturl.com/split/api/splitChanges", fetcher.getTarget().toString()); } @@ -73,8 +79,9 @@ public void testFetcherWithSpecialCharacters() throws URISyntaxException, Invoca URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClientMock, rootTarget, TELEMETRY_STORAGE); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); SplitChange change = fetcher.fetch(1234567, new FetchOptions.Builder().cacheControlHeaders(true).build()); @@ -104,8 +111,9 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClientMock, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); fetcher.fetch(-1, new FetchOptions.Builder().targetChangeNumber(123).build()); fetcher.fetch(-1, new FetchOptions.Builder().build()); @@ -119,7 +127,8 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept public void testRandomNumberGeneration() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(httpClientMock, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); Set seen = new HashSet<>(); long min = (long)Math.pow(2, 63) * (-1); diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/client/HttpSplitClientTest.java index 91c946cac..6a2fd010a 100644 --- a/client/src/test/java/io/split/client/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/client/HttpSplitClientTest.java @@ -59,12 +59,24 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation Assert.assertEquals(2, split.sets.size()); } - @Test(expected = IllegalStateException.class) + @Test public void testGetError() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build()); + Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (long) splitHttpResponse.statusCode); + } + + @Test(expected = IllegalStateException.class) + public void testException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + RequestDecorator decorator = null; + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build()); From 8041204c760f3bd613b20c87247cdf20a0fc773c Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 13 Mar 2024 11:42:11 -0700 Subject: [PATCH 13/88] moved flagset warning out of splithttp client and moved the client class to service --- .../java/io/split/client/HttpSplitChangeFetcher.java | 6 +++++- .../src/main/java/io/split/client/RequestDecorator.java | 2 +- .../io/split/{client => service}/SplitHttpClient.java | 2 +- .../split/{client => service}/SplitHttpClientImpl.java | 9 ++------- .../java/io/split/client/HttpSplitChangeFetcherTest.java | 2 ++ .../test/java/io/split/client/HttpSplitClientTest.java | 6 ++---- 6 files changed, 13 insertions(+), 14 deletions(-) rename client/src/main/java/io/split/{client => service}/SplitHttpClient.java (95%) rename client/src/main/java/io/split/{client => service}/SplitHttpClientImpl.java (91%) diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index 8419c76f4..609070b7d 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -8,6 +8,7 @@ import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; import io.split.engine.experiments.SplitChangeFetcher; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.enums.HTTPLatenciesEnum; import io.split.telemetry.domain.enums.ResourceEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; @@ -76,7 +77,10 @@ public SplitChange fetch(long since, FetchOptions options) { int statusCode = response.statusCode; if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.statusMessage)); + if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { + _log.error("The amount of flag sets provided are big causing uri length error."); + throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.statusMessage)); + } _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, statusCode); throw new IllegalStateException(String.format("Could not retrieve splitChanges since %s; http return code %s", since, statusCode)); } diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index de4695544..49d491868 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -16,7 +16,7 @@ public Map getHeaderOverrides() { } } -class RequestDecorator { +public final class RequestDecorator { UserCustomHeaderDecorator _headerDecorator; private static final Set forbiddenHeaders = new HashSet<>(Arrays.asList( diff --git a/client/src/main/java/io/split/client/SplitHttpClient.java b/client/src/main/java/io/split/service/SplitHttpClient.java similarity index 95% rename from client/src/main/java/io/split/client/SplitHttpClient.java rename to client/src/main/java/io/split/service/SplitHttpClient.java index 6d54d768f..637510e78 100644 --- a/client/src/main/java/io/split/client/SplitHttpClient.java +++ b/client/src/main/java/io/split/service/SplitHttpClient.java @@ -1,4 +1,4 @@ -package io.split.client; +package io.split.service; import io.split.engine.common.FetchOptions; import io.split.telemetry.domain.enums.HttpParamsWrapper; diff --git a/client/src/main/java/io/split/client/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java similarity index 91% rename from client/src/main/java/io/split/client/SplitHttpClientImpl.java rename to client/src/main/java/io/split/service/SplitHttpClientImpl.java index a578b1913..92cab6659 100644 --- a/client/src/main/java/io/split/client/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -1,7 +1,6 @@ -package io.split.client; +package io.split.service; -import io.split.client.exceptions.UriTooLongException; -import io.split.client.utils.Json; +import io.split.client.RequestDecorator; import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; import io.split.client.dtos.SplitHttpResponse; @@ -63,10 +62,6 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { SplitHttpResponse httpResponse = new SplitHttpResponse(); httpResponse.statusMessage = ""; if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { - _log.error("The amount of flag sets provided are big causing uri length error."); - throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.getReasonPhrase())); - } _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); httpResponse.statusMessage = response.getReasonPhrase(); } diff --git a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java index e5a70198c..794a7f057 100644 --- a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java @@ -5,6 +5,8 @@ import io.split.client.dtos.SplitChange; import io.split.engine.common.FetchOptions; import io.split.engine.metrics.Metrics; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryRuntimeProducer; import io.split.telemetry.storage.TelemetryStorage; diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/client/HttpSplitClientTest.java index 6a2fd010a..b8effa2ae 100644 --- a/client/src/test/java/io/split/client/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/client/HttpSplitClientTest.java @@ -8,17 +8,15 @@ import io.split.client.utils.Json; import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; -import io.split.telemetry.storage.InMemoryTelemetryStorage; -import io.split.telemetry.storage.TelemetryStorage; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.classic.methods.HttpUriRequest; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import io.split.telemetry.domain.enums.HttpParamsWrapper; import org.apache.hc.core5.http.*; import org.junit.Assert; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; import java.io.IOException; import java.io.InputStreamReader; From ab42b943fba36c915b8ca36c12e1b4c52327dde3 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 14 Mar 2024 10:54:36 -0700 Subject: [PATCH 14/88] updated segment fetcher class --- .../client/HttpSegmentChangeFetcher.java | 36 +++++-------------- .../client/HttpSegmentChangeFetcherTest.java | 21 +++++++---- .../client/HttpSplitChangeFetcherTest.java | 2 +- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java index 84bf09509..7014646d6 100644 --- a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java @@ -2,26 +2,23 @@ import com.google.common.annotations.VisibleForTesting; import io.split.client.dtos.SegmentChange; +import io.split.client.dtos.SplitHttpResponse; import io.split.client.utils.Json; import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; import io.split.engine.segments.SegmentChangeFetcher; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.enums.HTTPLatenciesEnum; import io.split.telemetry.domain.enums.LastSynchronizationRecordsEnum; import io.split.telemetry.domain.enums.ResourceEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.net.URIBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import static com.google.common.base.Preconditions.checkNotNull; @@ -37,16 +34,16 @@ public final class HttpSegmentChangeFetcher implements SegmentChangeFetcher { private static final String CACHE_CONTROL_HEADER_NAME = "Cache-Control"; private static final String CACHE_CONTROL_HEADER_VALUE = "no-cache"; - private final CloseableHttpClient _client; + private final SplitHttpClient _client; private final URI _target; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public static HttpSegmentChangeFetcher create(CloseableHttpClient client, URI root, TelemetryRuntimeProducer telemetryRuntimeProducer) + public static HttpSegmentChangeFetcher create(SplitHttpClient client, URI root, TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { return new HttpSegmentChangeFetcher(client, Utils.appendPath(root, "api/segmentChanges"), telemetryRuntimeProducer); } - private HttpSegmentChangeFetcher(CloseableHttpClient client, URI uri, TelemetryRuntimeProducer telemetryRuntimeProducer) { + private HttpSegmentChangeFetcher(SplitHttpClient client, URI uri, TelemetryRuntimeProducer telemetryRuntimeProducer) { _client = client; _target = uri; checkNotNull(_target); @@ -57,7 +54,7 @@ private HttpSegmentChangeFetcher(CloseableHttpClient client, URI uri, TelemetryR public SegmentChange fetch(String segmentName, long since, FetchOptions options) { long start = System.currentTimeMillis(); - CloseableHttpResponse response = null; + SplitHttpResponse response = null; try { String path = _target.getPath() + "/" + segmentName; @@ -69,23 +66,12 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options) } URI uri = uriBuilder.build(); - HttpGet request = new HttpGet(uri); - if(options.cacheControlHeadersEnabled()) { - request.setHeader(CACHE_CONTROL_HEADER_NAME, CACHE_CONTROL_HEADER_VALUE); - } - - response = _client.execute(request); - - int statusCode = response.getCode(); - - if (_log.isDebugEnabled()) { - _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); - } + response = _client.get(uri, options); + int statusCode = response.statusCode; if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, statusCode); - _log.error(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); if (statusCode == HttpStatus.SC_FORBIDDEN) { _log.error("factory instantiation: you passed a client side type sdkKey, " + "please grab an sdk key from the Split user interface that is of type server side"); @@ -93,18 +79,14 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options) throw new IllegalStateException(String.format("Could not retrieve segment changes for %s, since %s; http return code %s", segmentName, since, statusCode)); } - _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.SEGMENTS, System.currentTimeMillis()); - String json = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - - return Json.fromJson(json, SegmentChange.class); + return Json.fromJson(response.body, SegmentChange.class); } catch (Exception e) { throw new IllegalStateException(String.format("Error occurred when trying to sync segment: %s, since: %s. Details: %s", segmentName, since, e), e); } finally { _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.SEGMENTS, System.currentTimeMillis()-start); - Utils.forceClose(response); } diff --git a/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java index be1fb4b3c..e40c61dd9 100644 --- a/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java @@ -4,6 +4,8 @@ import io.split.client.dtos.SegmentChange; import io.split.engine.common.FetchOptions; import io.split.engine.metrics.Metrics; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryStorage; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; @@ -31,8 +33,9 @@ public class HttpSegmentChangeFetcherTest { public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://api.split.io/api/segmentChanges"))); } @@ -40,8 +43,9 @@ public void testDefaultURL() throws URISyntaxException { public void testCustomURLNoPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); } @@ -49,8 +53,9 @@ public void testCustomURLNoPathNoBackslash() throws URISyntaxException { public void testCustomURLAppendingPath() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split/"); CloseableHttpClient httpClient = HttpClients.custom().build(); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); } @@ -58,8 +63,9 @@ public void testCustomURLAppendingPath() throws URISyntaxException { public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(httpClient, rootTarget, TELEMETRY_STORAGE); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); } @@ -68,9 +74,10 @@ public void testFetcherWithSpecialCharacters() throws URISyntaxException, IOExce URI rootTarget = URI.create("https://api.split.io/api/segmentChanges"); CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("segment-change-special-chatacters.json", HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(httpClientMock, rootTarget, TELEMETRY_STORAGE); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); SegmentChange change = fetcher.fetch("some_segment", 1234567, new FetchOptions.Builder().build()); @@ -94,10 +101,12 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(httpClientMock, rootTarget, Mockito.mock(TelemetryStorage.class)); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryStorage.class)); fetcher.fetch("someSegment", -1, new FetchOptions.Builder().targetChangeNumber(123).build()); fetcher.fetch("someSegment2",-1, new FetchOptions.Builder().build()); diff --git a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java index 794a7f057..4140f726d 100644 --- a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java @@ -41,8 +41,8 @@ public class HttpSplitChangeFetcherTest { public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); - Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://api.split.io/api/splitChanges", fetcher.getTarget().toString()); From 7dd45c2a1e8d2e478c09ebb089190ab80758dd01 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 14 Mar 2024 11:00:05 -0700 Subject: [PATCH 15/88] polish --- .../test/java/io/split/client/HttpSplitChangeFetcherTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java index 4140f726d..794a7f057 100644 --- a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java @@ -41,8 +41,8 @@ public class HttpSplitChangeFetcherTest { public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://api.split.io/api/splitChanges", fetcher.getTarget().toString()); From 0675dc42bcf38f0815a82b4c054f1e1d49dfd8fb Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 14 Mar 2024 12:35:14 -0700 Subject: [PATCH 16/88] polish --- .../main/java/io/split/client/HttpSegmentChangeFetcher.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java index 7014646d6..e55952304 100644 --- a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java @@ -30,9 +30,6 @@ public final class HttpSegmentChangeFetcher implements SegmentChangeFetcher { private static final String SINCE = "since"; private static final String TILL = "till"; - private static final String PREFIX = "segmentChangeFetcher"; - private static final String CACHE_CONTROL_HEADER_NAME = "Cache-Control"; - private static final String CACHE_CONTROL_HEADER_VALUE = "no-cache"; private final SplitHttpClient _client; private final URI _target; From a6d725c03a3e77d7a3575409908bd985a7951421 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 14 Mar 2024 13:05:03 -0700 Subject: [PATCH 17/88] updated impression sender class --- .../impressions/HttpImpressionsSender.java | 39 ++++++++----------- .../HttpImpressionsSenderTest.java | 27 +++++++++---- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index 0a08e5dad..ba8382653 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -2,16 +2,15 @@ import com.google.common.annotations.VisibleForTesting; import io.split.client.dtos.ImpressionCount; +import io.split.client.dtos.SplitHttpResponse; import io.split.client.dtos.TestImpressions; import io.split.client.utils.Utils; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.enums.HTTPLatenciesEnum; import io.split.telemetry.domain.enums.LastSynchronizationRecordsEnum; import io.split.telemetry.domain.enums.ResourceEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.classic.methods.HttpPost; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpStatus; import org.slf4j.Logger; @@ -22,6 +21,7 @@ import java.net.URISyntaxException; import java.util.HashMap; import java.util.List; +import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; @@ -36,13 +36,13 @@ public class HttpImpressionsSender implements ImpressionsSender { private static final Logger _logger = LoggerFactory.getLogger(HttpImpressionsSender.class); - private final CloseableHttpClient _client; + private final SplitHttpClient _client; private final URI _impressionBulkTarget; private final URI _impressionCountTarget; private final ImpressionsManager.Mode _mode; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public static HttpImpressionsSender create(CloseableHttpClient client, URI eventsRootEndpoint, ImpressionsManager.Mode mode, + public static HttpImpressionsSender create(SplitHttpClient client, URI eventsRootEndpoint, ImpressionsManager.Mode mode, TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { return new HttpImpressionsSender(client, Utils.appendPath(eventsRootEndpoint, BULK_ENDPOINT_PATH), @@ -51,7 +51,7 @@ public static HttpImpressionsSender create(CloseableHttpClient client, URI event telemetryRuntimeProducer); } - private HttpImpressionsSender(CloseableHttpClient client, URI impressionBulkTarget, URI impressionCountTarget, ImpressionsManager.Mode mode, + private HttpImpressionsSender(SplitHttpClient client, URI impressionBulkTarget, URI impressionCountTarget, ImpressionsManager.Mode mode, TelemetryRuntimeProducer telemetryRuntimeProducer) { _client = client; _mode = mode; @@ -63,22 +63,18 @@ private HttpImpressionsSender(CloseableHttpClient client, URI impressionBulkTarg @Override public void postImpressionsBulk(List impressions) { - CloseableHttpResponse response = null; + SplitHttpResponse response = null; long initTime = System.currentTimeMillis(); try { HttpEntity entity = Utils.toJsonEntity(impressions); + Map additionalHeader = new HashMap<>(); + additionalHeader.put(IMPRESSIONS_MODE_HEADER, _mode.toString()); + response = _client.post(_impressionBulkTarget, entity, additionalHeader); - HttpPost request = new HttpPost(_impressionBulkTarget); - request.addHeader(IMPRESSIONS_MODE_HEADER, _mode.toString()); - request.setEntity(entity); - - response = _client.execute(request); - - int status = response.getCode(); + int status = response.statusCode; if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, status); - _logger.warn(String.format("Response status was: %s. Reason: %s", status , response.getReasonPhrase())); } _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS, System.currentTimeMillis()); @@ -86,9 +82,7 @@ public void postImpressionsBulk(List impressions) { _logger.warn("Exception when posting impressions" + impressions, t); } finally { _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS, System.currentTimeMillis() - initTime); - Utils.forceClose(response); } - } @Override @@ -99,13 +93,14 @@ public void postCounters(HashMap raw) { return; } - HttpPost request = new HttpPost(_impressionCountTarget); - request.setEntity(Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw))); - try (CloseableHttpResponse response = _client.execute(request)) { - int status = response.getCode(); + try { + SplitHttpResponse response = _client.post(_impressionCountTarget, + Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw)), + null); + + int status = response.statusCode; if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, status); - _logger.warn(String.format("Response status was: %s. Reason: %s", status , response.getReasonPhrase())); } _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS_COUNT, System.currentTimeMillis() - initTime); _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT, System.currentTimeMillis()); diff --git a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java index ee586ffe4..624f49788 100644 --- a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java +++ b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java @@ -3,9 +3,12 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.client.dtos.ImpressionCount; import io.split.client.dtos.KeyImpression; import io.split.client.dtos.TestImpressions; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryStorage; import org.apache.hc.client5.http.classic.methods.HttpPost; @@ -42,7 +45,8 @@ public class HttpImpressionsSenderTest { public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://api.split.io/api/testImpressions/bulk"))); } @@ -50,7 +54,8 @@ public void testDefaultURL() throws URISyntaxException { public void testCustomURLNoPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/api/testImpressions/bulk"))); } @@ -58,7 +63,8 @@ public void testCustomURLNoPathNoBackslash() throws URISyntaxException { public void testCustomURLAppendingPath() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split/"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/testImpressions/bulk"))); } @@ -66,7 +72,8 @@ public void testCustomURLAppendingPath() throws URISyntaxException { public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/testImpressions/bulk"))); } @@ -76,9 +83,10 @@ public void testImpressionCountsEndpointOptimized() throws URISyntaxException, I // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); // Send counters - HttpImpressionsSender sender = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); HashMap toSend = new HashMap<>(); toSend.put(new ImpressionCounter.Key("test1", 0), 4); toSend.put(new ImpressionCounter.Key("test2", 0), 5); @@ -106,9 +114,10 @@ public void testImpressionCountsEndpointDebug() throws URISyntaxException, IOExc // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); // Send counters - HttpImpressionsSender sender = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); HashMap toSend = new HashMap<>(); toSend.put(new ImpressionCounter.Key("test1", 0), 4); toSend.put(new ImpressionCounter.Key("test2", 0), 5); @@ -124,8 +133,9 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); - HttpImpressionsSender sender = HttpImpressionsSender.create(httpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); // Send impressions List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( @@ -155,8 +165,9 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException // Do the same flow for imrpessionsMode = debug CloseableHttpClient httpClientDebugMode = TestHelper.mockHttpClient("", HttpStatus.SC_OK); + SplitHttpClient splitHtpClient2 = SplitHttpClientImpl.create(httpClientDebugMode, new RequestDecorator(null)); - sender = HttpImpressionsSender.create(httpClientDebugMode, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + sender = HttpImpressionsSender.create(splitHtpClient2, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); sender.postImpressionsBulk(toSend); captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClientDebugMode).execute(captor.capture()); From d10e3dc327dc04e8a3dc1750b9e8c4afde6875af Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 14 Mar 2024 13:42:55 -0700 Subject: [PATCH 18/88] polish --- client/src/main/java/io/split/service/SplitHttpClientImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 92cab6659..5497a69f2 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -13,7 +13,6 @@ import org.apache.hc.core5.http.io.entity.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; From b8fdfdd42159ba2bc5e39afb00fa2f3579e21035 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 18 Mar 2024 09:48:05 -0700 Subject: [PATCH 19/88] updated Telemetry submitter and sender classes --- .../HttpTelemetryMemorySender.java | 5 +++-- .../TelemetryInMemorySubmitter.java | 3 ++- .../io/split/service/HttpPostImpTest.java | 7 +++++-- .../TelemetryInMemorySubmitterTest.java | 20 +++++++++++++------ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java b/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java index 1cfd39fb3..9fc25bd63 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java @@ -4,6 +4,7 @@ import io.split.client.dtos.UniqueKeys; import io.split.client.utils.Utils; import io.split.service.HttpPostImp; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.Config; import io.split.telemetry.domain.Stats; import io.split.telemetry.domain.enums.HttpParamsWrapper; @@ -31,7 +32,7 @@ public class HttpTelemetryMemorySender{ private final URI _uniqueKeysTarget; private final HttpPostImp _httpPost; - public static HttpTelemetryMemorySender create(CloseableHttpClient client, URI telemetryRootEndpoint, + public static HttpTelemetryMemorySender create(SplitHttpClient client, URI telemetryRootEndpoint, TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { return new HttpTelemetryMemorySender(client, Utils.appendPath(telemetryRootEndpoint,CONFIG_ENDPOINT_PATH), @@ -42,7 +43,7 @@ public static HttpTelemetryMemorySender create(CloseableHttpClient client, URI t } @VisibleForTesting - HttpTelemetryMemorySender(CloseableHttpClient client, URI impressionConfigTarget, URI impressionStatsTarget, + HttpTelemetryMemorySender(SplitHttpClient client, URI impressionConfigTarget, URI impressionStatsTarget, URI uniqueKeysTarget,TelemetryRuntimeProducer telemetryRuntimeProducer) { _httpPost = new HttpPostImp(client, telemetryRuntimeProducer); _impressionConfigTarget = impressionConfigTarget; diff --git a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java index 4f52bcdf1..004955485 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java @@ -7,6 +7,7 @@ import io.split.client.impressions.ImpressionsManager; import io.split.integrations.IntegrationsConfig; import io.split.integrations.NewRelicListener; +import io.split.service.SplitHttpClient; import io.split.storages.SegmentCacheConsumer; import io.split.storages.SplitCacheConsumer; import io.split.telemetry.domain.Config; @@ -38,7 +39,7 @@ public class TelemetryInMemorySubmitter implements TelemetrySynchronizer{ private SegmentCacheConsumer _segmentCacheConsumer; private final long _initStartTime; - public TelemetryInMemorySubmitter(CloseableHttpClient client, URI telemetryRootEndpoint, TelemetryStorageConsumer telemetryStorageConsumer, + public TelemetryInMemorySubmitter(SplitHttpClient client, URI telemetryRootEndpoint, TelemetryStorageConsumer telemetryStorageConsumer, SplitCacheConsumer splitCacheConsumer, SegmentCacheConsumer segmentCacheConsumer, TelemetryRuntimeProducer telemetryRuntimeProducer, long initStartTime) throws URISyntaxException { _httpHttpTelemetryMemorySender = HttpTelemetryMemorySender.create(client, telemetryRootEndpoint, telemetryRuntimeProducer); diff --git a/client/src/test/java/io/split/service/HttpPostImpTest.java b/client/src/test/java/io/split/service/HttpPostImpTest.java index b6b422d89..fb4dc0414 100644 --- a/client/src/test/java/io/split/service/HttpPostImpTest.java +++ b/client/src/test/java/io/split/service/HttpPostImpTest.java @@ -1,6 +1,7 @@ package io.split.service; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryStorage; @@ -21,8 +22,9 @@ public class HttpPostImpTest{ @Test public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(client, new RequestDecorator(null)); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); - HttpPostImp httpPostImp = new HttpPostImp(client, telemetryStorage); + HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); Assert.assertNotEquals(0, telemetryStorage.getLastSynchronization().get_telemetry()); @@ -32,8 +34,9 @@ public void testPostWith200() throws InvocationTargetException, NoSuchMethodExce @Test public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_CLIENT_ERROR); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(client, new RequestDecorator(null)); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); - HttpPostImp httpPostImp = new HttpPostImp(client, telemetryStorage); + HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); diff --git a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java index 10aa46298..cf0f9a45d 100644 --- a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java +++ b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java @@ -1,7 +1,10 @@ package io.split.telemetry.synchronizer; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.client.dtos.UniqueKeys; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.storages.SegmentCacheConsumer; import io.split.storages.SplitCacheConsumer; import io.split.client.ApiKeyCounter; @@ -46,7 +49,8 @@ public class TelemetryInMemorySubmitterTest { @Test public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, new RequestDecorator(null)); + TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().build(); telemetrySynchronizer.synchronizeConfig(splitClientConfig, 100l, new HashMap(), new ArrayList()); @@ -57,7 +61,8 @@ public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodExcep @Test public void testSynchronizeStats() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, new RequestDecorator(null)); + TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); telemetrySynchronizer.synchronizeStats(); Mockito.verify(httpClient, Mockito.times(1)).execute(Mockito.any()); @@ -66,7 +71,8 @@ public void testSynchronizeStats() throws Exception { @Test public void testSynchronizeUniqueKeys() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, new RequestDecorator(null)); + TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); List keys = new ArrayList<>(); keys.add("key-1"); @@ -89,7 +95,8 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException ApiKeyCounter.getApiKeyCounterInstance().add(SECOND_KEY); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, null); + TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().flagSetsFilter(Arrays.asList("a", "_b", "a", "a", "c", "d", "_d")).build(); populateConfig(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); @@ -110,7 +117,8 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException public void testStats() throws Exception { TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, null); + TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); populateStats(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); telemetryStorageConsumer.setAccessible(true); @@ -175,7 +183,7 @@ public void testStats() throws Exception { Assert.assertEquals(1, stats.getUpdatesFromSSE().getSplits()); } - private TelemetryInMemorySubmitter getTelemetrySynchronizer(CloseableHttpClient httpClient) throws URISyntaxException { + private TelemetryInMemorySubmitter getTelemetrySynchronizer(SplitHttpClient httpClient) throws URISyntaxException { TelemetryStorageConsumer consumer = Mockito.mock(InMemoryTelemetryStorage.class); TelemetryRuntimeProducer telemetryRuntimeProducer = Mockito.mock(TelemetryRuntimeProducer.class); SplitCacheConsumer splitCacheConsumer = Mockito.mock(SplitCacheConsumer.class); From 61446c8edeecf35c87546b53798df3fdebd5cd57 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 18 Mar 2024 10:54:16 -0700 Subject: [PATCH 20/88] fixed tests --- .../test/java/io/split/service/HttpPostImpTest.java | 9 +++++---- .../synchronizer/TelemetryInMemorySubmitterTest.java | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/client/src/test/java/io/split/service/HttpPostImpTest.java b/client/src/test/java/io/split/service/HttpPostImpTest.java index fb4dc0414..64baa28d2 100644 --- a/client/src/test/java/io/split/service/HttpPostImpTest.java +++ b/client/src/test/java/io/split/service/HttpPostImpTest.java @@ -14,15 +14,16 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URI; +import java.net.URISyntaxException; public class HttpPostImpTest{ private static final String URL = "www.split.io"; @Test - public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException { CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(client, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null)); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); @@ -32,9 +33,9 @@ public void testPostWith200() throws InvocationTargetException, NoSuchMethodExce } @Test - public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException { CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_CLIENT_ERROR); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(client, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null)); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); diff --git a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java index cf0f9a45d..add699ea9 100644 --- a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java +++ b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java @@ -49,7 +49,7 @@ public class TelemetryInMemorySubmitterTest { @Test public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().build(); @@ -61,7 +61,7 @@ public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodExcep @Test public void testSynchronizeStats() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); telemetrySynchronizer.synchronizeStats(); @@ -71,7 +71,7 @@ public void testSynchronizeStats() throws Exception { @Test public void testSynchronizeUniqueKeys() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); List keys = new ArrayList<>(); @@ -95,7 +95,7 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException ApiKeyCounter.getApiKeyCounterInstance().add(SECOND_KEY); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, null); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, null); TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().flagSetsFilter(Arrays.asList("a", "_b", "a", "a", "c", "d", "_d")).build(); populateConfig(telemetryStorage); @@ -117,7 +117,7 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException public void testStats() throws Exception { TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = new SplitHttpClientImpl(httpClient, null); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, null); TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); populateStats(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); From 7ca4ed82d96a403b7cb869794417aae8db100a77 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 18 Mar 2024 12:44:54 -0700 Subject: [PATCH 21/88] updated factory and config --- .../io/split/client/RequestDecorator.java | 5 ---- .../io/split/client/SplitClientConfig.java | 30 +++++++++++++++---- .../io/split/client/SplitFactoryImpl.java | 17 +++++++---- .../client/UserCustomHeaderDecorator.java | 8 +++++ .../split/client/SplitClientConfigTest.java | 18 +++++++++++ .../HttpSplitClientTest.java | 0 6 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 client/src/main/java/io/split/client/UserCustomHeaderDecorator.java rename client/src/test/java/io/split/{client => service}/HttpSplitClientTest.java (100%) diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 49d491868..97257cd43 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -3,11 +3,6 @@ import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; import java.util.*; -interface UserCustomHeaderDecorator -{ - Map getHeaderOverrides(); -} - class NoOpHeaderDecorator implements UserCustomHeaderDecorator { public NoOpHeaderDecorator() {} @Override diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 11e2ec2bc..50dc73d2f 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -10,11 +10,8 @@ import pluggable.CustomStorageWrapper; import java.io.IOException; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.*; import java.io.InputStream; -import java.util.Properties; import java.util.concurrent.ThreadFactory; import static io.split.inputValidation.FlagSetsValidator.cleanup; @@ -90,6 +87,8 @@ public class SplitClientConfig { private final long _lastSeenCacheSize; private final HashSet _flagSetsFilter; private final int _invalidSets; + private final UserCustomHeaderDecorator _userCustomHeaderDecorator; + public static Builder builder() { return new Builder(); @@ -145,7 +144,8 @@ private SplitClientConfig(String endpoint, long lastSeenCacheSize, ThreadFactory threadFactory, HashSet flagSetsFilter, - int invalidSets) { + int invalidSets, + UserCustomHeaderDecorator userCustomHeaderDecorator) { _endpoint = endpoint; _eventsEndpoint = eventsEndpoint; _featuresRefreshRate = pollForFeatureChangesEveryNSeconds; @@ -197,6 +197,7 @@ private SplitClientConfig(String endpoint, _threadFactory = threadFactory; _flagSetsFilter = flagSetsFilter; _invalidSets = invalidSets; + _userCustomHeaderDecorator = userCustomHeaderDecorator; Properties props = new Properties(); try { @@ -393,6 +394,10 @@ public int getInvalidSets() { return _invalidSets; } + public UserCustomHeaderDecorator userCustomHeaderDecorator() { + return _userCustomHeaderDecorator; + } + public static final class Builder { private String _endpoint = SDK_ENDPOINT; @@ -449,6 +454,7 @@ public static final class Builder { private ThreadFactory _threadFactory; private HashSet _flagSetsFilter = new HashSet<>(); private int _invalidSetsCount = 0; + private UserCustomHeaderDecorator _userCustomHeaderDecorator = null; public Builder() { } @@ -932,6 +938,17 @@ public Builder flagSetsFilter(List flagSetsFilter) { return this; } + /** + * User Custom Header Decorator + * + * @param userCustomHeaderDecorator + * @return this builder + */ + public Builder userCustomHeaderDecorator(UserCustomHeaderDecorator userCustomHeaderDecorator) { + _userCustomHeaderDecorator = userCustomHeaderDecorator; + return this; + } + /** * Thread Factory * @@ -1091,7 +1108,8 @@ public SplitClientConfig build() { _lastSeenCacheSize, _threadFactory, _flagSetsFilter, - _invalidSetsCount); + _invalidSetsCount, + _userCustomHeaderDecorator); } } } \ 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 9adfc55e3..bd2a1ffec 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -58,6 +58,8 @@ import io.split.engine.segments.SegmentChangeFetcher; import io.split.engine.segments.SegmentSynchronizationTaskImp; import io.split.integrations.IntegrationsConfig; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.storages.SegmentCache; import io.split.storages.SegmentCacheConsumer; import io.split.storages.SegmentCacheProducer; @@ -154,6 +156,7 @@ public class SplitFactoryImpl implements SplitFactory { private final EventsTask _eventsTask; private final SyncManager _syncManager; private final CloseableHttpClient _httpclient; + private final SplitHttpClient _splitHttpClient; private final UserStorageWrapper _userStorageWrapper; private final ImpressionsSender _impressionsSender; private final URI _rootTarget; @@ -184,6 +187,8 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn // HttpClient _httpclient = buildHttpClient(apiToken, config, _sdkMetadata); + UserCustomHeaderDecorator _userCustomHeaderDecorator = config.userCustomHeaderDecorator(); + _splitHttpClient = SplitHttpClientImpl.create(_httpclient, new RequestDecorator(_userCustomHeaderDecorator)); // Roots _rootTarget = URI.create(config.endpoint()); @@ -196,7 +201,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn ImpressionsStorage impressionsStorage = new InMemoryImpressionsStorage(config.impressionsQueueSize()); _splitCache = splitCache; _segmentCache = segmentCache; - _telemetrySynchronizer = new TelemetryInMemorySubmitter(_httpclient, URI.create(config.telemetryURL()), telemetryStorage, + _telemetrySynchronizer = new TelemetryInMemorySubmitter(_splitHttpClient, URI.create(config.telemetryURL()), telemetryStorage, splitCache, _segmentCache, telemetryStorage, _startTime); // Segments @@ -213,7 +218,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn config.getThreadFactory()); //ImpressionSender - _impressionsSender = HttpImpressionsSender.create(_httpclient, URI.create(config.eventsEndpoint()), config.impressionsMode(), + _impressionsSender = HttpImpressionsSender.create(_splitHttpClient, URI.create(config.eventsEndpoint()), config.impressionsMode(), _telemetryStorageProducer); //UniqueKeysTracker @@ -224,7 +229,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn // EventClient EventsStorage eventsStorage = new InMemoryEventsStorage(config.eventsQueueSize(), _telemetryStorageProducer); - EventsSender eventsSender = EventsSender.create(_httpclient, _eventsRootTarget, _telemetryStorageProducer); + EventsSender eventsSender = EventsSender.create(_splitHttpClient, _eventsRootTarget, _telemetryStorageProducer); _eventsTask = EventsTask.create(config.eventSendIntervalInMillis(), eventsStorage, eventsSender, config.getThreadFactory()); _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); @@ -275,6 +280,7 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _splitSynchronizationTask = null; _eventsTask = null; _httpclient = null; + _splitHttpClient = null; _rootTarget = null; _eventsRootTarget = null; @@ -356,6 +362,7 @@ protected SplitFactoryImpl(SplitClientConfig config) { _telemetrySyncTask = null; _eventsTask = null; _httpclient = null; + _splitHttpClient = null; _impressionsSender = null; _rootTarget = null; _eventsRootTarget = null; @@ -560,7 +567,7 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, private SegmentSynchronizationTaskImp buildSegments(SplitClientConfig config, SegmentCacheProducer segmentCacheProducer, SplitCacheConsumer splitCacheConsumer) throws URISyntaxException { - SegmentChangeFetcher segmentChangeFetcher = HttpSegmentChangeFetcher.create(_httpclient, _rootTarget, _telemetryStorageProducer); + SegmentChangeFetcher segmentChangeFetcher = HttpSegmentChangeFetcher.create(_splitHttpClient, _rootTarget, _telemetryStorageProducer); return new SegmentSynchronizationTaskImp(segmentChangeFetcher, config.segmentsRefreshRate(), @@ -573,7 +580,7 @@ private SegmentSynchronizationTaskImp buildSegments(SplitClientConfig config, Se private SplitFetcher buildSplitFetcher(SplitCacheProducer splitCacheProducer, SplitParser splitParser, FlagSetsFilter flagSetsFilter) throws URISyntaxException { - SplitChangeFetcher splitChangeFetcher = HttpSplitChangeFetcher.create(_httpclient, _rootTarget, _telemetryStorageProducer); + SplitChangeFetcher splitChangeFetcher = HttpSplitChangeFetcher.create(_splitHttpClient, _rootTarget, _telemetryStorageProducer); return new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, _telemetryStorageProducer,flagSetsFilter); } diff --git a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java new file mode 100644 index 000000000..79f704ee5 --- /dev/null +++ b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java @@ -0,0 +1,8 @@ +package io.split.client; + +import java.util.*; + +public interface UserCustomHeaderDecorator +{ + Map getHeaderOverrides(); +} diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 8e87ce938..a417dd281 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -10,6 +10,7 @@ import org.mockito.Mockito; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -235,4 +236,21 @@ public void IntegrationConfigAsyncNotNull() { Assert.assertEquals(0, config.integrationsConfig().getImpressionsListeners(IntegrationsConfig.Execution.SYNC).size()); Assert.assertEquals(1, config.integrationsConfig().getImpressionsListeners(IntegrationsConfig.Execution.ASYNC).size()); } + + @Test + public void checkUserCustomdHeaderDecorator() { + UserCustomHeaderDecorator ucd = new UserCustomHeaderDecorator() { + @Override + public Map getHeaderOverrides() { + return null; + } + }; + SplitClientConfig config = SplitClientConfig.builder().userCustomHeaderDecorator(ucd).build(); + Assert.assertNotNull(config.userCustomHeaderDecorator()); + Assert.assertEquals(ucd, config.userCustomHeaderDecorator()); + + SplitClientConfig config2 = SplitClientConfig.builder().build(); + Assert.assertNull(config2.userCustomHeaderDecorator()); + + } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java similarity index 100% rename from client/src/test/java/io/split/client/HttpSplitClientTest.java rename to client/src/test/java/io/split/service/HttpSplitClientTest.java From 19013dc75718b3a73d56e8d35e443a08f27829e3 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 18 Mar 2024 14:17:45 -0700 Subject: [PATCH 22/88] fixed tests --- .../io/split/client/events/EventsSender.java | 14 ++++++------- .../java/io/split/service/HttpPostImp.java | 15 +++++++------- .../HttpTelemetryMemorySender.java | 5 +++-- .../TelemetryInMemorySubmitter.java | 3 ++- .../split/client/events/EventsSenderTest.java | 15 ++++++++++---- .../io/split/service/HttpPostImpTest.java | 12 +++++++---- .../io/split/service/HttpSplitClientTest.java | 3 ++- .../TelemetryInMemorySubmitterTest.java | 20 +++++++++++++------ 8 files changed, 54 insertions(+), 33 deletions(-) diff --git a/client/src/main/java/io/split/client/events/EventsSender.java b/client/src/main/java/io/split/client/events/EventsSender.java index 64ab3e90c..2c023ef3f 100644 --- a/client/src/main/java/io/split/client/events/EventsSender.java +++ b/client/src/main/java/io/split/client/events/EventsSender.java @@ -4,9 +4,9 @@ import io.split.client.dtos.Event; import io.split.client.utils.Utils; import io.split.service.HttpPostImp; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import java.net.URI; import java.net.URISyntaxException; @@ -18,20 +18,20 @@ public class EventsSender { private static final String BULK_ENDPOINT_PATH = "api/events/bulk"; private final URI _bulkEndpoint; - private final CloseableHttpClient _client; + private final SplitHttpClient _client; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; private final HttpPostImp _httpPostImp; - public static EventsSender create(CloseableHttpClient httpclient, URI eventsTarget, TelemetryRuntimeProducer telemetryRuntimeProducer) + public static EventsSender create(SplitHttpClient splitHttpclient, URI eventsTarget, TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { - return new EventsSender(httpclient, Utils.appendPath(eventsTarget, BULK_ENDPOINT_PATH), telemetryRuntimeProducer); + return new EventsSender(splitHttpclient, Utils.appendPath(eventsTarget, BULK_ENDPOINT_PATH), telemetryRuntimeProducer); } - EventsSender(CloseableHttpClient httpclient, URI eventsTarget, TelemetryRuntimeProducer telemetryRuntimeProducer) { - _client = checkNotNull(httpclient); + EventsSender(SplitHttpClient splitHttpclient, URI eventsTarget, TelemetryRuntimeProducer telemetryRuntimeProducer) { + _client = splitHttpclient; _bulkEndpoint = checkNotNull(eventsTarget); _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); - _httpPostImp = new HttpPostImp(httpclient, telemetryRuntimeProducer); + _httpPostImp = new HttpPostImp(_client, telemetryRuntimeProducer); } public void sendEvents(List _data) { diff --git a/client/src/main/java/io/split/service/HttpPostImp.java b/client/src/main/java/io/split/service/HttpPostImp.java index a98744c7c..73d23bd81 100644 --- a/client/src/main/java/io/split/service/HttpPostImp.java +++ b/client/src/main/java/io/split/service/HttpPostImp.java @@ -1,10 +1,9 @@ package io.split.service; +import io.split.client.dtos.SplitHttpResponse; import io.split.client.utils.Utils; import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpStatus; import org.slf4j.Logger; @@ -17,10 +16,10 @@ public class HttpPostImp { private static final Logger _logger = LoggerFactory.getLogger(HttpPostImp.class); - private CloseableHttpClient _client; + private SplitHttpClient _client; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public HttpPostImp(CloseableHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer) { + public HttpPostImp(SplitHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer) { _client = client; _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); } @@ -28,6 +27,7 @@ public HttpPostImp(CloseableHttpClient client, TelemetryRuntimeProducer telemetr public void post(URI uri, Object object, String posted, HttpParamsWrapper httpParamsWrapper) { long initTime = System.currentTimeMillis(); HttpEntity entity = Utils.toJsonEntity(object); + HttpPost request = new HttpPost(uri); request.setEntity(entity); @@ -35,12 +35,11 @@ public void post(URI uri, Object object, String posted, HttpParamsWrapper httpPa _logger.debug(String.format("[%s] %s", request.getMethod(), uri)); } - try (CloseableHttpResponse response = _client.execute(request)) { - - int status = response.getCode(); + try { + SplitHttpResponse response = _client.post(uri, entity, null); + int status = response.statusCode; if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(httpParamsWrapper.getResourceEnum(), status); - _logger.warn(String.format("Response status was: %s. Reason: %s", status , response.getReasonPhrase())); return; } _telemetryRuntimeProducer.recordSyncLatency(httpParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); diff --git a/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java b/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java index 1cfd39fb3..9fc25bd63 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java @@ -4,6 +4,7 @@ import io.split.client.dtos.UniqueKeys; import io.split.client.utils.Utils; import io.split.service.HttpPostImp; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.Config; import io.split.telemetry.domain.Stats; import io.split.telemetry.domain.enums.HttpParamsWrapper; @@ -31,7 +32,7 @@ public class HttpTelemetryMemorySender{ private final URI _uniqueKeysTarget; private final HttpPostImp _httpPost; - public static HttpTelemetryMemorySender create(CloseableHttpClient client, URI telemetryRootEndpoint, + public static HttpTelemetryMemorySender create(SplitHttpClient client, URI telemetryRootEndpoint, TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { return new HttpTelemetryMemorySender(client, Utils.appendPath(telemetryRootEndpoint,CONFIG_ENDPOINT_PATH), @@ -42,7 +43,7 @@ public static HttpTelemetryMemorySender create(CloseableHttpClient client, URI t } @VisibleForTesting - HttpTelemetryMemorySender(CloseableHttpClient client, URI impressionConfigTarget, URI impressionStatsTarget, + HttpTelemetryMemorySender(SplitHttpClient client, URI impressionConfigTarget, URI impressionStatsTarget, URI uniqueKeysTarget,TelemetryRuntimeProducer telemetryRuntimeProducer) { _httpPost = new HttpPostImp(client, telemetryRuntimeProducer); _impressionConfigTarget = impressionConfigTarget; diff --git a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java index 4f52bcdf1..004955485 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java @@ -7,6 +7,7 @@ import io.split.client.impressions.ImpressionsManager; import io.split.integrations.IntegrationsConfig; import io.split.integrations.NewRelicListener; +import io.split.service.SplitHttpClient; import io.split.storages.SegmentCacheConsumer; import io.split.storages.SplitCacheConsumer; import io.split.telemetry.domain.Config; @@ -38,7 +39,7 @@ public class TelemetryInMemorySubmitter implements TelemetrySynchronizer{ private SegmentCacheConsumer _segmentCacheConsumer; private final long _initStartTime; - public TelemetryInMemorySubmitter(CloseableHttpClient client, URI telemetryRootEndpoint, TelemetryStorageConsumer telemetryStorageConsumer, + public TelemetryInMemorySubmitter(SplitHttpClient client, URI telemetryRootEndpoint, TelemetryStorageConsumer telemetryStorageConsumer, SplitCacheConsumer splitCacheConsumer, SegmentCacheConsumer segmentCacheConsumer, TelemetryRuntimeProducer telemetryRuntimeProducer, long initStartTime) throws URISyntaxException { _httpHttpTelemetryMemorySender = HttpTelemetryMemorySender.create(client, telemetryRootEndpoint, telemetryRuntimeProducer); diff --git a/client/src/test/java/io/split/client/events/EventsSenderTest.java b/client/src/test/java/io/split/client/events/EventsSenderTest.java index 73ed904db..1a2873fb0 100644 --- a/client/src/test/java/io/split/client/events/EventsSenderTest.java +++ b/client/src/test/java/io/split/client/events/EventsSenderTest.java @@ -1,5 +1,8 @@ package io.split.client.events; +import io.split.client.RequestDecorator; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.TelemetryRuntimeProducer; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.junit.Assert; @@ -16,29 +19,33 @@ public class EventsSenderTest { @Test public void testDefaultURL() throws URISyntaxException { + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); URI rootTarget = URI.create("https://api.split.io"); - EventsSender fetcher = EventsSender.create(CLOSEABLE_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); + EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://api.split.io/api/events/bulk", fetcher.getBulkEndpoint().toString()); } @Test public void testCustomURLNoPathNoBackslash() throws URISyntaxException { + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); URI rootTarget = URI.create("https://kubernetesturl.com"); - EventsSender fetcher = EventsSender.create(CLOSEABLE_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); + EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/api/events/bulk", fetcher.getBulkEndpoint().toString()); } @Test public void testCustomURLAppendingPath() throws URISyntaxException { + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); URI rootTarget = URI.create("https://kubernetesturl.com/split/"); - EventsSender fetcher = EventsSender.create(CLOSEABLE_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); + EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/split/api/events/bulk", fetcher.getBulkEndpoint().toString()); } @Test public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); URI rootTarget = URI.create("https://kubernetesturl.com/split"); - EventsSender fetcher = EventsSender.create(CLOSEABLE_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); + EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/split/api/events/bulk", fetcher.getBulkEndpoint().toString()); } } \ No newline at end of file diff --git a/client/src/test/java/io/split/service/HttpPostImpTest.java b/client/src/test/java/io/split/service/HttpPostImpTest.java index b6b422d89..64baa28d2 100644 --- a/client/src/test/java/io/split/service/HttpPostImpTest.java +++ b/client/src/test/java/io/split/service/HttpPostImpTest.java @@ -1,6 +1,7 @@ package io.split.service; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryStorage; @@ -13,16 +14,18 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URI; +import java.net.URISyntaxException; public class HttpPostImpTest{ private static final String URL = "www.split.io"; @Test - public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException { CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null)); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); - HttpPostImp httpPostImp = new HttpPostImp(client, telemetryStorage); + HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); Assert.assertNotEquals(0, telemetryStorage.getLastSynchronization().get_telemetry()); @@ -30,10 +33,11 @@ public void testPostWith200() throws InvocationTargetException, NoSuchMethodExce } @Test - public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException { CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_CLIENT_ERROR); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null)); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); - HttpPostImp httpPostImp = new HttpPostImp(client, telemetryStorage); + HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index b8effa2ae..36305c621 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -1,8 +1,9 @@ -package io.split.client; +package io.split.service; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.client.dtos.*; import io.split.client.impressions.Impression; import io.split.client.utils.Json; diff --git a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java index 10aa46298..f005173e3 100644 --- a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java +++ b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java @@ -1,7 +1,10 @@ package io.split.telemetry.synchronizer; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.client.dtos.UniqueKeys; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.storages.SegmentCacheConsumer; import io.split.storages.SplitCacheConsumer; import io.split.client.ApiKeyCounter; @@ -46,7 +49,8 @@ public class TelemetryInMemorySubmitterTest { @Test public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().build(); telemetrySynchronizer.synchronizeConfig(splitClientConfig, 100l, new HashMap(), new ArrayList()); @@ -57,7 +61,8 @@ public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodExcep @Test public void testSynchronizeStats() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); telemetrySynchronizer.synchronizeStats(); Mockito.verify(httpClient, Mockito.times(1)).execute(Mockito.any()); @@ -66,7 +71,8 @@ public void testSynchronizeStats() throws Exception { @Test public void testSynchronizeUniqueKeys() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); List keys = new ArrayList<>(); keys.add("key-1"); @@ -89,7 +95,8 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException ApiKeyCounter.getApiKeyCounterInstance().add(SECOND_KEY); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().flagSetsFilter(Arrays.asList("a", "_b", "a", "a", "c", "d", "_d")).build(); populateConfig(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); @@ -110,7 +117,8 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException public void testStats() throws Exception { TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(httpClient); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); populateStats(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); telemetryStorageConsumer.setAccessible(true); @@ -175,7 +183,7 @@ public void testStats() throws Exception { Assert.assertEquals(1, stats.getUpdatesFromSSE().getSplits()); } - private TelemetryInMemorySubmitter getTelemetrySynchronizer(CloseableHttpClient httpClient) throws URISyntaxException { + private TelemetryInMemorySubmitter getTelemetrySynchronizer(SplitHttpClient httpClient) throws URISyntaxException { TelemetryStorageConsumer consumer = Mockito.mock(InMemoryTelemetryStorage.class); TelemetryRuntimeProducer telemetryRuntimeProducer = Mockito.mock(TelemetryRuntimeProducer.class); SplitCacheConsumer splitCacheConsumer = Mockito.mock(SplitCacheConsumer.class); From 50ba346bb182000fb08e7f838131c7abb0597f60 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 18 Mar 2024 14:37:48 -0700 Subject: [PATCH 23/88] polish --- .../io/split/client/UserCustomHeaderDecorator.java | 4 ++++ .../main/java/io/split/service/SplitHttpClient.java | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java index 79f704ee5..ee0cc2922 100644 --- a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java +++ b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java @@ -4,5 +4,9 @@ public interface UserCustomHeaderDecorator { + /** + * Get the additional headers needed for all http operations + * @return HashMap of addition headers + */ Map getHeaderOverrides(); } diff --git a/client/src/main/java/io/split/service/SplitHttpClient.java b/client/src/main/java/io/split/service/SplitHttpClient.java index 637510e78..6dc483317 100644 --- a/client/src/main/java/io/split/service/SplitHttpClient.java +++ b/client/src/main/java/io/split/service/SplitHttpClient.java @@ -10,7 +10,20 @@ import java.util.Map; public interface SplitHttpClient { + /** + * Wrapper for HTTP get method + * @param uri the URL to be used + * @param options The FetchOptions object that contains headers. + * @return The response structure SplitHttpResponse + */ public SplitHttpResponse get(URI uri, FetchOptions options); + /** + * Wrapper for HTTP post method + * @param uri the URL to be used + * @param entity HttpEntity object that has The body load + * @param additionalHeaders Any additional headers to be added. + * @return The response structure SplitHttpResponse + */ public SplitHttpResponse post (URI uri, HttpEntity entity, From 6baef402e7c63e0fde30d08917963cebd5228c94 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 19 Mar 2024 10:34:47 -0700 Subject: [PATCH 24/88] updated sse classes --- .../io/split/client/SplitFactoryImpl.java | 2 +- .../java/io/split/engine/common/SplitAPI.java | 15 ++++---- .../io/split/engine/sse/AuthApiClientImp.java | 25 +++++-------- .../split/engine/sse/AuthApiClientTest.java | 35 ++++++++++++------- 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index bd2a1ffec..d33749b0f 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -255,7 +255,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn // SyncManager SplitTasks splitTasks = SplitTasks.build(_splitSynchronizationTask, _segmentSynchronizationTaskImp, _impressionsManager, _eventsTask, _telemetrySyncTask, _uniqueKeysTracker); - SplitAPI splitAPI = SplitAPI.build(_httpclient, buildSSEdHttpClient(apiToken, config, _sdkMetadata)); + SplitAPI splitAPI = SplitAPI.build(_splitHttpClient, buildSSEdHttpClient(apiToken, config, _sdkMetadata)); _syncManager = SyncManagerImp.build(splitTasks, _splitFetcher, splitCache, splitAPI, segmentCache, _gates, _telemetryStorageProducer, _telemetrySynchronizer, config, splitParser, flagSetsFilter); diff --git a/client/src/main/java/io/split/engine/common/SplitAPI.java b/client/src/main/java/io/split/engine/common/SplitAPI.java index 00b0c0e58..22714cac7 100644 --- a/client/src/main/java/io/split/engine/common/SplitAPI.java +++ b/client/src/main/java/io/split/engine/common/SplitAPI.java @@ -1,25 +1,27 @@ package io.split.engine.common; +import io.split.client.dtos.Split; +import io.split.service.SplitHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SplitAPI { - private final CloseableHttpClient _httpClient; + private final SplitHttpClient _httpClient; private final CloseableHttpClient _sseHttpClient; private static final Logger _log = LoggerFactory.getLogger(SplitAPI.class); - private SplitAPI(CloseableHttpClient httpClient, CloseableHttpClient sseHttpClient) { + private SplitAPI(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient) { _httpClient = httpClient; _sseHttpClient = sseHttpClient; } - public static SplitAPI build(CloseableHttpClient httpClient, CloseableHttpClient sseHttpClient){ + public static SplitAPI build(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient){ return new SplitAPI(httpClient,sseHttpClient); } - public CloseableHttpClient getHttpClient() { + public SplitHttpClient getHttpClient() { return _httpClient; } @@ -28,11 +30,6 @@ public CloseableHttpClient getSseHttpClient() { } public void close(){ - try { - _httpClient.close(); - } catch (Exception e){ - _log.error("Error trying to close httpcClient", e); - } try { _sseHttpClient.close(); } catch (Exception e){ diff --git a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java index 9f750ada3..706d4c828 100644 --- a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java +++ b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java @@ -1,34 +1,32 @@ package io.split.engine.sse; import com.google.gson.JsonObject; +import io.split.client.dtos.SplitHttpResponse; import io.split.client.utils.Json; +import io.split.engine.common.FetchOptions; import io.split.engine.sse.dtos.AuthenticationResponse; import io.split.engine.sse.dtos.RawAuthResponse; +import io.split.service.SplitHttpClient; import io.split.telemetry.domain.enums.HTTPLatenciesEnum; import io.split.telemetry.domain.enums.LastSynchronizationRecordsEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.net.URIBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; -import java.nio.charset.StandardCharsets; import static com.google.common.base.Preconditions.checkNotNull; public class AuthApiClientImp implements AuthApiClient { private static final Logger _log = LoggerFactory.getLogger(AuthApiClientImp.class); - private final CloseableHttpClient _httpClient; + private final SplitHttpClient _httpClient; private final String _target; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public AuthApiClientImp(String url, CloseableHttpClient httpClient, TelemetryRuntimeProducer telemetryRuntimeProducer) { + public AuthApiClientImp(String url, SplitHttpClient httpClient, TelemetryRuntimeProducer telemetryRuntimeProducer) { _httpClient = checkNotNull(httpClient); _target = checkNotNull(url); _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); @@ -39,23 +37,16 @@ public AuthenticationResponse Authenticate() { try { long initTime = System.currentTimeMillis(); URI uri = new URIBuilder(_target).build(); - HttpGet request = new HttpGet(uri); - - CloseableHttpResponse response = _httpClient.execute(request); - Integer statusCode = response.getCode(); - - if (_log.isDebugEnabled()) { - _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); - } + SplitHttpResponse response = _httpClient.get(uri, new FetchOptions.Builder().cacheControlHeaders(false).build()); + Integer statusCode = response.statusCode; if (statusCode == HttpStatus.SC_OK) { _log.debug(String.format("Success connection to: %s", _target)); - String jsonContent = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); _telemetryRuntimeProducer.recordTokenRefreshes(); _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.TOKEN, System.currentTimeMillis()); _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.TOKEN, System.currentTimeMillis()-initTime); - return getSuccessResponse(jsonContent); + return getSuccessResponse(response.body); } _log.error(String.format("Problem to connect to : %s. Response status: %s", _target, statusCode)); diff --git a/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java b/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java index dab743602..5ecfd1a92 100644 --- a/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java +++ b/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java @@ -1,7 +1,10 @@ package io.split.engine.sse; import io.split.TestHelper; +import io.split.client.RequestDecorator; import io.split.engine.sse.dtos.AuthenticationResponse; +import io.split.service.SplitHttpClient; +import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryStorage; import org.apache.commons.lang3.StringUtils; @@ -14,6 +17,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.net.URISyntaxException; public class AuthApiClientTest { private static TelemetryStorage TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); @@ -23,10 +27,10 @@ public void setUp() { TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); } @Test - public void authenticateWithPushEnabledShouldReturnSuccess() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void authenticateWithPushEnabledShouldReturnSuccess() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-enabled.json", HttpStatus.SC_OK); - - AuthApiClient authApiClient = new AuthApiClientImp( "www.split-test.io", httpClientMock, TELEMETRY_STORAGE); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + AuthApiClient authApiClient = new AuthApiClientImp( "www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertTrue(result.isPushEnabled()); @@ -41,10 +45,11 @@ public void authenticateWithPushEnabledShouldReturnSuccess() throws IOException, } @Test - public void authenticateWithPushEnabledWithWrongTokenShouldReturnError() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void authenticateWithPushEnabledWithWrongTokenShouldReturnError() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-enabled-wrong-token.json", HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - AuthApiClient authApiClient = new AuthApiClientImp( "www.split-test.io", httpClientMock, TELEMETRY_STORAGE); + AuthApiClient authApiClient = new AuthApiClientImp( "www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertFalse(result.isPushEnabled()); @@ -55,10 +60,11 @@ public void authenticateWithPushEnabledWithWrongTokenShouldReturnError() throws } @Test - public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-disabled.json", HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", httpClientMock, TELEMETRY_STORAGE); + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertFalse(result.isPushEnabled()); @@ -68,10 +74,11 @@ public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException } @Test - public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("", HttpStatus.SC_INTERNAL_SERVER_ERROR); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", httpClientMock, TELEMETRY_STORAGE); + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertFalse(result.isPushEnabled()); @@ -81,10 +88,11 @@ public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOExcepti } @Test - public void authenticateServerBadRequestShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void authenticateServerBadRequestShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("", HttpStatus.SC_BAD_REQUEST); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", httpClientMock, TELEMETRY_STORAGE); + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertFalse(result.isPushEnabled()); @@ -94,10 +102,11 @@ public void authenticateServerBadRequestShouldReturnErrorWithoutRetry() throws I } @Test - public void authenticateServerUnauthorizedShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void authenticateServerUnauthorizedShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("", HttpStatus.SC_UNAUTHORIZED); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", httpClientMock, TELEMETRY_STORAGE); + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertFalse(result.isPushEnabled()); From c04dbfc2e30ca34d285fee7d13c2fe034440d126 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 20 Mar 2024 10:39:48 -0700 Subject: [PATCH 25/88] Updated version and changes --- CHANGES.txt | 3 +++ client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ec4d34a39..87460f2b6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +4.12.0 (XXX XX, 2024) +- Added support for injecting user-defined custom headers for all outgoing HTTP calls, typically useful for proxy authentication purposes. + 4.11.1 (Feb 29, 2024) - Fixed deadlock in UniqueKeysTracker when sending Unique Keys. diff --git a/client/pom.xml b/client/pom.xml index 131fe248c..a0becea3c 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.11.1 + 4.12.0-rc1 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index b797e50fe..30b90d945 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.11.1 + 4.12.0-rc1 2.1.0 diff --git a/pom.xml b/pom.xml index 4c5c2871b..3b7e17ed1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.11.1 + 4.12.0-rc1 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 2f9da5c8c..962d8c51f 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.11.1 + 4.12.0-rc1 redis-wrapper 3.1.0 diff --git a/testing/pom.xml b/testing/pom.xml index d3f815e27..d0f537dc6 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.11.1 + 4.12.0-rc1 java-client-testing jar From 58dcfad50d0e51695f286644800f802713a39489 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 20 Mar 2024 11:43:14 -0700 Subject: [PATCH 26/88] polishing --- .../main/java/io/split/client/HttpSplitChangeFetcher.java | 4 ---- .../src/main/java/io/split/client/RequestDecorator.java | 8 ++++++-- .../java/io/split/client/UserCustomHeaderDecorator.java | 2 +- .../split/client/impressions/HttpImpressionsSender.java | 2 +- client/src/main/java/io/split/engine/common/SplitAPI.java | 1 - .../main/java/io/split/service/SplitHttpClientImpl.java | 1 - .../telemetry/synchronizer/HttpTelemetryMemorySender.java | 1 - .../synchronizer/TelemetryInMemorySubmitter.java | 1 - 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index 609070b7d..aec630122 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -31,10 +31,6 @@ public final class HttpSplitChangeFetcher implements SplitChangeFetcher { private static final String SINCE = "since"; private static final String TILL = "till"; private static final String SETS = "sets"; - - private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; - private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; - private final SplitHttpClient _client; private final URI _target; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 97257cd43..11082e548 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -1,13 +1,17 @@ package io.split.client; import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; -import java.util.*; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Arrays; +import java.util.Set; class NoOpHeaderDecorator implements UserCustomHeaderDecorator { public NoOpHeaderDecorator() {} @Override public Map getHeaderOverrides() { - return new HashMap(); + return new HashMap<>(); } } diff --git a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java index ee0cc2922..761416551 100644 --- a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java +++ b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java @@ -1,6 +1,6 @@ package io.split.client; -import java.util.*; +import java.util.Map; public interface UserCustomHeaderDecorator { diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index ba8382653..5380c1dca 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -63,7 +63,7 @@ private HttpImpressionsSender(SplitHttpClient client, URI impressionBulkTarget, @Override public void postImpressionsBulk(List impressions) { - SplitHttpResponse response = null; + SplitHttpResponse response; long initTime = System.currentTimeMillis(); try { HttpEntity entity = Utils.toJsonEntity(impressions); diff --git a/client/src/main/java/io/split/engine/common/SplitAPI.java b/client/src/main/java/io/split/engine/common/SplitAPI.java index 22714cac7..b3b42966f 100644 --- a/client/src/main/java/io/split/engine/common/SplitAPI.java +++ b/client/src/main/java/io/split/engine/common/SplitAPI.java @@ -1,6 +1,5 @@ package io.split.engine.common; -import io.split.client.dtos.Split; import io.split.service.SplitHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.slf4j.Logger; diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 5497a69f2..7e33c37c2 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -79,7 +79,6 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { HttpEntity entity, Map additionalHeaders) throws IOException { CloseableHttpResponse response = null; - long initTime = System.currentTimeMillis(); try { HttpPost request = new HttpPost(uri); if (additionalHeaders != null) { diff --git a/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java b/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java index 9fc25bd63..4388eecaa 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/HttpTelemetryMemorySender.java @@ -9,7 +9,6 @@ import io.split.telemetry.domain.Stats; import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.telemetry.storage.TelemetryRuntimeProducer; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java index 004955485..fcde455ea 100644 --- a/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java +++ b/client/src/main/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitter.java @@ -18,7 +18,6 @@ import io.split.telemetry.domain.enums.ImpressionsDataTypeEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; import io.split.telemetry.storage.TelemetryStorageConsumer; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import java.net.URI; import java.net.URISyntaxException; From 72679b9d0f3f886e8435fd1e097ed5b6afbb61ce Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 20 Mar 2024 11:57:45 -0700 Subject: [PATCH 27/88] polish --- client/src/main/java/io/split/service/SplitHttpClientImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 7e33c37c2..2461e0bc9 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -93,7 +93,7 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { int status = response.getCode(); - String statusMessage = new String(""); + String statusMessage = ""; if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { statusMessage = response.getReasonPhrase(); _log.warn(String.format("Response status was: %s. Reason: %s", status, response.getReasonPhrase())); From 02b802f6e5cdd4fe26ef06a94e832e65365cc63e Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 20 Mar 2024 12:01:03 -0700 Subject: [PATCH 28/88] polish --- .../src/main/java/io/split/client/SplitClientConfig.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 50dc73d2f..025a40d94 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -10,9 +10,12 @@ import pluggable.CustomStorageWrapper; import java.io.IOException; -import java.util.*; -import java.io.InputStream; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Properties; import java.util.concurrent.ThreadFactory; +import java.io.InputStream; import static io.split.inputValidation.FlagSetsValidator.cleanup; From 62885521ba8662166b657ca9cef178f293c42080 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 25 Mar 2024 10:11:10 -0700 Subject: [PATCH 29/88] Converted reserved headers to lower to have case insesitive check, and polishing. --- .../client/HttpSegmentChangeFetcher.java | 13 ++++------ .../split/client/HttpSplitChangeFetcher.java | 12 ++++----- .../io/split/client/RequestDecorator.java | 26 +++++++++---------- .../io/split/client/SplitFactoryImpl.java | 11 +++----- .../impressions/HttpImpressionsSender.java | 11 +++----- .../java/io/split/service/HttpPostImp.java | 11 +++----- .../io/split/service/SplitHttpClientImpl.java | 10 +++---- .../io/split/client/RequestDecoratorTest.java | 12 +++++++++ 8 files changed, 49 insertions(+), 57 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java index e55952304..f55d250b3 100644 --- a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java @@ -51,7 +51,7 @@ private HttpSegmentChangeFetcher(SplitHttpClient client, URI uri, TelemetryRunti public SegmentChange fetch(String segmentName, long since, FetchOptions options) { long start = System.currentTimeMillis(); - SplitHttpResponse response = null; + SplitHttpResponse response; try { String path = _target.getPath() + "/" + segmentName; @@ -65,16 +65,15 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options) URI uri = uriBuilder.build(); response = _client.get(uri, options); - int statusCode = response.statusCode; - if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, statusCode); - if (statusCode == HttpStatus.SC_FORBIDDEN) { + if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, response.statusCode); + if (response.statusCode == HttpStatus.SC_FORBIDDEN) { _log.error("factory instantiation: you passed a client side type sdkKey, " + "please grab an sdk key from the Split user interface that is of type server side"); } throw new IllegalStateException(String.format("Could not retrieve segment changes for %s, since %s; http return code %s", - segmentName, since, statusCode)); + segmentName, since, response.statusCode)); } _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.SEGMENTS, System.currentTimeMillis()); @@ -85,8 +84,6 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options) } finally { _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.SEGMENTS, System.currentTimeMillis()-start); } - - } @VisibleForTesting diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index aec630122..91e23939b 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -70,15 +70,13 @@ public SplitChange fetch(long since, FetchOptions options) { URI uri = uriBuilder.build(); response = _client.get(uri, options); - int statusCode = response.statusCode; - - if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - if (statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { + if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + if (response.statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { _log.error("The amount of flag sets provided are big causing uri length error."); - throw new UriTooLongException(String.format("Status code: %s. Message: %s", statusCode, response.statusMessage)); + throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode, response.statusMessage)); } - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, statusCode); - throw new IllegalStateException(String.format("Could not retrieve splitChanges since %s; http return code %s", since, statusCode)); + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode); + throw new IllegalStateException(String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode)); } return Json.fromJson(response.body, SplitChange.class); diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 11082e548..25a4b8f88 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -19,18 +19,18 @@ public final class RequestDecorator { UserCustomHeaderDecorator _headerDecorator; private static final Set forbiddenHeaders = new HashSet<>(Arrays.asList( - "SplitSDKVersion", - "SplitMachineIp", - "SplitMachineName", - "SplitImpressionsMode", - "Host", - "Referrer", - "Content-Type", - "Content-Length", - "Content-Encoding", - "Accept", - "Keep-Alive", - "X-Fastly-Debug" + "splitsdkversion", + "splitmachineip", + "splitmachinename", + "splitimpressionsmode", + "host", + "referrer", + "content-type", + "content-length", + "content-encoding", + "accept", + "keep-alive", + "x-fastly-debug" )); public RequestDecorator(UserCustomHeaderDecorator headerDecorator) { @@ -55,6 +55,6 @@ public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { } private boolean isHeaderAllowed(String headerName) { - return !forbiddenHeaders.contains(headerName); + return !forbiddenHeaders.contains(headerName.toLowerCase()); } } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index d33749b0f..380a53e46 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -155,7 +155,6 @@ public class SplitFactoryImpl implements SplitFactory { private final SplitSynchronizationTask _splitSynchronizationTask; private final EventsTask _eventsTask; private final SyncManager _syncManager; - private final CloseableHttpClient _httpclient; private final SplitHttpClient _splitHttpClient; private final UserStorageWrapper _userStorageWrapper; private final ImpressionsSender _impressionsSender; @@ -186,9 +185,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn _gates = new SDKReadinessGates(); // HttpClient - _httpclient = buildHttpClient(apiToken, config, _sdkMetadata); - UserCustomHeaderDecorator _userCustomHeaderDecorator = config.userCustomHeaderDecorator(); - _splitHttpClient = SplitHttpClientImpl.create(_httpclient, new RequestDecorator(_userCustomHeaderDecorator)); + _splitHttpClient = buildSplitHttpClient(apiToken, config, _sdkMetadata); // Roots _rootTarget = URI.create(config.endpoint()); @@ -279,7 +276,6 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _splitFetcher = null; _splitSynchronizationTask = null; _eventsTask = null; - _httpclient = null; _splitHttpClient = null; _rootTarget = null; _eventsRootTarget = null; @@ -361,7 +357,6 @@ protected SplitFactoryImpl(SplitClientConfig config) { _telemetrySynchronizer = null; _telemetrySyncTask = null; _eventsTask = null; - _httpclient = null; _splitHttpClient = null; _impressionsSender = null; _rootTarget = null; @@ -478,7 +473,7 @@ public boolean isDestroyed() { return isTerminated; } - private static CloseableHttpClient buildHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) { + private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) throws URISyntaxException { SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() .setSslContext(SSLContexts.createSystemDefault()) .setTlsVersions(TLS.V_1_1, TLS.V_1_2) @@ -512,7 +507,7 @@ private static CloseableHttpClient buildHttpClient(String apiToken, SplitClientC httpClientbuilder = setupProxy(httpClientbuilder, config); } - return httpClientbuilder.build(); + return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.userCustomHeaderDecorator())); } private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) { diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index 5380c1dca..d48f9f12a 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -71,10 +71,8 @@ public void postImpressionsBulk(List impressions) { additionalHeader.put(IMPRESSIONS_MODE_HEADER, _mode.toString()); response = _client.post(_impressionBulkTarget, entity, additionalHeader); - int status = response.statusCode; - - if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, status); + if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode); } _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS, System.currentTimeMillis()); @@ -98,9 +96,8 @@ public void postCounters(HashMap raw) { Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw)), null); - int status = response.statusCode; - if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, status); + if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, response.statusCode); } _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS_COUNT, System.currentTimeMillis() - initTime); _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT, System.currentTimeMillis()); diff --git a/client/src/main/java/io/split/service/HttpPostImp.java b/client/src/main/java/io/split/service/HttpPostImp.java index 73d23bd81..585abaf85 100644 --- a/client/src/main/java/io/split/service/HttpPostImp.java +++ b/client/src/main/java/io/split/service/HttpPostImp.java @@ -8,7 +8,6 @@ import org.apache.hc.core5.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.hc.client5.http.classic.methods.HttpPost; import java.net.URI; @@ -28,18 +27,14 @@ public void post(URI uri, Object object, String posted, HttpParamsWrapper httpPa long initTime = System.currentTimeMillis(); HttpEntity entity = Utils.toJsonEntity(object); - HttpPost request = new HttpPost(uri); - request.setEntity(entity); - if (_logger.isDebugEnabled()) { - _logger.debug(String.format("[%s] %s", request.getMethod(), uri)); + _logger.debug(String.format("[Post] %s", uri)); } try { SplitHttpResponse response = _client.post(uri, entity, null); - int status = response.statusCode; - if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(httpParamsWrapper.getResourceEnum(), status); + if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(httpParamsWrapper.getResourceEnum(), response.statusCode); return; } _telemetryRuntimeProducer.recordSyncLatency(httpParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 2461e0bc9..598adbf67 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -52,19 +52,17 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { response = _client.execute(request); - int statusCode = response.getCode(); - if (_log.isDebugEnabled()) { - _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), statusCode)); + _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), response.getCode())); } SplitHttpResponse httpResponse = new SplitHttpResponse(); httpResponse.statusMessage = ""; - if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _log.warn(String.format("Response status was: %s. Reason: %s", statusCode , response.getReasonPhrase())); + if (response.getCode() < HttpStatus.SC_OK || response.getCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { + _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode() , response.getReasonPhrase())); httpResponse.statusMessage = response.getReasonPhrase(); } - httpResponse.statusCode = statusCode; + httpResponse.statusCode = response.getCode(); httpResponse.body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); return httpResponse; } catch (Exception e) { diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index b7c5e500f..3dc17b918 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -61,6 +61,18 @@ public Map getHeaderOverrides() { {{ put("first", "1"); put("SplitSDKVersion", "2.4"); + put("SplitMachineip", "xx"); + put("splitMachineName", "xx"); + put("splitimpressionsmode", "xx"); + put("HOST", "xx"); + put("referrer", "xx"); + put("content-type", "xx"); + put("content-length", "xx"); + put("content-encoding", "xx"); + put("ACCEPT", "xx"); + put("keep-alive", "xx"); + put("x-fastly-debug", "xx"); + }}; } } From 35f3e4d44df748051a193c8be5f119def4f9be84 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 25 Mar 2024 10:43:07 -0700 Subject: [PATCH 30/88] fix checkstyle test --- .../src/main/java/io/split/client/HttpSplitChangeFetcher.java | 4 +++- client/src/main/java/io/split/client/SplitFactoryImpl.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index 91e23939b..347486109 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -76,7 +76,9 @@ public SplitChange fetch(long since, FetchOptions options) { throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode, response.statusMessage)); } _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode); - throw new IllegalStateException(String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode)); + throw new IllegalStateException( + String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode) + ); } return Json.fromJson(response.body, SplitChange.class); diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 380a53e46..2de955e93 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -473,7 +473,8 @@ public boolean isDestroyed() { return isTerminated; } - private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) throws URISyntaxException { + private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) + throws URISyntaxException { SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() .setSslContext(SSLContexts.createSystemDefault()) .setTlsVersions(TLS.V_1_1, TLS.V_1_2) From 0060f98785e1f9a97af64d7135e12b81b158a6c2 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 25 Mar 2024 10:56:31 -0700 Subject: [PATCH 31/88] fixing sonar covering fail --- client/src/main/java/io/split/service/HttpPostImp.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/src/main/java/io/split/service/HttpPostImp.java b/client/src/main/java/io/split/service/HttpPostImp.java index 585abaf85..cb5b5190d 100644 --- a/client/src/main/java/io/split/service/HttpPostImp.java +++ b/client/src/main/java/io/split/service/HttpPostImp.java @@ -27,10 +27,6 @@ public void post(URI uri, Object object, String posted, HttpParamsWrapper httpPa long initTime = System.currentTimeMillis(); HttpEntity entity = Utils.toJsonEntity(object); - if (_logger.isDebugEnabled()) { - _logger.debug(String.format("[Post] %s", uri)); - } - try { SplitHttpResponse response = _client.post(uri, entity, null); if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { From 4c3337224589694f31ad3d836297f7ce17870abf Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 25 Mar 2024 15:27:38 -0700 Subject: [PATCH 32/88] Fixing sonar coverage --- .../client/HttpSegmentChangeFetcherTest.java | 22 +++++++++++++ .../client/HttpSplitChangeFetcherTest.java | 33 ++++++++++++++++--- .../split/client/events/EventsSenderTest.java | 16 +++++++++ .../HttpImpressionsSenderTest.java | 17 ++++++++-- 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java index e40c61dd9..07aae12ea 100644 --- a/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java @@ -116,4 +116,26 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept Assert.assertFalse(captured.get(1).getUri().toString().contains("till=")); } + @Test(expected = IllegalStateException.class) + public void testFetcherWithError() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + URI rootTarget = URI.create("https://api.split.io"); + + HttpEntity entityMock = Mockito.mock(HttpEntity.class); + when(entityMock.getContent()).thenReturn(new StringBufferInputStream("{\"till\": 1}")); + ClassicHttpResponse response = Mockito.mock(ClassicHttpResponse.class); + when(response.getCode()).thenReturn(400); + when(response.getEntity()).thenReturn(entityMock); + when(response.getHeaders()).thenReturn(new Header[0]); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + + when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); + + Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryStorage.class)); + + fetcher.fetch("someSegment", -1, new FetchOptions.Builder().build()); + } } diff --git a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java index 794a7f057..c73e22fd1 100644 --- a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java @@ -28,10 +28,9 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.sql.Array; +import java.util.*; +import java.util.stream.Collectors; import static org.mockito.Mockito.when; @@ -143,4 +142,30 @@ public void testRandomNumberGeneration() throws URISyntaxException { Assert.assertTrue(seen.size() >= (total * 0.9999)); } + + @Test(expected = IllegalStateException.class) + public void testURLTooLong() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + URI rootTarget = URI.create("https://api.split.io"); + + HttpEntity entityMock = Mockito.mock(HttpEntity.class); + when(entityMock.getContent()).thenReturn(new ByteArrayInputStream("{\"till\": 1}".getBytes(StandardCharsets.UTF_8))); + ClassicHttpResponse response = Mockito.mock(ClassicHttpResponse.class); + when(response.getCode()).thenReturn(414); + when(response.getEntity()).thenReturn(entityMock); + when(response.getHeaders()).thenReturn(new Header[0]); + CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); + when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); + + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); + List sets = new ArrayList(); + for (Integer i=0; i<100; i++) { + sets.add("set" + i.toString()); + } + String result = sets.stream() + .map(n -> String.valueOf(n)) + .collect(Collectors.joining(",", "", "")); + fetcher.fetch(-1, new FetchOptions.Builder().flagSetsFilter(result).cacheControlHeaders(false).build()); + } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/events/EventsSenderTest.java b/client/src/test/java/io/split/client/events/EventsSenderTest.java index 1a2873fb0..b53a7fd9e 100644 --- a/client/src/test/java/io/split/client/events/EventsSenderTest.java +++ b/client/src/test/java/io/split/client/events/EventsSenderTest.java @@ -1,16 +1,23 @@ package io.split.client.events; +import io.split.TestHelper; import io.split.client.RequestDecorator; +import io.split.client.dtos.Event; import io.split.service.SplitHttpClient; import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.TelemetryRuntimeProducer; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.HttpStatus; +import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; +import java.util.*; public class EventsSenderTest { @@ -48,4 +55,13 @@ public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/split/api/events/bulk", fetcher.getBulkEndpoint().toString()); } + @Test + public void testHttpError() throws URISyntaxException, IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { + URI rootTarget = URI.create("https://kubernetesturl.com/split"); + CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_BAD_REQUEST); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + EventsSender sender = EventsSender.create(splitHtpClient, rootTarget, TELEMETRY_RUNTIME_CONSUMER); + // should not raise exception + sender.sendEvents(new ArrayList<>()); + } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java index 624f49788..29412da1c 100644 --- a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java +++ b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java @@ -27,6 +27,7 @@ import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -142,7 +143,7 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)) - )), new TestImpressions("t2", Arrays.asList( + )), new TestImpressions("t2", Arrays.asList( KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null)) @@ -160,7 +161,8 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException HttpPost asPostRequest = (HttpPost) request; InputStreamReader reader = new InputStreamReader(asPostRequest.getEntity().getContent()); Gson gson = new Gson(); - List payload = gson.fromJson(reader, new TypeToken>() { }.getType()); + List payload = gson.fromJson(reader, new TypeToken>() { + }.getType()); assertThat(payload.size(), is(equalTo(2))); // Do the same flow for imrpessionsMode = debug @@ -175,4 +177,15 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException assertThat(request.getHeaders().length, is(1)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("DEBUG"))); } + + @Test + public void testHttpError() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + URI rootTarget = URI.create("https://kubernetesturl.com/split"); + CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_BAD_REQUEST); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); + // Should not raise exception + sender.postImpressionsBulk(new ArrayList<>()); + sender.postCounters(new HashMap<>()); + } } From aa283e39e66643e6187f1bab59c909c7260cef6a Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 26 Mar 2024 15:24:01 -0700 Subject: [PATCH 33/88] added headers to httpsplitresponse and polish --- .../client/HttpSegmentChangeFetcher.java | 4 +--- .../split/client/HttpSplitChangeFetcher.java | 4 +--- .../split/client/dtos/SplitHttpResponse.java | 5 ++++- .../impressions/HttpImpressionsSender.java | 4 +--- .../io/split/engine/sse/AuthApiClientImp.java | 2 +- .../io/split/service/SplitHttpClient.java | 2 +- .../io/split/service/SplitHttpClientImpl.java | 17 +++++++++++------ .../io/split/service/HttpSplitClientTest.java | 19 +++++++++++++++---- 8 files changed, 35 insertions(+), 22 deletions(-) diff --git a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java index f55d250b3..65c5e01f3 100644 --- a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java @@ -51,8 +51,6 @@ private HttpSegmentChangeFetcher(SplitHttpClient client, URI uri, TelemetryRunti public SegmentChange fetch(String segmentName, long since, FetchOptions options) { long start = System.currentTimeMillis(); - SplitHttpResponse response; - try { String path = _target.getPath() + "/" + segmentName; URIBuilder uriBuilder = new URIBuilder(_target) @@ -64,7 +62,7 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options) URI uri = uriBuilder.build(); - response = _client.get(uri, options); + SplitHttpResponse response = _client.get(uri, options, null); if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, response.statusCode); diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index 347486109..36d5be744 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -57,8 +57,6 @@ public SplitChange fetch(long since, FetchOptions options) { long start = System.currentTimeMillis(); - SplitHttpResponse response = null; - try { URIBuilder uriBuilder = new URIBuilder(_target).addParameter(SINCE, "" + since); if (options.hasCustomCN()) { @@ -68,7 +66,7 @@ public SplitChange fetch(long since, FetchOptions options) { uriBuilder.addParameter(SETS, "" + options.flagSetsFilter()); } URI uri = uriBuilder.build(); - response = _client.get(uri, options); + SplitHttpResponse response = _client.get(uri, options, null); if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { if (response.statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { diff --git a/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java b/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java index a708a4648..8dac4662d 100644 --- a/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java +++ b/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java @@ -1,10 +1,13 @@ package io.split.client.dtos; +import java.util.Map; +import org.apache.hc.core5.http.Header; /** * A structure for returning http call results information */ -public class SplitHttpResponse { +public final class SplitHttpResponse { public Integer statusCode; public String statusMessage; public String body; + public Header[] responseHeaders; } diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index d48f9f12a..ec6cb4aea 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -62,14 +62,12 @@ private HttpImpressionsSender(SplitHttpClient client, URI impressionBulkTarget, @Override public void postImpressionsBulk(List impressions) { - - SplitHttpResponse response; long initTime = System.currentTimeMillis(); try { HttpEntity entity = Utils.toJsonEntity(impressions); Map additionalHeader = new HashMap<>(); additionalHeader.put(IMPRESSIONS_MODE_HEADER, _mode.toString()); - response = _client.post(_impressionBulkTarget, entity, additionalHeader); + SplitHttpResponse response = _client.post(_impressionBulkTarget, entity, additionalHeader); if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode); diff --git a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java index 706d4c828..d4187a5eb 100644 --- a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java +++ b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java @@ -37,7 +37,7 @@ public AuthenticationResponse Authenticate() { try { long initTime = System.currentTimeMillis(); URI uri = new URIBuilder(_target).build(); - SplitHttpResponse response = _httpClient.get(uri, new FetchOptions.Builder().cacheControlHeaders(false).build()); + SplitHttpResponse response = _httpClient.get(uri, new FetchOptions.Builder().cacheControlHeaders(false).build(), null); Integer statusCode = response.statusCode; if (statusCode == HttpStatus.SC_OK) { diff --git a/client/src/main/java/io/split/service/SplitHttpClient.java b/client/src/main/java/io/split/service/SplitHttpClient.java index 6dc483317..33aa1dbae 100644 --- a/client/src/main/java/io/split/service/SplitHttpClient.java +++ b/client/src/main/java/io/split/service/SplitHttpClient.java @@ -16,7 +16,7 @@ public interface SplitHttpClient { * @param options The FetchOptions object that contains headers. * @return The response structure SplitHttpResponse */ - public SplitHttpResponse get(URI uri, FetchOptions options); + public SplitHttpResponse get(URI uri, FetchOptions options, Map additionalHeaders); /** * Wrapper for HTTP post method * @param uri the URL to be used diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 598adbf67..c9e9f689b 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -40,11 +40,16 @@ public static SplitHttpClientImpl create( _requestDecorator = requestDecorator; } - public SplitHttpResponse get(URI uri, FetchOptions options) { + public SplitHttpResponse get(URI uri, FetchOptions options, Map additionalHeaders) { CloseableHttpResponse response = null; try { HttpGet request = new HttpGet(uri); + if (additionalHeaders != null) { + for (Map.Entry entry : additionalHeaders.entrySet()) { + request.addHeader(entry.getKey().toString(), entry.getValue()); + } + } if(options.cacheControlHeadersEnabled()) { request.setHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE); } @@ -58,6 +63,7 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { SplitHttpResponse httpResponse = new SplitHttpResponse(); httpResponse.statusMessage = ""; + httpResponse.responseHeaders = response.getHeaders(); if (response.getCode() < HttpStatus.SC_OK || response.getCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode() , response.getReasonPhrase())); httpResponse.statusMessage = response.getReasonPhrase(); @@ -89,17 +95,16 @@ public SplitHttpResponse get(URI uri, FetchOptions options) { response = _client.execute(request); - int status = response.getCode(); - String statusMessage = ""; - if (status < HttpStatus.SC_OK || status >= HttpStatus.SC_MULTIPLE_CHOICES) { + if (response.getCode() < HttpStatus.SC_OK || response.getCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { statusMessage = response.getReasonPhrase(); - _log.warn(String.format("Response status was: %s. Reason: %s", status, response.getReasonPhrase())); + _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode(), response.getReasonPhrase())); } SplitHttpResponse httpResponse = new SplitHttpResponse(); - httpResponse.statusCode = status; + httpResponse.statusCode = response.getCode(); httpResponse.body = ""; httpResponse.statusMessage = statusMessage; + httpResponse.responseHeaders = response.getHeaders(); return httpResponse; } catch (Exception e) { throw new IOException(String.format("Problem in http post operation: %s", e), e); diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index 36305c621..4dfe94f91 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -14,7 +14,8 @@ import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.classic.methods.HttpUriRequest; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.core5.http.*; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.Header; import org.junit.Assert; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -41,11 +42,21 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation RequestDecorator decorator = new RequestDecorator(null); SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + Map additionalHeaders = new HashMap<>(); + additionalHeaders.put("AdditionalHeader", "add"); SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build()); + new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders); SplitChange change = Json.fromJson(splitHttpResponse.body, SplitChange.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); + verify(httpClientMock).execute(captor.capture()); + HttpUriRequest request = captor.getValue(); + assertThat(request.getFirstHeader("AdditionalHeader").getValue(), is(equalTo("add"))); + + Header[] headers = splitHttpResponse.responseHeaders; + assertThat(headers[0].getName(), is(equalTo("Via"))); + assertThat(headers[0].getValue(), is(equalTo("HTTP/1.1 m_proxy_rio1"))); Assert.assertNotNull(change); Assert.assertEquals(1, change.splits.size()); Assert.assertNotNull(change.splits.get(0)); @@ -66,7 +77,7 @@ public void testGetError() throws URISyntaxException, InvocationTargetException, SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build()); + new FetchOptions.Builder().cacheControlHeaders(true).build(), null); Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (long) splitHttpResponse.statusCode); } @@ -78,7 +89,7 @@ public void testException() throws URISyntaxException, InvocationTargetException SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); splitHtpClient.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build()); + new FetchOptions.Builder().cacheControlHeaders(true).build(), null); } @Test From 06bec689fe3bb83631871468c9eda236025b7c53 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 26 Mar 2024 15:41:52 -0700 Subject: [PATCH 34/88] used setHeader instead of addHeader for decorator --- client/src/main/java/io/split/client/RequestDecorator.java | 2 +- client/src/test/java/io/split/client/RequestDecoratorTest.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 25a4b8f88..fe7eb7897 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -44,7 +44,7 @@ public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { Map headers = _headerDecorator.getHeaderOverrides(); for (Map.Entry entry : headers.entrySet()) { if (isHeaderAllowed(entry.getKey().toString())) { - request.addHeader(entry.getKey().toString(), entry.getValue()); + request.setHeader(entry.getKey().toString(), entry.getValue()); } } } catch (Exception e) { diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index 3dc17b918..840e8f955 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -39,6 +39,7 @@ public Map getHeaderOverrides() { MyCustomHeaders myHeaders = new MyCustomHeaders(); RequestDecorator decorator = new RequestDecorator(myHeaders); HttpGet request = new HttpGet("http://anyhost"); + request.addHeader("first", "myfirstheader"); request = (HttpGet) decorator.decorateHeaders(request); Assert.assertEquals(3, request.getHeaders().length); Assert.assertEquals("1", request.getHeader("first").getValue()); From 2eb378e0aca6c5ec64a0469e7c345238a8418a21 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 27 Mar 2024 11:19:42 -0700 Subject: [PATCH 35/88] allowed multiple values per header --- .../io/split/client/RequestDecorator.java | 14 ++++- .../client/UserCustomHeaderDecorator.java | 3 +- .../io/split/client/RequestDecoratorTest.java | 62 +++++++++++-------- .../split/client/SplitClientConfigTest.java | 2 +- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index fe7eb7897..e4be9ff9d 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -6,11 +6,12 @@ import java.util.Map; import java.util.Arrays; import java.util.Set; +import java.util.List; class NoOpHeaderDecorator implements UserCustomHeaderDecorator { public NoOpHeaderDecorator() {} @Override - public Map getHeaderOverrides() { + public Map> getHeaderOverrides() { return new HashMap<>(); } } @@ -41,10 +42,17 @@ public RequestDecorator(UserCustomHeaderDecorator headerDecorator) { public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { try { - Map headers = _headerDecorator.getHeaderOverrides(); + Map> headers = _headerDecorator.getHeaderOverrides(); for (Map.Entry entry : headers.entrySet()) { if (isHeaderAllowed(entry.getKey().toString())) { - request.setHeader(entry.getKey().toString(), entry.getValue()); + List values = (List) entry.getValue(); + for (int i = 0; i < values.size(); i++) { + if (i == 0) { + request.setHeader(entry.getKey().toString(), values.get(i)); + } else { + request.addHeader(entry.getKey().toString(), values.get(i)); + } + } } } } catch (Exception e) { diff --git a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java index 761416551..236b38afd 100644 --- a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java +++ b/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java @@ -1,6 +1,7 @@ package io.split.client; import java.util.Map; +import java.util.List; public interface UserCustomHeaderDecorator { @@ -8,5 +9,5 @@ public interface UserCustomHeaderDecorator * Get the additional headers needed for all http operations * @return HashMap of addition headers */ - Map getHeaderOverrides(); + Map> getHeaderOverrides(); } diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index 840e8f955..e13e95e88 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -2,10 +2,18 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.ProtocolException; import org.junit.Assert; import org.junit.Test; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -24,15 +32,15 @@ public void testNoOp() { @Test public void testAddCustomHeaders() throws ProtocolException { - class MyCustomHeaders implements UserCustomHeaderDecorator { + class MyCustomHeaders implements UserCustomHeaderDecorator { public MyCustomHeaders() {} @Override - public Map getHeaderOverrides() { - return new HashMap() + public Map> getHeaderOverrides() { + return new HashMap>() {{ - put("first", "1"); - put("second", "2"); - put("third", "3"); + put("first", List.of("1")); + put("second", List.of("2.1", "2.2")); + put("third", List.of("3")); }}; } } @@ -41,15 +49,19 @@ public Map getHeaderOverrides() { HttpGet request = new HttpGet("http://anyhost"); request.addHeader("first", "myfirstheader"); request = (HttpGet) decorator.decorateHeaders(request); - Assert.assertEquals(3, request.getHeaders().length); + + Assert.assertEquals(4, request.getHeaders().length); Assert.assertEquals("1", request.getHeader("first").getValue()); - Assert.assertEquals("2", request.getHeader("second").getValue()); + + Header[] second = request.getHeaders("second"); + Assert.assertEquals("2.1", second[0].getValue()); + Assert.assertEquals("2.2", second[1].getValue()); Assert.assertEquals("3", request.getHeader("third").getValue()); HttpPost request2 = new HttpPost("http://anyhost"); request2.addHeader("myheader", "value"); request2 = (HttpPost) decorator.decorateHeaders(request2); - Assert.assertEquals(4, request2.getHeaders().length); + Assert.assertEquals(5, request2.getHeaders().length); } @Test @@ -57,22 +69,22 @@ public void testAddBlockedHeaders() throws ProtocolException { class MyCustomHeaders implements UserCustomHeaderDecorator { public MyCustomHeaders() {} @Override - public Map getHeaderOverrides() { - return new HashMap() + public Map> getHeaderOverrides() { + return new HashMap>() {{ - put("first", "1"); - put("SplitSDKVersion", "2.4"); - put("SplitMachineip", "xx"); - put("splitMachineName", "xx"); - put("splitimpressionsmode", "xx"); - put("HOST", "xx"); - put("referrer", "xx"); - put("content-type", "xx"); - put("content-length", "xx"); - put("content-encoding", "xx"); - put("ACCEPT", "xx"); - put("keep-alive", "xx"); - put("x-fastly-debug", "xx"); + put("first", List.of("1")); + put("SplitSDKVersion", List.of("2.4")); + put("SplitMachineip", List.of("xx")); + put("splitMachineName", List.of("xx")); + put("splitimpressionsmode", List.of("xx")); + put("HOST", List.of("xx")); + put("referrer", List.of("xx")); + put("content-type", List.of("xx")); + put("content-length", List.of("xx")); + put("content-encoding", List.of("xx")); + put("ACCEPT", List.of("xx")); + put("keep-alive", List.of("xx")); + put("x-fastly-debug", List.of("xx")); }}; } @@ -90,7 +102,7 @@ public void customDecoratorError() { class MyCustomHeaders implements UserCustomHeaderDecorator { public MyCustomHeaders() {} @Override - public Map getHeaderOverrides() { + public Map> getHeaderOverrides() { throw new RuntimeException(); } } diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index a417dd281..113079309 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -241,7 +241,7 @@ public void IntegrationConfigAsyncNotNull() { public void checkUserCustomdHeaderDecorator() { UserCustomHeaderDecorator ucd = new UserCustomHeaderDecorator() { @Override - public Map getHeaderOverrides() { + public Map> getHeaderOverrides() { return null; } }; From 83aeb2ac18be16c6b6c0ef11646f643819c15342 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 27 Mar 2024 11:37:10 -0700 Subject: [PATCH 36/88] fixed test --- .../test/java/io/split/client/RequestDecoratorTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index e13e95e88..d8643324f 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.Arrays; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -38,9 +37,9 @@ public MyCustomHeaders() {} public Map> getHeaderOverrides() { return new HashMap>() {{ - put("first", List.of("1")); - put("second", List.of("2.1", "2.2")); - put("third", List.of("3")); + put("first", Arrays.asList("1")); + put("second", Arrays.asList("2.1", "2.2")); + put("third", Arrays.asList("3")); }}; } } From 807a815bf355ba6598e48d07c278527ff9e5da51 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 27 Mar 2024 11:42:16 -0700 Subject: [PATCH 37/88] fixed test --- .../io/split/client/RequestDecoratorTest.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index d8643324f..752b2c3e1 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -71,19 +71,19 @@ public MyCustomHeaders() {} public Map> getHeaderOverrides() { return new HashMap>() {{ - put("first", List.of("1")); - put("SplitSDKVersion", List.of("2.4")); - put("SplitMachineip", List.of("xx")); - put("splitMachineName", List.of("xx")); - put("splitimpressionsmode", List.of("xx")); - put("HOST", List.of("xx")); - put("referrer", List.of("xx")); - put("content-type", List.of("xx")); - put("content-length", List.of("xx")); - put("content-encoding", List.of("xx")); - put("ACCEPT", List.of("xx")); - put("keep-alive", List.of("xx")); - put("x-fastly-debug", List.of("xx")); + put("first", Arrays.asList("1")); + put("SplitSDKVersion", Arrays.asList("2.4")); + put("SplitMachineip", Arrays.asList("xx")); + put("splitMachineName", Arrays.asList("xx")); + put("splitimpressionsmode", Arrays.asList("xx")); + put("HOST", Arrays.asList("xx")); + put("referrer", Arrays.asList("xx")); + put("content-type", Arrays.asList("xx")); + put("content-length", Arrays.asList("xx")); + put("content-encoding", Arrays.asList("xx")); + put("ACCEPT", Arrays.asList("xx")); + put("keep-alive", Arrays.asListf("xx")); + put("x-fastly-debug", Arrays.asList("xx")); }}; } From aa9aafdf3f16d8c2efd3383b0e20a6823d4e148b Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 27 Mar 2024 12:43:47 -0700 Subject: [PATCH 38/88] Renamed UserCustomHeaderDecorator to CustomHeaderDecorator --- ...orator.java => CustomHeaderDecorator.java} | 2 +- .../client/HttpSegmentChangeFetcher.java | 10 +++--- .../split/client/HttpSplitChangeFetcher.java | 12 +++---- .../io/split/client/RequestDecorator.java | 6 ++-- .../io/split/client/SplitClientConfig.java | 20 ++++++------ .../io/split/client/SplitFactoryImpl.java | 2 +- .../split/client/dtos/SplitHttpResponse.java | 31 ++++++++++++++++--- .../impressions/HttpImpressionsSender.java | 8 ++--- .../io/split/engine/sse/AuthApiClientImp.java | 4 +-- .../java/io/split/service/HttpPostImp.java | 4 +-- .../io/split/service/SplitHttpClientImpl.java | 20 +++++------- .../io/split/client/RequestDecoratorTest.java | 8 ++--- .../split/client/SplitClientConfigTest.java | 10 +++--- .../io/split/service/HttpSplitClientTest.java | 10 +++--- 14 files changed, 81 insertions(+), 66 deletions(-) rename client/src/main/java/io/split/client/{UserCustomHeaderDecorator.java => CustomHeaderDecorator.java} (85%) diff --git a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java b/client/src/main/java/io/split/client/CustomHeaderDecorator.java similarity index 85% rename from client/src/main/java/io/split/client/UserCustomHeaderDecorator.java rename to client/src/main/java/io/split/client/CustomHeaderDecorator.java index 236b38afd..827ee112d 100644 --- a/client/src/main/java/io/split/client/UserCustomHeaderDecorator.java +++ b/client/src/main/java/io/split/client/CustomHeaderDecorator.java @@ -3,7 +3,7 @@ import java.util.Map; import java.util.List; -public interface UserCustomHeaderDecorator +public interface CustomHeaderDecorator { /** * Get the additional headers needed for all http operations diff --git a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java index 65c5e01f3..bd365590c 100644 --- a/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java @@ -64,18 +64,18 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options) SplitHttpResponse response = _client.get(uri, options, null); - if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, response.statusCode); - if (response.statusCode == HttpStatus.SC_FORBIDDEN) { + if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, response.statusCode()); + if (response.statusCode() == HttpStatus.SC_FORBIDDEN) { _log.error("factory instantiation: you passed a client side type sdkKey, " + "please grab an sdk key from the Split user interface that is of type server side"); } throw new IllegalStateException(String.format("Could not retrieve segment changes for %s, since %s; http return code %s", - segmentName, since, response.statusCode)); + segmentName, since, response.statusCode())); } _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.SEGMENTS, System.currentTimeMillis()); - return Json.fromJson(response.body, SegmentChange.class); + return Json.fromJson(response.body(), SegmentChange.class); } catch (Exception e) { throw new IllegalStateException(String.format("Error occurred when trying to sync segment: %s, since: %s. Details: %s", segmentName, since, e), e); diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index 36d5be744..fcf4502d2 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -68,18 +68,18 @@ public SplitChange fetch(long since, FetchOptions options) { URI uri = uriBuilder.build(); SplitHttpResponse response = _client.get(uri, options, null); - if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - if (response.statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) { + if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { + if (response.statusCode() == HttpStatus.SC_REQUEST_URI_TOO_LONG) { _log.error("The amount of flag sets provided are big causing uri length error."); - throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode, response.statusMessage)); + throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode(), response.statusMessage())); } - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode); + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode()); throw new IllegalStateException( - String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode) + String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode()) ); } - return Json.fromJson(response.body, SplitChange.class); + return Json.fromJson(response.body(), SplitChange.class); } catch (Exception e) { throw new IllegalStateException(String.format("Problem fetching splitChanges since %s: %s", since, e), e); } finally { diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index e4be9ff9d..c5e2237ee 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -8,7 +8,7 @@ import java.util.Set; import java.util.List; -class NoOpHeaderDecorator implements UserCustomHeaderDecorator { +class NoOpHeaderDecorator implements CustomHeaderDecorator { public NoOpHeaderDecorator() {} @Override public Map> getHeaderOverrides() { @@ -17,7 +17,7 @@ public Map> getHeaderOverrides() { } public final class RequestDecorator { - UserCustomHeaderDecorator _headerDecorator; + CustomHeaderDecorator _headerDecorator; private static final Set forbiddenHeaders = new HashSet<>(Arrays.asList( "splitsdkversion", @@ -34,7 +34,7 @@ public final class RequestDecorator { "x-fastly-debug" )); - public RequestDecorator(UserCustomHeaderDecorator headerDecorator) { + public RequestDecorator(CustomHeaderDecorator headerDecorator) { _headerDecorator = (headerDecorator == null) ? new NoOpHeaderDecorator() : headerDecorator; diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 025a40d94..6794b7bc6 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -90,7 +90,7 @@ public class SplitClientConfig { private final long _lastSeenCacheSize; private final HashSet _flagSetsFilter; private final int _invalidSets; - private final UserCustomHeaderDecorator _userCustomHeaderDecorator; + private final CustomHeaderDecorator _customHeaderDecorator; public static Builder builder() { @@ -148,7 +148,7 @@ private SplitClientConfig(String endpoint, ThreadFactory threadFactory, HashSet flagSetsFilter, int invalidSets, - UserCustomHeaderDecorator userCustomHeaderDecorator) { + CustomHeaderDecorator customHeaderDecorator) { _endpoint = endpoint; _eventsEndpoint = eventsEndpoint; _featuresRefreshRate = pollForFeatureChangesEveryNSeconds; @@ -200,7 +200,7 @@ private SplitClientConfig(String endpoint, _threadFactory = threadFactory; _flagSetsFilter = flagSetsFilter; _invalidSets = invalidSets; - _userCustomHeaderDecorator = userCustomHeaderDecorator; + _customHeaderDecorator = customHeaderDecorator; Properties props = new Properties(); try { @@ -397,8 +397,8 @@ public int getInvalidSets() { return _invalidSets; } - public UserCustomHeaderDecorator userCustomHeaderDecorator() { - return _userCustomHeaderDecorator; + public CustomHeaderDecorator customHeaderDecorator() { + return _customHeaderDecorator; } public static final class Builder { @@ -457,7 +457,7 @@ public static final class Builder { private ThreadFactory _threadFactory; private HashSet _flagSetsFilter = new HashSet<>(); private int _invalidSetsCount = 0; - private UserCustomHeaderDecorator _userCustomHeaderDecorator = null; + private CustomHeaderDecorator _customHeaderDecorator = null; public Builder() { } @@ -944,11 +944,11 @@ public Builder flagSetsFilter(List flagSetsFilter) { /** * User Custom Header Decorator * - * @param userCustomHeaderDecorator + * @param customHeaderDecorator * @return this builder */ - public Builder userCustomHeaderDecorator(UserCustomHeaderDecorator userCustomHeaderDecorator) { - _userCustomHeaderDecorator = userCustomHeaderDecorator; + public Builder customHeaderDecorator(CustomHeaderDecorator customHeaderDecorator) { + _customHeaderDecorator = customHeaderDecorator; return this; } @@ -1112,7 +1112,7 @@ public SplitClientConfig build() { _threadFactory, _flagSetsFilter, _invalidSetsCount, - _userCustomHeaderDecorator); + _customHeaderDecorator); } } } \ 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 2de955e93..35bbed8c3 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -508,7 +508,7 @@ private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClient httpClientbuilder = setupProxy(httpClientbuilder, config); } - return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.userCustomHeaderDecorator())); + return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.customHeaderDecorator())); } private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) { diff --git a/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java b/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java index 8dac4662d..a5474cf5b 100644 --- a/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java +++ b/client/src/main/java/io/split/client/dtos/SplitHttpResponse.java @@ -5,9 +5,30 @@ /** * A structure for returning http call results information */ -public final class SplitHttpResponse { - public Integer statusCode; - public String statusMessage; - public String body; - public Header[] responseHeaders; +public class SplitHttpResponse { + private final Integer _statusCode; + private final String _statusMessage; + private final String _body; + private final Header[] _responseHeaders; + + public SplitHttpResponse(Integer statusCode, String statusMessage, String body, Header[] headers) { + _statusCode = statusCode; + _statusMessage = statusMessage; + _body = body; + _responseHeaders = headers; + } + public Integer statusCode() { + return _statusCode; + } + public String statusMessage() { + return _statusMessage; + } + + public String body() { + return _body; + } + + public Header[] responseHeaders() { + return _responseHeaders; + } } diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index ec6cb4aea..919fe8920 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -69,8 +69,8 @@ public void postImpressionsBulk(List impressions) { additionalHeader.put(IMPRESSIONS_MODE_HEADER, _mode.toString()); SplitHttpResponse response = _client.post(_impressionBulkTarget, entity, additionalHeader); - if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode); + if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode()); } _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS, System.currentTimeMillis()); @@ -94,8 +94,8 @@ public void postCounters(HashMap raw) { Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw)), null); - if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, response.statusCode); + if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, response.statusCode()); } _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS_COUNT, System.currentTimeMillis() - initTime); _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT, System.currentTimeMillis()); diff --git a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java index d4187a5eb..c500cf0dc 100644 --- a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java +++ b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java @@ -38,7 +38,7 @@ public AuthenticationResponse Authenticate() { long initTime = System.currentTimeMillis(); URI uri = new URIBuilder(_target).build(); SplitHttpResponse response = _httpClient.get(uri, new FetchOptions.Builder().cacheControlHeaders(false).build(), null); - Integer statusCode = response.statusCode; + Integer statusCode = response.statusCode(); if (statusCode == HttpStatus.SC_OK) { _log.debug(String.format("Success connection to: %s", _target)); @@ -46,7 +46,7 @@ public AuthenticationResponse Authenticate() { _telemetryRuntimeProducer.recordTokenRefreshes(); _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.TOKEN, System.currentTimeMillis()); _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.TOKEN, System.currentTimeMillis()-initTime); - return getSuccessResponse(response.body); + return getSuccessResponse(response.body()); } _log.error(String.format("Problem to connect to : %s. Response status: %s", _target, statusCode)); diff --git a/client/src/main/java/io/split/service/HttpPostImp.java b/client/src/main/java/io/split/service/HttpPostImp.java index cb5b5190d..e5baa001b 100644 --- a/client/src/main/java/io/split/service/HttpPostImp.java +++ b/client/src/main/java/io/split/service/HttpPostImp.java @@ -29,8 +29,8 @@ public void post(URI uri, Object object, String posted, HttpParamsWrapper httpPa try { SplitHttpResponse response = _client.post(uri, entity, null); - if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) { - _telemetryRuntimeProducer.recordSyncError(httpParamsWrapper.getResourceEnum(), response.statusCode); + if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { + _telemetryRuntimeProducer.recordSyncError(httpParamsWrapper.getResourceEnum(), response.statusCode()); return; } _telemetryRuntimeProducer.recordSyncLatency(httpParamsWrapper.getHttpLatenciesEnum(), System.currentTimeMillis() - initTime); diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index c9e9f689b..3a57c0fe8 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -61,16 +61,15 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), response.getCode())); } - SplitHttpResponse httpResponse = new SplitHttpResponse(); - httpResponse.statusMessage = ""; - httpResponse.responseHeaders = response.getHeaders(); + String statusMessage = ""; if (response.getCode() < HttpStatus.SC_OK || response.getCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode() , response.getReasonPhrase())); - httpResponse.statusMessage = response.getReasonPhrase(); + statusMessage = response.getReasonPhrase(); } - httpResponse.statusCode = response.getCode(); - httpResponse.body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - return httpResponse; + return new SplitHttpResponse(response.getCode(), + statusMessage, + EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8), + response.getHeaders()); } catch (Exception e) { throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); } finally { @@ -100,12 +99,7 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map statusMessage = response.getReasonPhrase(); _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode(), response.getReasonPhrase())); } - SplitHttpResponse httpResponse = new SplitHttpResponse(); - httpResponse.statusCode = response.getCode(); - httpResponse.body = ""; - httpResponse.statusMessage = statusMessage; - httpResponse.responseHeaders = response.getHeaders(); - return httpResponse; + return new SplitHttpResponse(response.getCode(), statusMessage, "", response.getHeaders()); } catch (Exception e) { throw new IOException(String.format("Problem in http post operation: %s", e), e); } finally { diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index 752b2c3e1..d3a2d1c12 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -31,7 +31,7 @@ public void testNoOp() { @Test public void testAddCustomHeaders() throws ProtocolException { - class MyCustomHeaders implements UserCustomHeaderDecorator { + class MyCustomHeaders implements CustomHeaderDecorator { public MyCustomHeaders() {} @Override public Map> getHeaderOverrides() { @@ -65,7 +65,7 @@ public Map> getHeaderOverrides() { @Test public void testAddBlockedHeaders() throws ProtocolException { - class MyCustomHeaders implements UserCustomHeaderDecorator { + class MyCustomHeaders implements CustomHeaderDecorator { public MyCustomHeaders() {} @Override public Map> getHeaderOverrides() { @@ -82,7 +82,7 @@ public Map> getHeaderOverrides() { put("content-length", Arrays.asList("xx")); put("content-encoding", Arrays.asList("xx")); put("ACCEPT", Arrays.asList("xx")); - put("keep-alive", Arrays.asListf("xx")); + put("keep-alive", Arrays.asList("xx")); put("x-fastly-debug", Arrays.asList("xx")); }}; @@ -98,7 +98,7 @@ public Map> getHeaderOverrides() { @Test(expected = IllegalArgumentException.class) public void customDecoratorError() { - class MyCustomHeaders implements UserCustomHeaderDecorator { + class MyCustomHeaders implements CustomHeaderDecorator { public MyCustomHeaders() {} @Override public Map> getHeaderOverrides() { diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 113079309..bd8648cf8 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -239,18 +239,18 @@ public void IntegrationConfigAsyncNotNull() { @Test public void checkUserCustomdHeaderDecorator() { - UserCustomHeaderDecorator ucd = new UserCustomHeaderDecorator() { + CustomHeaderDecorator ucd = new CustomHeaderDecorator() { @Override public Map> getHeaderOverrides() { return null; } }; - SplitClientConfig config = SplitClientConfig.builder().userCustomHeaderDecorator(ucd).build(); - Assert.assertNotNull(config.userCustomHeaderDecorator()); - Assert.assertEquals(ucd, config.userCustomHeaderDecorator()); + SplitClientConfig config = SplitClientConfig.builder().customHeaderDecorator(ucd).build(); + Assert.assertNotNull(config.customHeaderDecorator()); + Assert.assertEquals(ucd, config.customHeaderDecorator()); SplitClientConfig config2 = SplitClientConfig.builder().build(); - Assert.assertNull(config2.userCustomHeaderDecorator()); + Assert.assertNull(config2.customHeaderDecorator()); } } \ No newline at end of file diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index 4dfe94f91..9a1af3b24 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -47,14 +47,14 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders); - SplitChange change = Json.fromJson(splitHttpResponse.body, SplitChange.class); + SplitChange change = Json.fromJson(splitHttpResponse.body(), SplitChange.class); ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClientMock).execute(captor.capture()); HttpUriRequest request = captor.getValue(); assertThat(request.getFirstHeader("AdditionalHeader").getValue(), is(equalTo("add"))); - Header[] headers = splitHttpResponse.responseHeaders; + Header[] headers = splitHttpResponse.responseHeaders(); assertThat(headers[0].getName(), is(equalTo("Via"))); assertThat(headers[0].getValue(), is(equalTo("HTTP/1.1 m_proxy_rio1"))); Assert.assertNotNull(change); @@ -78,7 +78,7 @@ public void testGetError() throws URISyntaxException, InvocationTargetException, SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), null); - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (long) splitHttpResponse.statusCode); + Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (long) splitHttpResponse.statusCode()); } @Test(expected = IllegalStateException.class) @@ -129,7 +129,7 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce Gson gson = new Gson(); List payload = gson.fromJson(reader, new TypeToken>() { }.getType()); assertThat(payload.size(), is(equalTo(2))); - Assert.assertEquals(200,(long) splitHttpResponse.statusCode); + Assert.assertEquals(200,(long) splitHttpResponse.statusCode()); } @Test @@ -140,7 +140,7 @@ public void testPosttNoExceptionOnHttpErrorCode() throws URISyntaxException, Inv SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null); - Assert.assertEquals(500, (long) splitHttpResponse.statusCode); + Assert.assertEquals(500, (long) splitHttpResponse.statusCode()); } From 493c8f6fe35108237ea3f1d41a5258d583a49681 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Wed, 27 Mar 2024 14:58:07 -0700 Subject: [PATCH 39/88] added RequestContext and refactored RequestDecorator classes --- .../split/client/CustomHeaderDecorator.java | 4 +- .../io/split/client/RequestDecorator.java | 19 ++++++- .../io/split/client/dtos/RequestContext.java | 20 +++++++ .../io/split/client/RequestDecoratorTest.java | 52 +++++++++---------- .../split/client/SplitClientConfigTest.java | 3 +- 5 files changed, 67 insertions(+), 31 deletions(-) create mode 100644 client/src/main/java/io/split/client/dtos/RequestContext.java diff --git a/client/src/main/java/io/split/client/CustomHeaderDecorator.java b/client/src/main/java/io/split/client/CustomHeaderDecorator.java index 827ee112d..934c43681 100644 --- a/client/src/main/java/io/split/client/CustomHeaderDecorator.java +++ b/client/src/main/java/io/split/client/CustomHeaderDecorator.java @@ -1,5 +1,7 @@ package io.split.client; +import io.split.client.dtos.RequestContext; + import java.util.Map; import java.util.List; @@ -9,5 +11,5 @@ public interface CustomHeaderDecorator * Get the additional headers needed for all http operations * @return HashMap of addition headers */ - Map> getHeaderOverrides(); + Map> getHeaderOverrides(RequestContext context); } diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index c5e2237ee..8bc9e216b 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -1,17 +1,22 @@ package io.split.client; +import io.split.client.dtos.RequestContext; + import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.Header; + import java.util.HashSet; import java.util.HashMap; import java.util.Map; import java.util.Arrays; +import java.util.ArrayList; import java.util.Set; import java.util.List; class NoOpHeaderDecorator implements CustomHeaderDecorator { public NoOpHeaderDecorator() {} @Override - public Map> getHeaderOverrides() { + public Map> getHeaderOverrides(RequestContext context) { return new HashMap<>(); } } @@ -42,7 +47,7 @@ public RequestDecorator(CustomHeaderDecorator headerDecorator) { public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { try { - Map> headers = _headerDecorator.getHeaderOverrides(); + Map> headers = _headerDecorator.getHeaderOverrides(new RequestContext(convertToMap(request.getHeaders()))); for (Map.Entry entry : headers.entrySet()) { if (isHeaderAllowed(entry.getKey().toString())) { List values = (List) entry.getValue(); @@ -65,4 +70,14 @@ public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { private boolean isHeaderAllowed(String headerName) { return !forbiddenHeaders.contains(headerName.toLowerCase()); } + private Map> convertToMap(Header[] to_convert) { + Map> to_return = new HashMap>(); + for (Integer i = 0; i < to_convert.length; i++ ) { + if (!to_return.containsKey(to_convert[i].getName())) { + to_return.put(to_convert[i].getName(), new ArrayList()); + } + to_return.get(to_convert[i].getName()).add(to_convert[i].getValue()); + } + return to_return; + } } diff --git a/client/src/main/java/io/split/client/dtos/RequestContext.java b/client/src/main/java/io/split/client/dtos/RequestContext.java new file mode 100644 index 000000000..29fb7f77b --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/RequestContext.java @@ -0,0 +1,20 @@ +package io.split.client.dtos; + +import java.util.Map; +import java.util.List; +/** + * A structure returning a context for RequestDecorator class + */ + +public class RequestContext +{ + private final Map> _headers; + + public RequestContext(Map> headers) { + _headers = headers; + } + + public Map> headers() { + return _headers; + } +} diff --git a/client/src/test/java/io/split/client/RequestDecoratorTest.java b/client/src/test/java/io/split/client/RequestDecoratorTest.java index d3a2d1c12..62868eb40 100644 --- a/client/src/test/java/io/split/client/RequestDecoratorTest.java +++ b/client/src/test/java/io/split/client/RequestDecoratorTest.java @@ -3,7 +3,6 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.core5.http.Header; -import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.ProtocolException; import org.junit.Assert; import org.junit.Test; @@ -11,6 +10,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import io.split.client.dtos.RequestContext; + import java.util.List; import java.util.Arrays; import java.util.HashMap; @@ -34,13 +35,12 @@ public void testAddCustomHeaders() throws ProtocolException { class MyCustomHeaders implements CustomHeaderDecorator { public MyCustomHeaders() {} @Override - public Map> getHeaderOverrides() { - return new HashMap>() - {{ - put("first", Arrays.asList("1")); - put("second", Arrays.asList("2.1", "2.2")); - put("third", Arrays.asList("3")); - }}; + public Map> getHeaderOverrides(RequestContext context) { + Map> additionalHeaders = context.headers(); + additionalHeaders.put("first", Arrays.asList("1")); + additionalHeaders.put("second", Arrays.asList("2.1", "2.2")); + additionalHeaders.put("third", Arrays.asList("3")); + return additionalHeaders; } } MyCustomHeaders myHeaders = new MyCustomHeaders(); @@ -68,24 +68,22 @@ public void testAddBlockedHeaders() throws ProtocolException { class MyCustomHeaders implements CustomHeaderDecorator { public MyCustomHeaders() {} @Override - public Map> getHeaderOverrides() { - return new HashMap>() - {{ - put("first", Arrays.asList("1")); - put("SplitSDKVersion", Arrays.asList("2.4")); - put("SplitMachineip", Arrays.asList("xx")); - put("splitMachineName", Arrays.asList("xx")); - put("splitimpressionsmode", Arrays.asList("xx")); - put("HOST", Arrays.asList("xx")); - put("referrer", Arrays.asList("xx")); - put("content-type", Arrays.asList("xx")); - put("content-length", Arrays.asList("xx")); - put("content-encoding", Arrays.asList("xx")); - put("ACCEPT", Arrays.asList("xx")); - put("keep-alive", Arrays.asList("xx")); - put("x-fastly-debug", Arrays.asList("xx")); - - }}; + public Map> getHeaderOverrides(RequestContext context) { + Map> additionalHeaders = context.headers(); + additionalHeaders.put("first", Arrays.asList("1")); + additionalHeaders.put("SplitSDKVersion", Arrays.asList("2.4")); + additionalHeaders.put("SplitMachineip", Arrays.asList("xx")); + additionalHeaders.put("splitMachineName", Arrays.asList("xx")); + additionalHeaders.put("splitimpressionsmode", Arrays.asList("xx")); + additionalHeaders.put("HOST", Arrays.asList("xx")); + additionalHeaders.put("referrer", Arrays.asList("xx")); + additionalHeaders.put("content-type", Arrays.asList("xx")); + additionalHeaders.put("content-length", Arrays.asList("xx")); + additionalHeaders.put("content-encoding", Arrays.asList("xx")); + additionalHeaders.put("ACCEPT", Arrays.asList("xx")); + additionalHeaders.put("keep-alive", Arrays.asList("xx")); + additionalHeaders.put("x-fastly-debug", Arrays.asList("xx")); + return additionalHeaders; } } MyCustomHeaders myHeaders = new MyCustomHeaders(); @@ -101,7 +99,7 @@ public void customDecoratorError() { class MyCustomHeaders implements CustomHeaderDecorator { public MyCustomHeaders() {} @Override - public Map> getHeaderOverrides() { + public Map> getHeaderOverrides(RequestContext context) { throw new RuntimeException(); } } diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index bd8648cf8..1b640071c 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -4,6 +4,7 @@ import io.split.client.impressions.Impression; import io.split.client.impressions.ImpressionListener; import io.split.client.impressions.ImpressionsManager; +import io.split.client.dtos.RequestContext; import io.split.integrations.IntegrationsConfig; import org.junit.Assert; import org.junit.Test; @@ -241,7 +242,7 @@ public void IntegrationConfigAsyncNotNull() { public void checkUserCustomdHeaderDecorator() { CustomHeaderDecorator ucd = new CustomHeaderDecorator() { @Override - public Map> getHeaderOverrides() { + public Map> getHeaderOverrides(RequestContext context) { return null; } }; From 495d39cbe16d63d746b743c93cdfe4c657e8b60f Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 11:24:54 -0300 Subject: [PATCH 40/88] fix header overrides --- .../io/split/client/RequestDecorator.java | 33 +-- .../io/split/client/SplitFactoryImpl.java | 203 +++++++++++------- .../impressions/HttpImpressionsSender.java | 33 +-- .../io/split/service/SplitHttpClient.java | 20 +- .../io/split/service/SplitHttpClientImpl.java | 80 ++++--- .../client/HttpSegmentChangeFetcherTest.java | 80 ++++--- .../client/HttpSplitChangeFetcherTest.java | 71 ++++-- .../split/client/events/EventsSenderTest.java | 32 ++- .../HttpImpressionsSenderTest.java | 101 ++++++--- .../split/engine/sse/AuthApiClientTest.java | 59 +++-- .../io/split/service/HttpPostImpTest.java | 32 ++- .../io/split/service/HttpSplitClientTest.java | 87 +++++--- .../TelemetryInMemorySubmitterTest.java | 61 ++++-- 13 files changed, 577 insertions(+), 315 deletions(-) diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 8bc9e216b..bf51597fe 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -2,7 +2,8 @@ import io.split.client.dtos.RequestContext; -import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +//`import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.Header; import java.util.HashSet; @@ -13,8 +14,10 @@ import java.util.Set; import java.util.List; -class NoOpHeaderDecorator implements CustomHeaderDecorator { - public NoOpHeaderDecorator() {} +class NoOpHeaderDecorator implements CustomHeaderDecorator { + public NoOpHeaderDecorator() { + } + @Override public Map> getHeaderOverrides(RequestContext context) { return new HashMap<>(); @@ -36,8 +39,7 @@ public final class RequestDecorator { "content-encoding", "accept", "keep-alive", - "x-fastly-debug" - )); + "x-fastly-debug")); public RequestDecorator(CustomHeaderDecorator headerDecorator) { _headerDecorator = (headerDecorator == null) @@ -45,23 +47,25 @@ public RequestDecorator(CustomHeaderDecorator headerDecorator) { : headerDecorator; } - public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { + public HttpRequest decorateHeaders(HttpRequest request) { try { - Map> headers = _headerDecorator.getHeaderOverrides(new RequestContext(convertToMap(request.getHeaders()))); - for (Map.Entry entry : headers.entrySet()) { - if (isHeaderAllowed(entry.getKey().toString())) { - List values = (List) entry.getValue(); + Map> headers = _headerDecorator + .getHeaderOverrides(new RequestContext(convertToMap(request.getHeaders()))); + for (Map.Entry> entry : headers.entrySet()) { + if (isHeaderAllowed(entry.getKey())) { + List values = entry.getValue(); for (int i = 0; i < values.size(); i++) { if (i == 0) { - request.setHeader(entry.getKey().toString(), values.get(i)); + request.setHeader(entry.getKey(), values.get(i)); } else { - request.addHeader(entry.getKey().toString(), values.get(i)); + request.addHeader(entry.getKey(), values.get(i)); } } } } } catch (Exception e) { - throw new IllegalArgumentException(String.format("Problem adding custom headers to request decorator: %s", e), e); + throw new IllegalArgumentException( + String.format("Problem adding custom headers to request decorator: %s", e), e); } return request; @@ -70,9 +74,10 @@ public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) { private boolean isHeaderAllowed(String headerName) { return !forbiddenHeaders.contains(headerName.toLowerCase()); } + private Map> convertToMap(Header[] to_convert) { Map> to_return = new HashMap>(); - for (Integer i = 0; i < to_convert.length; i++ ) { + for (Integer i = 0; i < to_convert.length; i++) { if (!to_return.containsKey(to_convert[i].getName())) { to_return.put(to_convert[i].getName(), new ArrayList()); } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 35bbed8c3..c8db4e013 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -26,7 +26,6 @@ import io.split.client.impressions.strategy.ProcessImpressionNone; import io.split.client.impressions.strategy.ProcessImpressionOptimized; import io.split.client.impressions.strategy.ProcessImpressionStrategy; -import io.split.client.interceptors.AuthorizationInterceptorFilter; import io.split.client.interceptors.ClientKeyInterceptorFilter; import io.split.client.interceptors.FlagSetsFilter; import io.split.client.interceptors.FlagSetsFilterImpl; @@ -122,8 +121,9 @@ public class SplitFactoryImpl implements SplitFactory { private static final Logger _log = LoggerFactory.getLogger(SplitFactory.class); - private static final String LEGACY_LOG_MESSAGE = "The sdk initialize in localhost mode using Legacy file. The splitFile or " + - "inputStream doesn't add it to the config."; + private static final String LEGACY_LOG_MESSAGE = "The sdk initialize in localhost mode using Legacy file. The splitFile or " + + + "inputStream doesn't add it to the config."; private final static long SSE_CONNECT_TIMEOUT = 30000; private final static long SSE_SOCKET_TIMEOUT = 70000; @@ -136,7 +136,7 @@ public class SplitFactoryImpl implements SplitFactory { private final SplitClient _client; private final SplitManager _manager; - //Cache + // Cache private final SplitCacheConsumer _splitCache; private final SegmentCacheConsumer _segmentCache; @@ -148,7 +148,7 @@ public class SplitFactoryImpl implements SplitFactory { private final SDKMetadata _sdkMetadata; private OperationMode _operationMode; - //Depending on mode are not mandatory + // Depending on mode are not mandatory private final TelemetrySyncTask _telemetrySyncTask; private final SegmentSynchronizationTaskImp _segmentSynchronizationTaskImp; private final SplitFetcher _splitFetcher; @@ -162,7 +162,7 @@ public class SplitFactoryImpl implements SplitFactory { private final URI _eventsRootTarget; private final UniqueKeysTracker _uniqueKeysTracker; - //Constructor for standalone mode + // Constructor for standalone mode public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyntaxException { _userStorageWrapper = null; _operationMode = config.operationMode(); @@ -176,9 +176,11 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn _telemetryStorageProducer = telemetryStorage; if (config.blockUntilReady() == -1) { - //BlockUntilReady not been set - _log.warn("no setBlockUntilReadyTimeout parameter has been set - incorrect control treatments could be logged” " + - "if no ready config has been set when building factory"); + // BlockUntilReady not been set + _log.warn( + "no setBlockUntilReadyTimeout parameter has been set - incorrect control treatments could be logged” " + + + "if no ready config has been set when building factory"); } // SDKReadinessGates @@ -198,7 +200,8 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn ImpressionsStorage impressionsStorage = new InMemoryImpressionsStorage(config.impressionsQueueSize()); _splitCache = splitCache; _segmentCache = segmentCache; - _telemetrySynchronizer = new TelemetryInMemorySubmitter(_splitHttpClient, URI.create(config.telemetryURL()), telemetryStorage, + _telemetrySynchronizer = new TelemetryInMemorySubmitter(_splitHttpClient, URI.create(config.telemetryURL()), + telemetryStorage, splitCache, _segmentCache, telemetryStorage, _startTime); // Segments @@ -214,11 +217,12 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn config.featuresRefreshRate(), config.getThreadFactory()); - //ImpressionSender - _impressionsSender = HttpImpressionsSender.create(_splitHttpClient, URI.create(config.eventsEndpoint()), config.impressionsMode(), + // ImpressionSender + _impressionsSender = HttpImpressionsSender.create(_splitHttpClient, URI.create(config.eventsEndpoint()), + config.impressionsMode(), _telemetryStorageProducer); - //UniqueKeysTracker + // UniqueKeysTracker _uniqueKeysTracker = createUniqueKeysTracker(config); // Impressions @@ -227,9 +231,11 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn // EventClient EventsStorage eventsStorage = new InMemoryEventsStorage(config.eventsQueueSize(), _telemetryStorageProducer); EventsSender eventsSender = EventsSender.create(_splitHttpClient, _eventsRootTarget, _telemetryStorageProducer); - _eventsTask = EventsTask.create(config.eventSendIntervalInMillis(), eventsStorage, eventsSender, config.getThreadFactory()); + _eventsTask = EventsTask.create(config.eventSendIntervalInMillis(), eventsStorage, eventsSender, + config.getThreadFactory()); - _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); + _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, + config.getThreadFactory()); // Evaluator _evaluator = new EvaluatorImp(splitCache, segmentCache); @@ -242,8 +248,8 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn config, _gates, _evaluator, - _telemetryStorageProducer, //TelemetryEvaluation instance - _telemetryStorageProducer, //TelemetryConfiguration instance + _telemetryStorageProducer, // TelemetryEvaluation instance + _telemetryStorageProducer, // TelemetryConfiguration instance flagSetsFilter); // SplitManager @@ -255,7 +261,8 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn SplitAPI splitAPI = SplitAPI.build(_splitHttpClient, buildSSEdHttpClient(apiToken, config, _sdkMetadata)); _syncManager = SyncManagerImp.build(splitTasks, _splitFetcher, splitCache, splitAPI, - segmentCache, _gates, _telemetryStorageProducer, _telemetrySynchronizer, config, splitParser, flagSetsFilter); + segmentCache, _gates, _telemetryStorageProducer, _telemetrySynchronizer, config, splitParser, + flagSetsFilter); _syncManager.start(); // DestroyOnShutDown @@ -269,9 +276,10 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn } } - //Constructor for consumer mode - protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStorageWrapper customStorageWrapper) throws URISyntaxException { - //Variables that are not used in Consumer mode. + // Constructor for consumer mode + protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStorageWrapper customStorageWrapper) + throws URISyntaxException { + // Variables that are not used in Consumer mode. _segmentSynchronizationTaskImp = null; _splitFetcher = null; _splitSynchronizationTask = null; @@ -282,13 +290,18 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor Metadata metadata = new Metadata(config.ipAddressEnabled(), SplitClientConfig.splitSdkVersion); _userStorageWrapper = new UserStorageWrapper(customStorageWrapper); - UserCustomSegmentAdapterConsumer userCustomSegmentAdapterConsumer= new UserCustomSegmentAdapterConsumer(customStorageWrapper); - UserCustomSplitAdapterConsumer userCustomSplitAdapterConsumer = new UserCustomSplitAdapterConsumer(customStorageWrapper); - // TODO migrate impressions sender to Task instead manager and not instantiate Producer here. + UserCustomSegmentAdapterConsumer userCustomSegmentAdapterConsumer = new UserCustomSegmentAdapterConsumer( + customStorageWrapper); + UserCustomSplitAdapterConsumer userCustomSplitAdapterConsumer = new UserCustomSplitAdapterConsumer( + customStorageWrapper); + // TODO migrate impressions sender to Task instead manager and not instantiate + // Producer here. UserCustomImpressionAdapterConsumer userCustomImpressionAdapterConsumer = new UserCustomImpressionAdapterConsumer(); - UserCustomImpressionAdapterProducer userCustomImpressionAdapterProducer = new UserCustomImpressionAdapterProducer(customStorageWrapper, + UserCustomImpressionAdapterProducer userCustomImpressionAdapterProducer = new UserCustomImpressionAdapterProducer( + customStorageWrapper, metadata); - UserCustomEventAdapterProducer userCustomEventAdapterProducer = new UserCustomEventAdapterProducer(customStorageWrapper, metadata); + UserCustomEventAdapterProducer userCustomEventAdapterProducer = new UserCustomEventAdapterProducer( + customStorageWrapper, metadata); _operationMode = config.operationMode(); _sdkMetadata = createSdkMetadata(config.ipAddressEnabled(), SplitClientConfig.splitSdkVersion); @@ -302,9 +315,11 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _segmentCache = userCustomSegmentAdapterConsumer; if (config.blockUntilReady() == -1) { - //BlockUntilReady not been set - _log.warn("no setBlockUntilReadyTimeout parameter has been set - incorrect control treatments could be logged” " + - "if no ready config has been set when building factory"); + // BlockUntilReady not been set + _log.warn( + "no setBlockUntilReadyTimeout parameter has been set - incorrect control treatments could be logged” " + + + "if no ready config has been set when building factory"); } // SDKReadinessGates @@ -314,8 +329,10 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor _evaluator = new EvaluatorImp(userCustomSplitAdapterConsumer, userCustomSegmentAdapterConsumer); _impressionsSender = PluggableImpressionSender.create(customStorageWrapper); _uniqueKeysTracker = createUniqueKeysTracker(config); - _impressionsManager = buildImpressionsManager(config, userCustomImpressionAdapterConsumer, userCustomImpressionAdapterProducer); - _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, config.getThreadFactory()); + _impressionsManager = buildImpressionsManager(config, userCustomImpressionAdapterConsumer, + userCustomImpressionAdapterProducer); + _telemetrySyncTask = new TelemetrySyncTask(config.get_telemetryRefreshRate(), _telemetrySynchronizer, + config.getThreadFactory()); SplitTasks splitTasks = SplitTasks.build(null, null, _impressionsManager, null, _telemetrySyncTask, _uniqueKeysTracker); @@ -323,9 +340,11 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor // Synchronizer Synchronizer synchronizer = new ConsumerSynchronizer(splitTasks); FlagSetsFilter flagSetsFilter = new FlagSetsFilterImpl(new HashSet<>()); - if(!config.getSetsFilter().isEmpty()) { - _log.warn("FlagSets filter is not applicable for Consumer modes where the SDK does not keep rollout data in sync. FlagSet " + - "filter was discarded"); + if (!config.getSetsFilter().isEmpty()) { + _log.warn( + "FlagSets filter is not applicable for Consumer modes where the SDK does not keep rollout data in sync. FlagSet " + + + "filter was discarded"); } _client = new SplitClientImpl(this, userCustomSplitAdapterConsumer, @@ -334,11 +353,10 @@ protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStor config, _gates, _evaluator, - _telemetryStorageProducer, //TelemetryEvaluation instance - _telemetryStorageProducer, //TelemetryConfiguration instance + _telemetryStorageProducer, // TelemetryEvaluation instance + _telemetryStorageProducer, // TelemetryConfiguration instance flagSetsFilter); - // SyncManager _syncManager = new ConsumerSyncManager(synchronizer); _syncManager.start(); @@ -371,29 +389,31 @@ protected SplitFactoryImpl(SplitClientConfig config) { _gates = new SDKReadinessGates(); _segmentCache = segmentCache; - //SegmentFetcher + // SegmentFetcher SegmentChangeFetcher segmentChangeFetcher = new LocalhostSegmentFetcherNoop(); - if(config.segmentDirectory() != null){ + if (config.segmentDirectory() != null) { segmentChangeFetcher = new LocalhostSegmentChangeFetcher(config.segmentDirectory()); } - _segmentSynchronizationTaskImp = new SegmentSynchronizationTaskImp(segmentChangeFetcher, + _segmentSynchronizationTaskImp = new SegmentSynchronizationTaskImp(segmentChangeFetcher, config.segmentsRefreshRate(), config.numThreadsForSegmentFetch(), segmentCache, _telemetryStorageProducer, _splitCache, - config.getThreadFactory()); + config.getThreadFactory()); // SplitFetcher SplitChangeFetcher splitChangeFetcher = createSplitChangeFetcher(config); SplitParser splitParser = new SplitParser(); - _splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCache, _telemetryStorageProducer, flagSetsFilter); + _splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCache, _telemetryStorageProducer, + flagSetsFilter); // SplitSynchronizationTask - _splitSynchronizationTask = new SplitSynchronizationTask(_splitFetcher, splitCache, config.featuresRefreshRate(), config.getThreadFactory()); + _splitSynchronizationTask = new SplitSynchronizationTask(_splitFetcher, splitCache, + config.featuresRefreshRate(), config.getThreadFactory()); _impressionsManager = new ImpressionsManager.NoOpImpressionsManager(); @@ -413,12 +433,13 @@ protected SplitFactoryImpl(SplitClientConfig config) { config, _gates, _evaluator, - _telemetryStorageProducer, //TelemetryEvaluation instance - _telemetryStorageProducer, //TelemetryConfiguration instance + _telemetryStorageProducer, // TelemetryEvaluation instance + _telemetryStorageProducer, // TelemetryConfiguration instance flagSetsFilter); // Synchronizer - Synchronizer synchronizer = new LocalhostSynchronizer(splitTasks, _splitFetcher, config.localhostRefreshEnabled()); + Synchronizer synchronizer = new LocalhostSynchronizer(splitTasks, _splitFetcher, + config.localhostRefreshEnabled()); // SplitManager _manager = new SplitManagerImpl(splitCache, config, _gates, _telemetryStorageProducer); @@ -456,9 +477,9 @@ public synchronized void destroy() { _log.info("Shutdown called for split"); _syncManager.shutdown(); _log.info("Successful shutdown of syncManager"); - if(OperationMode.STANDALONE.equals(_operationMode)) { + if (OperationMode.STANDALONE.equals(_operationMode)) { _telemetryStorageProducer.recordSessionLength(System.currentTimeMillis() - _startTime); - } else if(OperationMode.CONSUMER.equals(_operationMode)) { + } else if (OperationMode.CONSUMER.equals(_operationMode)) { _userStorageWrapper.disconnect(); } } catch (IOException e) { @@ -473,7 +494,8 @@ public boolean isDestroyed() { return isTerminated; } - private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) + private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, + SDKMetadata sdkMetadata) throws URISyntaxException { SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() .setSslContext(SSLContexts.createSystemDefault()) @@ -498,8 +520,6 @@ private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClient HttpClientBuilder httpClientbuilder = HttpClients.custom() .setConnectionManager(cm) .setDefaultRequestConfig(requestConfig) - .addRequestInterceptorLast(AuthorizationInterceptorFilter.instance(apiToken)) - .addRequestInterceptorLast(SdkMetadataInterceptorFilter.instance(sdkMetadata)) .addRequestInterceptorLast(new GzipEncoderRequestInterceptor()) .addResponseInterceptorLast((new GzipDecoderResponseInterceptor())); @@ -508,10 +528,14 @@ private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClient httpClientbuilder = setupProxy(httpClientbuilder, config); } - return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.customHeaderDecorator())); + return SplitHttpClientImpl.create(httpClientbuilder.build(), + new RequestDecorator(config.customHeaderDecorator()), + apiToken, + sdkMetadata); } - private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) { + private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, + SDKMetadata sdkMetadata) { RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(Timeout.ofMilliseconds(SSE_CONNECT_TIMEOUT)) .build(); @@ -553,17 +577,20 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, _log.debug("Proxy setup using credentials"); BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); AuthScope siteScope = new AuthScope(config.proxy().getHostName(), config.proxy().getPort()); - Credentials siteCreds = new UsernamePasswordCredentials(config.proxyUsername(), config.proxyPassword().toCharArray()); + Credentials siteCreds = new UsernamePasswordCredentials(config.proxyUsername(), + config.proxyPassword().toCharArray()); credsProvider.setCredentials(siteScope, siteCreds); httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - return httpClientbuilder; + return httpClientbuilder; } - private SegmentSynchronizationTaskImp buildSegments(SplitClientConfig config, SegmentCacheProducer segmentCacheProducer, - SplitCacheConsumer splitCacheConsumer) throws URISyntaxException { - SegmentChangeFetcher segmentChangeFetcher = HttpSegmentChangeFetcher.create(_splitHttpClient, _rootTarget, _telemetryStorageProducer); + private SegmentSynchronizationTaskImp buildSegments(SplitClientConfig config, + SegmentCacheProducer segmentCacheProducer, + SplitCacheConsumer splitCacheConsumer) throws URISyntaxException { + SegmentChangeFetcher segmentChangeFetcher = HttpSegmentChangeFetcher.create(_splitHttpClient, _rootTarget, + _telemetryStorageProducer); return new SegmentSynchronizationTaskImp(segmentChangeFetcher, config.segmentsRefreshRate(), @@ -574,14 +601,17 @@ private SegmentSynchronizationTaskImp buildSegments(SplitClientConfig config, Se config.getThreadFactory()); } - private SplitFetcher buildSplitFetcher(SplitCacheProducer splitCacheProducer, SplitParser splitParser, FlagSetsFilter flagSetsFilter) throws - URISyntaxException { - SplitChangeFetcher splitChangeFetcher = HttpSplitChangeFetcher.create(_splitHttpClient, _rootTarget, _telemetryStorageProducer); - return new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, _telemetryStorageProducer,flagSetsFilter); + private SplitFetcher buildSplitFetcher(SplitCacheProducer splitCacheProducer, SplitParser splitParser, + FlagSetsFilter flagSetsFilter) throws URISyntaxException { + SplitChangeFetcher splitChangeFetcher = HttpSplitChangeFetcher.create(_splitHttpClient, _rootTarget, + _telemetryStorageProducer); + return new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, _telemetryStorageProducer, + flagSetsFilter); } - private ImpressionsManagerImpl buildImpressionsManager(SplitClientConfig config, ImpressionsStorageConsumer impressionsStorageConsumer, - ImpressionsStorageProducer impressionsStorageProducer) throws URISyntaxException { + private ImpressionsManagerImpl buildImpressionsManager(SplitClientConfig config, + ImpressionsStorageConsumer impressionsStorageConsumer, + ImpressionsStorageProducer impressionsStorageProducer) throws URISyntaxException { List impressionListeners = new ArrayList<>(); if (config.integrationsConfig() != null) { config.integrationsConfig().getImpressionsListeners(IntegrationsConfig.Execution.ASYNC).stream() @@ -594,13 +624,15 @@ private ImpressionsManagerImpl buildImpressionsManager(SplitClientConfig config, } ProcessImpressionStrategy processImpressionStrategy = null; ImpressionCounter counter = null; - ImpressionListener listener = !impressionListeners.isEmpty() ? new ImpressionListener.FederatedImpressionListener(impressionListeners) + ImpressionListener listener = !impressionListeners.isEmpty() + ? new ImpressionListener.FederatedImpressionListener(impressionListeners) : null; - switch (config.impressionsMode()){ + switch (config.impressionsMode()) { case OPTIMIZED: counter = new ImpressionCounter(); ImpressionObserver impressionObserver = new ImpressionObserver(config.getLastSeenCacheSize()); - processImpressionStrategy = new ProcessImpressionOptimized(listener != null, impressionObserver, counter, _telemetryStorageProducer); + processImpressionStrategy = new ProcessImpressionOptimized(listener != null, impressionObserver, + counter, _telemetryStorageProducer); break; case DEBUG: impressionObserver = new ImpressionObserver(config.getLastSeenCacheSize()); @@ -611,7 +643,8 @@ private ImpressionsManagerImpl buildImpressionsManager(SplitClientConfig config, processImpressionStrategy = new ProcessImpressionNone(listener != null, _uniqueKeysTracker, counter); break; } - return ImpressionsManagerImpl.instance(config, _telemetryStorageProducer, impressionsStorageConsumer, impressionsStorageProducer, + return ImpressionsManagerImpl.instance(config, _telemetryStorageProducer, impressionsStorageConsumer, + impressionsStorageProducer, _impressionsSender, processImpressionStrategy, counter, listener); } @@ -632,9 +665,10 @@ private SDKMetadata createSdkMetadata(boolean ipAddressEnabled, String splitSdkV } private void manageSdkReady(SplitClientConfig config) { - ExecutorService executorService = buildExecutorService(config.getThreadFactory(), "SPLIT-SDKReadyForConsumer-%d"); + ExecutorService executorService = buildExecutorService(config.getThreadFactory(), + "SPLIT-SDKReadyForConsumer-%d"); executorService.submit(() -> { - while(!_userStorageWrapper.connect()) { + while (!_userStorageWrapper.connect()) { try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { @@ -643,16 +677,18 @@ private void manageSdkReady(SplitClientConfig config) { } } _gates.sdkInternalReady(); - _telemetrySynchronizer.synchronizeConfig(config, System.currentTimeMillis(), ApiKeyCounter.getApiKeyCounterInstance(). - getFactoryInstances(), new ArrayList<>()); + _telemetrySynchronizer.synchronizeConfig(config, System.currentTimeMillis(), + ApiKeyCounter.getApiKeyCounterInstance().getFactoryInstances(), new ArrayList<>()); }); } - private UniqueKeysTracker createUniqueKeysTracker(SplitClientConfig config){ - if (config.impressionsMode().equals(ImpressionsManager.Mode.NONE)){ - int uniqueKeysRefreshRate = config.operationMode().equals(OperationMode.STANDALONE) ? config.uniqueKeysRefreshRateInMemory() + private UniqueKeysTracker createUniqueKeysTracker(SplitClientConfig config) { + if (config.impressionsMode().equals(ImpressionsManager.Mode.NONE)) { + int uniqueKeysRefreshRate = config.operationMode().equals(OperationMode.STANDALONE) + ? config.uniqueKeysRefreshRateInMemory() : config.uniqueKeysRefreshRateRedis(); - return new UniqueKeysTrackerImp(_telemetrySynchronizer, uniqueKeysRefreshRate, config.filterUniqueKeysRefreshRate(), + return new UniqueKeysTrackerImp(_telemetrySynchronizer, uniqueKeysRefreshRate, + config.filterUniqueKeysRefreshRate(), config.getThreadFactory()); } return null; @@ -673,7 +709,7 @@ private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClien inputStreamProvider = new StaticContentInputStreamProvider(inputStream); } try { - switch (fileType){ + switch (fileType) { case JSON: return new JsonLocalhostSplitChangeFetcher(inputStreamProvider); case YAML: @@ -685,10 +721,13 @@ private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClien } } catch (Exception e) { _log.warn(String.format("There was no file named %s found. " + - "We created a split client that returns default treatments for all feature flags for all of your users. " + - "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + - "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + - "considered comments", + "We created a split client that returns default treatments for all feature flags for all of your users. " + + + "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + + + "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + + + "considered comments", splitFile, splitFile), e); } _log.warn(LEGACY_LOG_MESSAGE); @@ -707,4 +746,4 @@ private FileTypeEnum getFileTypeFromFileName(String fileName) { } } -} \ No newline at end of file +} diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index 919fe8920..f6fd19331 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,8 +43,9 @@ public class HttpImpressionsSender implements ImpressionsSender { private final ImpressionsManager.Mode _mode; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; - public static HttpImpressionsSender create(SplitHttpClient client, URI eventsRootEndpoint, ImpressionsManager.Mode mode, - TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { + public static HttpImpressionsSender create(SplitHttpClient client, URI eventsRootEndpoint, + ImpressionsManager.Mode mode, + TelemetryRuntimeProducer telemetryRuntimeProducer) throws URISyntaxException { return new HttpImpressionsSender(client, Utils.appendPath(eventsRootEndpoint, BULK_ENDPOINT_PATH), Utils.appendPath(eventsRootEndpoint, COUNT_ENDPOINT_PATH), @@ -51,8 +53,9 @@ public static HttpImpressionsSender create(SplitHttpClient client, URI eventsRoo telemetryRuntimeProducer); } - private HttpImpressionsSender(SplitHttpClient client, URI impressionBulkTarget, URI impressionCountTarget, ImpressionsManager.Mode mode, - TelemetryRuntimeProducer telemetryRuntimeProducer) { + private HttpImpressionsSender(SplitHttpClient client, URI impressionBulkTarget, URI impressionCountTarget, + ImpressionsManager.Mode mode, + TelemetryRuntimeProducer telemetryRuntimeProducer) { _client = client; _mode = mode; _impressionBulkTarget = impressionBulkTarget; @@ -65,19 +68,21 @@ public void postImpressionsBulk(List impressions) { long initTime = System.currentTimeMillis(); try { HttpEntity entity = Utils.toJsonEntity(impressions); - Map additionalHeader = new HashMap<>(); - additionalHeader.put(IMPRESSIONS_MODE_HEADER, _mode.toString()); - SplitHttpResponse response = _client.post(_impressionBulkTarget, entity, additionalHeader); + Map> additionalHeaders = Collections.singletonMap(IMPRESSIONS_MODE_HEADER, + List.of(_mode.toString())); + SplitHttpResponse response = _client.post(_impressionBulkTarget, entity, additionalHeaders); if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode()); } - _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS, System.currentTimeMillis()); + _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS, + System.currentTimeMillis()); } catch (Throwable t) { _logger.warn("Exception when posting impressions" + impressions, t); } finally { - _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS, System.currentTimeMillis() - initTime); + _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS, + System.currentTimeMillis() - initTime); } } @@ -91,14 +96,16 @@ public void postCounters(HashMap raw) { try { SplitHttpResponse response = _client.post(_impressionCountTarget, - Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw)), - null); + Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw)), + null); if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { _telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, response.statusCode()); } - _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS_COUNT, System.currentTimeMillis() - initTime); - _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT, System.currentTimeMillis()); + _telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS_COUNT, + System.currentTimeMillis() - initTime); + _telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT, + System.currentTimeMillis()); } catch (IOException exc) { _logger.warn("Exception when posting impression counters: ", exc); } diff --git a/client/src/main/java/io/split/service/SplitHttpClient.java b/client/src/main/java/io/split/service/SplitHttpClient.java index 33aa1dbae..1e44a49ba 100644 --- a/client/src/main/java/io/split/service/SplitHttpClient.java +++ b/client/src/main/java/io/split/service/SplitHttpClient.java @@ -1,31 +1,33 @@ package io.split.service; import io.split.engine.common.FetchOptions; -import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.client.dtos.SplitHttpResponse; import org.apache.hc.core5.http.HttpEntity; import java.io.IOException; import java.net.URI; +import java.util.List; import java.util.Map; public interface SplitHttpClient { /** * Wrapper for HTTP get method - * @param uri the URL to be used + * + * @param uri the URL to be used * @param options The FetchOptions object that contains headers. * @return The response structure SplitHttpResponse */ - public SplitHttpResponse get(URI uri, FetchOptions options, Map additionalHeaders); + public SplitHttpResponse get(URI uri, FetchOptions options, Map> additionalHeaders); + /** * Wrapper for HTTP post method - * @param uri the URL to be used - * @param entity HttpEntity object that has The body load + * + * @param uri the URL to be used + * @param entity HttpEntity object that has The body load * @param additionalHeaders Any additional headers to be added. * @return The response structure SplitHttpResponse */ - public SplitHttpResponse post - (URI uri, - HttpEntity entity, - Map additionalHeaders) throws IOException; + public SplitHttpResponse post(URI uri, + HttpEntity entity, + Map> additionalHeaders) throws IOException; } diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 3a57c0fe8..1c28ebbd2 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -1,6 +1,7 @@ package io.split.service; import io.split.client.RequestDecorator; +import io.split.client.utils.SDKMetadata; import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; import io.split.client.dtos.SplitHttpResponse; @@ -16,60 +17,78 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import org.apache.hc.core5.http.HttpRequest; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Map; public final class SplitHttpClientImpl implements SplitHttpClient { + private static final Logger _log = LoggerFactory.getLogger(SplitHttpClient.class); private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; + private static final String HEADER_API_KEY = "Authorization"; + private static final String HEADER_CLIENT_KEY = "SplitSDKClientKey"; + private static final String HEADER_CLIENT_MACHINE_NAME = "SplitSDKMachineName"; + private static final String HEADER_CLIENT_MACHINE_IP = "SplitSDKMachineIP"; + private static final String HEADER_CLIENT_VERSION = "SplitSDKVersion"; + private final CloseableHttpClient _client; private final RequestDecorator _requestDecorator; + private final String _apikey; + private final SDKMetadata _metadata; - public static SplitHttpClientImpl create( - CloseableHttpClient client, - RequestDecorator requestDecorator - ) throws URISyntaxException { - return new SplitHttpClientImpl(client, requestDecorator); + public static SplitHttpClientImpl create(CloseableHttpClient client, + RequestDecorator requestDecorator, + String apikey, + SDKMetadata metadata) throws URISyntaxException { + return new SplitHttpClientImpl(client, requestDecorator, apikey, metadata); } - private SplitHttpClientImpl - (CloseableHttpClient client, - RequestDecorator requestDecorator) { + private SplitHttpClientImpl(CloseableHttpClient client, + RequestDecorator requestDecorator, + String apikey, + SDKMetadata metadata) { _client = client; _requestDecorator = requestDecorator; + _apikey = apikey; + _metadata = metadata; } - public SplitHttpResponse get(URI uri, FetchOptions options, Map additionalHeaders) { + public SplitHttpResponse get(URI uri, FetchOptions options, Map> additionalHeaders) { CloseableHttpResponse response = null; try { HttpGet request = new HttpGet(uri); + setBasicHeaders(request); if (additionalHeaders != null) { - for (Map.Entry entry : additionalHeaders.entrySet()) { - request.addHeader(entry.getKey().toString(), entry.getValue()); + for (Map.Entry> entry : additionalHeaders.entrySet()) { + request.addHeader(entry.getKey(), entry.getValue()); } } - if(options.cacheControlHeadersEnabled()) { + if (options.cacheControlHeadersEnabled()) { request.setHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE); } - request = (HttpGet) _requestDecorator.decorateHeaders(request); + + _requestDecorator.decorateHeaders(request); response = _client.execute(request); if (_log.isDebugEnabled()) { - _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), response.getCode())); + _log.debug(String.format("[%s] %s. Status code: %s", request.getMethod(), uri.toURL(), + response.getCode())); } String statusMessage = ""; if (response.getCode() < HttpStatus.SC_OK || response.getCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { - _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode() , response.getReasonPhrase())); + _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode(), + response.getReasonPhrase())); statusMessage = response.getReasonPhrase(); } return new SplitHttpResponse(response.getCode(), - statusMessage, - EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8), - response.getHeaders()); + statusMessage, + EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8), + response.getHeaders()); } catch (Exception e) { throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e); } finally { @@ -77,16 +96,16 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map } } - public SplitHttpResponse post - (URI uri, - HttpEntity entity, - Map additionalHeaders) throws IOException { + public SplitHttpResponse post(URI uri, HttpEntity entity, Map> additionalHeaders) + throws IOException { + CloseableHttpResponse response = null; try { HttpPost request = new HttpPost(uri); + setBasicHeaders(request); if (additionalHeaders != null) { - for (Map.Entry entry : additionalHeaders.entrySet()) { - request.addHeader(entry.getKey().toString(), entry.getValue()); + for (Map.Entry> entry : additionalHeaders.entrySet()) { + request.addHeader(entry.getKey(), entry.getValue()); } } request.setEntity(entity); @@ -97,7 +116,8 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map String statusMessage = ""; if (response.getCode() < HttpStatus.SC_OK || response.getCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { statusMessage = response.getReasonPhrase(); - _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode(), response.getReasonPhrase())); + _log.warn(String.format("Response status was: %s. Reason: %s", response.getCode(), + response.getReasonPhrase())); } return new SplitHttpResponse(response.getCode(), statusMessage, "", response.getHeaders()); } catch (Exception e) { @@ -106,4 +126,14 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map Utils.forceClose(response); } } + + private void setBasicHeaders(HttpRequest request) { + request.setHeader(HEADER_API_KEY, "Bearer " + _apikey); + request.setHeader(HEADER_CLIENT_VERSION, _metadata.getSdkVersion()); + request.setHeader(HEADER_CLIENT_MACHINE_IP, _metadata.getMachineIp()); + request.setHeader(HEADER_CLIENT_MACHINE_NAME, _metadata.getMachineName()); + request.setHeader(HEADER_CLIENT_KEY, _apikey.length() > 4 + ? _apikey.substring(_apikey.length() - 4) + : _apikey); + } } diff --git a/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java index 07aae12ea..a8113d8ef 100644 --- a/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSegmentChangeFetcherTest.java @@ -2,6 +2,7 @@ import io.split.TestHelper; import io.split.client.dtos.SegmentChange; +import io.split.client.utils.SDKMetadata; import io.split.engine.common.FetchOptions; import io.split.engine.metrics.Metrics; import io.split.service.SplitHttpClient; @@ -33,51 +34,68 @@ public class HttpSegmentChangeFetcherTest { public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://api.split.io/api/segmentChanges"))); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://api.split.io/api/segmentChanges"))); } @Test public void testCustomURLNoPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); } @Test public void testCustomURLAppendingPath() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split/"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); } @Test public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/segmentChanges"))); } @Test - public void testFetcherWithSpecialCharacters() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testFetcherWithSpecialCharacters() throws URISyntaxException, IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://api.split.io/api/segmentChanges"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("segment-change-special-chatacters.json", HttpStatus.SC_OK); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("segment-change-special-chatacters.json", + HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", + metadata()); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + TELEMETRY_STORAGE); SegmentChange change = fetcher.fetch("some_segment", 1234567, new FetchOptions.Builder().build()); @@ -89,7 +107,8 @@ public void testFetcherWithSpecialCharacters() throws URISyntaxException, IOExce } @Test - public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://api.split.io"); HttpEntity entityMock = Mockito.mock(HttpEntity.class); @@ -101,15 +120,18 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); - when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); + when(httpClientMock.execute(requestCaptor.capture())) + .thenReturn(TestHelper.classicResponseToCloseableMock(response)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryStorage.class)); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + Mockito.mock(TelemetryStorage.class)); fetcher.fetch("someSegment", -1, new FetchOptions.Builder().targetChangeNumber(123).build()); - fetcher.fetch("someSegment2",-1, new FetchOptions.Builder().build()); + fetcher.fetch("someSegment2", -1, new FetchOptions.Builder().build()); List captured = requestCaptor.getAllValues(); Assert.assertEquals(captured.size(), 2); Assert.assertTrue(captured.get(0).getUri().toString().contains("till=123")); @@ -117,7 +139,8 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept } @Test(expected = IllegalStateException.class) - public void testFetcherWithError() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testFetcherWithError() throws IOException, URISyntaxException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://api.split.io"); HttpEntity entityMock = Mockito.mock(HttpEntity.class); @@ -129,13 +152,20 @@ public void testFetcherWithError() throws IOException, URISyntaxException, Illeg ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); - when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); + when(httpClientMock.execute(requestCaptor.capture())) + .thenReturn(TestHelper.classicResponseToCloseableMock(response)); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryStorage.class)); + HttpSegmentChangeFetcher fetcher = HttpSegmentChangeFetcher.create(splitHtpClient, rootTarget, + Mockito.mock(TelemetryStorage.class)); fetcher.fetch("someSegment", -1, new FetchOptions.Builder().build()); } + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } } diff --git a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java index c73e22fd1..8d18f8456 100644 --- a/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java @@ -3,6 +3,7 @@ import io.split.TestHelper; import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; +import io.split.client.utils.SDKMetadata; import io.split.engine.common.FetchOptions; import io.split.engine.metrics.Metrics; import io.split.service.SplitHttpClient; @@ -36,12 +37,14 @@ public class HttpSplitChangeFetcherTest { private static final TelemetryStorage TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); + @Test public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); Metrics.NoopMetrics metrics = new Metrics.NoopMetrics(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://api.split.io/api/splitChanges", fetcher.getTarget().toString()); @@ -51,7 +54,8 @@ public void testDefaultURL() throws URISyntaxException { public void testCustomURLNoPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://kubernetesturl.com/split/api/splitChanges", fetcher.getTarget().toString()); @@ -61,7 +65,8 @@ public void testCustomURLNoPathNoBackslash() throws URISyntaxException { public void testCustomURLAppendingPath() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split/"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://kubernetesturl.com/split/api/splitChanges", fetcher.getTarget().toString()); } @@ -70,17 +75,22 @@ public void testCustomURLAppendingPath() throws URISyntaxException { public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); Assert.assertEquals("https://kubernetesturl.com/split/api/splitChanges", fetcher.getTarget().toString()); } @Test - public void testFetcherWithSpecialCharacters() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testFetcherWithSpecialCharacters() throws URISyntaxException, InvocationTargetException, + NoSuchMethodException, IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_OK); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", + HttpStatus.SC_OK); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", + metadata()); HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, TELEMETRY_STORAGE); @@ -99,11 +109,13 @@ public void testFetcherWithSpecialCharacters() throws URISyntaxException, Invoca } @Test - public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://api.split.io"); HttpEntity entityMock = Mockito.mock(HttpEntity.class); - when(entityMock.getContent()).thenReturn(new ByteArrayInputStream("{\"till\": 1}".getBytes(StandardCharsets.UTF_8))); + when(entityMock.getContent()) + .thenReturn(new ByteArrayInputStream("{\"till\": 1}".getBytes(StandardCharsets.UTF_8))); ClassicHttpResponse response = Mockito.mock(ClassicHttpResponse.class); when(response.getCode()).thenReturn(200); when(response.getEntity()).thenReturn(entityMock); @@ -111,10 +123,13 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + when(httpClientMock.execute(requestCaptor.capture())) + .thenReturn(TestHelper.classicResponseToCloseableMock(response)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, + Mockito.mock(TelemetryRuntimeProducer.class)); fetcher.fetch(-1, new FetchOptions.Builder().targetChangeNumber(123).build()); fetcher.fetch(-1, new FetchOptions.Builder().build()); @@ -128,11 +143,13 @@ public void testFetcherWithCDNBypassOption() throws IOException, URISyntaxExcept public void testRandomNumberGeneration() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, + Mockito.mock(TelemetryRuntimeProducer.class)); Set seen = new HashSet<>(); - long min = (long)Math.pow(2, 63) * (-1); + long min = (long) Math.pow(2, 63) * (-1); final long total = 10000000; for (long x = 0; x < total; x++) { long r = fetcher.makeRandomTill(); @@ -144,23 +161,28 @@ public void testRandomNumberGeneration() throws URISyntaxException { } @Test(expected = IllegalStateException.class) - public void testURLTooLong() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testURLTooLong() throws IOException, URISyntaxException, IllegalAccessException, NoSuchMethodException, + InvocationTargetException { URI rootTarget = URI.create("https://api.split.io"); HttpEntity entityMock = Mockito.mock(HttpEntity.class); - when(entityMock.getContent()).thenReturn(new ByteArrayInputStream("{\"till\": 1}".getBytes(StandardCharsets.UTF_8))); + when(entityMock.getContent()) + .thenReturn(new ByteArrayInputStream("{\"till\": 1}".getBytes(StandardCharsets.UTF_8))); ClassicHttpResponse response = Mockito.mock(ClassicHttpResponse.class); when(response.getCode()).thenReturn(414); when(response.getEntity()).thenReturn(entityMock); when(response.getHeaders()).thenReturn(new Header[0]); CloseableHttpClient httpClientMock = Mockito.mock(CloseableHttpClient.class); ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); - when(httpClientMock.execute(requestCaptor.capture())).thenReturn(TestHelper.classicResponseToCloseableMock(response)); + when(httpClientMock.execute(requestCaptor.capture())) + .thenReturn(TestHelper.classicResponseToCloseableMock(response)); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, Mockito.mock(TelemetryRuntimeProducer.class)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); + HttpSplitChangeFetcher fetcher = HttpSplitChangeFetcher.create(splitHtpClient, rootTarget, + Mockito.mock(TelemetryRuntimeProducer.class)); List sets = new ArrayList(); - for (Integer i=0; i<100; i++) { + for (Integer i = 0; i < 100; i++) { sets.add("set" + i.toString()); } String result = sets.stream() @@ -168,4 +190,9 @@ public void testURLTooLong() throws IOException, URISyntaxException, IllegalAcce .collect(Collectors.joining(",", "", "")); fetcher.fetch(-1, new FetchOptions.Builder().flagSetsFilter(result).cacheControlHeaders(false).build()); } -} \ No newline at end of file + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } + +} diff --git a/client/src/test/java/io/split/client/events/EventsSenderTest.java b/client/src/test/java/io/split/client/events/EventsSenderTest.java index b53a7fd9e..c9ddb754b 100644 --- a/client/src/test/java/io/split/client/events/EventsSenderTest.java +++ b/client/src/test/java/io/split/client/events/EventsSenderTest.java @@ -2,13 +2,12 @@ import io.split.TestHelper; import io.split.client.RequestDecorator; -import io.split.client.dtos.Event; +import io.split.client.utils.SDKMetadata; import io.split.service.SplitHttpClient; import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.TelemetryRuntimeProducer; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.core5.http.HttpStatus; -import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; @@ -21,12 +20,14 @@ public class EventsSenderTest { - private static final TelemetryRuntimeProducer TELEMETRY_RUNTIME_CONSUMER = Mockito.mock(TelemetryRuntimeProducer.class); + private static final TelemetryRuntimeProducer TELEMETRY_RUNTIME_CONSUMER = Mockito + .mock(TelemetryRuntimeProducer.class); private static final CloseableHttpClient CLOSEABLE_HTTP_CLIENT = Mockito.mock(CloseableHttpClient.class); @Test public void testDefaultURL() throws URISyntaxException { - SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, + new RequestDecorator(null), "qwerty", metadata()); URI rootTarget = URI.create("https://api.split.io"); EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://api.split.io/api/events/bulk", fetcher.getBulkEndpoint().toString()); @@ -34,7 +35,8 @@ public void testDefaultURL() throws URISyntaxException { @Test public void testCustomURLNoPathNoBackslash() throws URISyntaxException { - SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, + new RequestDecorator(null), "qwerty", metadata()); URI rootTarget = URI.create("https://kubernetesturl.com"); EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/api/events/bulk", fetcher.getBulkEndpoint().toString()); @@ -42,7 +44,8 @@ public void testCustomURLNoPathNoBackslash() throws URISyntaxException { @Test public void testCustomURLAppendingPath() throws URISyntaxException { - SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, + new RequestDecorator(null), "qwerty", metadata()); URI rootTarget = URI.create("https://kubernetesturl.com/split/"); EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/split/api/events/bulk", fetcher.getBulkEndpoint().toString()); @@ -50,18 +53,27 @@ public void testCustomURLAppendingPath() throws URISyntaxException { @Test public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { - SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, new RequestDecorator(null)); + SplitHttpClient SPLIT_HTTP_CLIENT = SplitHttpClientImpl.create(CLOSEABLE_HTTP_CLIENT, + new RequestDecorator(null), "qwerty", metadata()); URI rootTarget = URI.create("https://kubernetesturl.com/split"); EventsSender fetcher = EventsSender.create(SPLIT_HTTP_CLIENT, rootTarget, TELEMETRY_RUNTIME_CONSUMER); Assert.assertEquals("https://kubernetesturl.com/split/api/events/bulk", fetcher.getBulkEndpoint().toString()); } + @Test - public void testHttpError() throws URISyntaxException, IOException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { + public void testHttpError() throws URISyntaxException, IOException, InvocationTargetException, + IllegalAccessException, NoSuchMethodException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_BAD_REQUEST); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); EventsSender sender = EventsSender.create(splitHtpClient, rootTarget, TELEMETRY_RUNTIME_CONSUMER); // should not raise exception sender.sendEvents(new ArrayList<>()); } -} \ No newline at end of file + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } + +} diff --git a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java index 29412da1c..d2d3373ad 100644 --- a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java +++ b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java @@ -7,6 +7,7 @@ import io.split.client.dtos.ImpressionCount; import io.split.client.dtos.KeyImpression; import io.split.client.dtos.TestImpressions; +import io.split.client.utils.SDKMetadata; import io.split.service.SplitHttpClient; import io.split.service.SplitHttpClientImpl; import io.split.telemetry.storage.InMemoryTelemetryStorage; @@ -46,48 +47,63 @@ public class HttpImpressionsSenderTest { public void testDefaultURL() throws URISyntaxException { URI rootTarget = URI.create("https://api.split.io"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://api.split.io/api/testImpressions/bulk"))); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://api.split.io/api/testImpressions/bulk"))); } @Test public void testCustomURLNoPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/api/testImpressions/bulk"))); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://kubernetesturl.com/api/testImpressions/bulk"))); } @Test public void testCustomURLAppendingPath() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split/"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/testImpressions/bulk"))); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/testImpressions/bulk"))); } @Test public void testCustomURLAppendingPathNoBackslash() throws URISyntaxException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = HttpClients.custom().build(); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); - HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); - Assert.assertThat(fetcher.getTarget().toString(), Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/testImpressions/bulk"))); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); + HttpImpressionsSender fetcher = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + Assert.assertThat(fetcher.getTarget().toString(), + Matchers.is(Matchers.equalTo("https://kubernetesturl.com/split/api/testImpressions/bulk"))); } @Test - public void testImpressionCountsEndpointOptimized() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testImpressionCountsEndpointOptimized() throws URISyntaxException, IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); // Send counters - HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); HashMap toSend = new HashMap<>(); toSend.put(new ImpressionCounter.Key("test1", 0), 4); toSend.put(new ImpressionCounter.Key("test2", 0), 5); @@ -97,7 +113,8 @@ public void testImpressionCountsEndpointOptimized() throws URISyntaxException, I ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClient).execute(captor.capture()); HttpUriRequest request = captor.getValue(); - assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/count")))); + assertThat(request.getUri(), + is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/count")))); assertThat(request.getHeaders().length, is(0)); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; @@ -110,15 +127,18 @@ public void testImpressionCountsEndpointOptimized() throws URISyntaxException, I } @Test - public void testImpressionCountsEndpointDebug() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testImpressionCountsEndpointDebug() throws URISyntaxException, IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); // Send counters - HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); HashMap toSend = new HashMap<>(); toSend.put(new ImpressionCounter.Key("test1", 0), 4); toSend.put(new ImpressionCounter.Key("test2", 0), 5); @@ -129,32 +149,35 @@ public void testImpressionCountsEndpointDebug() throws URISyntaxException, IOExc } @Test - public void testImpressionBulksEndpoint() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testImpressionBulksEndpoint() throws URISyntaxException, IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); - HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); // Send impressions List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)) - )), new TestImpressions("t2", Arrays.asList( - KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null)) - ))); + KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)))), + new TestImpressions("t2", Arrays.asList( + KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null))))); sender.postImpressionsBulk(toSend); // Capture outgoing request and validate it ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClient).execute(captor.capture()); HttpUriRequest request = captor.getValue(); - assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); + assertThat(request.getUri(), + is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); assertThat(request.getHeaders().length, is(1)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("OPTIMIZED"))); assertThat(request, instanceOf(HttpPost.class)); @@ -167,9 +190,11 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException // Do the same flow for imrpessionsMode = debug CloseableHttpClient httpClientDebugMode = TestHelper.mockHttpClient("", HttpStatus.SC_OK); - SplitHttpClient splitHtpClient2 = SplitHttpClientImpl.create(httpClientDebugMode, new RequestDecorator(null)); + SplitHttpClient splitHtpClient2 = SplitHttpClientImpl.create(httpClientDebugMode, new RequestDecorator(null), + "qwerty", metadata()); - sender = HttpImpressionsSender.create(splitHtpClient2, rootTarget, ImpressionsManager.Mode.DEBUG, TELEMETRY_STORAGE); + sender = HttpImpressionsSender.create(splitHtpClient2, rootTarget, ImpressionsManager.Mode.DEBUG, + TELEMETRY_STORAGE); sender.postImpressionsBulk(toSend); captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClientDebugMode).execute(captor.capture()); @@ -179,13 +204,21 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException } @Test - public void testHttpError() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testHttpError() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, + InvocationTargetException { URI rootTarget = URI.create("https://kubernetesturl.com/split"); CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_BAD_REQUEST); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); - HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); + HttpImpressionsSender sender = HttpImpressionsSender.create(splitHtpClient, rootTarget, + ImpressionsManager.Mode.OPTIMIZED, TELEMETRY_STORAGE); // Should not raise exception sender.postImpressionsBulk(new ArrayList<>()); sender.postCounters(new HashMap<>()); } + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } + } diff --git a/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java b/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java index 5ecfd1a92..f5dd0b342 100644 --- a/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java +++ b/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java @@ -2,6 +2,7 @@ import io.split.TestHelper; import io.split.client.RequestDecorator; +import io.split.client.utils.SDKMetadata; import io.split.engine.sse.dtos.AuthenticationResponse; import io.split.service.SplitHttpClient; import io.split.service.SplitHttpClientImpl; @@ -26,11 +27,15 @@ public class AuthApiClientTest { public void setUp() { TELEMETRY_STORAGE = Mockito.mock(InMemoryTelemetryStorage.class); } + @Test - public void authenticateWithPushEnabledShouldReturnSuccess() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-enabled.json", HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); - AuthApiClient authApiClient = new AuthApiClientImp( "www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); + public void authenticateWithPushEnabledShouldReturnSuccess() throws IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, URISyntaxException { + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-enabled.json", + HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertTrue(result.isPushEnabled()); @@ -40,16 +45,20 @@ public void authenticateWithPushEnabledShouldReturnSuccess() throws IOException, Assert.assertTrue(result.getExpiration() > 0); Mockito.verify(TELEMETRY_STORAGE, Mockito.times(1)).recordTokenRefreshes(); Mockito.verify(TELEMETRY_STORAGE, Mockito.times(1)).recordSyncLatency(Mockito.anyObject(), Mockito.anyLong()); - Mockito.verify(TELEMETRY_STORAGE, Mockito.times(1)).recordSuccessfulSync(Mockito.anyObject(), Mockito.anyLong()); + Mockito.verify(TELEMETRY_STORAGE, Mockito.times(1)).recordSuccessfulSync(Mockito.anyObject(), + Mockito.anyLong()); } @Test - public void authenticateWithPushEnabledWithWrongTokenShouldReturnError() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-enabled-wrong-token.json", HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + public void authenticateWithPushEnabledWithWrongTokenShouldReturnError() throws IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, URISyntaxException { + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-enabled-wrong-token.json", + HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); - AuthApiClient authApiClient = new AuthApiClientImp( "www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); Assert.assertFalse(result.isPushEnabled()); @@ -60,9 +69,12 @@ public void authenticateWithPushEnabledWithWrongTokenShouldReturnError() throws } @Test - public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-disabled.json", HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, URISyntaxException { + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-disabled.json", + HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); @@ -74,9 +86,11 @@ public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException } @Test - public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { + public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("", HttpStatus.SC_INTERNAL_SERVER_ERROR); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); @@ -88,10 +102,12 @@ public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOExcepti } @Test - public void authenticateServerBadRequestShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { + public void authenticateServerBadRequestShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("", HttpStatus.SC_BAD_REQUEST); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); @@ -102,9 +118,11 @@ public void authenticateServerBadRequestShouldReturnErrorWithoutRetry() throws I } @Test - public void authenticateServerUnauthorizedShouldReturnErrorWithoutRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { + public void authenticateServerUnauthorizedShouldReturnErrorWithoutRetry() throws IOException, + IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("", HttpStatus.SC_UNAUTHORIZED); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); AuthenticationResponse result = authApiClient.Authenticate(); @@ -115,4 +133,9 @@ public void authenticateServerUnauthorizedShouldReturnErrorWithoutRetry() throws Assert.assertFalse(result.isRetry()); Mockito.verify(TELEMETRY_STORAGE, Mockito.times(1)).recordAuthRejections(); } + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } + } diff --git a/client/src/test/java/io/split/service/HttpPostImpTest.java b/client/src/test/java/io/split/service/HttpPostImpTest.java index 64baa28d2..6d72bcb2c 100644 --- a/client/src/test/java/io/split/service/HttpPostImpTest.java +++ b/client/src/test/java/io/split/service/HttpPostImpTest.java @@ -2,6 +2,7 @@ import io.split.TestHelper; import io.split.client.RequestDecorator; +import io.split.client.utils.SDKMetadata; import io.split.telemetry.domain.enums.HttpParamsWrapper; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryStorage; @@ -16,31 +17,42 @@ import java.net.URI; import java.net.URISyntaxException; -public class HttpPostImpTest{ +public class HttpPostImpTest { private static final String URL = "www.split.io"; @Test - public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException { - CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null)); + public void testPostWith200() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, + IOException, URISyntaxException { + CloseableHttpClient client = TestHelper.mockHttpClient(URL, HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null), "qwerty", + metadata()); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); Assert.assertNotEquals(0, telemetryStorage.getLastSynchronization().get_telemetry()); - Assert.assertEquals(1, telemetryStorage.popHTTPLatencies().get_telemetry().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + telemetryStorage.popHTTPLatencies().get_telemetry().stream().mapToInt(Long::intValue).sum()); } @Test - public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException { - CloseableHttpClient client =TestHelper.mockHttpClient(URL, HttpStatus.SC_CLIENT_ERROR); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null)); + public void testPostWith400() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, + IOException, URISyntaxException { + CloseableHttpClient client = TestHelper.mockHttpClient(URL, HttpStatus.SC_CLIENT_ERROR); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(client, new RequestDecorator(null), "qwerty", + metadata()); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); HttpPostImp httpPostImp = new HttpPostImp(splitHttpClient, telemetryStorage); httpPostImp.post(URI.create(URL), new Object(), "Metrics", HttpParamsWrapper.TELEMETRY); Mockito.verify(client, Mockito.times(1)).execute(Mockito.any()); - Assert.assertEquals(1, telemetryStorage.popHTTPErrors().get_telemetry().get(Long.valueOf(HttpStatus.SC_CLIENT_ERROR)).intValue()); + Assert.assertEquals(1, telemetryStorage.popHTTPErrors().get_telemetry() + .get(Long.valueOf(HttpStatus.SC_CLIENT_ERROR)).intValue()); } -} \ No newline at end of file + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } + +} diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index 9a1af3b24..4e4f170a1 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -7,6 +7,7 @@ import io.split.client.dtos.*; import io.split.client.impressions.Impression; import io.split.client.utils.Json; +import io.split.client.utils.SDKMetadata; import io.split.client.utils.Utils; import io.split.engine.common.FetchOptions; import io.split.service.SplitHttpClient; @@ -36,14 +37,15 @@ public class HttpSplitClientTest { @Test - public void testGetWithSpecialCharacters() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testGetWithSpecialCharacters() throws URISyntaxException, InvocationTargetException, + NoSuchMethodException, IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_OK); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", + HttpStatus.SC_OK); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); - Map additionalHeaders = new HashMap<>(); - additionalHeaders.put("AdditionalHeader", "add"); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator, "qwerty", metadata()); + Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", List.of("add")); SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders); @@ -70,86 +72,103 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation } @Test - public void testGetError() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testGetError() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, + IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", + HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator, "qwerty", metadata()); SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), null); Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (long) splitHttpResponse.statusCode()); } @Test(expected = IllegalStateException.class) - public void testException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, + IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", + HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = null; - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator, "qwerty", metadata()); splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), null); } @Test - public void testPost() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + public void testPost() throws URISyntaxException, IOException, IllegalAccessException, NoSuchMethodException, + InvocationTargetException { URI rootTarget = URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk"); // Setup response mock CloseableHttpClient httpClient = TestHelper.mockHttpClient("", HttpStatus.SC_OK); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, decorator); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClient, decorator, "qwerty", metadata()); // Send impressions List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)) - )), new TestImpressions("t2", Arrays.asList( - KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null)) - ))); - Map additionalHeaders = new HashMap<>(); - additionalHeaders.put("SplitSDKImpressionsMode", "OPTIMIZED"); - SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders); + KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)))), + new TestImpressions("t2", Arrays.asList( + KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null))))); + + Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", List.of("add")); + SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), + additionalHeaders); // Capture outgoing request and validate it ArgumentCaptor captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClient).execute(captor.capture()); HttpUriRequest request = captor.getValue(); - assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); + assertThat(request.getUri(), + is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); assertThat(request.getHeaders().length, is(1)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("OPTIMIZED"))); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; InputStreamReader reader = new InputStreamReader(asPostRequest.getEntity().getContent()); Gson gson = new Gson(); - List payload = gson.fromJson(reader, new TypeToken>() { }.getType()); + List payload = gson.fromJson(reader, new TypeToken>() { + }.getType()); assertThat(payload.size(), is(equalTo(2))); - Assert.assertEquals(200,(long) splitHttpResponse.statusCode()); + Assert.assertEquals(200, (long) splitHttpResponse.statusCode()); } @Test - public void testPosttNoExceptionOnHttpErrorCode() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testPosttNoExceptionOnHttpErrorCode() throws URISyntaxException, InvocationTargetException, + NoSuchMethodException, IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", + HttpStatus.SC_INTERNAL_SERVER_ERROR); RequestDecorator decorator = new RequestDecorator(null); - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator); - SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null); + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator, "qwerty", metadata()); + SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, + Utils.toJsonEntity(Arrays.asList(new String[] { "A", "B", "C", "D" })), null); Assert.assertEquals(500, (long) splitHttpResponse.statusCode()); } @Test(expected = IOException.class) - public void testPosttException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException { + public void testPosttException() throws URISyntaxException, InvocationTargetException, NoSuchMethodException, + IllegalAccessException, IOException { URI rootTarget = URI.create("https://api.split.io/splitChanges?since=1234567"); - CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", HttpStatus.SC_INTERNAL_SERVER_ERROR); + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("split-change-special-characters.json", + HttpStatus.SC_INTERNAL_SERVER_ERROR); + + SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, null, "qwerty", metadata()); + splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList(new String[] { "A", "B", "C", "D" })), null); + } - SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, null); - splitHtpClient.post(rootTarget, Utils.toJsonEntity(Arrays.asList( new String[] { "A", "B", "C", "D" })), null); + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); } -} \ No newline at end of file + +} diff --git a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java index f005173e3..31019aa85 100644 --- a/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java +++ b/client/src/test/java/io/split/telemetry/synchronizer/TelemetryInMemorySubmitterTest.java @@ -3,6 +3,7 @@ import io.split.TestHelper; import io.split.client.RequestDecorator; import io.split.client.dtos.UniqueKeys; +import io.split.client.utils.SDKMetadata; import io.split.service.SplitHttpClient; import io.split.service.SplitHttpClientImpl; import io.split.storages.SegmentCacheConsumer; @@ -47,21 +48,24 @@ public class TelemetryInMemorySubmitterTest { public static final String TELEMETRY_ENDPOINT = "https://telemetry.split.io/api/v1"; @Test - public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException { + public void testSynchronizeConfig() throws URISyntaxException, NoSuchMethodException, IOException, + IllegalAccessException, InvocationTargetException { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); SplitClientConfig splitClientConfig = SplitClientConfig.builder().build(); - telemetrySynchronizer.synchronizeConfig(splitClientConfig, 100l, new HashMap(), new ArrayList()); + telemetrySynchronizer.synchronizeConfig(splitClientConfig, 100l, new HashMap(), + new ArrayList()); Mockito.verify(httpClient, Mockito.times(1)).execute(Mockito.any()); } - @Test public void testSynchronizeStats() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); telemetrySynchronizer.synchronizeStats(); @@ -71,7 +75,8 @@ public void testSynchronizeStats() throws Exception { @Test public void testSynchronizeUniqueKeys() throws Exception { CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); TelemetrySynchronizer telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); List keys = new ArrayList<>(); @@ -86,7 +91,8 @@ public void testSynchronizeUniqueKeys() throws Exception { } @Test - public void testConfig() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException, URISyntaxException, NoSuchFieldException { + public void testConfig() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, + IOException, URISyntaxException, NoSuchFieldException { ApiKeyCounter.getApiKeyCounterInstance().clearApiKeys(); ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY); ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY); @@ -95,9 +101,11 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException ApiKeyCounter.getApiKeyCounterInstance().add(SECOND_KEY); TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); - SplitClientConfig splitClientConfig = SplitClientConfig.builder().flagSetsFilter(Arrays.asList("a", "_b", "a", "a", "c", "d", "_d")).build(); + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .flagSetsFilter(Arrays.asList("a", "_b", "a", "a", "c", "d", "_d")).build(); populateConfig(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); telemetryStorageConsumer.setAccessible(true); @@ -105,7 +113,8 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException modifiersField.setAccessible(true); modifiersField.setInt(telemetryStorageConsumer, telemetryStorageConsumer.getModifiers() & ~Modifier.FINAL); telemetryStorageConsumer.set(telemetrySynchronizer, telemetryStorage); - Config config = telemetrySynchronizer.generateConfig(splitClientConfig, 100l, ApiKeyCounter.getApiKeyCounterInstance().getFactoryInstances(), new ArrayList<>()); + Config config = telemetrySynchronizer.generateConfig(splitClientConfig, 100l, + ApiKeyCounter.getApiKeyCounterInstance().getFactoryInstances(), new ArrayList<>()); Assert.assertEquals(3, config.getRedundantFactories()); Assert.assertEquals(2, config.getBurTimeouts()); Assert.assertEquals(3, config.getNonReadyUsages()); @@ -117,7 +126,8 @@ public void testConfig() throws InvocationTargetException, NoSuchMethodException public void testStats() throws Exception { TelemetryStorage telemetryStorage = new InMemoryTelemetryStorage(); CloseableHttpClient httpClient = TestHelper.mockHttpClient(TELEMETRY_ENDPOINT, HttpStatus.SC_OK); - SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null)); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClient, new RequestDecorator(null), "qwerty", + metadata()); TelemetryInMemorySubmitter telemetrySynchronizer = getTelemetrySynchronizer(splitHttpClient); populateStats(telemetryStorage); Field telemetryStorageConsumer = TelemetryInMemorySubmitter.class.getDeclaredField("_telemetryStorageConsumer"); @@ -130,12 +140,18 @@ public void testStats() throws Exception { Stats stats = telemetrySynchronizer.generateStats(); Assert.assertEquals(2, stats.getMethodLatencies().getTreatment().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(2, stats.getMethodLatencies().getTreatments().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentsWithConfig().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentWithConfig().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentByFlagSet().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentByFlagSets().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentWithConfigByFlagSet().stream().mapToInt(Long::intValue).sum()); - Assert.assertEquals(1, stats.getMethodLatencies().getTreatmentWithConfigByFlagSets().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + stats.getMethodLatencies().getTreatmentsWithConfig().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + stats.getMethodLatencies().getTreatmentWithConfig().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + stats.getMethodLatencies().getTreatmentByFlagSet().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + stats.getMethodLatencies().getTreatmentByFlagSets().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + stats.getMethodLatencies().getTreatmentWithConfigByFlagSet().stream().mapToInt(Long::intValue).sum()); + Assert.assertEquals(1, + stats.getMethodLatencies().getTreatmentWithConfigByFlagSets().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(0, stats.getMethodLatencies().getTrack().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(3, stats.getHttpLatencies().get_splits().stream().mapToInt(Long::intValue).sum()); Assert.assertEquals(2, stats.getHttpLatencies().get_telemetry().stream().mapToInt(Long::intValue).sum()); @@ -188,7 +204,9 @@ private TelemetryInMemorySubmitter getTelemetrySynchronizer(SplitHttpClient http TelemetryRuntimeProducer telemetryRuntimeProducer = Mockito.mock(TelemetryRuntimeProducer.class); SplitCacheConsumer splitCacheConsumer = Mockito.mock(SplitCacheConsumer.class); SegmentCacheConsumer segmentCacheConsumer = Mockito.mock(SegmentCacheConsumer.class); - TelemetryInMemorySubmitter telemetrySynchronizer = new TelemetryInMemorySubmitter(httpClient, URI.create(TELEMETRY_ENDPOINT), consumer, splitCacheConsumer, segmentCacheConsumer, telemetryRuntimeProducer, 0l); + TelemetryInMemorySubmitter telemetrySynchronizer = new TelemetryInMemorySubmitter(httpClient, + URI.create(TELEMETRY_ENDPOINT), consumer, splitCacheConsumer, segmentCacheConsumer, + telemetryRuntimeProducer, 0l); return telemetrySynchronizer; } @@ -274,4 +292,9 @@ private void populateConfig(TelemetryStorage telemetryStorage) { telemetryStorage.recordNonReadyUsage(); telemetryStorage.recordNonReadyUsage(); } -} \ No newline at end of file + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } + +} From 7189a3354594f7633452392b1f77f92f572b16fd Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 11:31:37 -0300 Subject: [PATCH 41/88] java 8 compliance --- .../io/split/client/impressions/HttpImpressionsSender.java | 2 +- .../src/test/java/io/split/service/HttpSplitClientTest.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java index f6fd19331..06df64cc4 100644 --- a/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java +++ b/client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java @@ -69,7 +69,7 @@ public void postImpressionsBulk(List impressions) { try { HttpEntity entity = Utils.toJsonEntity(impressions); Map> additionalHeaders = Collections.singletonMap(IMPRESSIONS_MODE_HEADER, - List.of(_mode.toString())); + Collections.singletonList(_mode.toString())); SplitHttpResponse response = _client.post(_impressionBulkTarget, entity, additionalHeaders); if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index 4e4f170a1..ba15270b1 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -45,7 +45,8 @@ public void testGetWithSpecialCharacters() throws URISyntaxException, Invocation RequestDecorator decorator = new RequestDecorator(null); SplitHttpClient splitHtpClient = SplitHttpClientImpl.create(httpClientMock, decorator, "qwerty", metadata()); - Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", List.of("add")); + Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", + Collections.singletonList("add")); SplitHttpResponse splitHttpResponse = splitHtpClient.get(rootTarget, new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders); @@ -119,7 +120,8 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null))))); - Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", List.of("add")); + Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", + Collections.singletonList("add")); SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders); From 546a22001ef264934eae6c63a97e9a739659d600 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Fri, 29 Mar 2024 11:32:40 -0300 Subject: [PATCH 42/88] forward decorator into streaming --- .../io/split/client/NoOpHeaderDecorator.java | 18 ++++++++++++++++++ .../java/io/split/client/RequestDecorator.java | 8 -------- .../java/io/split/client/SplitFactoryImpl.java | 14 ++++++++++---- .../io/split/engine/common/PushManagerImp.java | 2 +- .../java/io/split/engine/common/SplitAPI.java | 11 ++++++++--- .../split/engine/sse/EventSourceClientImp.java | 13 +++++++++---- .../io/split/engine/sse/client/SSEClient.java | 11 +++++++++-- .../engine/sse/EventSourceClientTest.java | 7 ++++--- .../io/split/engine/sse/SSEClientTest.java | 3 ++- 9 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 client/src/main/java/io/split/client/NoOpHeaderDecorator.java diff --git a/client/src/main/java/io/split/client/NoOpHeaderDecorator.java b/client/src/main/java/io/split/client/NoOpHeaderDecorator.java new file mode 100644 index 000000000..8ce04fdbc --- /dev/null +++ b/client/src/main/java/io/split/client/NoOpHeaderDecorator.java @@ -0,0 +1,18 @@ +package io.split.client; + +import io.split.client.CustomHeaderDecorator; +import io.split.client.dtos.RequestContext; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class NoOpHeaderDecorator implements CustomHeaderDecorator { + public NoOpHeaderDecorator() { + } + + @Override + public Map> getHeaderOverrides(RequestContext context) { + return new HashMap<>(); + } +} diff --git a/client/src/main/java/io/split/client/RequestDecorator.java b/client/src/main/java/io/split/client/RequestDecorator.java index 8bc9e216b..718717e59 100644 --- a/client/src/main/java/io/split/client/RequestDecorator.java +++ b/client/src/main/java/io/split/client/RequestDecorator.java @@ -13,14 +13,6 @@ import java.util.Set; import java.util.List; -class NoOpHeaderDecorator implements CustomHeaderDecorator { - public NoOpHeaderDecorator() {} - @Override - public Map> getHeaderOverrides(RequestContext context) { - return new HashMap<>(); - } -} - public final class RequestDecorator { CustomHeaderDecorator _headerDecorator; diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 35bbed8c3..9625690b9 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -185,7 +185,8 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn _gates = new SDKReadinessGates(); // HttpClient - _splitHttpClient = buildSplitHttpClient(apiToken, config, _sdkMetadata); + RequestDecorator requestDecorator = new RequestDecorator(config.customHeaderDecorator()); + _splitHttpClient = buildSplitHttpClient(apiToken, config, _sdkMetadata, requestDecorator); // Roots _rootTarget = URI.create(config.endpoint()); @@ -252,7 +253,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn // SyncManager SplitTasks splitTasks = SplitTasks.build(_splitSynchronizationTask, _segmentSynchronizationTaskImp, _impressionsManager, _eventsTask, _telemetrySyncTask, _uniqueKeysTracker); - SplitAPI splitAPI = SplitAPI.build(_splitHttpClient, buildSSEdHttpClient(apiToken, config, _sdkMetadata)); + SplitAPI splitAPI = SplitAPI.build(_splitHttpClient, buildSSEdHttpClient(apiToken, config, _sdkMetadata), requestDecorator); _syncManager = SyncManagerImp.build(splitTasks, _splitFetcher, splitCache, splitAPI, segmentCache, _gates, _telemetryStorageProducer, _telemetrySynchronizer, config, splitParser, flagSetsFilter); @@ -473,7 +474,12 @@ public boolean isDestroyed() { return isTerminated; } - private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) + private static SplitHttpClient buildSplitHttpClient( + String apiToken, + SplitClientConfig config, + SDKMetadata sdkMetadata, + RequestDecorator requestDecorator + ) throws URISyntaxException { SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() .setSslContext(SSLContexts.createSystemDefault()) @@ -508,7 +514,7 @@ private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClient httpClientbuilder = setupProxy(httpClientbuilder, config); } - return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.customHeaderDecorator())); + return SplitHttpClientImpl.create(httpClientbuilder.build(), requestDecorator); } private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) { diff --git a/client/src/main/java/io/split/engine/common/PushManagerImp.java b/client/src/main/java/io/split/engine/common/PushManagerImp.java index ff3343ed4..b6118efb6 100644 --- a/client/src/main/java/io/split/engine/common/PushManagerImp.java +++ b/client/src/main/java/io/split/engine/common/PushManagerImp.java @@ -83,7 +83,7 @@ public static PushManagerImp build(Synchronizer synchronizer, PushStatusTracker pushStatusTracker = new PushStatusTrackerImp(statusMessages, telemetryRuntimeProducer); return new PushManagerImp(new AuthApiClientImp(authUrl, splitAPI.getHttpClient(), telemetryRuntimeProducer), EventSourceClientImp.build(streamingUrl, featureFlagsWorker, segmentWorker, pushStatusTracker, splitAPI.getSseHttpClient(), - telemetryRuntimeProducer, threadFactory), + telemetryRuntimeProducer, threadFactory, splitAPI.getRequestDecorator()), featureFlagsWorker, segmentWorker, pushStatusTracker, diff --git a/client/src/main/java/io/split/engine/common/SplitAPI.java b/client/src/main/java/io/split/engine/common/SplitAPI.java index b3b42966f..229f34cbc 100644 --- a/client/src/main/java/io/split/engine/common/SplitAPI.java +++ b/client/src/main/java/io/split/engine/common/SplitAPI.java @@ -1,5 +1,6 @@ package io.split.engine.common; +import io.split.client.RequestDecorator; import io.split.service.SplitHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.slf4j.Logger; @@ -9,15 +10,17 @@ public class SplitAPI { private final SplitHttpClient _httpClient; private final CloseableHttpClient _sseHttpClient; + private final RequestDecorator _requestDecorator; private static final Logger _log = LoggerFactory.getLogger(SplitAPI.class); - private SplitAPI(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient) { + private SplitAPI(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient, RequestDecorator requestDecorator) { _httpClient = httpClient; _sseHttpClient = sseHttpClient; + _requestDecorator = requestDecorator; } - public static SplitAPI build(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient){ - return new SplitAPI(httpClient,sseHttpClient); + public static SplitAPI build(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient, RequestDecorator requestDecorator){ + return new SplitAPI(httpClient, sseHttpClient, requestDecorator); } public SplitHttpClient getHttpClient() { @@ -28,6 +31,8 @@ public CloseableHttpClient getSseHttpClient() { return _sseHttpClient; } + public RequestDecorator getRequestDecorator() { return _requestDecorator; } + public void close(){ try { _sseHttpClient.close(); diff --git a/client/src/main/java/io/split/engine/sse/EventSourceClientImp.java b/client/src/main/java/io/split/engine/sse/EventSourceClientImp.java index 35d1c05d7..212d929f3 100644 --- a/client/src/main/java/io/split/engine/sse/EventSourceClientImp.java +++ b/client/src/main/java/io/split/engine/sse/EventSourceClientImp.java @@ -2,6 +2,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; +import io.split.client.RequestDecorator; import io.split.engine.sse.client.RawEvent; import io.split.engine.sse.client.SSEClient; import io.split.engine.sse.dtos.SegmentQueueDto; @@ -40,7 +41,8 @@ public class EventSourceClientImp implements EventSourceClient { PushStatusTracker pushStatusTracker, CloseableHttpClient sseHttpClient, TelemetryRuntimeProducer telemetryRuntimeProducer, - ThreadFactory threadFactory) { + ThreadFactory threadFactory, + RequestDecorator requestDecorator) { _baseStreamingUrl = checkNotNull(baseStreamingUrl); _notificationParser = checkNotNull(notificationParser); _notificationProcessor = checkNotNull(notificationProcessor); @@ -51,7 +53,8 @@ public class EventSourceClientImp implements EventSourceClient { status -> { _pushStatusTracker.handleSseStatus(status); return null; }, sseHttpClient, telemetryRuntimeProducer, - threadFactory); + threadFactory, + requestDecorator); _firstEvent = new AtomicBoolean(); } @@ -61,14 +64,16 @@ public static EventSourceClientImp build(String baseStreamingUrl, PushStatusTracker pushStatusTracker, CloseableHttpClient sseHttpClient, TelemetryRuntimeProducer telemetryRuntimeProducer, - ThreadFactory threadFactory) { + ThreadFactory threadFactory, + RequestDecorator requestDecorator) { return new EventSourceClientImp(baseStreamingUrl, new NotificationParserImp(), NotificationProcessorImp.build(featureFlagsWorker, segmentWorker, pushStatusTracker), pushStatusTracker, sseHttpClient, telemetryRuntimeProducer, - threadFactory); + threadFactory, + requestDecorator); } @Override diff --git a/client/src/main/java/io/split/engine/sse/client/SSEClient.java b/client/src/main/java/io/split/engine/sse/client/SSEClient.java index 30dd16f20..9c2024d99 100644 --- a/client/src/main/java/io/split/engine/sse/client/SSEClient.java +++ b/client/src/main/java/io/split/engine/sse/client/SSEClient.java @@ -1,10 +1,12 @@ package io.split.engine.sse.client; import com.google.common.base.Strings; +import io.split.client.RequestDecorator; import io.split.telemetry.domain.StreamingEvent; import io.split.telemetry.domain.enums.StreamEventsEnum; import io.split.telemetry.storage.TelemetryRuntimeProducer; import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.slf4j.Logger; @@ -56,6 +58,7 @@ private enum ConnectionState { private final AtomicReference _ongoingResponse = new AtomicReference<>(); private final AtomicReference _ongoingRequest = new AtomicReference<>(); private AtomicBoolean _forcedStop; + private final RequestDecorator _requestDecorator; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; @@ -63,13 +66,15 @@ public SSEClient(Function eventCallback, Function statusCallback, CloseableHttpClient client, TelemetryRuntimeProducer telemetryRuntimeProducer, - ThreadFactory threadFactory) { + ThreadFactory threadFactory, + RequestDecorator requestDecorator) { _eventCallback = eventCallback; _statusCallback = statusCallback; _client = client; _forcedStop = new AtomicBoolean(); _telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer); _connectionExecutor = buildExecutorService(threadFactory, "SPLIT-SSEConnection-%d"); + _requestDecorator = requestDecorator; } public synchronized boolean open(URI uri) { @@ -177,7 +182,9 @@ private void connectAndLoop(URI uri, CountDownLatch signal) { } private boolean establishConnection(URI uri, CountDownLatch signal) { - _ongoingRequest.set(new HttpGet(uri)); + HttpGet request = new HttpGet(uri); + request = (HttpGet) _requestDecorator.decorateHeaders(request); + _ongoingRequest.set(request); try { _ongoingResponse.set(_client.execute(_ongoingRequest.get())); if (_ongoingResponse.get().getCode() != 200) { diff --git a/client/src/test/java/io/split/engine/sse/EventSourceClientTest.java b/client/src/test/java/io/split/engine/sse/EventSourceClientTest.java index c5bc22b1b..604b6371f 100644 --- a/client/src/test/java/io/split/engine/sse/EventSourceClientTest.java +++ b/client/src/test/java/io/split/engine/sse/EventSourceClientTest.java @@ -1,6 +1,7 @@ package io.split.engine.sse; import io.split.SSEMockServer; +import io.split.client.RequestDecorator; import io.split.engine.sse.client.SSEClient; import io.split.engine.sse.dtos.ErrorNotification; import io.split.engine.sse.dtos.FeatureFlagChangeNotification; @@ -42,7 +43,7 @@ public void startShouldConnect() throws IOException { TelemetryRuntimeProducer telemetryRuntimeProducer = Mockito.mock(InMemoryTelemetryStorage.class); sseServer.start(); - EventSourceClient eventSourceClient = new EventSourceClientImp("http://localhost:" + sseServer.getPort(), _notificationParser, _notificationProcessor, _pushStatusTracker, buildHttpClient(), telemetryRuntimeProducer, null); + EventSourceClient eventSourceClient = new EventSourceClientImp("http://localhost:" + sseServer.getPort(), _notificationParser, _notificationProcessor, _pushStatusTracker, buildHttpClient(), telemetryRuntimeProducer, null, new RequestDecorator(null)); boolean result = eventSourceClient.start("channel-test", "token-test"); @@ -57,7 +58,7 @@ public void startShouldReconnect() throws IOException { SSEMockServer sseServer = buildSSEMockServer(eventQueue); TelemetryRuntimeProducer telemetryRuntimeProducer = Mockito.mock(InMemoryTelemetryStorage.class); sseServer.start(); - EventSourceClient eventSourceClient = new EventSourceClientImp("http://fake:" + sseServer.getPort(), _notificationParser, _notificationProcessor, _pushStatusTracker, buildHttpClient(), telemetryRuntimeProducer, null); + EventSourceClient eventSourceClient = new EventSourceClientImp("http://fake:" + sseServer.getPort(), _notificationParser, _notificationProcessor, _pushStatusTracker, buildHttpClient(), telemetryRuntimeProducer, null, new RequestDecorator(null)); boolean result = eventSourceClient.start("channel-test", "token-test"); @@ -74,7 +75,7 @@ public void startAndReceiveNotification() throws IOException { SSEMockServer sseServer = buildSSEMockServer(eventQueue); TelemetryRuntimeProducer telemetryRuntimeProducer = Mockito.mock(InMemoryTelemetryStorage.class); sseServer.start(); - EventSourceClient eventSourceClient = new EventSourceClientImp("http://localhost:" + sseServer.getPort(), _notificationParser, _notificationProcessor, _pushStatusTracker, buildHttpClient(), telemetryRuntimeProducer, null); + EventSourceClient eventSourceClient = new EventSourceClientImp("http://localhost:" + sseServer.getPort(), _notificationParser, _notificationProcessor, _pushStatusTracker, buildHttpClient(), telemetryRuntimeProducer, null, new RequestDecorator(null)); boolean result = eventSourceClient.start("channel-test", "token-test"); diff --git a/client/src/test/java/io/split/engine/sse/SSEClientTest.java b/client/src/test/java/io/split/engine/sse/SSEClientTest.java index 97aaa4de5..15f13d3b3 100644 --- a/client/src/test/java/io/split/engine/sse/SSEClientTest.java +++ b/client/src/test/java/io/split/engine/sse/SSEClientTest.java @@ -1,5 +1,6 @@ package io.split.engine.sse; +import io.split.client.RequestDecorator; import io.split.engine.sse.client.SSEClient; import io.split.telemetry.storage.InMemoryTelemetryStorage; import io.split.telemetry.storage.TelemetryRuntimeProducer; @@ -38,7 +39,7 @@ public void basicUsageTest() throws URISyntaxException, InterruptedException { CloseableHttpClient httpClient = httpClientbuilder.build(); SSEClient sse = new SSEClient(e -> null, - s -> null, httpClient, telemetryRuntimeProducer, null); + s -> null, httpClient, telemetryRuntimeProducer, null, new RequestDecorator(null)); sse.open(uri); Thread.sleep(5000); sse.close(); From 7896c268093ca32a2cff9e95f6cde23f5dd093dc Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 11:51:00 -0300 Subject: [PATCH 43/88] add repeated headers one by one --- .../main/java/io/split/service/SplitHttpClientImpl.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index 1c28ebbd2..ed4bb5aa5 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -63,7 +63,9 @@ public SplitHttpResponse get(URI uri, FetchOptions options, Map> entry : additionalHeaders.entrySet()) { - request.addHeader(entry.getKey(), entry.getValue()); + for (String value : entry.getValue()) { + request.addHeader(entry.getKey(), value); + } } } if (options.cacheControlHeadersEnabled()) { @@ -105,7 +107,9 @@ public SplitHttpResponse post(URI uri, HttpEntity entity, Map> entry : additionalHeaders.entrySet()) { - request.addHeader(entry.getKey(), entry.getValue()); + for (String value : entry.getValue()) { + request.addHeader(entry.getKey(), value); + } } } request.setEntity(entity); From ed63169b12b5c5c948be983c404cba8e33771077 Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 11:58:30 -0300 Subject: [PATCH 44/88] fix header count --- .../split/client/impressions/HttpImpressionsSenderTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java index d2d3373ad..a61ed7ede 100644 --- a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java +++ b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java @@ -115,7 +115,7 @@ public void testImpressionCountsEndpointOptimized() throws URISyntaxException, I HttpUriRequest request = captor.getValue(); assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/count")))); - assertThat(request.getHeaders().length, is(0)); + assertThat(request.getHeaders().length, is(5)); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; InputStreamReader reader = new InputStreamReader(asPostRequest.getEntity().getContent()); @@ -178,7 +178,7 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException HttpUriRequest request = captor.getValue(); assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); - assertThat(request.getHeaders().length, is(1)); + assertThat(request.getHeaders().length, is(6)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("OPTIMIZED"))); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; @@ -199,7 +199,7 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClientDebugMode).execute(captor.capture()); request = captor.getValue(); - assertThat(request.getHeaders().length, is(1)); + assertThat(request.getHeaders().length, is(6)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("DEBUG"))); } From 372cc05742cbf6d1db14edcc7abf4cde96eefb75 Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 12:01:21 -0300 Subject: [PATCH 45/88] remove header count from test --- .../io/split/client/impressions/HttpImpressionsSenderTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java index a61ed7ede..18a4141cb 100644 --- a/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java +++ b/client/src/test/java/io/split/client/impressions/HttpImpressionsSenderTest.java @@ -115,7 +115,6 @@ public void testImpressionCountsEndpointOptimized() throws URISyntaxException, I HttpUriRequest request = captor.getValue(); assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/count")))); - assertThat(request.getHeaders().length, is(5)); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; InputStreamReader reader = new InputStreamReader(asPostRequest.getEntity().getContent()); @@ -178,7 +177,6 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException HttpUriRequest request = captor.getValue(); assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); - assertThat(request.getHeaders().length, is(6)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("OPTIMIZED"))); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; @@ -199,7 +197,6 @@ public void testImpressionBulksEndpoint() throws URISyntaxException, IOException captor = ArgumentCaptor.forClass(HttpUriRequest.class); verify(httpClientDebugMode).execute(captor.capture()); request = captor.getValue(); - assertThat(request.getHeaders().length, is(6)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("DEBUG"))); } From b65e6678ddd6aa71322df6e37079a94c5dd2b36f Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 12:08:39 -0300 Subject: [PATCH 46/88] remove getHeaders in test --- client/src/test/java/io/split/service/HttpSplitClientTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index ba15270b1..eba038af0 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -131,7 +131,6 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce HttpUriRequest request = captor.getValue(); assertThat(request.getUri(), is(equalTo(URI.create("https://kubernetesturl.com/split/api/testImpressions/bulk")))); - assertThat(request.getHeaders().length, is(1)); assertThat(request.getFirstHeader("SplitSDKImpressionsMode").getValue(), is(equalTo("OPTIMIZED"))); assertThat(request, instanceOf(HttpPost.class)); HttpPost asPostRequest = (HttpPost) request; From c81ea7ec03132cf5d8cf55c8610f4e02fdd10fb3 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Fri, 29 Mar 2024 12:26:56 -0300 Subject: [PATCH 47/88] added impressionsMode in failure test --- .../src/test/java/io/split/service/HttpSplitClientTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/test/java/io/split/service/HttpSplitClientTest.java b/client/src/test/java/io/split/service/HttpSplitClientTest.java index eba038af0..946775f39 100644 --- a/client/src/test/java/io/split/service/HttpSplitClientTest.java +++ b/client/src/test/java/io/split/service/HttpSplitClientTest.java @@ -120,8 +120,8 @@ public void testPost() throws URISyntaxException, IOException, IllegalAccessExce KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null))))); - Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", - Collections.singletonList("add")); + Map> additionalHeaders = Collections.singletonMap("SplitSDKImpressionsMode", + Collections.singletonList("OPTIMIZED")); SplitHttpResponse splitHttpResponse = splitHtpClient.post(rootTarget, Utils.toJsonEntity(toSend), additionalHeaders); From 1df6d661777ed157aa4c8ec1f3bb5def321db2e1 Mon Sep 17 00:00:00 2001 From: Matias Melograno Date: Fri, 29 Mar 2024 13:05:57 -0300 Subject: [PATCH 48/88] preparing rc --- client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index a0becea3c..12cda4f36 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc1 + 4.12.0-rc2 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index 30b90d945..d72620667 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc1 + 4.12.0-rc2 2.1.0 diff --git a/pom.xml b/pom.xml index 3b7e17ed1..06f94991b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.12.0-rc1 + 4.12.0-rc2 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 962d8c51f..498ec361b 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc1 + 4.12.0-rc2 redis-wrapper 3.1.0 diff --git a/testing/pom.xml b/testing/pom.xml index d0f537dc6..4bbe4b31d 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc1 + 4.12.0-rc2 java-client-testing jar From bdc409eb1446388a86dddde607e188c38c1da2d5 Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 13:29:39 -0300 Subject: [PATCH 49/88] close http client --- .../java/io/split/engine/common/SplitAPI.java | 18 +++++++++++++----- .../java/io/split/service/SplitHttpClient.java | 4 +++- .../io/split/service/SplitHttpClientImpl.java | 5 +++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/client/src/main/java/io/split/engine/common/SplitAPI.java b/client/src/main/java/io/split/engine/common/SplitAPI.java index 229f34cbc..adb0500de 100644 --- a/client/src/main/java/io/split/engine/common/SplitAPI.java +++ b/client/src/main/java/io/split/engine/common/SplitAPI.java @@ -19,7 +19,8 @@ private SplitAPI(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient, _requestDecorator = requestDecorator; } - public static SplitAPI build(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient, RequestDecorator requestDecorator){ + public static SplitAPI build(SplitHttpClient httpClient, CloseableHttpClient sseHttpClient, + RequestDecorator requestDecorator) { return new SplitAPI(httpClient, sseHttpClient, requestDecorator); } @@ -31,13 +32,20 @@ public CloseableHttpClient getSseHttpClient() { return _sseHttpClient; } - public RequestDecorator getRequestDecorator() { return _requestDecorator; } + public RequestDecorator getRequestDecorator() { + return _requestDecorator; + } - public void close(){ + public void close() { + try { + _httpClient.close(); + } catch (Exception e) { + _log.error("Error trying to close regular http client", e); + } try { _sseHttpClient.close(); - } catch (Exception e){ + } catch (Exception e) { _log.error("Error trying to close sseHttpClient", e); } } -} \ No newline at end of file +} diff --git a/client/src/main/java/io/split/service/SplitHttpClient.java b/client/src/main/java/io/split/service/SplitHttpClient.java index 1e44a49ba..1c88bcd4e 100644 --- a/client/src/main/java/io/split/service/SplitHttpClient.java +++ b/client/src/main/java/io/split/service/SplitHttpClient.java @@ -4,12 +4,14 @@ import io.split.client.dtos.SplitHttpResponse; import org.apache.hc.core5.http.HttpEntity; + +import java.io.Closeable; import java.io.IOException; import java.net.URI; import java.util.List; import java.util.Map; -public interface SplitHttpClient { +public interface SplitHttpClient extends Closeable { /** * Wrapper for HTTP get method * diff --git a/client/src/main/java/io/split/service/SplitHttpClientImpl.java b/client/src/main/java/io/split/service/SplitHttpClientImpl.java index ed4bb5aa5..64ca3a55c 100644 --- a/client/src/main/java/io/split/service/SplitHttpClientImpl.java +++ b/client/src/main/java/io/split/service/SplitHttpClientImpl.java @@ -140,4 +140,9 @@ private void setBasicHeaders(HttpRequest request) { ? _apikey.substring(_apikey.length() - 4) : _apikey); } + + @Override + public void close() throws IOException { + _client.close(); + } } From c917ff98b3fd2f61dd54abd7201ae223eb394d1f Mon Sep 17 00:00:00 2001 From: Martin Redolatti Date: Fri, 29 Mar 2024 13:32:44 -0300 Subject: [PATCH 50/88] bump version in pom.xml files --- client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index 12cda4f36..7a6a53ca6 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc2 + 4.12.0-rc3 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index d72620667..d2d75905f 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc2 + 4.12.0-rc3 2.1.0 diff --git a/pom.xml b/pom.xml index 06f94991b..91f89a449 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.12.0-rc2 + 4.12.0-rc3 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 498ec361b..0beb3ed73 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc2 + 4.12.0-rc3 redis-wrapper 3.1.0 diff --git a/testing/pom.xml b/testing/pom.xml index 4bbe4b31d..e49a96c67 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc2 + 4.12.0-rc3 java-client-testing jar From 4468b2a2e129162b4ecf41b87cd38e8108b5495e Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 19 Apr 2024 12:56:22 -0700 Subject: [PATCH 51/88] added unsupported matcher flow --- .../split/engine/experiments/SplitParser.java | 36 ++++++++++++++++--- .../engine/experiments/SplitParserTest.java | 23 ++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index d5ae12f15..fe0b5a88e 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -1,11 +1,7 @@ package io.split.engine.experiments; import com.google.common.collect.Lists; -import io.split.client.dtos.Condition; -import io.split.client.dtos.Matcher; -import io.split.client.dtos.MatcherGroup; -import io.split.client.dtos.Partition; -import io.split.client.dtos.Split; +import io.split.client.dtos.*; import io.split.engine.matchers.AllKeysMatcher; import io.split.engine.matchers.AttributeMatcher; import io.split.engine.matchers.BetweenMatcher; @@ -59,6 +55,11 @@ private ParsedSplit parseWithoutExceptionHandling(Split split) { for (Condition condition : split.conditions) { List partitions = condition.partitions; + if (checkUnsupportedMatcherExist(condition.matcherGroup.matchers)) { + _log.error("Unsupported matcher type found for feature flag: " + split.name + " , will revert to default template matcher."); + parsedConditionList.add(getTemplateCondition()); + break; + } CombiningMatcher matcher = toMatcher(condition.matcherGroup); parsedConditionList.add(new ParsedCondition(condition.conditionType, matcher, partitions, condition.label)); } @@ -67,6 +68,31 @@ private ParsedSplit parseWithoutExceptionHandling(Split split) { split.changeNumber, split.trafficAllocation, split.trafficAllocationSeed, split.algo, split.configurations, split.sets); } + private boolean checkUnsupportedMatcherExist(List matchers) { + for (io.split.client.dtos.Matcher matcher : matchers) { + try { + matcher.matcherType.equals(null); + } catch (NullPointerException e) { + // If the exception is caught, it means unsupported matcher + return true; + } + } + return false; + } + + private ParsedCondition getTemplateCondition() { + List templatePartitions = Lists.newArrayList(); + Partition partition = new Partition(); + partition.treatment = "control"; + partition.size = 100; + templatePartitions.add(partition); + return new ParsedCondition( + ConditionType.ROLLOUT, + CombiningMatcher.of(new AllKeysMatcher()), + templatePartitions, + "unsupported matcher type"); + } + private CombiningMatcher toMatcher(MatcherGroup matcherGroup) { List matchers = matcherGroup.matchers; checkArgument(!matchers.isEmpty()); diff --git a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java index 634e93c62..e34a7991a 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java @@ -1,6 +1,7 @@ package io.split.engine.experiments; import com.google.common.collect.Lists; +import io.split.client.utils.Json; import io.split.storages.SegmentCache; import io.split.storages.memory.SegmentCacheInMemoryImpl; import io.split.client.dtos.*; @@ -39,6 +40,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; /** * Tests for ExperimentParser @@ -529,6 +531,27 @@ public void contains_string() { set_matcher_test(c, m); } + public void unsupportedMatcher() { + SplitParser parser = new SplitParser(); + String splitWithUndefinedMatcher = "{\"since\":-1,\"till\": 1457726098069,\"splits\": [{ \"changeNumber\": 123, \"trafficTypeName\": \"user\", \"name\": \"some_name\"," + + "\"trafficAllocation\": 100, \"trafficAllocationSeed\": 123456, \"seed\": 321654, \"status\": \"ACTIVE\"," + + "\"killed\": false, \"defaultTreatment\": \"off\", \"algo\": 2,\"conditions\": [{ \"partitions\": [" + + "{\"treatment\": \"on\", \"size\": 50}, {\"treatment\": \"off\", \"size\": 50}], \"contitionType\": \"ROLLOUT\"," + + "\"label\": \"some_label\", \"matcherGroup\": { \"matchers\": [{ \"matcherType\": \"UNKNOWN\", \"negate\": false}]," + + "\"combiner\": \"AND\"}}], \"sets\": [\"set1\"]}]}"; + SplitChange change = Json.fromJson(splitWithUndefinedMatcher, SplitChange.class); + for (Split split : change.splits) { + // should not cause exception + ParsedSplit parsedSplit = parser.parse(split); + for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { + // Check the matcher is ALL_KEYS + assertTrue(matcher.matcher().toString().equals(" in segment all")); + } + } + } + } + public void set_matcher_test(Condition c, io.split.engine.matchers.Matcher m) { // SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); From 8e7d57e2840326e941836e07920156af9f9b2d64 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 19 Apr 2024 13:05:22 -0700 Subject: [PATCH 52/88] polish --- .../main/java/io/split/engine/experiments/SplitParser.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index fe0b5a88e..4e5d786cd 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -1,7 +1,12 @@ package io.split.engine.experiments; import com.google.common.collect.Lists; -import io.split.client.dtos.*; +import io.split.client.dtos.Condition; +import io.split.client.dtos.Matcher; +import io.split.client.dtos.MatcherGroup; +import io.split.client.dtos.Partition; +import io.split.client.dtos.Split; +import io.split.client.dtos.ConditionType; import io.split.engine.matchers.AllKeysMatcher; import io.split.engine.matchers.AttributeMatcher; import io.split.engine.matchers.BetweenMatcher; From e9e852e6f3735ff768ff93f4d16dbe41790597b6 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 19 Apr 2024 13:21:34 -0700 Subject: [PATCH 53/88] polish --- .../src/main/java/io/split/engine/experiments/SplitParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index 4e5d786cd..22fa06788 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -7,6 +7,7 @@ import io.split.client.dtos.Partition; import io.split.client.dtos.Split; import io.split.client.dtos.ConditionType; +import io.split.client.dtos.MatcherType; import io.split.engine.matchers.AllKeysMatcher; import io.split.engine.matchers.AttributeMatcher; import io.split.engine.matchers.BetweenMatcher; @@ -76,7 +77,7 @@ private ParsedSplit parseWithoutExceptionHandling(Split split) { private boolean checkUnsupportedMatcherExist(List matchers) { for (io.split.client.dtos.Matcher matcher : matchers) { try { - matcher.matcherType.equals(null); + MatcherType typeCheck = matcher.matcherType; } catch (NullPointerException e) { // If the exception is caught, it means unsupported matcher return true; From 450242920268f8aa39f2b00eace0dcc1d3286bad Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 19 Apr 2024 13:49:15 -0700 Subject: [PATCH 54/88] polish --- .../java/io/split/engine/experiments/SplitParser.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index 22fa06788..3484f5307 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -75,15 +75,18 @@ private ParsedSplit parseWithoutExceptionHandling(Split split) { } private boolean checkUnsupportedMatcherExist(List matchers) { + MatcherType typeCheck = null; for (io.split.client.dtos.Matcher matcher : matchers) { + typeCheck = null; try { - MatcherType typeCheck = matcher.matcherType; + typeCheck = matcher.matcherType; } catch (NullPointerException e) { // If the exception is caught, it means unsupported matcher - return true; + break; } } - return false; + if (typeCheck != null) return false; + return true; } private ParsedCondition getTemplateCondition() { From 8d4bc044fdc9c3a4e26724dadeefcd788f5083e4 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 22 Apr 2024 08:52:22 -0700 Subject: [PATCH 55/88] polish --- client/src/main/java/io/split/engine/evaluator/Labels.java | 1 + .../main/java/io/split/engine/experiments/SplitParser.java | 4 +++- .../java/io/split/engine/experiments/SplitParserTest.java | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/evaluator/Labels.java b/client/src/main/java/io/split/engine/evaluator/Labels.java index b51a4e14b..59cfceefb 100644 --- a/client/src/main/java/io/split/engine/evaluator/Labels.java +++ b/client/src/main/java/io/split/engine/evaluator/Labels.java @@ -6,4 +6,5 @@ public class Labels { public static final String KILLED = "killed"; public static final String DEFINITION_NOT_FOUND = "definition not found"; public static final String EXCEPTION = "exception"; + public static final String UNSUPPORTED_MATCHER = "unsupported matcher type"; } \ No newline at end of file diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index 3484f5307..da4f0edcc 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -8,6 +8,7 @@ import io.split.client.dtos.Split; import io.split.client.dtos.ConditionType; import io.split.client.dtos.MatcherType; +import io.split.engine.evaluator.Labels; import io.split.engine.matchers.AllKeysMatcher; import io.split.engine.matchers.AttributeMatcher; import io.split.engine.matchers.BetweenMatcher; @@ -63,6 +64,7 @@ private ParsedSplit parseWithoutExceptionHandling(Split split) { List partitions = condition.partitions; if (checkUnsupportedMatcherExist(condition.matcherGroup.matchers)) { _log.error("Unsupported matcher type found for feature flag: " + split.name + " , will revert to default template matcher."); + parsedConditionList.clear(); parsedConditionList.add(getTemplateCondition()); break; } @@ -99,7 +101,7 @@ private ParsedCondition getTemplateCondition() { ConditionType.ROLLOUT, CombiningMatcher.of(new AllKeysMatcher()), templatePartitions, - "unsupported matcher type"); + Labels.UNSUPPORTED_MATCHER); } private CombiningMatcher toMatcher(MatcherGroup matcherGroup) { diff --git a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java index e34a7991a..8fa28c375 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java @@ -5,6 +5,7 @@ import io.split.storages.SegmentCache; import io.split.storages.memory.SegmentCacheInMemoryImpl; import io.split.client.dtos.*; +import io.split.engine.evaluator.Labels; import io.split.engine.ConditionsTestUtil; import io.split.engine.SDKReadinessGates; import io.split.engine.matchers.AttributeMatcher; @@ -531,6 +532,7 @@ public void contains_string() { set_matcher_test(c, m); } + @Test public void unsupportedMatcher() { SplitParser parser = new SplitParser(); String splitWithUndefinedMatcher = "{\"since\":-1,\"till\": 1457726098069,\"splits\": [{ \"changeNumber\": 123, \"trafficTypeName\": \"user\", \"name\": \"some_name\"," @@ -544,6 +546,7 @@ public void unsupportedMatcher() { // should not cause exception ParsedSplit parsedSplit = parser.parse(split); for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + assertTrue(parsedCondition.label() == Labels.UNSUPPORTED_MATCHER); for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { // Check the matcher is ALL_KEYS assertTrue(matcher.matcher().toString().equals(" in segment all")); From 6e2a8ecfa7e65835e1fa7b6fcd0fef8a98be3251 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 23 Apr 2024 13:07:15 -0700 Subject: [PATCH 56/88] added semver class --- .../exceptions/SemverParseException.java | 7 + .../java/io/split/engine/matchers/Semver.java | 161 ++++++++++++++++++ .../io/split/engine/matchers/SemverTest.java | 109 ++++++++++++ .../test/resources/semver/between-semver.csv | 18 ++ .../test/resources/semver/equal-to-semver.csv | 7 + .../semver/invalid-semantic-versions.csv | 28 +++ .../semver/valid-semantic-versions.csv | 25 +++ 7 files changed, 355 insertions(+) create mode 100644 client/src/main/java/io/split/client/exceptions/SemverParseException.java create mode 100644 client/src/main/java/io/split/engine/matchers/Semver.java create mode 100644 client/src/test/java/io/split/engine/matchers/SemverTest.java create mode 100644 client/src/test/resources/semver/between-semver.csv create mode 100644 client/src/test/resources/semver/equal-to-semver.csv create mode 100644 client/src/test/resources/semver/invalid-semantic-versions.csv create mode 100644 client/src/test/resources/semver/valid-semantic-versions.csv diff --git a/client/src/main/java/io/split/client/exceptions/SemverParseException.java b/client/src/main/java/io/split/client/exceptions/SemverParseException.java new file mode 100644 index 000000000..892ba7535 --- /dev/null +++ b/client/src/main/java/io/split/client/exceptions/SemverParseException.java @@ -0,0 +1,7 @@ +package io.split.client.exceptions; + +public class SemverParseException extends Exception { + public SemverParseException(String message) { + super(message); + } +} diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java new file mode 100644 index 000000000..82b16558b --- /dev/null +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -0,0 +1,161 @@ +package io.split.engine.matchers; + +import io.split.client.exceptions.SemverParseException; +import io.split.engine.experiments.SplitParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.common.primitives.Ints; +import java.util.Arrays; + +public class Semver { + private final String MetadataDelimiter = "+"; + private final String PreReleaseDelimiter = "-"; + private final String ValueDelimiter = "\\."; + + private static final Logger _log = LoggerFactory.getLogger(SplitParser.class); + + private Long _major; + private Long _minor; + private Long _patch; + private String[] _preRelease; + private boolean _isStable; + private String _metadata; + private String _version; + + public static Semver build(String version) { + if (version.isEmpty()) return null; + try { + return new Semver(version); + } catch (Exception ex) { + _log.error("An error occurred during the creation of a Semver instance:", ex.getMessage()); + return null; + } + } + + public String Version() { + return _version; + } + + public Long Major() { + return _major; + } + + public Long Minor() { + return _minor; + } + + public Long Patch() { + return _patch; + } + + public String[] PreRelease() { + return _preRelease; + } + + public String Metadata() { + return _metadata; + } + + public boolean IsStable() { + return _isStable; + } + + /** + * Precedence comparision between 2 Semver objects. + * + * @return the value {@code 0} if {@code this == toCompare}; + * a value less than {@code 0} if {@code this < toCompare}; and + * a value greater than {@code 0} if {@code this > toCompare} + */ + public int Compare(Semver toCompare) { + if (_version.equals(toCompare.Version())) { + return 0; + } + // Compare major, minor, and patch versions numerically + int result = Long.compare(_major, toCompare.Major()); + if (result != 0) { + return result; + } + result = Long.compare(_minor, toCompare.Minor()); + if (result != 0) { + return result; + } + result = Long.compare(_patch, toCompare.Patch()); + if (result != 0) { + return result; + } + if (!_isStable && toCompare.IsStable()) { + return -1; + } else if (_isStable && !toCompare.IsStable()) { + return 1; + } + // Compare pre-release versions lexically + int minLength = Math.min(_preRelease.length, toCompare.PreRelease().length); + for (int i = 0; i < minLength; i++) { + if (_preRelease[i].equals(toCompare.PreRelease()[i])) { + continue; + } + if ( Ints.tryParse(_preRelease[i]) != null && Ints.tryParse(toCompare._preRelease[i]) != null) { + return Integer.compare(Integer.parseInt(_preRelease[i]), Integer.parseInt(toCompare._preRelease[i])); + } + return AdjustNumber(_preRelease[i].compareTo(toCompare._preRelease[i])); + } + // Compare lengths of pre-release versions + return Integer.compare(_preRelease.length, toCompare._preRelease.length); + } + + private int AdjustNumber(int number) { + if (number > 0) return 1; + if (number < 0) return -1; + return 0; + } + private Semver(String version) throws SemverParseException { + String vWithoutMetadata = setAndRemoveMetadataIfExists(version); + String vWithoutPreRelease = setAndRemovePreReleaseIfExists(vWithoutMetadata); + setMajorMinorAndPatch(vWithoutPreRelease); + _version = setVersion(); + } + private String setAndRemoveMetadataIfExists(String version) throws SemverParseException { + int index = version.indexOf(MetadataDelimiter); + if (index == -1) { + return version; + } + _metadata = version.substring(index+1); + if (_metadata == null || _metadata.isEmpty()) { + throw new SemverParseException("Unable to convert to Semver, incorrect pre release data"); + } + return version.substring(0, index); + } + private String setAndRemovePreReleaseIfExists(String vWithoutMetadata) throws SemverParseException { + int index = vWithoutMetadata.indexOf(PreReleaseDelimiter); + if (index == -1) { + _isStable = true; + return vWithoutMetadata; + } + String preReleaseData = vWithoutMetadata.substring(index+1); + _preRelease = preReleaseData.split(ValueDelimiter); + if (_preRelease == null || Arrays.stream(_preRelease).allMatch(pr -> pr == null || pr.isEmpty())) { + throw new SemverParseException("Unable to convert to Semver, incorrect pre release data"); + } + return vWithoutMetadata.substring(0, index); + } + private void setMajorMinorAndPatch(String version) throws SemverParseException { + String[] vParts = version.split(ValueDelimiter); + if (vParts.length != 3) + throw new SemverParseException("Unable to convert to Semver, incorrect format: " + version); + _major = Long.parseUnsignedLong(vParts[0]); + _minor = Long.parseUnsignedLong(vParts[1]); + _patch = Long.parseUnsignedLong(vParts[2]); + } + + private String setVersion() { + String toReturn = _major + ValueDelimiter + _minor + ValueDelimiter + _patch; + if (_preRelease != null && _preRelease.length != 0) { + toReturn = toReturn + PreReleaseDelimiter + String.join(ValueDelimiter, _preRelease); + } + if (_metadata != null && !_metadata.isEmpty()) { + toReturn = toReturn + MetadataDelimiter + _metadata; + } + return toReturn; + } +} diff --git a/client/src/test/java/io/split/engine/matchers/SemverTest.java b/client/src/test/java/io/split/engine/matchers/SemverTest.java new file mode 100644 index 000000000..42cae6ec9 --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/SemverTest.java @@ -0,0 +1,109 @@ +package io.split.engine.matchers; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Test; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; + +/** + * Tests for AllKeysMatcher + */ +public class SemverTest { + + @Test + public void testValidVersions() throws IOException { + List> versions = new ArrayList<>(); + BufferedReader br = new BufferedReader(new FileReader("src/test/resources/semver/valid-semantic-versions.csv")); + String line; + boolean firstLine = true; + while ((line = br.readLine()) != null) { + if (firstLine) {firstLine = false; continue; } + String[] values = line.split(","); + versions.add(Arrays.asList(values)); + } + for(List version : versions) { + assertTrue(Semver.build(version.get(0)) != null); + assertTrue(Semver.build(version.get(1)) != null); + } + } + + @Test + public void testInvalidVersions() throws IOException { + List> versions = new ArrayList<>(); + BufferedReader br = new BufferedReader(new FileReader("src/test/resources/semver/invalid-semantic-versions.csv")); + String line; + boolean firstLine = true; + while ((line = br.readLine()) != null) { + if (firstLine) {firstLine = false; continue; } + String[] values = line.split(","); + versions.add(Arrays.asList(values)); + } + for(List version : versions) { + assertTrue(Semver.build(version.get(0)) == null); + } + } + + @Test + public void testCompareVersions() throws IOException { + List> versions = new ArrayList<>(); + BufferedReader br = new BufferedReader(new FileReader("src/test/resources/semver/valid-semantic-versions.csv")); + String line; + boolean firstLine = true; + while ((line = br.readLine()) != null) { + if (firstLine) {firstLine = false; continue; } + String[] values = line.split(","); + versions.add(Arrays.asList(values)); + } + for(List version : versions) { + assertTrue(Semver.build(version.get(0)).Compare(Semver.build(version.get(1))) == 1); + assertTrue(Semver.build(version.get(1)).Compare(Semver.build(version.get(0))) == -1); + } + + versions.clear(); + br = new BufferedReader(new FileReader("src/test/resources/semver/equal-to-semver.csv")); + firstLine = true; + while ((line = br.readLine()) != null) { + if (firstLine) {firstLine = false; continue; } + String[] values = line.split(","); + versions.add(Arrays.asList(values)); + } + for(List version : versions) { + Semver version1 = Semver.build(version.get(0)); + Semver version2 = Semver.build(version.get(1)); + + if (version.get(2).equals("true")) { + assertTrue(version1.Version().equals(version2.Version())); + } else { + assertTrue(!version1.Version().equals(version2.Version())); + } + } + + versions.clear(); + br = new BufferedReader(new FileReader("src/test/resources/semver/between-semver.csv")); + firstLine = true; + while ((line = br.readLine()) != null) { + if (firstLine) {firstLine = false; continue; } + String[] values = line.split(","); + versions.add(Arrays.asList(values)); + } + for(List version : versions) { + Semver version1 = Semver.build(version.get(0)); + Semver version2 = Semver.build(version.get(1)); + Semver version3 = Semver.build(version.get(2)); + + if (version.get(3).equals("true")) { + assertTrue(version2.Compare(version1) >= 0 && version3.Compare(version2) >= 0); + } else { + assertTrue(version2.Compare(version1) < 0 || version3.Compare(version2) < 0); + } + } + + } + +} diff --git a/client/src/test/resources/semver/between-semver.csv b/client/src/test/resources/semver/between-semver.csv new file mode 100644 index 000000000..71bdf3b24 --- /dev/null +++ b/client/src/test/resources/semver/between-semver.csv @@ -0,0 +1,18 @@ +version1,version2,version3,expected +1.1.1,2.2.2,3.3.3,true +1.1.1-rc.1,1.1.1-rc.2,1.1.1-rc.3,true +1.0.0-alpha,1.0.0-alpha.1,1.0.0-alpha.beta,true +1.0.0-alpha.1,1.0.0-alpha.beta,1.0.0-beta,true +1.0.0-alpha.beta,1.0.0-beta,1.0.0-beta.2,true +1.0.0-beta,1.0.0-beta.2,1.0.0-beta.11,true +1.0.0-beta.2,1.0.0-beta.11,1.0.0-rc.1,true +1.0.0-beta.11,1.0.0-rc.1,1.0.0,true +1.1.2,1.1.3,1.1.4,true +1.2.1,1.3.1,1.4.1,true +2.0.0,3.0.0,4.0.0,true +2.2.2,2.2.3-rc1,2.2.3,true +2.2.2,2.3.2-rc100,2.3.3,true +1.0.0-rc.1+build.1,1.2.3-beta,1.2.3-rc.1+build.123,true +3.3.3,3.3.3-alpha,3.3.4,false +2.2.2-rc.1,2.2.2+metadata,2.2.2-rc.10,false +1.1.1-rc.1,1.1.1-rc.3,1.1.1-rc.2,false \ No newline at end of file diff --git a/client/src/test/resources/semver/equal-to-semver.csv b/client/src/test/resources/semver/equal-to-semver.csv new file mode 100644 index 000000000..87d8db5ae --- /dev/null +++ b/client/src/test/resources/semver/equal-to-semver.csv @@ -0,0 +1,7 @@ +version1,version2,equals +1.1.1,1.1.1,true +1.1.1,1.1.1+metadata,false +1.1.1,1.1.1-rc.1,false +88.88.88,88.88.88,true +1.2.3----RC-SNAPSHOT.12.9.1--.12,1.2.3----RC-SNAPSHOT.12.9.1--.12,true +10.2.3-DEV-SNAPSHOT,10.2.3-SNAPSHOT-123,false \ No newline at end of file diff --git a/client/src/test/resources/semver/invalid-semantic-versions.csv b/client/src/test/resources/semver/invalid-semantic-versions.csv new file mode 100644 index 000000000..7a7f9fbcf --- /dev/null +++ b/client/src/test/resources/semver/invalid-semantic-versions.csv @@ -0,0 +1,28 @@ +invalid +1 +1.2 +1.alpha.2 ++invalid +-invalid +-invalid+invalid +-invalid.01 +alpha +alpha.beta +alpha.beta.1 +alpha.1 +alpha+beta +alpha_beta +alpha. +alpha.. +beta +-alpha. +1.2 +1.2.3.DEV +1.2-SNAPSHOT +1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788 +1.2-RC-SNAPSHOT +-1.0.3-gamma+b7718 ++justmeta +1.1.1+ +1.1.1- +#99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12 \ No newline at end of file diff --git a/client/src/test/resources/semver/valid-semantic-versions.csv b/client/src/test/resources/semver/valid-semantic-versions.csv new file mode 100644 index 000000000..f491e77f2 --- /dev/null +++ b/client/src/test/resources/semver/valid-semantic-versions.csv @@ -0,0 +1,25 @@ +higher,lower +1.1.2,1.1.1 +1.0.0,1.0.0-rc.1 +1.1.0-rc.1,1.0.0-beta.11 +1.0.0-beta.11,1.0.0-beta.2 +1.0.0-beta.2,1.0.0-beta +1.0.0-beta,1.0.0-alpha.beta +1.0.0-alpha.beta,1.0.0-alpha.1 +1.0.0-alpha.1,1.0.0-alpha +2.2.2-rc.2+metadata-lalala,2.2.2-rc.1.2 +1.2.3,0.0.4 +1.1.2+meta,1.1.2-prerelease+meta +1.0.0-beta,1.0.0-alpha +1.0.0-alpha0.valid,1.0.0-alpha.0valid +1.0.0-rc.1+build.1,1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay +10.2.3-DEV-SNAPSHOT,1.2.3-SNAPSHOT-123 +1.1.1-rc2,1.0.0-0A.is.legal +1.2.3----RC-SNAPSHOT.12.9.1--.12+788,1.2.3----R-S.12.9.1--.12+meta +1.2.3----RC-SNAPSHOT.12.9.1--.12.88,1.2.3----RC-SNAPSHOT.12.9.1--.12 +9223372036854775807.9223372036854775807.9223372036854775807,9223372036854775807.9223372036854775807.9223372036854775806 +1.1.1-alpha.beta.rc.build.java.pr.support.10,1.1.1-alpha.beta.rc.build.java.pr.support +1.1.2,1.1.1 +1.2.1,1.1.1 +2.1.1,1.1.1 +1.1.1-rc.1,1.1.1-rc.0 \ No newline at end of file From 4b12f7f473122286b974d0017b866015548c2d0b Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 10:26:44 -0700 Subject: [PATCH 57/88] added equalto semver matcher --- .../io/split/client/dtos/MatcherType.java | 5 +- .../split/engine/experiments/SplitParser.java | 15 ++--- .../engine/matchers/EqualToMatcherSemver.java | 57 +++++++++++++++++++ .../engine/matchers/EqualToSemverTest.java | 23 ++++++++ 4 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java create mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java diff --git a/client/src/main/java/io/split/client/dtos/MatcherType.java b/client/src/main/java/io/split/client/dtos/MatcherType.java index ec22baec7..1e93cb07c 100644 --- a/client/src/main/java/io/split/client/dtos/MatcherType.java +++ b/client/src/main/java/io/split/client/dtos/MatcherType.java @@ -30,5 +30,8 @@ public enum MatcherType { EQUAL_TO_BOOLEAN, /* Dependency Matcher */ - IN_SPLIT_TREATMENT + IN_SPLIT_TREATMENT, + + /* Semver matchers */ + EQUAL_TO_SEMVER } diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index da4f0edcc..a46277c46 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -9,16 +9,7 @@ import io.split.client.dtos.ConditionType; import io.split.client.dtos.MatcherType; import io.split.engine.evaluator.Labels; -import io.split.engine.matchers.AllKeysMatcher; -import io.split.engine.matchers.AttributeMatcher; -import io.split.engine.matchers.BetweenMatcher; -import io.split.engine.matchers.BooleanMatcher; -import io.split.engine.matchers.CombiningMatcher; -import io.split.engine.matchers.DependencyMatcher; -import io.split.engine.matchers.EqualToMatcher; -import io.split.engine.matchers.GreaterThanOrEqualToMatcher; -import io.split.engine.matchers.LessThanOrEqualToMatcher; -import io.split.engine.matchers.UserDefinedSegmentMatcher; +import io.split.engine.matchers.*; import io.split.engine.matchers.collections.ContainsAllOfSetMatcher; import io.split.engine.matchers.collections.ContainsAnyOfSetMatcher; import io.split.engine.matchers.collections.EqualToSetMatcher; @@ -193,6 +184,10 @@ private AttributeMatcher toMatcher(Matcher matcher) { + ". matcher.booleanMatcherData() MUST NOT BE null"); delegate = new BooleanMatcher(matcher.booleanMatcherData); break; + case EQUAL_TO_SEMVER: + checkNotNull(matcher.stringMatcherData); + delegate = new EqualToMatcherSemver(matcher.stringMatcherData); + break; default: throw new IllegalArgumentException("Unknown matcher type: " + matcher.matcherType); } diff --git a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java b/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java new file mode 100644 index 000000000..d2f249bea --- /dev/null +++ b/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java @@ -0,0 +1,57 @@ +package io.split.engine.matchers; + +import io.split.engine.evaluator.EvaluationContext; + +import java.util.Map; + +/** + * Created by adilaijaz on 3/7/16. + */ +public class EqualToMatcherSemver implements Matcher { + + private final Semver _semVer; + + public EqualToMatcherSemver(String dataType) { + _semVer = Semver.build(dataType.toString()); + } + + @Override + public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { + if (matchValue == null) { + return false; + } + Semver matchSemver = Semver.build(matchValue.toString()); + if (matchSemver == null) { + return false; + } + + return _semVer != null && matchSemver.Version().equals(_semVer.Version()); + } + + @Override + public String toString() { + StringBuilder bldr = new StringBuilder(); + bldr.append("== "); + bldr.append(_semVer); + return bldr.toString(); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + _semVer.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (!(obj instanceof EqualToMatcherSemver)) return false; + + EqualToMatcherSemver other = (EqualToMatcherSemver) obj; + + return _semVer == other._semVer; + } + +} diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java new file mode 100644 index 000000000..d04b1c911 --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java @@ -0,0 +1,23 @@ +package io.split.engine.matchers; + +import io.split.engine.matchers.EqualToMatcherSemver; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class EqualToSemverTest { + + @Test + public void works() { + EqualToMatcherSemver equalToMatcherSemver = new EqualToMatcherSemver("2.1.8"); + + assertTrue( equalToMatcherSemver.match("2.1.8", null, null, null) == true); + assertTrue( equalToMatcherSemver.match("2.1.9", null, null, null) == false); + assertTrue( equalToMatcherSemver.match("2.1.8-rc", null, null, null) == false); + assertTrue( equalToMatcherSemver.match("2.1.8+build", null, null, null) == false); + } +} From ac565aa5d18e10512bee98db51a441c6259e0a66 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 10:35:35 -0700 Subject: [PATCH 58/88] polish --- .../io/split/engine/experiments/SplitParser.java | 12 +++++++++++- .../split/engine/matchers/EqualToMatcherSemver.java | 7 ++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index a46277c46..bf11c8e92 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -9,7 +9,17 @@ import io.split.client.dtos.ConditionType; import io.split.client.dtos.MatcherType; import io.split.engine.evaluator.Labels; -import io.split.engine.matchers.*; +import io.split.engine.matchers.AllKeysMatcher; +import io.split.engine.matchers.AttributeMatcher; +import io.split.engine.matchers.BetweenMatcher; +import io.split.engine.matchers.BooleanMatcher; +import io.split.engine.matchers.CombiningMatcher; +import io.split.engine.matchers.DependencyMatcher; +import io.split.engine.matchers.EqualToMatcher; +import io.split.engine.matchers.GreaterThanOrEqualToMatcher; +import io.split.engine.matchers.LessThanOrEqualToMatcher; +import io.split.engine.matchers.UserDefinedSegmentMatcher; +import io.split.engine.matchers.EqualToMatcherSemver; import io.split.engine.matchers.collections.ContainsAllOfSetMatcher; import io.split.engine.matchers.collections.ContainsAnyOfSetMatcher; import io.split.engine.matchers.collections.EqualToSetMatcher; diff --git a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java b/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java index d2f249bea..918e6f244 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java @@ -4,15 +4,12 @@ import java.util.Map; -/** - * Created by adilaijaz on 3/7/16. - */ public class EqualToMatcherSemver implements Matcher { private final Semver _semVer; - public EqualToMatcherSemver(String dataType) { - _semVer = Semver.build(dataType.toString()); + public EqualToMatcherSemver(String semVer) { + _semVer = Semver.build(semVer); } @Override From 9d4b21e29e61d3edb7e3148aadfc698b32ba412e Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 11:04:14 -0700 Subject: [PATCH 59/88] added greater or equalto semver matcher --- .../io/split/client/dtos/MatcherType.java | 3 +- .../split/engine/experiments/SplitParser.java | 6 +++ .../GreaterThanOrEqualToSemverMatcher.java | 54 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java diff --git a/client/src/main/java/io/split/client/dtos/MatcherType.java b/client/src/main/java/io/split/client/dtos/MatcherType.java index 1e93cb07c..d1fd34f98 100644 --- a/client/src/main/java/io/split/client/dtos/MatcherType.java +++ b/client/src/main/java/io/split/client/dtos/MatcherType.java @@ -33,5 +33,6 @@ public enum MatcherType { IN_SPLIT_TREATMENT, /* Semver matchers */ - EQUAL_TO_SEMVER + EQUAL_TO_SEMVER, + GREATER_THAN_OR_EQUAL_TO_SEMVER } diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index bf11c8e92..839c36cf9 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -29,6 +29,8 @@ import io.split.engine.matchers.strings.RegularExpressionMatcher; import io.split.engine.matchers.strings.StartsWithAnyOfMatcher; import io.split.engine.matchers.strings.WhitelistMatcher; +import io.split.engine.matchers.GreaterThanOrEqualToSemverMatcher; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -198,6 +200,10 @@ private AttributeMatcher toMatcher(Matcher matcher) { checkNotNull(matcher.stringMatcherData); delegate = new EqualToMatcherSemver(matcher.stringMatcherData); break; + case GREATER_THAN_OR_EQUAL_TO_SEMVER: + checkNotNull(matcher.stringMatcherData); + delegate = new GreaterThanOrEqualToSemverMatcher(matcher.stringMatcherData); + break; default: throw new IllegalArgumentException("Unknown matcher type: " + matcher.matcherType); } diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java new file mode 100644 index 000000000..1cb50d32e --- /dev/null +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java @@ -0,0 +1,54 @@ +package io.split.engine.matchers; + +import io.split.engine.evaluator.EvaluationContext; + +import java.util.Map; + +public class GreaterThanOrEqualToSemverMatcher implements Matcher { + + private final Semver _semVer; + + public GreaterThanOrEqualToSemverMatcher(String semVer) { + _semVer = Semver.build(semVer); + } + + @Override + public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { + if (matchValue == null) { + return false; + } + Semver matchSemver = Semver.build(matchValue.toString()); + if (matchSemver == null) { + return false; + } + + return _semVer != null && matchSemver.Compare(_semVer) >= 0; + } + + @Override + public String toString() { + StringBuilder bldr = new StringBuilder(); + bldr.append("== "); + bldr.append(_semVer); + return bldr.toString(); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + _semVer.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (!(obj instanceof GreaterThanOrEqualToSemverMatcher)) return false; + + GreaterThanOrEqualToSemverMatcher other = (GreaterThanOrEqualToSemverMatcher) obj; + + return _semVer == other._semVer; + } + +} From b200a20ffd6da1d8cc41b623cbc84169b7225772 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 11:06:46 -0700 Subject: [PATCH 60/88] plish and test --- .../java/io/split/engine/matchers/Semver.java | 4 +++- .../GreaterThanOrEqualToSemverTest.java | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java index 82b16558b..ca1396d2c 100644 --- a/client/src/main/java/io/split/engine/matchers/Semver.java +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -5,6 +5,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.primitives.Ints; + +import java.sql.Array; import java.util.Arrays; public class Semver { @@ -17,7 +19,7 @@ public class Semver { private Long _major; private Long _minor; private Long _patch; - private String[] _preRelease; + private String[] _preRelease = new String[] {}; private boolean _isStable; private String _metadata; private String _version; diff --git a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java new file mode 100644 index 000000000..d981e3de9 --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java @@ -0,0 +1,23 @@ +package io.split.engine.matchers; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class GreaterThanOrEqualToSemverTest { + + @Test + public void works() { + GreaterThanOrEqualToSemverMatcher greaterThanOrEqualToSemverMatcher = new GreaterThanOrEqualToSemverMatcher("2.1.8"); + + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.9", null, null, null) == true); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null) == false); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.0.10", null, null, null) == false); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null) == true); + } +} From ab2fb7f8f89d5320f15322d227432b906baade70 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 11:07:51 -0700 Subject: [PATCH 61/88] polish --- client/src/main/java/io/split/engine/matchers/Semver.java | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java index ca1396d2c..36a1ab571 100644 --- a/client/src/main/java/io/split/engine/matchers/Semver.java +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory; import com.google.common.primitives.Ints; -import java.sql.Array; import java.util.Arrays; public class Semver { From d06e38e5095c041f94cddb2be89c9b96d9582b95 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 11:29:26 -0700 Subject: [PATCH 62/88] polish --- .../split/engine/experiments/SplitParser.java | 4 ++-- ...rSemver.java => EqualToSemverMatcher.java} | 8 +++---- .../matchers/EqualToSemverMatcherTest.java | 22 ++++++++++++++++++ .../engine/matchers/EqualToSemverTest.java | 23 ------------------- 4 files changed, 28 insertions(+), 29 deletions(-) rename client/src/main/java/io/split/engine/matchers/{EqualToMatcherSemver.java => EqualToSemverMatcher.java} (83%) create mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java delete mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index bf11c8e92..25e6605a0 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -19,7 +19,7 @@ import io.split.engine.matchers.GreaterThanOrEqualToMatcher; import io.split.engine.matchers.LessThanOrEqualToMatcher; import io.split.engine.matchers.UserDefinedSegmentMatcher; -import io.split.engine.matchers.EqualToMatcherSemver; +import io.split.engine.matchers.EqualToSemverMatcher; import io.split.engine.matchers.collections.ContainsAllOfSetMatcher; import io.split.engine.matchers.collections.ContainsAnyOfSetMatcher; import io.split.engine.matchers.collections.EqualToSetMatcher; @@ -196,7 +196,7 @@ private AttributeMatcher toMatcher(Matcher matcher) { break; case EQUAL_TO_SEMVER: checkNotNull(matcher.stringMatcherData); - delegate = new EqualToMatcherSemver(matcher.stringMatcherData); + delegate = new EqualToSemverMatcher(matcher.stringMatcherData); break; default: throw new IllegalArgumentException("Unknown matcher type: " + matcher.matcherType); diff --git a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java similarity index 83% rename from client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java rename to client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 918e6f244..7e652c6e1 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -4,11 +4,11 @@ import java.util.Map; -public class EqualToMatcherSemver implements Matcher { +public class EqualToSemverMatcher implements Matcher { private final Semver _semVer; - public EqualToMatcherSemver(String semVer) { + public EqualToSemverMatcher(String semVer) { _semVer = Semver.build(semVer); } @@ -44,9 +44,9 @@ public int hashCode() { public boolean equals(Object obj) { if (obj == null) return false; if (this == obj) return true; - if (!(obj instanceof EqualToMatcherSemver)) return false; + if (!(obj instanceof EqualToSemverMatcher)) return false; - EqualToMatcherSemver other = (EqualToMatcherSemver) obj; + EqualToSemverMatcher other = (EqualToSemverMatcher) obj; return _semVer == other._semVer; } diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java new file mode 100644 index 000000000..06cdd8a8d --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java @@ -0,0 +1,22 @@ +package io.split.engine.matchers; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class EqualToSemverMatcherTest { + + @Test + public void works() { + EqualToSemverMatcher equalToSemverMatcher = new EqualToSemverMatcher("2.1.8"); + + assertTrue( equalToSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( equalToSemverMatcher.match("2.1.9", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8-rc", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8+build", null, null, null) == false); + } +} diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java deleted file mode 100644 index d04b1c911..000000000 --- a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.split.engine.matchers; - -import io.split.engine.matchers.EqualToMatcherSemver; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * Tests for EqualToSemverMatcher - */ - -public class EqualToSemverTest { - - @Test - public void works() { - EqualToMatcherSemver equalToMatcherSemver = new EqualToMatcherSemver("2.1.8"); - - assertTrue( equalToMatcherSemver.match("2.1.8", null, null, null) == true); - assertTrue( equalToMatcherSemver.match("2.1.9", null, null, null) == false); - assertTrue( equalToMatcherSemver.match("2.1.8-rc", null, null, null) == false); - assertTrue( equalToMatcherSemver.match("2.1.8+build", null, null, null) == false); - } -} From dc30d424815091a4396bed8b46ab2c12e3536d37 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 11:45:11 -0700 Subject: [PATCH 63/88] polish --- .../split/engine/experiments/SplitParser.java | 4 ++-- ...rSemver.java => EqualToSemverMatcher.java} | 8 +++---- .../matchers/EqualToSemverMatcherTest.java | 22 ++++++++++++++++++ .../engine/matchers/EqualToSemverTest.java | 23 ------------------- ...reaterThanOrEqualToSemverMatcherTest.java} | 2 +- 5 files changed, 29 insertions(+), 30 deletions(-) rename client/src/main/java/io/split/engine/matchers/{EqualToMatcherSemver.java => EqualToSemverMatcher.java} (83%) create mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java delete mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java rename client/src/test/java/io/split/engine/matchers/{GreaterThanOrEqualToSemverTest.java => GreaterThanOrEqualToSemverMatcherTest.java} (93%) diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index 839c36cf9..ca303e4cd 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -19,7 +19,7 @@ import io.split.engine.matchers.GreaterThanOrEqualToMatcher; import io.split.engine.matchers.LessThanOrEqualToMatcher; import io.split.engine.matchers.UserDefinedSegmentMatcher; -import io.split.engine.matchers.EqualToMatcherSemver; +import io.split.engine.matchers.EqualToSemverMatcher; import io.split.engine.matchers.collections.ContainsAllOfSetMatcher; import io.split.engine.matchers.collections.ContainsAnyOfSetMatcher; import io.split.engine.matchers.collections.EqualToSetMatcher; @@ -198,7 +198,7 @@ private AttributeMatcher toMatcher(Matcher matcher) { break; case EQUAL_TO_SEMVER: checkNotNull(matcher.stringMatcherData); - delegate = new EqualToMatcherSemver(matcher.stringMatcherData); + delegate = new EqualToSemverMatcher(matcher.stringMatcherData); break; case GREATER_THAN_OR_EQUAL_TO_SEMVER: checkNotNull(matcher.stringMatcherData); diff --git a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java similarity index 83% rename from client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java rename to client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 918e6f244..7e652c6e1 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -4,11 +4,11 @@ import java.util.Map; -public class EqualToMatcherSemver implements Matcher { +public class EqualToSemverMatcher implements Matcher { private final Semver _semVer; - public EqualToMatcherSemver(String semVer) { + public EqualToSemverMatcher(String semVer) { _semVer = Semver.build(semVer); } @@ -44,9 +44,9 @@ public int hashCode() { public boolean equals(Object obj) { if (obj == null) return false; if (this == obj) return true; - if (!(obj instanceof EqualToMatcherSemver)) return false; + if (!(obj instanceof EqualToSemverMatcher)) return false; - EqualToMatcherSemver other = (EqualToMatcherSemver) obj; + EqualToSemverMatcher other = (EqualToSemverMatcher) obj; return _semVer == other._semVer; } diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java new file mode 100644 index 000000000..06cdd8a8d --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java @@ -0,0 +1,22 @@ +package io.split.engine.matchers; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class EqualToSemverMatcherTest { + + @Test + public void works() { + EqualToSemverMatcher equalToSemverMatcher = new EqualToSemverMatcher("2.1.8"); + + assertTrue( equalToSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( equalToSemverMatcher.match("2.1.9", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8-rc", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8+build", null, null, null) == false); + } +} diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java deleted file mode 100644 index d04b1c911..000000000 --- a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.split.engine.matchers; - -import io.split.engine.matchers.EqualToMatcherSemver; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * Tests for EqualToSemverMatcher - */ - -public class EqualToSemverTest { - - @Test - public void works() { - EqualToMatcherSemver equalToMatcherSemver = new EqualToMatcherSemver("2.1.8"); - - assertTrue( equalToMatcherSemver.match("2.1.8", null, null, null) == true); - assertTrue( equalToMatcherSemver.match("2.1.9", null, null, null) == false); - assertTrue( equalToMatcherSemver.match("2.1.8-rc", null, null, null) == false); - assertTrue( equalToMatcherSemver.match("2.1.8+build", null, null, null) == false); - } -} diff --git a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java similarity index 93% rename from client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java rename to client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java index d981e3de9..f65e74ba0 100644 --- a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java +++ b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java @@ -8,7 +8,7 @@ * Tests for EqualToSemverMatcher */ -public class GreaterThanOrEqualToSemverTest { +public class GreaterThanOrEqualToSemverMatcherTest { @Test public void works() { From f68827b683a3bdaffba513febca03d7ddc2d111f Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 26 Apr 2024 11:51:32 -0700 Subject: [PATCH 64/88] added less than or equal semver matcher --- .../io/split/client/dtos/MatcherType.java | 3 +- .../split/engine/experiments/SplitParser.java | 9 +++- ...rSemver.java => EqualToSemverMatcher.java} | 8 +-- .../LessThanOrEqualToSemverMatcher.java | 54 +++++++++++++++++++ .../matchers/EqualToSemverMatcherTest.java | 22 ++++++++ .../engine/matchers/EqualToSemverTest.java | 23 -------- ...reaterThanOrEqualToSemverMatcherTest.java} | 2 +- .../LessThanOrEqualToSemverMatcherTest.java | 23 ++++++++ 8 files changed, 113 insertions(+), 31 deletions(-) rename client/src/main/java/io/split/engine/matchers/{EqualToMatcherSemver.java => EqualToSemverMatcher.java} (83%) create mode 100644 client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java create mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java delete mode 100644 client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java rename client/src/test/java/io/split/engine/matchers/{GreaterThanOrEqualToSemverTest.java => GreaterThanOrEqualToSemverMatcherTest.java} (93%) create mode 100644 client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java diff --git a/client/src/main/java/io/split/client/dtos/MatcherType.java b/client/src/main/java/io/split/client/dtos/MatcherType.java index d1fd34f98..6e2b4e8c0 100644 --- a/client/src/main/java/io/split/client/dtos/MatcherType.java +++ b/client/src/main/java/io/split/client/dtos/MatcherType.java @@ -34,5 +34,6 @@ public enum MatcherType { /* Semver matchers */ EQUAL_TO_SEMVER, - GREATER_THAN_OR_EQUAL_TO_SEMVER + GREATER_THAN_OR_EQUAL_TO_SEMVER, + LESS_THAN_OR_EQUAL_TO_SEMVER } diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index 839c36cf9..f8ff61cb0 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -19,7 +19,7 @@ import io.split.engine.matchers.GreaterThanOrEqualToMatcher; import io.split.engine.matchers.LessThanOrEqualToMatcher; import io.split.engine.matchers.UserDefinedSegmentMatcher; -import io.split.engine.matchers.EqualToMatcherSemver; +import io.split.engine.matchers.EqualToSemverMatcher; import io.split.engine.matchers.collections.ContainsAllOfSetMatcher; import io.split.engine.matchers.collections.ContainsAnyOfSetMatcher; import io.split.engine.matchers.collections.EqualToSetMatcher; @@ -30,6 +30,7 @@ import io.split.engine.matchers.strings.StartsWithAnyOfMatcher; import io.split.engine.matchers.strings.WhitelistMatcher; import io.split.engine.matchers.GreaterThanOrEqualToSemverMatcher; +import io.split.engine.matchers.LessThanOrEqualToSemverMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -198,12 +199,16 @@ private AttributeMatcher toMatcher(Matcher matcher) { break; case EQUAL_TO_SEMVER: checkNotNull(matcher.stringMatcherData); - delegate = new EqualToMatcherSemver(matcher.stringMatcherData); + delegate = new EqualToSemverMatcher(matcher.stringMatcherData); break; case GREATER_THAN_OR_EQUAL_TO_SEMVER: checkNotNull(matcher.stringMatcherData); delegate = new GreaterThanOrEqualToSemverMatcher(matcher.stringMatcherData); break; + case LESS_THAN_OR_EQUAL_TO_SEMVER: + checkNotNull(matcher.stringMatcherData); + delegate = new LessThanOrEqualToSemverMatcher(matcher.stringMatcherData); + break; default: throw new IllegalArgumentException("Unknown matcher type: " + matcher.matcherType); } diff --git a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java similarity index 83% rename from client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java rename to client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 918e6f244..7e652c6e1 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToMatcherSemver.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -4,11 +4,11 @@ import java.util.Map; -public class EqualToMatcherSemver implements Matcher { +public class EqualToSemverMatcher implements Matcher { private final Semver _semVer; - public EqualToMatcherSemver(String semVer) { + public EqualToSemverMatcher(String semVer) { _semVer = Semver.build(semVer); } @@ -44,9 +44,9 @@ public int hashCode() { public boolean equals(Object obj) { if (obj == null) return false; if (this == obj) return true; - if (!(obj instanceof EqualToMatcherSemver)) return false; + if (!(obj instanceof EqualToSemverMatcher)) return false; - EqualToMatcherSemver other = (EqualToMatcherSemver) obj; + EqualToSemverMatcher other = (EqualToSemverMatcher) obj; return _semVer == other._semVer; } diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java new file mode 100644 index 000000000..73fad9510 --- /dev/null +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java @@ -0,0 +1,54 @@ +package io.split.engine.matchers; + +import io.split.engine.evaluator.EvaluationContext; + +import java.util.Map; + +public class LessThanOrEqualToSemverMatcher implements Matcher { + + private final Semver _semVer; + + public LessThanOrEqualToSemverMatcher(String semVer) { + _semVer = Semver.build(semVer); + } + + @Override + public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { + if (matchValue == null) { + return false; + } + Semver matchSemver = Semver.build(matchValue.toString()); + if (matchSemver == null) { + return false; + } + + return _semVer != null && matchSemver.Compare(_semVer) <= 0; + } + + @Override + public String toString() { + StringBuilder bldr = new StringBuilder(); + bldr.append("== "); + bldr.append(_semVer); + return bldr.toString(); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + _semVer.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (!(obj instanceof LessThanOrEqualToSemverMatcher)) return false; + + LessThanOrEqualToSemverMatcher other = (LessThanOrEqualToSemverMatcher) obj; + + return _semVer == other._semVer; + } + +} diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java new file mode 100644 index 000000000..06cdd8a8d --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java @@ -0,0 +1,22 @@ +package io.split.engine.matchers; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class EqualToSemverMatcherTest { + + @Test + public void works() { + EqualToSemverMatcher equalToSemverMatcher = new EqualToSemverMatcher("2.1.8"); + + assertTrue( equalToSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( equalToSemverMatcher.match("2.1.9", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8-rc", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8+build", null, null, null) == false); + } +} diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java deleted file mode 100644 index d04b1c911..000000000 --- a/client/src/test/java/io/split/engine/matchers/EqualToSemverTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.split.engine.matchers; - -import io.split.engine.matchers.EqualToMatcherSemver; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * Tests for EqualToSemverMatcher - */ - -public class EqualToSemverTest { - - @Test - public void works() { - EqualToMatcherSemver equalToMatcherSemver = new EqualToMatcherSemver("2.1.8"); - - assertTrue( equalToMatcherSemver.match("2.1.8", null, null, null) == true); - assertTrue( equalToMatcherSemver.match("2.1.9", null, null, null) == false); - assertTrue( equalToMatcherSemver.match("2.1.8-rc", null, null, null) == false); - assertTrue( equalToMatcherSemver.match("2.1.8+build", null, null, null) == false); - } -} diff --git a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java similarity index 93% rename from client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java rename to client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java index d981e3de9..f65e74ba0 100644 --- a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverTest.java +++ b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java @@ -8,7 +8,7 @@ * Tests for EqualToSemverMatcher */ -public class GreaterThanOrEqualToSemverTest { +public class GreaterThanOrEqualToSemverMatcherTest { @Test public void works() { diff --git a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java new file mode 100644 index 000000000..6be2333a5 --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java @@ -0,0 +1,23 @@ +package io.split.engine.matchers; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class LessThanOrEqualToSemverMatcherTest { + + @Test + public void works() { + LessThanOrEqualToSemverMatcher lessThanOrEqualToSemverMatcher = new LessThanOrEqualToSemverMatcher("2.1.8"); + + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.9", null, null, null) == false); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null) == true); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.0.10", null, null, null) == true); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null) == true); + } +} From 325d47df08cfd0bf7c3835f341157b22f6fd9ce0 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 29 Apr 2024 10:07:41 -0700 Subject: [PATCH 65/88] added inlist semver matcher --- .../io/split/client/dtos/MatcherType.java | 3 +- .../split/engine/experiments/SplitParser.java | 11 ++- .../engine/matchers/InListSemverMatcher.java | 78 +++++++++++++++++++ .../matchers/InListSemverMatcherTest.java | 27 +++++++ 4 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java create mode 100644 client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java diff --git a/client/src/main/java/io/split/client/dtos/MatcherType.java b/client/src/main/java/io/split/client/dtos/MatcherType.java index 6e2b4e8c0..81a157566 100644 --- a/client/src/main/java/io/split/client/dtos/MatcherType.java +++ b/client/src/main/java/io/split/client/dtos/MatcherType.java @@ -35,5 +35,6 @@ public enum MatcherType { /* Semver matchers */ EQUAL_TO_SEMVER, GREATER_THAN_OR_EQUAL_TO_SEMVER, - LESS_THAN_OR_EQUAL_TO_SEMVER + LESS_THAN_OR_EQUAL_TO_SEMVER, + IN_LIST_SEMVER } diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index f8ff61cb0..477d9db8f 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -31,6 +31,7 @@ import io.split.engine.matchers.strings.WhitelistMatcher; import io.split.engine.matchers.GreaterThanOrEqualToSemverMatcher; import io.split.engine.matchers.LessThanOrEqualToSemverMatcher; +import io.split.engine.matchers.InListSemverMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -198,17 +199,21 @@ private AttributeMatcher toMatcher(Matcher matcher) { delegate = new BooleanMatcher(matcher.booleanMatcherData); break; case EQUAL_TO_SEMVER: - checkNotNull(matcher.stringMatcherData); + checkNotNull(matcher.stringMatcherData, "stringMatcherData is required for EQUAL_TO_SEMVER matcher type"); delegate = new EqualToSemverMatcher(matcher.stringMatcherData); break; case GREATER_THAN_OR_EQUAL_TO_SEMVER: - checkNotNull(matcher.stringMatcherData); + checkNotNull(matcher.stringMatcherData, "stringMatcherData is required for GREATER_THAN_OR_EQUAL_TO_SEMVER matcher type"); delegate = new GreaterThanOrEqualToSemverMatcher(matcher.stringMatcherData); break; case LESS_THAN_OR_EQUAL_TO_SEMVER: - checkNotNull(matcher.stringMatcherData); + checkNotNull(matcher.stringMatcherData, "stringMatcherData is required for LESS_THAN_OR_EQUAL_SEMVER matcher type"); delegate = new LessThanOrEqualToSemverMatcher(matcher.stringMatcherData); break; + case IN_LIST_SEMVER: + checkNotNull(matcher.whitelistMatcherData, "whitelistMatcherData is required for IN_LIST_SEMVER matcher type"); + delegate = new InListSemverMatcher(matcher.whitelistMatcherData.whitelist); + break; default: throw new IllegalArgumentException("Unknown matcher type: " + matcher.matcherType); } diff --git a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java new file mode 100644 index 000000000..852fd66ee --- /dev/null +++ b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java @@ -0,0 +1,78 @@ +package io.split.engine.matchers; + +import io.split.engine.evaluator.EvaluationContext; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class InListSemverMatcher implements Matcher { + + private final Set _semverlist = new HashSet<>(); + + public InListSemverMatcher(Collection whitelist) { + for (String item : whitelist) { + Semver semver = Semver.build(item); + if (semver == null) continue; + + _semverlist.add(semver); + } + } + + @Override + public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { + if (matchValue == null) { + return false; + } + Semver matchSemver = Semver.build(matchValue.toString()); + if (matchSemver == null) { + return false; + } + + for (Semver semverItem : _semverlist) { + if (semverItem.Version().equals(matchSemver.Version())) return true; + + } + return false; + } + + @Override + public String toString() { + StringBuilder bldr = new StringBuilder(); + bldr.append("in semver list "); + boolean first = true; + + for (Semver item : _semverlist) { + if (!first) { + bldr.append(','); + } + bldr.append('"'); + bldr.append(item.Version()); + bldr.append('"'); + first = false; + } + + bldr.append("]"); + return bldr.toString(); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + _semverlist.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (!(obj instanceof InListSemverMatcher)) return false; + + InListSemverMatcher other = (InListSemverMatcher) obj; + + return _semverlist == other._semverlist; + } + +} diff --git a/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java new file mode 100644 index 000000000..d501c2363 --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java @@ -0,0 +1,27 @@ +package io.split.engine.matchers; + +import com.google.common.collect.Lists; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class InListSemverMatcherTest { + + @Test + public void works() { + List whitelist = Lists.newArrayList("2.1.8", "3.4.0"); + InListSemverMatcher inListSemverMatcher = new InListSemverMatcher(whitelist); + + assertTrue( inListSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( inListSemverMatcher.match("2.1.9", null, null, null) == false); + assertTrue( inListSemverMatcher.match("2.1.8-rc", null, null, null) == false); + assertTrue( inListSemverMatcher.match("3.4.0", null, null, null) == true); + assertTrue( inListSemverMatcher.match("3.4.0+build", null, null, null) == false); + } +} From d0a2f945605994bad780699468b5c1fc0d72e7a3 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 29 Apr 2024 10:11:49 -0700 Subject: [PATCH 66/88] polish --- .../java/io/split/engine/matchers/EqualToSemverMatcher.java | 2 +- .../engine/matchers/GreaterThanOrEqualToSemverMatcher.java | 2 +- .../split/engine/matchers/LessThanOrEqualToSemverMatcher.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 7e652c6e1..257b34b0f 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -29,7 +29,7 @@ public boolean match(Object matchValue, String bucketingKey, Map public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append("== "); - bldr.append(_semVer); + bldr.append(_semVer.Version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java index 1cb50d32e..7ba317cfb 100644 --- a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java @@ -29,7 +29,7 @@ public boolean match(Object matchValue, String bucketingKey, Map public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append("== "); - bldr.append(_semVer); + bldr.append(_semVer.Version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java index 73fad9510..bbbbb3554 100644 --- a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java @@ -29,7 +29,7 @@ public boolean match(Object matchValue, String bucketingKey, Map public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append("== "); - bldr.append(_semVer); + bldr.append(_semVer.Version()); return bldr.toString(); } From 249209cf5aa53683d6354360904866acb70e026d Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 29 Apr 2024 11:01:24 -0700 Subject: [PATCH 67/88] added between semver matcher --- .../client/dtos/BetweenStringMatcherData.java | 11 ++++ .../java/io/split/client/dtos/Matcher.java | 1 + .../io/split/client/dtos/MatcherType.java | 3 +- .../split/engine/experiments/SplitParser.java | 5 ++ .../engine/matchers/BetweenSemverMatcher.java | 58 +++++++++++++++++++ .../matchers/BetweenSemverMatcherTest.java | 22 +++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 client/src/main/java/io/split/client/dtos/BetweenStringMatcherData.java create mode 100644 client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java create mode 100644 client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java diff --git a/client/src/main/java/io/split/client/dtos/BetweenStringMatcherData.java b/client/src/main/java/io/split/client/dtos/BetweenStringMatcherData.java new file mode 100644 index 000000000..3af1cc0c1 --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/BetweenStringMatcherData.java @@ -0,0 +1,11 @@ +package io.split.client.dtos; + +/** + * Metadata to support the between matcher. + * + * @author adil + */ +public class BetweenStringMatcherData { + public String start; + public String end; +} diff --git a/client/src/main/java/io/split/client/dtos/Matcher.java b/client/src/main/java/io/split/client/dtos/Matcher.java index 12c824d2c..fc2c65155 100644 --- a/client/src/main/java/io/split/client/dtos/Matcher.java +++ b/client/src/main/java/io/split/client/dtos/Matcher.java @@ -13,6 +13,7 @@ public class Matcher { public WhitelistMatcherData whitelistMatcherData; public UnaryNumericMatcherData unaryNumericMatcherData; public BetweenMatcherData betweenMatcherData; + public BetweenStringMatcherData betweenStringMatcherData; public DependencyMatcherData dependencyMatcherData; public Boolean booleanMatcherData; public String stringMatcherData; diff --git a/client/src/main/java/io/split/client/dtos/MatcherType.java b/client/src/main/java/io/split/client/dtos/MatcherType.java index 81a157566..b8c78a7bd 100644 --- a/client/src/main/java/io/split/client/dtos/MatcherType.java +++ b/client/src/main/java/io/split/client/dtos/MatcherType.java @@ -36,5 +36,6 @@ public enum MatcherType { EQUAL_TO_SEMVER, GREATER_THAN_OR_EQUAL_TO_SEMVER, LESS_THAN_OR_EQUAL_TO_SEMVER, - IN_LIST_SEMVER + IN_LIST_SEMVER, + BETWEEN_SEMVER } diff --git a/client/src/main/java/io/split/engine/experiments/SplitParser.java b/client/src/main/java/io/split/engine/experiments/SplitParser.java index 477d9db8f..b320dff66 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitParser.java +++ b/client/src/main/java/io/split/engine/experiments/SplitParser.java @@ -32,6 +32,7 @@ import io.split.engine.matchers.GreaterThanOrEqualToSemverMatcher; import io.split.engine.matchers.LessThanOrEqualToSemverMatcher; import io.split.engine.matchers.InListSemverMatcher; +import io.split.engine.matchers.BetweenSemverMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -214,6 +215,10 @@ private AttributeMatcher toMatcher(Matcher matcher) { checkNotNull(matcher.whitelistMatcherData, "whitelistMatcherData is required for IN_LIST_SEMVER matcher type"); delegate = new InListSemverMatcher(matcher.whitelistMatcherData.whitelist); break; + case BETWEEN_SEMVER: + checkNotNull(matcher.betweenStringMatcherData, "betweenStringMatcherData is required for BETWEEN_SEMVER matcher type"); + delegate = new BetweenSemverMatcher(matcher.betweenStringMatcherData.start, matcher.betweenStringMatcherData.end); + break; default: throw new IllegalArgumentException("Unknown matcher type: " + matcher.matcherType); } diff --git a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java new file mode 100644 index 000000000..cf51cbcb6 --- /dev/null +++ b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java @@ -0,0 +1,58 @@ +package io.split.engine.matchers; + +import io.split.engine.evaluator.EvaluationContext; + +import java.util.Map; + +public class BetweenSemverMatcher implements Matcher { + + private final Semver _semverStart; + private final Semver _semverEnd; + + public BetweenSemverMatcher(String semverStart, String semverEnd) { + _semverStart = Semver.build(semverStart); + _semverEnd = Semver.build(semverEnd); + } + + @Override + public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { + if (matchValue == null) { + return false; + } + Semver matchSemver = Semver.build(matchValue.toString()); + if (matchSemver == null || _semverStart == null || _semverStart == null) { + return false; + } + + return matchSemver.Compare(_semverStart) >= 0 && matchSemver.Compare(_semverEnd) <= 0; + } + + @Override + public String toString() { + StringBuilder bldr = new StringBuilder(); + bldr.append("between semver "); + bldr.append(_semverStart.Version()); + bldr.append(" and "); + bldr.append(_semverEnd.Version()); + return bldr.toString(); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + _semverStart.hashCode() + _semverEnd.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (!(obj instanceof BetweenSemverMatcher)) return false; + + BetweenSemverMatcher other = (BetweenSemverMatcher) obj; + + return _semverStart == other._semverStart && _semverEnd == other._semverEnd; + } + +} diff --git a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java new file mode 100644 index 000000000..87f6bf57c --- /dev/null +++ b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java @@ -0,0 +1,22 @@ +package io.split.engine.matchers; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for EqualToSemverMatcher + */ + +public class BetweenSemverMatcherTest { + + @Test + public void works() { + BetweenSemverMatcher betweenSemverMatcher = new BetweenSemverMatcher("2.1.8", "3.0.0"); + + assertTrue( betweenSemverMatcher.match("2.1.8", null, null, null) == true); + assertTrue( betweenSemverMatcher.match("2.1.9", null, null, null) == true); + assertTrue( betweenSemverMatcher.match("2.1.8-rc", null, null, null) == false); + assertTrue( betweenSemverMatcher.match("3.0.0+build", null, null, null) == true); + } +} From 110c038f1f062387d6ea81c7609e031dbf43fa3a Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 29 Apr 2024 11:07:39 -0700 Subject: [PATCH 68/88] polish --- .../java/io/split/engine/matchers/BetweenSemverMatcher.java | 2 +- .../java/io/split/engine/matchers/BetweenSemverMatcherTest.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java index cf51cbcb6..5d79a2c5a 100644 --- a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java @@ -20,7 +20,7 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } Semver matchSemver = Semver.build(matchValue.toString()); - if (matchSemver == null || _semverStart == null || _semverStart == null) { + if (matchSemver == null || _semverStart == null || _semverEnd == null) { return false; } diff --git a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java index 87f6bf57c..8c0ce665d 100644 --- a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java @@ -18,5 +18,7 @@ public void works() { assertTrue( betweenSemverMatcher.match("2.1.9", null, null, null) == true); assertTrue( betweenSemverMatcher.match("2.1.8-rc", null, null, null) == false); assertTrue( betweenSemverMatcher.match("3.0.0+build", null, null, null) == true); + assertTrue( betweenSemverMatcher.match("4.5.8", null, null, null) == false); + assertTrue( betweenSemverMatcher.match("1.0.4", null, null, null) == false); } } From 5d0cf8a8f667b43ad61ba6e6336e84d0ce92ec42 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 29 Apr 2024 13:51:03 -0700 Subject: [PATCH 69/88] updated unsupported matcher label --- client/src/main/java/io/split/engine/evaluator/Labels.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/evaluator/Labels.java b/client/src/main/java/io/split/engine/evaluator/Labels.java index 59cfceefb..ac5a465a9 100644 --- a/client/src/main/java/io/split/engine/evaluator/Labels.java +++ b/client/src/main/java/io/split/engine/evaluator/Labels.java @@ -6,5 +6,5 @@ public class Labels { public static final String KILLED = "killed"; public static final String DEFINITION_NOT_FOUND = "definition not found"; public static final String EXCEPTION = "exception"; - public static final String UNSUPPORTED_MATCHER = "unsupported matcher type"; + public static final String UNSUPPORTED_MATCHER = "targeting rule type unsupported by sdk"; } \ No newline at end of file From 2e0dbbb4ae11eecb40a27e9ab72d3af9e7a074e6 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 30 Apr 2024 14:07:01 -0700 Subject: [PATCH 70/88] added spec to splitchanges and auth urls, and updated tests --- client/src/main/java/io/split/Spec.java | 11 + .../split/client/HttpSplitChangeFetcher.java | 12 +- .../engine/matchers/EqualToSemverMatcher.java | 2 +- .../GreaterThanOrEqualToSemverMatcher.java | 2 +- .../engine/matchers/InListSemverMatcher.java | 2 +- .../LessThanOrEqualToSemverMatcher.java | 2 +- .../io/split/engine/sse/AuthApiClientImp.java | 4 +- .../split/client/utils/CustomDispatcher.java | 20 +- .../engine/experiments/SplitParserTest.java | 116 ++++- .../test/resources/semver/semver-splits.json | 431 ++++++++++++++++++ 10 files changed, 582 insertions(+), 20 deletions(-) create mode 100644 client/src/main/java/io/split/Spec.java create mode 100644 client/src/test/resources/semver/semver-splits.json diff --git a/client/src/main/java/io/split/Spec.java b/client/src/main/java/io/split/Spec.java new file mode 100644 index 000000000..9e03a59ab --- /dev/null +++ b/client/src/main/java/io/split/Spec.java @@ -0,0 +1,11 @@ +package io.split; + +public final class Spec { + + private Spec() { + // restrict instantiation + } + + public static final String SPEC_VERSION = "1.1"; +} + diff --git a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java index fcf4502d2..9f8d2036b 100644 --- a/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/HttpSplitChangeFetcher.java @@ -1,6 +1,7 @@ package io.split.client; import com.google.common.annotations.VisibleForTesting; + import io.split.client.dtos.SplitChange; import io.split.client.dtos.SplitHttpResponse; import io.split.client.exceptions.UriTooLongException; @@ -21,6 +22,7 @@ import java.net.URISyntaxException; import static com.google.common.base.Preconditions.checkNotNull; +import static io.split.Spec.SPEC_VERSION; /** * Created by adilaijaz on 5/30/15. @@ -31,6 +33,7 @@ public final class HttpSplitChangeFetcher implements SplitChangeFetcher { private static final String SINCE = "since"; private static final String TILL = "till"; private static final String SETS = "sets"; + private static final String SPEC = "s"; private final SplitHttpClient _client; private final URI _target; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; @@ -58,13 +61,14 @@ public SplitChange fetch(long since, FetchOptions options) { long start = System.currentTimeMillis(); try { - URIBuilder uriBuilder = new URIBuilder(_target).addParameter(SINCE, "" + since); - if (options.hasCustomCN()) { - uriBuilder.addParameter(TILL, "" + options.targetCN()); - } + URIBuilder uriBuilder = new URIBuilder(_target).addParameter(SPEC, "" + SPEC_VERSION); + uriBuilder.addParameter(SINCE, "" + since); if (!options.flagSetsFilter().isEmpty()) { uriBuilder.addParameter(SETS, "" + options.flagSetsFilter()); } + if (options.hasCustomCN()) { + uriBuilder.addParameter(TILL, "" + options.targetCN()); + } URI uri = uriBuilder.build(); SplitHttpResponse response = _client.get(uri, options, null); diff --git a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 257b34b0f..e2b0f2496 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -28,7 +28,7 @@ public boolean match(Object matchValue, String bucketingKey, Map @Override public String toString() { StringBuilder bldr = new StringBuilder(); - bldr.append("== "); + bldr.append("== semver "); bldr.append(_semVer.Version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java index 7ba317cfb..3c0b27780 100644 --- a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java @@ -28,7 +28,7 @@ public boolean match(Object matchValue, String bucketingKey, Map @Override public String toString() { StringBuilder bldr = new StringBuilder(); - bldr.append("== "); + bldr.append(">= semver "); bldr.append(_semVer.Version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java index 852fd66ee..0ba5db438 100644 --- a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java @@ -40,7 +40,7 @@ public boolean match(Object matchValue, String bucketingKey, Map @Override public String toString() { StringBuilder bldr = new StringBuilder(); - bldr.append("in semver list "); + bldr.append("in semver list ["); boolean first = true; for (Semver item : _semverlist) { diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java index bbbbb3554..b7134acc4 100644 --- a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java @@ -28,7 +28,7 @@ public boolean match(Object matchValue, String bucketingKey, Map @Override public String toString() { StringBuilder bldr = new StringBuilder(); - bldr.append("== "); + bldr.append("<= semver "); bldr.append(_semVer.Version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java index c500cf0dc..28464ebda 100644 --- a/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java +++ b/client/src/main/java/io/split/engine/sse/AuthApiClientImp.java @@ -18,10 +18,12 @@ import java.net.URI; import static com.google.common.base.Preconditions.checkNotNull; +import static io.split.Spec.SPEC_VERSION; public class AuthApiClientImp implements AuthApiClient { private static final Logger _log = LoggerFactory.getLogger(AuthApiClientImp.class); + private static final String SPEC = "s"; private final SplitHttpClient _httpClient; private final String _target; private final TelemetryRuntimeProducer _telemetryRuntimeProducer; @@ -36,7 +38,7 @@ public AuthApiClientImp(String url, SplitHttpClient httpClient, TelemetryRuntime public AuthenticationResponse Authenticate() { try { long initTime = System.currentTimeMillis(); - URI uri = new URIBuilder(_target).build(); + URI uri = new URIBuilder(_target).addParameter(SPEC, "" + SPEC_VERSION).build(); SplitHttpResponse response = _httpClient.get(uri, new FetchOptions.Builder().cacheControlHeaders(false).build(), null); Integer statusCode = response.statusCode(); diff --git a/client/src/test/java/io/split/client/utils/CustomDispatcher.java b/client/src/test/java/io/split/client/utils/CustomDispatcher.java index 62316b7a0..0b680156b 100644 --- a/client/src/test/java/io/split/client/utils/CustomDispatcher.java +++ b/client/src/test/java/io/split/client/utils/CustomDispatcher.java @@ -9,16 +9,16 @@ import java.util.*; public class CustomDispatcher extends Dispatcher { - public static final String INITIAL_SPLIT_CHANGES = "/api/splitChanges?since=-1"; - public static final String INITIAL_FLAGS_BY_SETS = "/api/splitChanges?since=-1&sets=set1%2Cset2"; - public static final String SINCE_1602796638344 = "/api/splitChanges?since=1602796638344&sets=set1%2Cset2"; - public static final String AUTH_ENABLED = "/api/auth/enabled"; - public static final String AUTH_DISABLED = "/api/auth/disabled"; - public static final String SINCE_1585948850109 = "/api/splitChanges?since=1585948850109"; - public static final String SINCE_1585948850109_FLAG_SET = "/api/splitChanges?since=-1&sets=set_1%2Cset_2"; - public static final String SINCE_1585948850110 = "/api/splitChanges?since=1585948850110"; - public static final String SINCE_1585948850111 = "/api/splitChanges?since=1585948850111"; - public static final String SINCE_1585948850112 = "/api/splitChanges?since=1585948850112"; + public static final String INITIAL_SPLIT_CHANGES = "/api/splitChanges?s=1.1&since=-1"; + public static final String INITIAL_FLAGS_BY_SETS = "/api/splitChanges?s=1.1&since=-1&sets=set1%2Cset2"; + public static final String SINCE_1602796638344 = "/api/splitChanges?s=1.1&since=1602796638344&sets=set1%2Cset2"; + public static final String AUTH_ENABLED = "/api/auth/enabled?s=1.1"; + public static final String AUTH_DISABLED = "/api/auth/disabled?s=1.1"; + public static final String SINCE_1585948850109 = "/api/splitChanges?s=1.1&since=1585948850109"; + public static final String SINCE_1585948850109_FLAG_SET = "/api/splitChanges?s=1.1&since=-1&sets=set_1%2Cset_2"; + public static final String SINCE_1585948850110 = "/api/splitChanges?s=1.1&since=1585948850110"; + public static final String SINCE_1585948850111 = "/api/splitChanges?s=1.1&since=1585948850111"; + public static final String SINCE_1585948850112 = "/api/splitChanges?s=1.1&since=1585948850112"; public static final String SEGMENT_TEST_INITIAL = "/api/segmentChanges/segment-test?since=-1"; public static final String SEGMENT3_INITIAL = "/api/segmentChanges/segment3?since=-1"; public static final String SEGMENT3_SINCE_1585948850110 = "/api/segmentChanges/segment3?since=1585948850110"; diff --git a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java index 8fa28c375..928ec6178 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java @@ -30,6 +30,10 @@ import org.junit.Test; import org.mockito.Mockito; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -533,7 +537,7 @@ public void contains_string() { } @Test - public void unsupportedMatcher() { + public void UnsupportedMatcher() { SplitParser parser = new SplitParser(); String splitWithUndefinedMatcher = "{\"since\":-1,\"till\": 1457726098069,\"splits\": [{ \"changeNumber\": 123, \"trafficTypeName\": \"user\", \"name\": \"some_name\"," + "\"trafficAllocation\": 100, \"trafficAllocationSeed\": 123456, \"seed\": 321654, \"status\": \"ACTIVE\"," @@ -555,6 +559,116 @@ public void unsupportedMatcher() { } } + @Test + public void EqualToSemverMatcher() throws IOException { + SplitParser parser = new SplitParser(); + String splits = new String(Files.readAllBytes(Paths.get("src/test/resources/semver/semver-splits.json")), StandardCharsets.UTF_8); + SplitChange change = Json.fromJson(splits, SplitChange.class); + for (Split split : change.splits) { + // should not cause exception + ParsedSplit parsedSplit = parser.parse(split); + if (split.name.equals("semver_equalto")) { + for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + assertTrue(parsedCondition.label().equals("equal to semver")); + for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { + // Check the matcher is ALL_KEYS + assertTrue(matcher.matcher().toString().equals(" == semver 1\\.22\\.9")); + return; + } + } + } + } + assertTrue(false); + } + + @Test + public void GreaterThanOrEqualSemverMatcher() throws IOException { + SplitParser parser = new SplitParser(); + String splits = new String(Files.readAllBytes(Paths.get("src/test/resources/semver/semver-splits.json")), StandardCharsets.UTF_8); + SplitChange change = Json.fromJson(splits, SplitChange.class); + for (Split split : change.splits) { + // should not cause exception + ParsedSplit parsedSplit = parser.parse(split); + if (split.name.equals("semver_greater_or_equalto")) { + for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + assertTrue(parsedCondition.label().equals("greater than or equal to semver")); + for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { + // Check the matcher is ALL_KEYS + assertTrue(matcher.matcher().toString().equals(" >= semver 1\\.22\\.9")); + return; + } + } + } + } + assertTrue(false); + } + + @Test + public void LessThanOrEqualSemverMatcher() throws IOException { + SplitParser parser = new SplitParser(); + String splits = new String(Files.readAllBytes(Paths.get("src/test/resources/semver/semver-splits.json")), StandardCharsets.UTF_8); + SplitChange change = Json.fromJson(splits, SplitChange.class); + for (Split split : change.splits) { + // should not cause exception + ParsedSplit parsedSplit = parser.parse(split); + if (split.name.equals("semver_less_or_equalto")) { + for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + assertTrue(parsedCondition.label().equals("less than or equal to semver")); + for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { + // Check the matcher is ALL_KEYS + assertTrue(matcher.matcher().toString().equals(" <= semver 1\\.22\\.9")); + return; + } + } + } + } + assertTrue(false); + } + + @Test + public void BetweenSemverMatcher() throws IOException { + SplitParser parser = new SplitParser(); + String splits = new String(Files.readAllBytes(Paths.get("src/test/resources/semver/semver-splits.json")), StandardCharsets.UTF_8); + SplitChange change = Json.fromJson(splits, SplitChange.class); + for (Split split : change.splits) { + // should not cause exception + ParsedSplit parsedSplit = parser.parse(split); + if (split.name.equals("semver_between")) { + for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + assertTrue(parsedCondition.label().equals("between semver")); + for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { + // Check the matcher is ALL_KEYS + assertTrue(matcher.matcher().toString().equals(" between semver 1\\.22\\.9 and 2\\.1\\.0")); + return; + } + } + } + } + assertTrue(false); + } + + @Test + public void InListSemverMatcher() throws IOException { + SplitParser parser = new SplitParser(); + String splits = new String(Files.readAllBytes(Paths.get("src/test/resources/semver/semver-splits.json")), StandardCharsets.UTF_8); + SplitChange change = Json.fromJson(splits, SplitChange.class); + for (Split split : change.splits) { + // should not cause exception + ParsedSplit parsedSplit = parser.parse(split); + if (split.name.equals("semver_inlist")) { + for (ParsedCondition parsedCondition : parsedSplit.parsedConditions()) { + assertTrue(parsedCondition.label().equals("in list semver")); + for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { + // Check the matcher is ALL_KEYS + assertTrue(matcher.matcher().toString().equals(" in semver list [\"1\\.22\\.9\",\"2\\.1\\.0\"]")); + return; + } + } + } + } + assertTrue(false); + } + public void set_matcher_test(Condition c, io.split.engine.matchers.Matcher m) { // SegmentSynchronizationTask segmentFetcher = new SegmentSynchronizationTaskImp(fetcherMap); diff --git a/client/src/test/resources/semver/semver-splits.json b/client/src/test/resources/semver/semver-splits.json new file mode 100644 index 000000000..a7e58689e --- /dev/null +++ b/client/src/test/resources/semver/semver-splits.json @@ -0,0 +1,431 @@ +{ + "splits":[ + { + "trafficTypeName":"user", + "name":"semver_between", + "trafficAllocation":100, + "trafficAllocationSeed":1068038034, + "seed":-1053389887, + "status":"ACTIVE", + "killed":false, + "defaultTreatment":"off", + "changeNumber":1675259356568, + "algo":2, + "configurations":null, + "conditions":[ + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":"version" + }, + "matcherType":"BETWEEN_SEMVER", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "dependencyMatcherData":null, + "booleanMatcherData":null, + "stringMatcherData":null, + "betweenStringMatcherData":{ + "start":"1.22.9", + "end":"2.1.0" + } + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":100 + }, + { + "treatment":"off", + "size":0 + } + ], + "label":"between semver" + }, + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":null + }, + "matcherType":"ALL_KEYS", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "booleanMatcherData":null, + "dependencyMatcherData":null, + "stringMatcherData":null + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":0 + }, + { + "treatment":"off", + "size":100 + } + ], + "label":"default rule" + } + ] + }, + { + "trafficTypeName":"user", + "name":"semver_equalto", + "trafficAllocation":100, + "trafficAllocationSeed":1068038034, + "seed":-1053389887, + "status":"ACTIVE", + "killed":false, + "defaultTreatment":"off", + "changeNumber":1675259356568, + "algo":2, + "configurations":null, + "conditions":[ + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":"version" + }, + "matcherType":"EQUAL_TO_SEMVER", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "dependencyMatcherData":null, + "booleanMatcherData":null, + "stringMatcherData":"1.22.9" + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":100 + }, + { + "treatment":"off", + "size":0 + } + ], + "label":"equal to semver" + }, + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":null + }, + "matcherType":"ALL_KEYS", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "booleanMatcherData":null, + "dependencyMatcherData":null, + "stringMatcherData":null + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":0 + }, + { + "treatment":"off", + "size":100 + } + ], + "label":"default rule" + } + ] + }, + { + "trafficTypeName":"user", + "name":"semver_greater_or_equalto", + "trafficAllocation":100, + "trafficAllocationSeed":1068038034, + "seed":-1053389887, + "status":"ACTIVE", + "killed":false, + "defaultTreatment":"off", + "changeNumber":1675259356568, + "algo":2, + "configurations":null, + "conditions":[ + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":"version" + }, + "matcherType":"GREATER_THAN_OR_EQUAL_TO_SEMVER", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "dependencyMatcherData":null, + "booleanMatcherData":null, + "stringMatcherData":"1.22.9" + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":100 + }, + { + "treatment":"off", + "size":0 + } + ], + "label":"greater than or equal to semver" + }, + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":null + }, + "matcherType":"ALL_KEYS", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "booleanMatcherData":null, + "dependencyMatcherData":null, + "stringMatcherData":null + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":0 + }, + { + "treatment":"off", + "size":100 + } + ], + "label":"default rule" + } + ] + }, + { + "trafficTypeName":"user", + "name":"semver_inlist", + "trafficAllocation":100, + "trafficAllocationSeed":1068038034, + "seed":-1053389887, + "status":"ACTIVE", + "killed":false, + "defaultTreatment":"off", + "changeNumber":1675259356568, + "algo":2, + "configurations":null, + "conditions":[ + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":"version" + }, + "matcherType":"IN_LIST_SEMVER", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":{ + "whitelist":[ + "1.22.9", + "2.1.0" + ] + }, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "dependencyMatcherData":null, + "booleanMatcherData":null, + "stringMatcherData":null, + "betweenStringMatcherData":null + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":100 + }, + { + "treatment":"off", + "size":0 + } + ], + "label":"in list semver" + }, + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":null + }, + "matcherType":"ALL_KEYS", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "booleanMatcherData":null, + "dependencyMatcherData":null, + "stringMatcherData":null + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":0 + }, + { + "treatment":"off", + "size":100 + } + ], + "label":"default rule" + } + ] + }, + { + "trafficTypeName":"user", + "name":"semver_less_or_equalto", + "trafficAllocation":100, + "trafficAllocationSeed":1068038034, + "seed":-1053389887, + "status":"ACTIVE", + "killed":false, + "defaultTreatment":"off", + "changeNumber":1675259356568, + "algo":2, + "configurations":null, + "conditions":[ + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":"version" + }, + "matcherType":"LESS_THAN_OR_EQUAL_TO_SEMVER", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "dependencyMatcherData":null, + "booleanMatcherData":null, + "stringMatcherData":"1.22.9" + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":100 + }, + { + "treatment":"off", + "size":0 + } + ], + "label":"less than or equal to semver" + }, + { + "conditionType":"ROLLOUT", + "matcherGroup":{ + "combiner":"AND", + "matchers":[ + { + "keySelector":{ + "trafficType":"user", + "attribute":null + }, + "matcherType":"ALL_KEYS", + "negate":false, + "userDefinedSegmentMatcherData":null, + "whitelistMatcherData":null, + "unaryNumericMatcherData":null, + "betweenMatcherData":null, + "booleanMatcherData":null, + "dependencyMatcherData":null, + "stringMatcherData":null + } + ] + }, + "partitions":[ + { + "treatment":"on", + "size":0 + }, + { + "treatment":"off", + "size":100 + } + ], + "label":"default rule" + } + ] + } + ], + "since":-1, + "till":1675259356568 +} \ No newline at end of file From 630363eface633e40ccd8b163331c7d9648bf4ab Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Tue, 30 Apr 2024 14:41:23 -0700 Subject: [PATCH 71/88] fix test --- .../test/java/io/split/engine/experiments/SplitParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java index 928ec6178..5eb013b62 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitParserTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitParserTest.java @@ -660,7 +660,7 @@ public void InListSemverMatcher() throws IOException { assertTrue(parsedCondition.label().equals("in list semver")); for (AttributeMatcher matcher : parsedCondition.matcher().attributeMatchers()) { // Check the matcher is ALL_KEYS - assertTrue(matcher.matcher().toString().equals(" in semver list [\"1\\.22\\.9\",\"2\\.1\\.0\"]")); + assertTrue(matcher.matcher().toString().startsWith(" in semver list")); return; } } From 90cb6020dfdb2625214d775dc548bc373db59cd7 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 2 May 2024 14:15:25 -0700 Subject: [PATCH 72/88] added removing zero leading numbers in pre release --- .../java/io/split/engine/matchers/Semver.java | 25 ++++++++++++++++--- .../io/split/engine/matchers/SemverTest.java | 6 ++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java index 82b16558b..6807c9e6c 100644 --- a/client/src/main/java/io/split/engine/matchers/Semver.java +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -143,14 +143,22 @@ private void setMajorMinorAndPatch(String version) throws SemverParseException { String[] vParts = version.split(ValueDelimiter); if (vParts.length != 3) throw new SemverParseException("Unable to convert to Semver, incorrect format: " + version); - _major = Long.parseUnsignedLong(vParts[0]); - _minor = Long.parseUnsignedLong(vParts[1]); - _patch = Long.parseUnsignedLong(vParts[2]); + _major = Long.parseLong(vParts[0]); + _minor = Long.parseLong(vParts[1]); + _patch = Long.parseLong(vParts[2]); } private String setVersion() { String toReturn = _major + ValueDelimiter + _minor + ValueDelimiter + _patch; - if (_preRelease != null && _preRelease.length != 0) { + if (_preRelease != null && _preRelease.length != 0) + { + for (int i = 0; i < _preRelease.length; i++) + { + if (isNumeric(_preRelease[i])) + { + _preRelease[i] = Long.toString(Long.parseLong(_preRelease[i])); + } + } toReturn = toReturn + PreReleaseDelimiter + String.join(ValueDelimiter, _preRelease); } if (_metadata != null && !_metadata.isEmpty()) { @@ -158,4 +166,13 @@ private String setVersion() { } return toReturn; } + + private static boolean isNumeric(String str) { + try { + Double.parseDouble(str); + return true; + } catch(NumberFormatException e){ + return false; + } + } } diff --git a/client/src/test/java/io/split/engine/matchers/SemverTest.java b/client/src/test/java/io/split/engine/matchers/SemverTest.java index 42cae6ec9..b02bd3909 100644 --- a/client/src/test/java/io/split/engine/matchers/SemverTest.java +++ b/client/src/test/java/io/split/engine/matchers/SemverTest.java @@ -105,5 +105,9 @@ public void testCompareVersions() throws IOException { } } - + @Test + public void testLeadingZeros() { + assertTrue(Semver.build("1.01.2").Version().equals("1\\.1\\.2")); + assertTrue(Semver.build("1.01.2-rc.01").Version().equals("1\\.1\\.2-rc\\.1")); + } } From f3dbbbc5a6709d5ae32e58e05c04afb6fa117ece Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 2 May 2024 15:49:45 -0700 Subject: [PATCH 73/88] polish --- .../split/engine/matchers/EqualToSemverMatcherTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java index 06cdd8a8d..28ecd15f6 100644 --- a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; /** * Tests for EqualToSemverMatcher @@ -14,9 +15,9 @@ public class EqualToSemverMatcherTest { public void works() { EqualToSemverMatcher equalToSemverMatcher = new EqualToSemverMatcher("2.1.8"); - assertTrue( equalToSemverMatcher.match("2.1.8", null, null, null) == true); - assertTrue( equalToSemverMatcher.match("2.1.9", null, null, null) == false); - assertTrue( equalToSemverMatcher.match("2.1.8-rc", null, null, null) == false); - assertTrue( equalToSemverMatcher.match("2.1.8+build", null, null, null) == false); + assertTrue( equalToSemverMatcher.match("2.1.8", null, null, null)); + assertFalse(equalToSemverMatcher.match("2.1.9", null, null, null)); + assertFalse(equalToSemverMatcher.match("2.1.8-rc", null, null, null)); + assertFalse( equalToSemverMatcher.match("2.1.8+build", null, null, null)); } } From 84af71b22965fb8a3a5df3608dfe6163fa605ac7 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 2 May 2024 15:56:53 -0700 Subject: [PATCH 74/88] polish --- .../GreaterThanOrEqualToSemverMatcherTest.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java index f65e74ba0..5cd90cb4d 100644 --- a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; /** * Tests for EqualToSemverMatcher @@ -14,10 +15,10 @@ public class GreaterThanOrEqualToSemverMatcherTest { public void works() { GreaterThanOrEqualToSemverMatcher greaterThanOrEqualToSemverMatcher = new GreaterThanOrEqualToSemverMatcher("2.1.8"); - assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8", null, null, null) == true); - assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.9", null, null, null) == true); - assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null) == false); - assertTrue( greaterThanOrEqualToSemverMatcher.match("2.0.10", null, null, null) == false); - assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null) == true); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8", null, null, null)); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.9", null, null, null)); + assertFalse( greaterThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null)); + assertFalse( greaterThanOrEqualToSemverMatcher.match("2.0.10", null, null, null)); + assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null)); } } From 28ef21004ded9798c5c535242462bc64b8e6c1a0 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 2 May 2024 16:01:48 -0700 Subject: [PATCH 75/88] polish --- .../matchers/LessThanOrEqualToSemverMatcher.java | 4 ++-- .../matchers/LessThanOrEqualToSemverMatcherTest.java | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java index 73fad9510..ace533d34 100644 --- a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java @@ -14,7 +14,7 @@ public LessThanOrEqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null) { + if (matchValue == null || _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -22,7 +22,7 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return _semVer != null && matchSemver.Compare(_semVer) <= 0; + return matchSemver.Compare(_semVer) <= 0; } @Override diff --git a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java index 6be2333a5..ad12dc8c4 100644 --- a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; /** * Tests for EqualToSemverMatcher @@ -14,10 +15,10 @@ public class LessThanOrEqualToSemverMatcherTest { public void works() { LessThanOrEqualToSemverMatcher lessThanOrEqualToSemverMatcher = new LessThanOrEqualToSemverMatcher("2.1.8"); - assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8", null, null, null) == true); - assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.9", null, null, null) == false); - assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null) == true); - assertTrue( lessThanOrEqualToSemverMatcher.match("2.0.10", null, null, null) == true); - assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null) == true); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8", null, null, null)); + assertFalse( lessThanOrEqualToSemverMatcher.match("2.1.9", null, null, null)); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null)); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.0.10", null, null, null)); + assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null)); } } From 780ceeeb673facbfe6f57626be7c56551c685e71 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Thu, 2 May 2024 16:07:34 -0700 Subject: [PATCH 76/88] polish --- .../split/engine/matchers/BetweenSemverMatcher.java | 4 ++-- .../engine/matchers/BetweenSemverMatcherTest.java | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java index 5d79a2c5a..a36d9c6d8 100644 --- a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java @@ -16,11 +16,11 @@ public BetweenSemverMatcher(String semverStart, String semverEnd) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null) { + if (matchValue == null || _semverStart == null || _semverEnd == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); - if (matchSemver == null || _semverStart == null || _semverEnd == null) { + if (matchSemver == null) { return false; } diff --git a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java index 8c0ce665d..cb979b8ed 100644 --- a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; /** * Tests for EqualToSemverMatcher @@ -14,11 +15,11 @@ public class BetweenSemverMatcherTest { public void works() { BetweenSemverMatcher betweenSemverMatcher = new BetweenSemverMatcher("2.1.8", "3.0.0"); - assertTrue( betweenSemverMatcher.match("2.1.8", null, null, null) == true); - assertTrue( betweenSemverMatcher.match("2.1.9", null, null, null) == true); - assertTrue( betweenSemverMatcher.match("2.1.8-rc", null, null, null) == false); - assertTrue( betweenSemverMatcher.match("3.0.0+build", null, null, null) == true); - assertTrue( betweenSemverMatcher.match("4.5.8", null, null, null) == false); - assertTrue( betweenSemverMatcher.match("1.0.4", null, null, null) == false); + assertTrue( betweenSemverMatcher.match("2.1.8", null, null, null)); + assertTrue( betweenSemverMatcher.match("2.1.9", null, null, null)); + assertFalse( betweenSemverMatcher.match("2.1.8-rc", null, null, null)); + assertTrue( betweenSemverMatcher.match("3.0.0+build", null, null, null)); + assertFalse( betweenSemverMatcher.match("4.5.8", null, null, null)); + assertFalse( betweenSemverMatcher.match("1.0.4", null, null, null)); } } From c62964efd00f8acc000d5f2b93030a842c2e76c9 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 3 May 2024 11:42:13 -0700 Subject: [PATCH 77/88] polish --- .../java/io/split/engine/matchers/EqualToSemverMatcher.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 7e652c6e1..4a5d3216c 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -14,7 +14,7 @@ public EqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null) { + if (matchValue == null || _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -22,7 +22,7 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return _semVer != null && matchSemver.Version().equals(_semVer.Version()); + return matchSemver.Version().equals(_semVer.Version()); } @Override From fdbd17f9f040630f26f706b8e2b1e497ce3b501e Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 3 May 2024 11:43:06 -0700 Subject: [PATCH 78/88] polish --- .../engine/matchers/GreaterThanOrEqualToSemverMatcher.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java index 1cb50d32e..e7ca31078 100644 --- a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java @@ -14,7 +14,7 @@ public GreaterThanOrEqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null) { + if (matchValue == null || _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -22,7 +22,7 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return _semVer != null && matchSemver.Compare(_semVer) >= 0; + return matchSemver.Compare(_semVer) >= 0; } @Override From 19ee1d20e84164599a604ae747c82631e3b4905a Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 3 May 2024 11:44:55 -0700 Subject: [PATCH 79/88] polish --- .../main/java/io/split/engine/matchers/InListSemverMatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java index 852fd66ee..231baf540 100644 --- a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java @@ -22,7 +22,7 @@ public InListSemverMatcher(Collection whitelist) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null) { + if (matchValue == null || _semverlist.isEmpty()) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); From d8d884a69969e2568331e8b60ff0e4cbd484dcf3 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 3 May 2024 12:28:36 -0700 Subject: [PATCH 80/88] updated changes --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index d51cf6cd9..a2ba61d18 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,6 @@ 4.12.0 (XXX XX, 2024) - Added support for injecting user-defined custom headers for all outgoing HTTP calls, typically useful for proxy authentication purposes. +- Added support for targeting rules based on semantic versions (https://semver.org/). 4.11.1 (Feb 29, 2024) - Fixed deadlock in UniqueKeysTracker when sending Unique Keys. From 5bc4f25000e98d2a085a058d26bd0e9157522451 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 3 May 2024 12:54:23 -0700 Subject: [PATCH 81/88] updated test coverage and version --- client/pom.xml | 2 +- .../engine/matchers/BetweenSemverMatcherTest.java | 11 +++++++++++ .../engine/matchers/EqualToSemverMatcherTest.java | 11 +++++++++++ .../GreaterThanOrEqualToSemverMatcherTest.java | 11 +++++++++++ .../engine/matchers/InListSemverMatcherTest.java | 14 ++++++++++++++ .../LessThanOrEqualToSemverMatcherTest.java | 11 +++++++++++ pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- 9 files changed, 62 insertions(+), 4 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index 7a6a53ca6..dfb0998e5 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc3 + 4.12.0-rc4 java-client jar diff --git a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java index cb979b8ed..41a4f76d4 100644 --- a/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/BetweenSemverMatcherTest.java @@ -21,5 +21,16 @@ public void works() { assertTrue( betweenSemverMatcher.match("3.0.0+build", null, null, null)); assertFalse( betweenSemverMatcher.match("4.5.8", null, null, null)); assertFalse( betweenSemverMatcher.match("1.0.4", null, null, null)); + assertTrue(betweenSemverMatcher.equals(betweenSemverMatcher)); + assertTrue(betweenSemverMatcher.hashCode() != 0); + } + + @Test + public void testNull() { + BetweenSemverMatcher betweenSemverMatcher = new BetweenSemverMatcher("2.1.8", "3.0.0"); + assertFalse( betweenSemverMatcher.match(null, null, null, null)); + + betweenSemverMatcher = new BetweenSemverMatcher("2.www.8", "3.xx.0"); + assertFalse(betweenSemverMatcher.match("2.www.8", null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java index 28ecd15f6..a5a41e2bb 100644 --- a/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/EqualToSemverMatcherTest.java @@ -19,5 +19,16 @@ public void works() { assertFalse(equalToSemverMatcher.match("2.1.9", null, null, null)); assertFalse(equalToSemverMatcher.match("2.1.8-rc", null, null, null)); assertFalse( equalToSemverMatcher.match("2.1.8+build", null, null, null)); + assertTrue(equalToSemverMatcher.equals(equalToSemverMatcher)); + assertTrue(equalToSemverMatcher.hashCode() != 0); + } + + @Test + public void testNull() { + EqualToSemverMatcher equalToSemverMatcher = new EqualToSemverMatcher("2.1.8"); + assertFalse( equalToSemverMatcher.match(null, null, null, null)); + + equalToSemverMatcher = new EqualToSemverMatcher("2.ee.8"); + assertFalse(equalToSemverMatcher.match("2.ee.8", null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java index 2d72d3c78..753034c70 100644 --- a/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcherTest.java @@ -19,5 +19,16 @@ public void works() { assertFalse( greaterThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null)); assertFalse( greaterThanOrEqualToSemverMatcher.match("2.0.10", null, null, null)); assertTrue( greaterThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null)); + assertTrue(greaterThanOrEqualToSemverMatcher.equals(greaterThanOrEqualToSemverMatcher)); + assertTrue(greaterThanOrEqualToSemverMatcher.hashCode() != 0); + } + + @Test + public void testNull() { + GreaterThanOrEqualToSemverMatcher greaterThanOrEqualToSemverMatcher = new GreaterThanOrEqualToSemverMatcher("2.1.8"); + assertFalse( greaterThanOrEqualToSemverMatcher.match(null, null, null, null)); + + greaterThanOrEqualToSemverMatcher = new GreaterThanOrEqualToSemverMatcher("2.ee.8"); + assertFalse(greaterThanOrEqualToSemverMatcher.match("2.ee.8", null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java index d501c2363..c01371251 100644 --- a/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/InListSemverMatcherTest.java @@ -5,6 +5,7 @@ import java.util.List; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -23,5 +24,18 @@ public void works() { assertTrue( inListSemverMatcher.match("2.1.8-rc", null, null, null) == false); assertTrue( inListSemverMatcher.match("3.4.0", null, null, null) == true); assertTrue( inListSemverMatcher.match("3.4.0+build", null, null, null) == false); + assertTrue(inListSemverMatcher.equals(inListSemverMatcher)); + assertTrue(inListSemverMatcher.hashCode() != 0); + } + + @Test + public void testNull() { + List whitelist = Lists.newArrayList("2.1.8", "3.4.0"); + InListSemverMatcher inListSemverMatcher = new InListSemverMatcher(whitelist); + assertFalse( inListSemverMatcher.match(null, null, null, null)); + + whitelist = Lists.newArrayList("2.1.eee", "3.xxx.0"); + inListSemverMatcher = new InListSemverMatcher(whitelist); + assertFalse(inListSemverMatcher.match("2.1.eee", null, null, null)); } } diff --git a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java index ad12dc8c4..349a608ae 100644 --- a/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java +++ b/client/src/test/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcherTest.java @@ -20,5 +20,16 @@ public void works() { assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8-rc", null, null, null)); assertTrue( lessThanOrEqualToSemverMatcher.match("2.0.10", null, null, null)); assertTrue( lessThanOrEqualToSemverMatcher.match("2.1.8+build", null, null, null)); + assertTrue(lessThanOrEqualToSemverMatcher.equals(lessThanOrEqualToSemverMatcher)); + assertTrue(lessThanOrEqualToSemverMatcher.hashCode() != 0); + } + + @Test + public void testNull() { + LessThanOrEqualToSemverMatcher lessThanOrEqualToSemverMatcher = new LessThanOrEqualToSemverMatcher("2.1.8"); + assertFalse( lessThanOrEqualToSemverMatcher.match(null, null, null, null)); + + lessThanOrEqualToSemverMatcher = new LessThanOrEqualToSemverMatcher("2.ee.8"); + assertFalse(lessThanOrEqualToSemverMatcher.match("2.ee.8", null, null, null)); } } diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index d2d75905f..a4b8810e8 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc3 + 4.12.0-rc4 2.1.0 diff --git a/pom.xml b/pom.xml index 91f89a449..192463bcb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.12.0-rc3 + 4.12.0-rc4 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 0beb3ed73..f852ac4b7 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc3 + 4.12.0-rc4 redis-wrapper 3.1.0 From aad9b022db6deeb91ba6976e6c5b682df935941a Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 3 May 2024 12:58:56 -0700 Subject: [PATCH 82/88] updated testing version --- testing/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/pom.xml b/testing/pom.xml index e49a96c67..8773a5631 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc3 + 4.12.0-rc4 java-client-testing jar From 676c481d498b2b0104992406b640a0cbc653dc47 Mon Sep 17 00:00:00 2001 From: Hyomin Park Date: Wed, 8 May 2024 22:05:25 -0400 Subject: [PATCH 83/88] Fix empty token handling in RawAuthResponse constructor RawAuthResponse constructor first checks to ensure provided token is not null and is not empty. Existing implementation used != operator to detect non-empty string, thus failed to handle when provided token is actually empty, i.e. "". The token comparison logic in RawAuthResponse constructor is now updated to use isEmpty() instead, more specifically, (token != null && !token.isEmpty()) to properly handle "" case. New test case with sample json has been added for validation; the test prior to the change would fail with java.lang.ArrayIndexOutOfBoundsException. --- .../split/engine/sse/dtos/RawAuthResponse.java | 2 +- .../io/split/engine/sse/AuthApiClientTest.java | 17 +++++++++++++++++ ...treaming-auth-push-disabled-empty-token.json | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 client/src/test/resources/streaming-auth-push-disabled-empty-token.json diff --git a/client/src/main/java/io/split/engine/sse/dtos/RawAuthResponse.java b/client/src/main/java/io/split/engine/sse/dtos/RawAuthResponse.java index 4082aac72..08f21d8a4 100644 --- a/client/src/main/java/io/split/engine/sse/dtos/RawAuthResponse.java +++ b/client/src/main/java/io/split/engine/sse/dtos/RawAuthResponse.java @@ -22,7 +22,7 @@ public RawAuthResponse(boolean pushEnabled, String token) { this.pushEnabled = pushEnabled; this.token = token; - if (token != null && token != "") { + if (token != null && !token.isEmpty()) { String tokenDecoded = decodeJwt(); this.jwt = Json.fromJson(tokenDecoded, Jwt.class); } else { diff --git a/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java b/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java index f5dd0b342..b6f05e04c 100644 --- a/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java +++ b/client/src/test/java/io/split/engine/sse/AuthApiClientTest.java @@ -85,6 +85,23 @@ public void authenticateWithPushDisabledShouldReturnSuccess() throws IOException Assert.assertTrue(StringUtils.isEmpty(result.getToken())); } + @Test + public void authenticateWithPushDisabledWithEmptyTokenShouldReturnSuccess() throws IOException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException, URISyntaxException { + CloseableHttpClient httpClientMock = TestHelper.mockHttpClient("streaming-auth-push-disabled-empty-token.json", + HttpStatus.SC_OK); + SplitHttpClient splitHttpClient = SplitHttpClientImpl.create(httpClientMock, new RequestDecorator(null), + "qwerty", metadata()); + + AuthApiClient authApiClient = new AuthApiClientImp("www.split-test.io", splitHttpClient, TELEMETRY_STORAGE); + AuthenticationResponse result = authApiClient.Authenticate(); + + Assert.assertFalse(result.isPushEnabled()); + Assert.assertTrue(StringUtils.isEmpty(result.getChannels())); + Assert.assertFalse(result.isRetry()); + Assert.assertTrue(StringUtils.isEmpty(result.getToken())); + } + @Test public void authenticateServerErrorShouldReturnErrorWithRetry() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, URISyntaxException { diff --git a/client/src/test/resources/streaming-auth-push-disabled-empty-token.json b/client/src/test/resources/streaming-auth-push-disabled-empty-token.json new file mode 100644 index 000000000..d40fd01c9 --- /dev/null +++ b/client/src/test/resources/streaming-auth-push-disabled-empty-token.json @@ -0,0 +1 @@ +{"pushEnabled":false,"token":""} \ No newline at end of file From 43d25ad3cb60203ec0ac6cde62fde2adc5d83578 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 14 May 2024 18:31:19 -0300 Subject: [PATCH 84/88] Pr suggestions --- .../java/io/split/engine/matchers/BetweenSemverMatcher.java | 2 +- .../engine/matchers/GreaterThanOrEqualToSemverMatcher.java | 2 +- .../java/io/split/engine/matchers/InListSemverMatcher.java | 3 +-- .../engine/matchers/LessThanOrEqualToSemverMatcher.java | 2 +- client/src/main/java/io/split/engine/matchers/Semver.java | 5 ++--- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java index a36d9c6d8..349961e4c 100644 --- a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java @@ -16,7 +16,7 @@ public BetweenSemverMatcher(String semverStart, String semverEnd) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semverStart == null || _semverEnd == null) { + if (matchValue == null || _semverStart == null || _semverEnd == null || !(matchValue instanceof String)) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java index b434717a0..14a614210 100644 --- a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java @@ -14,7 +14,7 @@ public GreaterThanOrEqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semVer == null) { + if (matchValue == null || _semVer == null || !(matchValue instanceof String)) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); diff --git a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java index 09fee913a..fc8545338 100644 --- a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java @@ -22,7 +22,7 @@ public InListSemverMatcher(Collection whitelist) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semverlist.isEmpty()) { + if (matchValue == null || !(matchValue instanceof String) || _semverlist.isEmpty()) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -32,7 +32,6 @@ public boolean match(Object matchValue, String bucketingKey, Map for (Semver semverItem : _semverlist) { if (semverItem.Version().equals(matchSemver.Version())) return true; - } return false; } diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java index f27d9fe3e..406c256b2 100644 --- a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java @@ -14,7 +14,7 @@ public LessThanOrEqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semVer == null) { + if (matchValue == null || !(matchValue instanceof String) || _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java index 9e71d9ba3..37245f124 100644 --- a/client/src/main/java/io/split/engine/matchers/Semver.java +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -4,7 +4,6 @@ import io.split.engine.experiments.SplitParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.primitives.Ints; import java.util.Arrays; @@ -96,8 +95,8 @@ public int Compare(Semver toCompare) { if (_preRelease[i].equals(toCompare.PreRelease()[i])) { continue; } - if ( Ints.tryParse(_preRelease[i]) != null && Ints.tryParse(toCompare._preRelease[i]) != null) { - return Integer.compare(Integer.parseInt(_preRelease[i]), Integer.parseInt(toCompare._preRelease[i])); + if ( isNumeric(_preRelease[i]) && isNumeric(toCompare._preRelease[i])) { + return Long.compare(Integer.parseInt(_preRelease[i]), Long.parseLong(toCompare._preRelease[i])); } return AdjustNumber(_preRelease[i].compareTo(toCompare._preRelease[i])); } From 8073fed4b7d833457560563bacda6728150783e1 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 15 May 2024 10:37:23 -0300 Subject: [PATCH 85/88] Update rc version --- client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index ae799474c..a5b146562 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc5 + 4.12.0-rc6 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index 57170a916..e6362ea0c 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc5 + 4.12.0-rc6 2.1.0 diff --git a/pom.xml b/pom.xml index 5bd3a1ed9..a42fc29b6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.12.0-rc5 + 4.12.0-rc6 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index bcf3d7745..753da10e1 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc5 + 4.12.0-rc6 redis-wrapper 3.1.0 diff --git a/testing/pom.xml b/testing/pom.xml index 5e471e484..b5dac4526 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc5 + 4.12.0-rc6 java-client-testing jar From 9ae9fe42e7d83aaa8bab82e13068805395227c21 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 15 May 2024 11:44:24 -0300 Subject: [PATCH 86/88] Sonarqube suggestions --- .../src/main/java/io/split/engine/matchers/Semver.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java index 37245f124..a974ecc7e 100644 --- a/client/src/main/java/io/split/engine/matchers/Semver.java +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -1,18 +1,16 @@ package io.split.engine.matchers; import io.split.client.exceptions.SemverParseException; -import io.split.engine.experiments.SplitParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; public class Semver { - private final String MetadataDelimiter = "+"; - private final String PreReleaseDelimiter = "-"; - private final String ValueDelimiter = "\\."; - - private static final Logger _log = LoggerFactory.getLogger(SplitParser.class); + private static final String MetadataDelimiter = "+"; + private static final String PreReleaseDelimiter = "-"; + private static final String ValueDelimiter = "\\."; + private static final Logger _log = LoggerFactory.getLogger(Semver.class); private Long _major; private Long _minor; From 3b813d885959685c9ee5d713aa9ceda1db889d18 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 15 May 2024 12:15:39 -0300 Subject: [PATCH 87/88] Update with sonarqube suggestions --- .../engine/matchers/BetweenSemverMatcher.java | 8 +-- .../engine/matchers/EqualToSemverMatcher.java | 6 +- .../GreaterThanOrEqualToSemverMatcher.java | 6 +- .../engine/matchers/InListSemverMatcher.java | 6 +- .../LessThanOrEqualToSemverMatcher.java | 6 +- .../java/io/split/engine/matchers/Semver.java | 56 +++++++++---------- .../io/split/engine/matchers/SemverTest.java | 17 +++--- 7 files changed, 52 insertions(+), 53 deletions(-) diff --git a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java index 349961e4c..326e21830 100644 --- a/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/BetweenSemverMatcher.java @@ -16,7 +16,7 @@ public BetweenSemverMatcher(String semverStart, String semverEnd) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semverStart == null || _semverEnd == null || !(matchValue instanceof String)) { + if (!(matchValue instanceof String) || _semverStart == null || _semverEnd == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -24,16 +24,16 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return matchSemver.Compare(_semverStart) >= 0 && matchSemver.Compare(_semverEnd) <= 0; + return matchSemver.compare(_semverStart) >= 0 && matchSemver.compare(_semverEnd) <= 0; } @Override public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append("between semver "); - bldr.append(_semverStart.Version()); + bldr.append(_semverStart.version()); bldr.append(" and "); - bldr.append(_semverEnd.Version()); + bldr.append(_semverEnd.version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java index 3ca8c377e..64d9135d2 100644 --- a/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/EqualToSemverMatcher.java @@ -14,7 +14,7 @@ public EqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semVer == null) { + if (!(matchValue instanceof String) || _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -22,14 +22,14 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return matchSemver.Version().equals(_semVer.Version()); + return matchSemver.version().equals(_semVer.version()); } @Override public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append("== semver "); - bldr.append(_semVer.Version()); + bldr.append(_semVer.version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java index 14a614210..ffc714cca 100644 --- a/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/GreaterThanOrEqualToSemverMatcher.java @@ -14,7 +14,7 @@ public GreaterThanOrEqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || _semVer == null || !(matchValue instanceof String)) { + if (!(matchValue instanceof String)|| _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -22,14 +22,14 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return matchSemver.Compare(_semVer) >= 0; + return matchSemver.compare(_semVer) >= 0; } @Override public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append(">= semver "); - bldr.append(_semVer.Version()); + bldr.append(_semVer.version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java index fc8545338..69fd1ea45 100644 --- a/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/InListSemverMatcher.java @@ -22,7 +22,7 @@ public InListSemverMatcher(Collection whitelist) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || !(matchValue instanceof String) || _semverlist.isEmpty()) { + if (!(matchValue instanceof String) || _semverlist.isEmpty()) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -31,7 +31,7 @@ public boolean match(Object matchValue, String bucketingKey, Map } for (Semver semverItem : _semverlist) { - if (semverItem.Version().equals(matchSemver.Version())) return true; + if (semverItem.version().equals(matchSemver.version())) return true; } return false; } @@ -47,7 +47,7 @@ public String toString() { bldr.append(','); } bldr.append('"'); - bldr.append(item.Version()); + bldr.append(item.version()); bldr.append('"'); first = false; } diff --git a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java index 406c256b2..dd05f8c4d 100644 --- a/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java +++ b/client/src/main/java/io/split/engine/matchers/LessThanOrEqualToSemverMatcher.java @@ -14,7 +14,7 @@ public LessThanOrEqualToSemverMatcher(String semVer) { @Override public boolean match(Object matchValue, String bucketingKey, Map attributes, EvaluationContext evaluationContext) { - if (matchValue == null || !(matchValue instanceof String) || _semVer == null) { + if (!(matchValue instanceof String) || _semVer == null) { return false; } Semver matchSemver = Semver.build(matchValue.toString()); @@ -22,14 +22,14 @@ public boolean match(Object matchValue, String bucketingKey, Map return false; } - return matchSemver.Compare(_semVer) <= 0; + return matchSemver.compare(_semVer) <= 0; } @Override public String toString() { StringBuilder bldr = new StringBuilder(); bldr.append("<= semver "); - bldr.append(_semVer.Version()); + bldr.append(_semVer.version()); return bldr.toString(); } diff --git a/client/src/main/java/io/split/engine/matchers/Semver.java b/client/src/main/java/io/split/engine/matchers/Semver.java index a974ecc7e..7a85a0d72 100644 --- a/client/src/main/java/io/split/engine/matchers/Semver.java +++ b/client/src/main/java/io/split/engine/matchers/Semver.java @@ -7,9 +7,9 @@ import java.util.Arrays; public class Semver { - private static final String MetadataDelimiter = "+"; - private static final String PreReleaseDelimiter = "-"; - private static final String ValueDelimiter = "\\."; + private static final String METADATA_DELIMITER = "+"; + private static final String PRERELEASE_DELIMITER = "-"; + private static final String VALUE_DELIMITER = "\\."; private static final Logger _log = LoggerFactory.getLogger(Semver.class); private Long _major; @@ -30,31 +30,31 @@ public static Semver build(String version) { } } - public String Version() { + public String version() { return _version; } - public Long Major() { + public Long major() { return _major; } - public Long Minor() { + public Long minor() { return _minor; } - public Long Patch() { + public Long patch() { return _patch; } - public String[] PreRelease() { + public String[] prerelease() { return _preRelease; } - public String Metadata() { + public String metadata() { return _metadata; } - public boolean IsStable() { + public boolean isStable() { return _isStable; } @@ -65,44 +65,44 @@ public boolean IsStable() { * a value less than {@code 0} if {@code this < toCompare}; and * a value greater than {@code 0} if {@code this > toCompare} */ - public int Compare(Semver toCompare) { - if (_version.equals(toCompare.Version())) { + public int compare(Semver toCompare) { + if (_version.equals(toCompare.version())) { return 0; } // Compare major, minor, and patch versions numerically - int result = Long.compare(_major, toCompare.Major()); + int result = Long.compare(_major, toCompare.major()); if (result != 0) { return result; } - result = Long.compare(_minor, toCompare.Minor()); + result = Long.compare(_minor, toCompare.minor()); if (result != 0) { return result; } - result = Long.compare(_patch, toCompare.Patch()); + result = Long.compare(_patch, toCompare.patch()); if (result != 0) { return result; } - if (!_isStable && toCompare.IsStable()) { + if (!_isStable && toCompare.isStable()) { return -1; - } else if (_isStable && !toCompare.IsStable()) { + } else if (_isStable && !toCompare.isStable()) { return 1; } // Compare pre-release versions lexically - int minLength = Math.min(_preRelease.length, toCompare.PreRelease().length); + int minLength = Math.min(_preRelease.length, toCompare.prerelease().length); for (int i = 0; i < minLength; i++) { - if (_preRelease[i].equals(toCompare.PreRelease()[i])) { + if (_preRelease[i].equals(toCompare.prerelease()[i])) { continue; } if ( isNumeric(_preRelease[i]) && isNumeric(toCompare._preRelease[i])) { return Long.compare(Integer.parseInt(_preRelease[i]), Long.parseLong(toCompare._preRelease[i])); } - return AdjustNumber(_preRelease[i].compareTo(toCompare._preRelease[i])); + return adjustNumber(_preRelease[i].compareTo(toCompare._preRelease[i])); } // Compare lengths of pre-release versions return Integer.compare(_preRelease.length, toCompare._preRelease.length); } - private int AdjustNumber(int number) { + private int adjustNumber(int number) { if (number > 0) return 1; if (number < 0) return -1; return 0; @@ -114,7 +114,7 @@ private Semver(String version) throws SemverParseException { _version = setVersion(); } private String setAndRemoveMetadataIfExists(String version) throws SemverParseException { - int index = version.indexOf(MetadataDelimiter); + int index = version.indexOf(METADATA_DELIMITER); if (index == -1) { return version; } @@ -125,20 +125,20 @@ private String setAndRemoveMetadataIfExists(String version) throws SemverParseEx return version.substring(0, index); } private String setAndRemovePreReleaseIfExists(String vWithoutMetadata) throws SemverParseException { - int index = vWithoutMetadata.indexOf(PreReleaseDelimiter); + int index = vWithoutMetadata.indexOf(PRERELEASE_DELIMITER); if (index == -1) { _isStable = true; return vWithoutMetadata; } String preReleaseData = vWithoutMetadata.substring(index+1); - _preRelease = preReleaseData.split(ValueDelimiter); + _preRelease = preReleaseData.split(VALUE_DELIMITER); if (_preRelease == null || Arrays.stream(_preRelease).allMatch(pr -> pr == null || pr.isEmpty())) { throw new SemverParseException("Unable to convert to Semver, incorrect pre release data"); } return vWithoutMetadata.substring(0, index); } private void setMajorMinorAndPatch(String version) throws SemverParseException { - String[] vParts = version.split(ValueDelimiter); + String[] vParts = version.split(VALUE_DELIMITER); if (vParts.length != 3) throw new SemverParseException("Unable to convert to Semver, incorrect format: " + version); _major = Long.parseLong(vParts[0]); @@ -147,7 +147,7 @@ private void setMajorMinorAndPatch(String version) throws SemverParseException { } private String setVersion() { - String toReturn = _major + ValueDelimiter + _minor + ValueDelimiter + _patch; + String toReturn = _major + VALUE_DELIMITER + _minor + VALUE_DELIMITER + _patch; if (_preRelease != null && _preRelease.length != 0) { for (int i = 0; i < _preRelease.length; i++) @@ -157,10 +157,10 @@ private String setVersion() { _preRelease[i] = Long.toString(Long.parseLong(_preRelease[i])); } } - toReturn = toReturn + PreReleaseDelimiter + String.join(ValueDelimiter, _preRelease); + toReturn = toReturn + PRERELEASE_DELIMITER + String.join(VALUE_DELIMITER, _preRelease); } if (_metadata != null && !_metadata.isEmpty()) { - toReturn = toReturn + MetadataDelimiter + _metadata; + toReturn = toReturn + METADATA_DELIMITER + _metadata; } return toReturn; } diff --git a/client/src/test/java/io/split/engine/matchers/SemverTest.java b/client/src/test/java/io/split/engine/matchers/SemverTest.java index b02bd3909..40da82643 100644 --- a/client/src/test/java/io/split/engine/matchers/SemverTest.java +++ b/client/src/test/java/io/split/engine/matchers/SemverTest.java @@ -1,6 +1,5 @@ package io.split.engine.matchers; -import org.apache.commons.lang3.RandomStringUtils; import org.junit.Test; import java.io.*; @@ -61,8 +60,8 @@ public void testCompareVersions() throws IOException { versions.add(Arrays.asList(values)); } for(List version : versions) { - assertTrue(Semver.build(version.get(0)).Compare(Semver.build(version.get(1))) == 1); - assertTrue(Semver.build(version.get(1)).Compare(Semver.build(version.get(0))) == -1); + assertTrue(Semver.build(version.get(0)).compare(Semver.build(version.get(1))) == 1); + assertTrue(Semver.build(version.get(1)).compare(Semver.build(version.get(0))) == -1); } versions.clear(); @@ -78,9 +77,9 @@ public void testCompareVersions() throws IOException { Semver version2 = Semver.build(version.get(1)); if (version.get(2).equals("true")) { - assertTrue(version1.Version().equals(version2.Version())); + assertTrue(version1.version().equals(version2.version())); } else { - assertTrue(!version1.Version().equals(version2.Version())); + assertTrue(!version1.version().equals(version2.version())); } } @@ -98,16 +97,16 @@ public void testCompareVersions() throws IOException { Semver version3 = Semver.build(version.get(2)); if (version.get(3).equals("true")) { - assertTrue(version2.Compare(version1) >= 0 && version3.Compare(version2) >= 0); + assertTrue(version2.compare(version1) >= 0 && version3.compare(version2) >= 0); } else { - assertTrue(version2.Compare(version1) < 0 || version3.Compare(version2) < 0); + assertTrue(version2.compare(version1) < 0 || version3.compare(version2) < 0); } } } @Test public void testLeadingZeros() { - assertTrue(Semver.build("1.01.2").Version().equals("1\\.1\\.2")); - assertTrue(Semver.build("1.01.2-rc.01").Version().equals("1\\.1\\.2-rc\\.1")); + assertTrue(Semver.build("1.01.2").version().equals("1\\.1\\.2")); + assertTrue(Semver.build("1.01.2-rc.01").version().equals("1\\.1\\.2-rc\\.1")); } } From b754a5d5d6c3e0d5a11a00f05b66a8d28103d27b Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 15 May 2024 15:41:23 -0300 Subject: [PATCH 88/88] Update to final version --- client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index a5b146562..b48aa1100 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc6 + 4.12.0 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index e6362ea0c..a6f21cd7c 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc6 + 4.12.0 2.1.0 diff --git a/pom.xml b/pom.xml index a42fc29b6..fc4f01fa5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.12.0-rc6 + 4.12.0 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 753da10e1..6f5231911 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.12.0-rc6 + 4.12.0 redis-wrapper 3.1.0 diff --git a/testing/pom.xml b/testing/pom.xml index b5dac4526..0faeed8c3 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.12.0-rc6 + 4.12.0 java-client-testing jar