Skip to content

Commit

Permalink
Merge branch 'gw/ch29266/flagstore' into eb/ch31891/variation-detail
Browse files Browse the repository at this point in the history
# Conflicts:
#	launchdarkly-android-client/src/main/java/com/launchdarkly/android/LDClient.java
  • Loading branch information
eli-darkly committed Feb 22, 2019
2 parents d7e5d64 + c654453 commit 19a9401
Show file tree
Hide file tree
Showing 27 changed files with 587 additions and 525 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package com.launchdarkly.android.response;
package com.launchdarkly.android;

import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.launchdarkly.android.LDClient;
import com.launchdarkly.android.LDConfig;
import com.launchdarkly.android.LDUser;
import com.launchdarkly.android.test.TestActivity;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

/**
Expand Down Expand Up @@ -63,18 +61,8 @@ public void startDateIsSaved() {

ldClient.boolVariation("boolFlag", true);

JsonObject features = summaryEventSharedPreferences.getFeaturesJsonObject();

Long startDate = null;
for (String key : features.keySet()) {
JsonObject asJsonObject = features.get(key).getAsJsonObject();
if (asJsonObject.has("startDate")) {
startDate = asJsonObject.get("startDate").getAsLong();
break;
}
}

Assert.assertNotNull(startDate);
SummaryEvent summaryEvent = summaryEventSharedPreferences.getSummaryEvent();
assertNotNull(summaryEvent.startDate);
}

@Test
Expand All @@ -84,7 +72,7 @@ public void counterIsUpdated() {
ldClient.clearSummaryEventSharedPreferences();

ldClient.boolVariation("boolFlag", true);
JsonObject features = summaryEventSharedPreferences.getFeaturesJsonObject();
JsonObject features = summaryEventSharedPreferences.getSummaryEvent().features;
JsonArray counters = features.get("boolFlag").getAsJsonObject().get("counters").getAsJsonArray();

Assert.assertEquals(counters.size(), 1);
Expand All @@ -94,7 +82,7 @@ public void counterIsUpdated() {
Assert.assertEquals(counter.get("count").getAsInt(), 1);

ldClient.boolVariation("boolFlag", true);
features = summaryEventSharedPreferences.getFeaturesJsonObject();
features = summaryEventSharedPreferences.getSummaryEvent().features;
counters = features.get("boolFlag").getAsJsonObject().get("counters").getAsJsonArray();

Assert.assertEquals(counters.size(), 1);
Expand All @@ -115,7 +103,7 @@ public void evaluationsAreSaved() {
ldClient.intVariation("intFlag", 6);
ldClient.stringVariation("stringFlag", "string");

JsonObject features = summaryEventSharedPreferences.getFeaturesJsonObject();
JsonObject features = summaryEventSharedPreferences.getSummaryEvent().features;

Assert.assertTrue(features.keySet().contains("boolFlag"));
Assert.assertTrue(features.keySet().contains("jsonFlag"));
Expand All @@ -138,16 +126,14 @@ public void sharedPreferencesAreCleared() {
ldClient.boolVariation("boolFlag", true);
ldClient.stringVariation("stringFlag", "string");

JsonObject features = summaryEventSharedPreferences.getFeaturesJsonObject();
JsonObject features = summaryEventSharedPreferences.getSummaryEvent().features;

Assert.assertTrue(features.keySet().contains("boolFlag"));
Assert.assertTrue(features.keySet().contains("stringFlag"));

ldClient.clearSummaryEventSharedPreferences();

features = summaryEventSharedPreferences.getFeaturesJsonObject();

Assert.assertFalse(features.keySet().contains("boolFlag"));
Assert.assertFalse(features.keySet().contains("stringFlag"));
SummaryEvent summaryEvent = summaryEventSharedPreferences.getSummaryEvent();
assertNull(summaryEvent);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.launchdarkly.android.response;
package com.launchdarkly.android.flagstore;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
Expand All @@ -7,6 +7,7 @@
import com.google.gson.JsonPrimitive;
import com.launchdarkly.android.EvaluationReason;
import com.launchdarkly.android.flagstore.Flag;
import com.launchdarkly.android.gson.GsonCache;

import org.junit.Test;

Expand All @@ -18,7 +19,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

public class UserFlagResponseTest {
public class FlagTest {
private static final Gson gson = GsonCache.getGson();

private static final Map<EvaluationReason, String> TEST_REASONS = ImmutableMap.<EvaluationReason, String>builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public void versionForEventsReturnsFlagVersionIfPresentOtherwiseReturnsVersion()
public void savesReasons() {
// This test assumes that if the store correctly serializes and deserializes one kind of EvaluationReason, it can handle any kind,
// since the actual marshaling is being done by UserFlagResponse. Therefore, the other variants of EvaluationReason are tested by
// UserFlagResponseTest.
// FlagTest.
final EvaluationReason reason = EvaluationReason.ruleMatch(1, "id");
final Flag flag1 = new Flag("key1", new JsonPrimitive(true), 11,
1, 1, null, null, reason);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import android.os.Build;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.launchdarkly.android.response.SummaryEventSharedPreferences;
import com.launchdarkly.android.tls.ModernTLSSocketFactory;
import com.launchdarkly.android.tls.SSLHandshakeInterceptor;
import com.launchdarkly.android.tls.TLSUtils;
Expand Down Expand Up @@ -43,7 +42,6 @@ class EventProcessor implements Closeable {
private final LDConfig config;
private final String environmentName;
private ScheduledExecutorService scheduler;
private SummaryEvent summaryEvent = null;
private final SummaryEventSharedPreferences summaryEventSharedPreferences;
private long currentTimeMs = System.currentTimeMillis();

Expand Down Expand Up @@ -92,12 +90,8 @@ boolean sendEvent(Event e) {
return queue.offer(e);
}

void setSummaryEvent(SummaryEvent summaryEvent) {
this.summaryEvent = summaryEvent;
}

@Override
public void close() throws IOException {
public void close() {
stop();
flush();
}
Expand All @@ -122,14 +116,14 @@ public void run() {
flush();
}

public synchronized void flush() {
synchronized void flush() {
if (isClientConnected(context, environmentName)) {
List<Event> events = new ArrayList<>(queue.size() + 1);
queue.drainTo(events);
SummaryEvent summaryEvent = summaryEventSharedPreferences.getSummaryEventAndClear();

if (summaryEvent != null) {
events.add(summaryEvent);
summaryEvent = null;
summaryEventSharedPreferences.clear();
}

if (!events.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
*/
class Foreground implements Application.ActivityLifecycleCallbacks {

static final long CHECK_DELAY = 500;
private static final long CHECK_DELAY = 500;

interface Listener {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void onFailure(@NonNull Call call, @NonNull IOException e) {
}

@Override
public void onResponse(@NonNull Call call, @NonNull final Response response) throws IOException {
public void onResponse(@NonNull Call call, @NonNull final Response response) {
String body = "";
try {
ResponseBody responseBody = response.body();
Expand Down Expand Up @@ -139,10 +139,9 @@ private Request getDefaultRequest(LDUser user) {
uri += "?withReasons=true";
}
Timber.d("Attempting to fetch Feature flags using uri: %s", uri);
final Request request = config.getRequestBuilderFor(environmentName) // default GET verb
return config.getRequestBuilderFor(environmentName) // default GET verb
.url(uri)
.build();
return request;
}

private Request getReportRequest(LDUser user) {
Expand All @@ -153,11 +152,10 @@ private Request getReportRequest(LDUser user) {
Timber.d("Attempting to report user using uri: %s", reportUri);
String userJson = GSON.toJson(user);
RequestBody reportBody = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), userJson);
final Request report = config.getRequestBuilderFor(environmentName)
return config.getRequestBuilderFor(environmentName)
.method("REPORT", reportBody) // custom REPORT verb
.url(reportUri)
.build();
return report;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.launchdarkly.android.flagstore.Flag;
import com.launchdarkly.android.response.GsonCache;
import com.launchdarkly.android.response.SummaryEventSharedPreferences;
import com.launchdarkly.android.gson.GsonCache;

import java.io.Closeable;
import java.io.IOException;
Expand Down Expand Up @@ -393,25 +389,23 @@ public Void apply(List<Void> input) {
/**
* Returns a map of all feature flags for the current user. No events are sent to LaunchDarkly.
*
* @return
* @return a map of all feature flags
*/
@Override
public Map<String, ?> allFlags() {
Map<String, Object> result = new HashMap<>();
List<Flag> flags = userManager.getCurrentUserFlagStore().getAllFlags();
for (Flag flag : flags) {
JsonElement jsonVal = flag.getValue();
if (jsonVal == null) {
if (jsonVal == null || jsonVal.isJsonNull()) {
result.put(flag.getKey(), null);
} else if (jsonVal.isJsonPrimitive() && jsonVal.getAsJsonPrimitive().isBoolean()) {
result.put(flag.getKey(), jsonVal.getAsBoolean());
} else if (jsonVal.isJsonPrimitive() && jsonVal.getAsJsonPrimitive().isNumber()) {
// TODO distinguish ints?
result.put(flag.getKey(), jsonVal.getAsFloat());
} else if (jsonVal.isJsonPrimitive() && jsonVal.getAsJsonPrimitive().isString()) {
result.put(flag.getKey(), jsonVal.getAsString());
} else {
// TODO
result.put(flag.getKey(), GsonCache.getGson().toJson(jsonVal));
}
}
Expand Down Expand Up @@ -516,7 +510,7 @@ public void close() throws IOException {
LDClient.closeInstances();
}

private void closeInternal() throws IOException {
private void closeInternal() {
updateProcessor.stop();
eventProcessor.close();
if (connectivityReceiver != null && application.get() != null) {
Expand All @@ -525,16 +519,9 @@ private void closeInternal() throws IOException {
}

private static void closeInstances() throws IOException {
IOException exception = null;
for (LDClient client : instances.values()) {
try {
client.closeInternal();
} catch (IOException e) {
exception = e;
}
client.closeInternal();
}
if (exception != null)
throw exception;
}

/**
Expand Down Expand Up @@ -672,8 +659,9 @@ void startForegroundUpdating() {
}

private void sendFlagRequestEvent(String flagKey, Flag flag, JsonElement value, JsonElement fallback, EvaluationReason reason) {
if (flag == null)
if (flag == null) {
return;
}

int version = flag.getVersionForEvents();
Integer variation = flag.getVariation();
Expand All @@ -692,8 +680,6 @@ private void sendFlagRequestEvent(String flagKey, Flag flag, JsonElement value,
}
}
}

sendSummaryEvent();
}

void startBackgroundPolling() {
Expand Down Expand Up @@ -723,39 +709,14 @@ private void sendEvent(Event event) {
*/
private void updateSummaryEvents(String flagKey, Flag flag, JsonElement result, JsonElement fallback) {
if (flag == null) {
userManager.getSummaryEventSharedPreferences().addOrUpdateEvent(flagKey, result, fallback, -1, -1, true);
userManager.getSummaryEventSharedPreferences().addOrUpdateEvent(flagKey, result, fallback, -1, null, true);
} else {
int version = flag.getVersionForEvents();
Integer variation = flag.getVariation();
if (variation == null)
variation = -1;

userManager.getSummaryEventSharedPreferences().addOrUpdateEvent(flagKey, result, fallback, version, variation, false);
}
}

/**
* Updates the cached summary event that will be sent to the server with the next batch of events.
*/
private void sendSummaryEvent() {
JsonObject features = userManager.getSummaryEventSharedPreferences().getFeaturesJsonObject();
if (features.keySet().size() == 0) {
return;
}
Long startDate = null;
for (String key : features.keySet()) {
JsonObject asJsonObject = features.get(key).getAsJsonObject();
if (asJsonObject.has("startDate")) {
startDate = asJsonObject.get("startDate").getAsLong();
asJsonObject.remove("startDate");
break;
}
}
SummaryEvent summaryEvent = new SummaryEvent(startDate, System.currentTimeMillis(), features);
Timber.d("Sending Summary Event: %s", summaryEvent.toString());
eventProcessor.setSummaryEvent(summaryEvent);
}

@VisibleForTesting
public void clearSummaryEventSharedPreferences() {
userManager.getSummaryEventSharedPreferences().clear();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.launchdarkly.android;


import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
Expand Down
Loading

0 comments on commit 19a9401

Please sign in to comment.