Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if (rootProject.name == 'android-client') {
}

ext {
splitVersion = '5.5.1'
splitVersion = '5.5.2-rc1'
jacocoVersion = '0.8.8'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private List<EventEntity> generateData(int from, int to, long timestamp, boolean
trackEvent.trafficTypeName = "traffic_" + i;
trackEvent.eventTypeId = "type_" + i;
trackEvent.key = "key";
trackEvent.value = i;
trackEvent.value = (double) i;
trackEvent.timestamp = timestamp + i;

EventEntity eventEntity = new EventEntity();
Expand Down
74 changes: 72 additions & 2 deletions main/src/androidTest/java/tests/integration/TrackTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.util.Log;

import androidx.test.platform.app.InstrumentationRegistry;

import com.google.gson.JsonArray;
import com.google.gson.JsonParser;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand All @@ -30,6 +35,8 @@
import io.split.android.client.SplitClient;
import io.split.android.client.SplitClientConfig;
import io.split.android.client.SplitFactory;
import java.util.Objects;

import io.split.android.client.SplitFactoryBuilder;
import io.split.android.client.api.Key;
import io.split.android.client.dtos.Event;
Expand All @@ -49,13 +56,15 @@
ArrayList<String> mJsonChanges = null;
ArrayList<CountDownLatch> mLatchs;
ArrayList<List<Event>> mEventsHits;
ArrayList<String> mRawEventsHitBodies;

@Before
public void setup() {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mCurReqId = 0;
mLatchs = new ArrayList<>();
mEventsHits = new ArrayList<>();
mRawEventsHitBodies = new ArrayList<>();
for (int i = 0; i < 6; i++) {
mLatchs.add(new CountDownLatch(1));
}
Expand Down Expand Up @@ -89,7 +98,9 @@
if (index > 0 && index < 4) {
code = 500;
} else {
List<Event> data = IntegrationHelper.buildEventsFromJson(request.getBody().readUtf8());
String body = request.getBody().readUtf8();
mRawEventsHitBodies.add(body);
List<Event> data = IntegrationHelper.buildEventsFromJson(body);
mEventsHits.add(data);
code = 200;
}
Expand Down Expand Up @@ -261,6 +272,65 @@
assertEquals(158576837, event.properties.get("id"));
}

@Test
public void trackWithNullValueSendsNullInPayload() throws InterruptedException, SplitInstantiationException {
CountDownLatch latch = new CountDownLatch(1);
String apiKey = IntegrationHelper.dummyApiKey();
SplitRoomDatabase splitRoomDatabase = DatabaseHelper.getTestDatabase(mContext);
splitRoomDatabase.clearAllTables();

final String url = mWebServer.url("/").url().toString();

Key key = new Key("CUSTOMER_ID", null);
SplitClientConfig config = new TestableSplitConfigBuilder()
.serviceEndpoints(ServiceEndpoints
.builder()
.apiEndpoint(url)
.eventsEndpoint(url)
.build())
.ready(30000)
.eventFlushInterval(5)
.eventsPerPush(5)
.eventsQueueSize(1000)
.enableDebug()
.trafficType("client")
.build();

SplitFactory splitFactory = SplitFactoryBuilder.build(apiKey, key, config, mContext);

SplitClient client = splitFactory.client();

SplitEventTaskHelper readyTask = new SplitEventTaskHelper(latch);
SplitEventTaskHelper readyTimeOutTask = new SplitEventTaskHelper(latch);

client.on(SplitEvent.SDK_READY, readyTask);
client.on(SplitEvent.SDK_READY_TIMED_OUT, readyTimeOutTask);

latch.await(20, TimeUnit.SECONDS);

client.track("trafficType", "no-value-event");
mLatchs.get(0).await(20, TimeUnit.SECONDS);
Thread.sleep(500);

Check warning on line 313 in main/src/androidTest/java/tests/integration/TrackTest.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Remove this use of "Thread.sleep()".

[S2925] "Thread.sleep" should not be used in tests See more on https://sonar.harness.io/project/issues?id=splitio_android-client&pullRequest=883&issues=34d0c2a4-4ede-45b6-9f7a-519c1cb4721f&open=34d0c2a4-4ede-45b6-9f7a-519c1cb4721f

assertNotNull("Expected at least one events/bulk hit", mRawEventsHitBodies.isEmpty() ? null : mRawEventsHitBodies.get(0));
String rawBody = mRawEventsHitBodies.get(0);
Log.d("Track_test", rawBody);
JsonArray events = JsonParser.parseString(rawBody).getAsJsonArray();
boolean found = false;
for (int i = 0; i < events.size(); i++) {
if ("no-value-event".equals(events.get(i).getAsJsonObject().get("eventTypeId").getAsString())) {
assertTrue("Expected value to be null in JSON payload, but got: " +
events.get(i).getAsJsonObject().get("value"),
events.get(i).getAsJsonObject().get("value").isJsonNull());
found = true;
break;
}
}
assertTrue("Event 'no-value-event' not found in payload", found);

client.destroy();
}

private String emptyChanges() {
return IntegrationHelper.emptySplitChanges(9567456937869L, 9567456937869L);
}
Expand All @@ -271,7 +341,7 @@
List<Event> events = mEventsHits.get(i);
if (events != null) {
Optional<Event> oe = events.stream()
.filter(event -> event.eventTypeId.equals(type) && event.value == value).findFirst();
.filter(event -> event.eventTypeId.equals(type) && Objects.equals(event.value, value)).findFirst();
if (oe.isPresent()) {
return oe.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ public final class SplitClientImpl implements SplitClient {
private final AttributesManager mAttributesManager;
private final Tracker mEventsTracker;

private static final double TRACK_DEFAULT_VALUE = 0.0;

private boolean mIsClientDestroyed = false;

public SplitClientImpl(SplitFactory container,
Expand Down Expand Up @@ -219,7 +217,7 @@ public void addEventListener(@NonNull SplitEventListener listener) {

@Override
public boolean track(String trafficType, String eventType) {
return track(mKey.matchingKey(), trafficType, eventType, TRACK_DEFAULT_VALUE, null);
return track(mKey.matchingKey(), trafficType, eventType, null, null);
}

@Override
Expand All @@ -229,7 +227,7 @@ public boolean track(String trafficType, String eventType, double value) {

@Override
public boolean track(String eventType) {
return track(mKey.matchingKey(), mConfig.trafficType(), eventType, TRACK_DEFAULT_VALUE, null);
return track(mKey.matchingKey(), mConfig.trafficType(), eventType, null, null);
}

@Override
Expand All @@ -239,7 +237,7 @@ public boolean track(String eventType, double value) {

@Override
public boolean track(String trafficType, String eventType, Map<String, Object> properties) {
return track(mKey.matchingKey(), trafficType, eventType, TRACK_DEFAULT_VALUE, properties);
return track(mKey.matchingKey(), trafficType, eventType, null, properties);
}

@Override
Expand All @@ -249,15 +247,15 @@ public boolean track(String trafficType, String eventType, double value, Map<Str

@Override
public boolean track(String eventType, Map<String, Object> properties) {
return track(mKey.matchingKey(), mConfig.trafficType(), eventType, TRACK_DEFAULT_VALUE, properties);
return track(mKey.matchingKey(), mConfig.trafficType(), eventType, null, properties);
}

@Override
public boolean track(String eventType, double value, Map<String, Object> properties) {
return track(mKey.matchingKey(), mConfig.trafficType(), eventType, value, properties);
}

private boolean track(String key, String trafficType, String eventType, double value, Map<String, Object> properties) {
private boolean track(String key, String trafficType, String eventType, Double value, Map<String, Object> properties) {
if (mIsClientDestroyed) {
mValidationLogger.e("Client has already been destroyed - no calls possible", "track");
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class SerializableEvent {
@SerializedName(KEY_FIELD)
public String key;
@SerializedName(VALUE_FIELD)
public double value;
public Double value;
@SerializedName(TIMESTAMP_FIELD)
public long timestamp;
@SerializedName(PROPERTIES_FIELD)
Expand All @@ -31,8 +31,8 @@ public class SerializableEvent {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Event event = (Event) o;
return Double.compare(event.value, value) == 0 &&
SerializableEvent event = (SerializableEvent) o;
return Objects.equals(value, event.value) &&
timestamp == event.timestamp &&
Objects.equals(eventTypeId, event.eventTypeId) &&
Objects.equals(trafficTypeName, event.trafficTypeName) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
event.eventTypeId = jsonObject.get(Event.EVENT_TYPE_FIELD).getAsString();
event.trafficTypeName = jsonObject.get(Event.TRAFFIC_TYPE_NAME_FIELD).getAsString();
event.key = jsonObject.get(Event.KEY_FIELD).getAsString();
event.value = jsonObject.get(Event.VALUE_FIELD).getAsDouble();
JsonElement valueElement = jsonObject.get(Event.VALUE_FIELD);

Check failure on line 31 in main/src/main/java/io/split/android/client/utils/deserializer/EventDeserializer.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Use static access with "io.split.android.client.dtos.SerializableEvent" for "VALUE_FIELD".

[S3252] "static" base class members should not be accessed via derived types See more on https://sonar.harness.io/project/issues?id=splitio_android-client&pullRequest=883&issues=882fafb8-a1a8-4201-baa3-004645be9334&open=882fafb8-a1a8-4201-baa3-004645be9334
event.value = (valueElement != null && !valueElement.isJsonNull()) ? valueElement.getAsDouble() : null;
event.timestamp = jsonObject.get(Event.TIMESTAMP_FIELD).getAsLong();
event.properties = buildMappedProperties(properties);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public void entityForModelEncryptsBody() {
mStorage.entityForModel(event);

verify(mSplitCipher).encrypt("{\"sizeInBytes\":0,\"eventTypeId\":\"test_event_0\"," +
"\"trafficTypeName\":\"custom\",\"key\":\"key1\",\"value\":0,\"timestamp\":0," +
"\"trafficTypeName\":\"custom\",\"key\":\"key1\",\"value\":null,\"timestamp\":0," +
"\"properties\":{}}");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void enableTracking(boolean enable) {

@Override
public boolean track(String key, String trafficType, String eventType,
double value, Map<String, Object> properties, boolean isSdkReady) {
Double value, Map<String, Object> properties, boolean isSdkReady) {
if (!isTrackingEnabled.get()) {
mTrackerLogger.v("Event not tracked because tracking is disabled");
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
public interface Tracker {
void enableTracking(boolean enable);

boolean track(String key, String trafficType, String eventType, double value,
boolean track(String key, String trafficType, String eventType, Double value,
Map<String, Object> properties, boolean isSdkReady);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
public String trafficType;
public String eventType;
public String key;
public double value;
public Double value;

Check warning on line 13 in tracker/src/main/java/io/split/android/client/tracker/TrackerEvent.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Make value a static final constant or non-public and provide accessors if needed.

[S1104] Class variable fields should not have public accessibility See more on https://sonar.harness.io/project/issues?id=splitio_android-client&pullRequest=883&issues=5eec2d8c-3d9b-49fd-9563-f204ca188e38&open=5eec2d8c-3d9b-49fd-9563-f204ca188e38
public long timestamp;
public Map<String, Object> properties;
public int sizeInBytes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,20 @@ public void successfulTrackPopulatesEventFieldsCorrectly() {
assertEquals(512, captured.sizeInBytes);
}

@Test
public void trackWithNullValueSucceeds() {
boolean result = mTracker.track("key", "traffic", "eventType", null, null, true);

assertTrue(result);

ArgumentCaptor<TrackerEvent> captor = ArgumentCaptor.forClass(TrackerEvent.class);
verify(mOnEventPush).accept(captor.capture());

TrackerEvent captured = captor.getValue();
assertNotNull(captured);
assertEquals(null, captured.value);
}

// Helper matcher for verifying TrackerEvent fields
private static <T> T argThat(ArgumentMatcherWithReturn<T> matcher) {
return org.mockito.ArgumentMatchers.argThat(matcher::matches);
Expand Down
Loading