diff --git a/src/main/java/io/split/android/client/dtos/Split.java b/src/main/java/io/split/android/client/dtos/Split.java index 395a4c3a3..be1b235f1 100644 --- a/src/main/java/io/split/android/client/dtos/Split.java +++ b/src/main/java/io/split/android/client/dtos/Split.java @@ -49,4 +49,7 @@ public class Split { @Nullable @SerializedName("sets") public Set sets; + + @SerializedName("trackImpressions") + public boolean trackImpressions = true; } diff --git a/src/main/java/io/split/android/engine/experiments/ParsedSplit.java b/src/main/java/io/split/android/engine/experiments/ParsedSplit.java index c00b17f8b..a9ae822f7 100644 --- a/src/main/java/io/split/android/engine/experiments/ParsedSplit.java +++ b/src/main/java/io/split/android/engine/experiments/ParsedSplit.java @@ -23,6 +23,7 @@ public class ParsedSplit { private final int mAlgo; private final Map mConfigurations; private final Set mSets; + private final boolean mTrackImpressions; public ParsedSplit( String feature, @@ -36,7 +37,8 @@ public ParsedSplit( int trafficAllocationSeed, int algo, Map configurations, - Set sets + Set sets, + boolean trackImpressions ) { mSplit = feature; mSeed = seed; @@ -47,6 +49,7 @@ public ParsedSplit( mChangeNumber = changeNumber; mAlgo = algo; mConfigurations = configurations; + mTrackImpressions = trackImpressions; if (mDefaultTreatment == null) { throw new IllegalArgumentException("DefaultTreatment is null"); @@ -104,6 +107,10 @@ public Set sets() { return mSets; } + public boolean trackImpression() { + return mTrackImpressions; + } + @Override public int hashCode() { int result = 17; @@ -116,6 +123,7 @@ public int hashCode() { result = 31 * result + (int) (mChangeNumber ^ (mChangeNumber >>> 32)); result = 31 * result + (mAlgo ^ (mAlgo >>> 32)); result = 31 * result + ((mSets != null) ? mSets.hashCode() : 0); + result = 31 * result + (mTrackImpressions ? 1 : 0); return result; } @@ -135,7 +143,8 @@ public boolean equals(Object obj) { && mChangeNumber == other.mChangeNumber && mAlgo == other.mAlgo && (Objects.equals(mConfigurations, other.mConfigurations)) - && (Objects.equals(mSets, other.mSets)); + && (Objects.equals(mSets, other.mSets) + && mTrackImpressions == other.mTrackImpressions); } @@ -146,7 +155,7 @@ public String toString() { ", default treatment:" + mDefaultTreatment + ", parsedConditions:" + mParsedCondition + ", trafficTypeName:" + mTrafficTypeName + ", changeNumber:" + mChangeNumber + - ", algo:" + mAlgo + ", config:" + mConfigurations + ", sets:" + mSets; + ", algo:" + mAlgo + ", config:" + mConfigurations + ", sets:" + mSets + ", trackImpression:" + mTrackImpressions; } } diff --git a/src/main/java/io/split/android/engine/experiments/SplitParser.java b/src/main/java/io/split/android/engine/experiments/SplitParser.java index 2763ecca7..5684afd88 100644 --- a/src/main/java/io/split/android/engine/experiments/SplitParser.java +++ b/src/main/java/io/split/android/engine/experiments/SplitParser.java @@ -124,7 +124,8 @@ private ParsedSplit parseWithoutExceptionHandling(Split split, String matchingKe split.trafficAllocationSeed, split.algo, split.configurations, - split.sets); + split.sets, + split.trackImpressions); } private CombiningMatcher toMatcher(MatcherGroup matcherGroup, String matchingKey) throws UnsupportedMatcherException { diff --git a/src/test/java/io/split/android/client/dtos/SplitDeserializationTest.java b/src/test/java/io/split/android/client/dtos/SplitDeserializationTest.java new file mode 100644 index 000000000..0fa373f9d --- /dev/null +++ b/src/test/java/io/split/android/client/dtos/SplitDeserializationTest.java @@ -0,0 +1,127 @@ +package io.split.android.client.dtos; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import io.split.android.client.utils.Json; + +public class SplitDeserializationTest { + + @Test + public void trackImpressionsDefaultsToTrueWhenNotPresentInSplit() { + assertTrue(Json.fromJson(getTestSplit(null), Split.class).trackImpressions); + } + + @Test + public void trackImpressionsValueIsParsedCorrectly() { + assertTrue(Json.fromJson(getTestSplit(true), Split.class).trackImpressions); + assertFalse(Json.fromJson(getTestSplit(false), Split.class).trackImpressions); + } + + private String getTestSplit(Boolean trackImpressions) { + return "{\n" + + ((trackImpressions != null) ? "\"trackImpressions\": " + trackImpressions + ",\n" : "") + + " \"trafficTypeName\": \"client\",\n" + + " \"name\": \"workm\",\n" + + " \"trafficAllocation\": 100,\n" + + " \"trafficAllocationSeed\": 147392224,\n" + + " \"seed\": 524417105,\n" + + " \"status\": \"ACTIVE\",\n" + + " \"killed\": false,\n" + + " \"defaultTreatment\": \"on\",\n" + + " \"changeNumber\": 1602796638344,\n" + + " \"algo\": 2,\n" + + " \"configurations\": {},\n" + + " \"conditions\": [\n" + + " {\n" + + " \"conditionType\": \"ROLLOUT\",\n" + + " \"matcherGroup\": {\n" + + " \"combiner\": \"AND\",\n" + + " \"matchers\": [\n" + + " {\n" + + " \"keySelector\": {\n" + + " \"trafficType\": \"client\",\n" + + " \"attribute\": null\n" + + " },\n" + + " \"matcherType\": \"IN_SEGMENT\",\n" + + " \"negate\": false,\n" + + " \"userDefinedSegmentMatcherData\": {\n" + + " \"segmentName\": \"new_segment\"\n" + + " },\n" + + " \"whitelistMatcherData\": null,\n" + + " \"unaryNumericMatcherData\": null,\n" + + " \"betweenMatcherData\": null,\n" + + " \"booleanMatcherData\": null,\n" + + " \"dependencyMatcherData\": null,\n" + + " \"stringMatcherData\": null\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"partitions\": [\n" + + " {\n" + + " \"treatment\": \"on\",\n" + + " \"size\": 0\n" + + " },\n" + + " {\n" + + " \"treatment\": \"off\",\n" + + " \"size\": 0\n" + + " },\n" + + " {\n" + + " \"treatment\": \"free\",\n" + + " \"size\": 100\n" + + " },\n" + + " {\n" + + " \"treatment\": \"conta\",\n" + + " \"size\": 0\n" + + " }\n" + + " ],\n" + + " \"label\": \"in segment new_segment\"\n" + + " },\n" + + " {\n" + + " \"conditionType\": \"ROLLOUT\",\n" + + " \"matcherGroup\": {\n" + + " \"combiner\": \"AND\",\n" + + " \"matchers\": [\n" + + " {\n" + + " \"keySelector\": {\n" + + " \"trafficType\": \"client\",\n" + + " \"attribute\": null\n" + + " },\n" + + " \"matcherType\": \"ALL_KEYS\",\n" + + " \"negate\": false,\n" + + " \"userDefinedSegmentMatcherData\": null,\n" + + " \"whitelistMatcherData\": null,\n" + + " \"unaryNumericMatcherData\": null,\n" + + " \"betweenMatcherData\": null,\n" + + " \"booleanMatcherData\": null,\n" + + " \"dependencyMatcherData\": null,\n" + + " \"stringMatcherData\": null\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"partitions\": [\n" + + " {\n" + + " \"treatment\": \"on\",\n" + + " \"size\": 100\n" + + " },\n" + + " {\n" + + " \"treatment\": \"off\",\n" + + " \"size\": 0\n" + + " },\n" + + " {\n" + + " \"treatment\": \"free\",\n" + + " \"size\": 0\n" + + " },\n" + + " {\n" + + " \"treatment\": \"conta\",\n" + + " \"size\": 0\n" + + " }\n" + + " ],\n" + + " \"label\": \"default rule\"\n" + + " }\n" + + " ]\n" + + " }"; + } +} diff --git a/src/test/java/io/split/android/engine/experiments/SplitParserTest.java b/src/test/java/io/split/android/engine/experiments/SplitParserTest.java index e6c1d6ca6..cf24758e2 100644 --- a/src/test/java/io/split/android/engine/experiments/SplitParserTest.java +++ b/src/test/java/io/split/android/engine/experiments/SplitParserTest.java @@ -3,7 +3,9 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -495,6 +497,22 @@ public void inLargeSegmentMatcherParsingTest() { verify(mMySegmentsStorageContainer, never()).getStorageForKey("matching_key"); } + @Test + public void trackImpressionsParsingTest(){ + SplitParser parser = createParser(); + + Split split = makeSplit("splitName", Collections.emptyList()); + split.trackImpressions = false; + Split split2 = makeSplit("splitName", Collections.emptyList()); + split2.trackImpressions = true; + + ParsedSplit actual = parser.parse(split); + ParsedSplit actual2 = parser.parse(split2); + + assertFalse(actual.trackImpression()); + assertTrue(actual2.trackImpression()); + } + private void set_matcher_test(Condition c, io.split.android.engine.matchers.Matcher m) { SplitParser parser = createParser(); @@ -536,6 +554,7 @@ private Split makeSplit(String name, List conditions, long changeNumb split.algo = 1; split.configurations = configurations; split.sets = Collections.emptySet(); + split.trackImpressions = true; return split; } diff --git a/src/test/java/io/split/android/helpers/SplitHelper.java b/src/test/java/io/split/android/helpers/SplitHelper.java index 0aec872e8..c0f4792c0 100644 --- a/src/test/java/io/split/android/helpers/SplitHelper.java +++ b/src/test/java/io/split/android/helpers/SplitHelper.java @@ -122,7 +122,8 @@ public static ParsedSplit createParsedSplit( seed, algo, configurations, - Collections.emptySet() + Collections.emptySet(), + true ); }