Skip to content

Commit ac98f64

Browse files
authored
fix/integration-with-evaluation-server: test and fix bugs (#3)
1 parent 1275bb1 commit ac98f64

File tree

12 files changed

+685
-26
lines changed

12 files changed

+685
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,4 @@ fabric.properties
115115

116116
# test data
117117
/src/test/resources/simplelogger.properties
118+
/src/test/java/co/featbit/Demos.java

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
<gson-version>2.8.9</gson-version>
5252
<slf4j-version>1.7.35</slf4j-version>
5353
<ttl-version>2.12.6</ttl-version>
54+
<junit-version>5.8.1</junit-version>
5455
</properties>
5556

5657
<dependencies>
@@ -103,6 +104,13 @@
103104
<version>${ttl-version}</version>
104105
</dependency>
105106

107+
<dependency>
108+
<groupId>org.junit.jupiter</groupId>
109+
<artifactId>junit-jupiter-engine</artifactId>
110+
<version>${junit-version}</version>
111+
<scope>test</scope>
112+
</dependency>
113+
106114
</dependencies>
107115

108116
<distributionManagement>

src/main/java/co/featbit/commons/json/JsonHelper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
* this class is only for internal use
1818
*/
1919
public abstract class JsonHelper {
20+
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
2021
private static final Gson gson = new GsonBuilder()
22+
.setDateFormat(DATE_FORMAT)
2123
.setPrettyPrinting()
2224
.serializeNulls()
2325
.disableHtmlEscaping()

src/main/java/co/featbit/server/DataModel.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import co.featbit.commons.json.JsonHelper;
44
import co.featbit.server.exterior.DataStoreTypes;
55
import com.google.common.collect.ImmutableMap;
6+
import com.google.gson.annotations.Expose;
67
import com.google.gson.annotations.JsonAdapter;
78

9+
import java.time.Instant;
810
import java.util.Collections;
11+
import java.util.Date;
912
import java.util.List;
1013
import java.util.Map;
1114

@@ -152,24 +155,22 @@ Map<DataStoreTypes.Category, Map<String, DataStoreTypes.Item>> toStorageType() {
152155
}
153156
}
154157

155-
static class Segment implements DataStoreTypes.Item {
156-
158+
@JsonAdapter(JsonHelper.AfterJsonParseDeserializableTypeAdapterFactory.class)
159+
static class Segment implements DataStoreTypes.Item, JsonHelper.AfterJsonParseDeserializable {
157160
private final String id;
158-
159161
private final Boolean isArchived;
160-
161-
private final Long timestamp;
162-
162+
@Expose(serialize = false)
163+
final Date updatedAt;
164+
@Expose(deserialize = false)
165+
private Long timestamp;
163166
private final List<String> included;
164-
165167
private final List<String> excluded;
166-
167168
private final List<TargetRule> rules;
168169

169-
Segment(String id, Boolean isArchived, Long timestamp, List<String> included, List<String> excluded, List<TargetRule> rules) {
170+
Segment(String id, Boolean isArchived, Date updatedAt, List<String> included, List<String> excluded, List<TargetRule> rules) {
170171
this.id = id;
171172
this.isArchived = isArchived;
172-
this.timestamp = timestamp;
173+
this.updatedAt = updatedAt;
173174
this.included = included;
174175
this.excluded = excluded;
175176
this.rules = rules;
@@ -222,12 +223,20 @@ public Boolean isMatchUser(String userKeyId) {
222223
public DataStoreTypes.Item toArchivedItem() {
223224
return new ArchivedItem(this.id, this.timestamp);
224225
}
226+
227+
@Override
228+
public void afterDeserialization() {
229+
this.timestamp = updatedAt.getTime();
230+
}
225231
}
226232

227233
@JsonAdapter(JsonHelper.AfterJsonParseDeserializableTypeAdapterFactory.class)
228234
static class FeatureFlag implements DataStoreTypes.Item, JsonHelper.AfterJsonParseDeserializable {
229235
final String id;
230-
private final Long timestamp;
236+
@Expose(serialize = false)
237+
final Date updatedAt;
238+
@Expose(deserialize = false)
239+
private Long timestamp;
231240
private final boolean isArchived;
232241
private final boolean exptIncludeAllTargets;
233242
private final boolean isEnabled;
@@ -239,11 +248,12 @@ static class FeatureFlag implements DataStoreTypes.Item, JsonHelper.AfterJsonPar
239248
private final List<TargetRule> rules;
240249
private final Fallthrough fallthrough;
241250
private final String disabledVariationId;
242-
private transient Map<String, Variation> variationMap;
251+
@Expose(serialize = false, deserialize = false)
252+
private Map<String, Variation> variationMap;
243253

244-
FeatureFlag(String id, Long timestamp, boolean isArchived, boolean exptIncludeAllTargets, boolean isEnabled, String name, String key, String variationType, List<Variation> variations, List<TargetUser> targetUsers, List<TargetRule> rules, Fallthrough fallthrough, String disabledVariationId) {
254+
FeatureFlag(String id, Date updatedAt, boolean isArchived, boolean exptIncludeAllTargets, boolean isEnabled, String name, String key, String variationType, List<Variation> variations, List<TargetUser> targetUsers, List<TargetRule> rules, Fallthrough fallthrough, String disabledVariationId) {
245255
this.id = id;
246-
this.timestamp = timestamp;
256+
this.updatedAt = updatedAt;
247257
this.isArchived = isArchived;
248258
this.exptIncludeAllTargets = exptIncludeAllTargets;
249259
this.isEnabled = isEnabled;
@@ -327,6 +337,7 @@ public String getVariationType() {
327337

328338
@Override
329339
public void afterDeserialization() {
340+
this.timestamp = updatedAt.getTime();
330341
if (!isArchived) {
331342
ImmutableMap.Builder<String, Variation> builder = ImmutableMap.builder();
332343
for (Variation variation : getVariations()) {

src/main/java/co/featbit/server/FBClientImp.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,12 @@ public final class FBClientImp implements FBClient {
103103
*/
104104
public FBClientImp(String envSecret, FBConfig config) {
105105
checkNotNull(config, "FBConfig Should not be null");
106-
checkArgument(Base64.isBase64(envSecret), "envSecret is invalid");
107-
checkArgument(Utils.isUrl(config.getStreamingURL()), "streaming uri is invalid");
108-
checkArgument(Utils.isUrl(config.getEventURL()), "event uri is invalid");
109106
this.offline = config.isOffline();
107+
if (!this.offline) {
108+
checkArgument(Base64.isBase64(envSecret), "envSecret is invalid");
109+
checkArgument(Utils.isUrl(config.getStreamingURL()), "streaming uri is invalid");
110+
checkArgument(Utils.isUrl(config.getEventURL()), "event uri is invalid");
111+
}
110112
ContextImp context = new ContextImp(envSecret, config);
111113
//init components
112114
//Insight processor
@@ -128,7 +130,7 @@ public FBClientImp(String envSecret, FBConfig config) {
128130
Status.DataUpdaterImpl dataUpdatorImpl = new Status.DataUpdaterImpl(this.storage);
129131
this.dataUpdater = dataUpdatorImpl;
130132
//data processor
131-
this.dataSynchronizer = config.getUpdateProcessorFactory().createUpdateProcessor(context, dataUpdatorImpl);
133+
this.dataSynchronizer = config.getDataSynchronizerFactory().createDataSynchronizer(context, dataUpdatorImpl);
132134
//data update status provider
133135
this.dataUpdateStatusProvider = new Status.DataUpdateStatusProviderImpl(dataUpdatorImpl);
134136

@@ -137,7 +139,7 @@ public FBClientImp(String envSecret, FBConfig config) {
137139
Future<Boolean> initFuture = this.dataSynchronizer.start();
138140
if (!startWait.isZero() && !startWait.isNegative()) {
139141
try {
140-
if (!(config.getUpdateProcessorFactory() instanceof FactoryImp.NullDataSynchronizerFactory)) {
142+
if (!(config.getDataSynchronizerFactory() instanceof FactoryImp.NullDataSynchronizerFactory)) {
141143
logger.info("FFC JAVA SDK: waiting for Client initialization in {} milliseconds", startWait.toMillis());
142144
}
143145
if (config.getDataStorageFactory() instanceof FactoryImp.NullDataStorageFactory) {

src/main/java/co/featbit/server/FBConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public DataStorageFactory getDataStorageFactory() {
3636
return dataStorageFactory;
3737
}
3838

39-
public DataSynchronizerFactory getUpdateProcessorFactory() {
39+
public DataSynchronizerFactory getDataSynchronizerFactory() {
4040
return dataSynchronizerFactory;
4141
}
4242

src/main/java/co/featbit/server/FactoryImp.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public HttpConfig createHttpConfig(BasicConfig config) {
3838

3939
static final class StreamingBuilderImpl extends StreamingBuilder {
4040
@Override
41-
public DataSynchronizer createUpdateProcessor(Context config, Status.DataUpdater dataUpdater) {
41+
public DataSynchronizer createDataSynchronizer(Context config, Status.DataUpdater dataUpdater) {
4242
Loggers.UPDATE_PROCESSOR.debug("Choose Streaming Update Processor");
4343
firstRetryDelay = firstRetryDelay == null ? DEFAULT_FIRST_RETRY_DURATION : firstRetryDelay;
4444
return new Streaming(dataUpdater, config, firstRetryDelay, maxRetryTimes);
@@ -109,7 +109,7 @@ static final class NullDataSynchronizerFactory implements DataSynchronizerFactor
109109
static final NullDataSynchronizerFactory SINGLETON = new NullDataSynchronizerFactory();
110110

111111
@Override
112-
public DataSynchronizer createUpdateProcessor(Context config, Status.DataUpdater dataUpdater) {
112+
public DataSynchronizer createDataSynchronizer(Context config, Status.DataUpdater dataUpdater) {
113113
if (config.basicConfig().isOffline()) {
114114
Loggers.CLIENT.debug("SDK is in offline mode");
115115
} else {

src/main/java/co/featbit/server/Loggers.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package co.featbit.server;
22

3+
import co.featbit.server.exterior.FBClient;
34
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
56

67
abstract class Loggers {
7-
static final String BASE_LOGGER_NAME = FBClientImp.class.getName();
8+
static final String BASE_LOGGER_NAME = FBClient.class.getName();
89
static final Logger CLIENT = LoggerFactory.getLogger(BASE_LOGGER_NAME);
9-
private static final String DATA_UPDATE_PROCESSOR_LOGGER_NAME = BASE_LOGGER_NAME + ".UpdateProcessor";
10-
static final Logger UPDATE_PROCESSOR = LoggerFactory.getLogger(DATA_UPDATE_PROCESSOR_LOGGER_NAME);
10+
private static final String DATA_SYNCHRONIZER_LOGGER_NAME = BASE_LOGGER_NAME + ".DataSynchronizer";
11+
static final Logger UPDATE_PROCESSOR = LoggerFactory.getLogger(DATA_SYNCHRONIZER_LOGGER_NAME);
1112
private static final String DATA_STORAGE_LOGGER_NAME = BASE_LOGGER_NAME + ".DataStorage";
1213
static final Logger DATA_STORAGE = LoggerFactory.getLogger(DATA_STORAGE_LOGGER_NAME);
1314
private static final String EVALUATION_LOGGER_NAME = BASE_LOGGER_NAME + ".Evaluation";

src/main/java/co/featbit/server/exterior/DataSynchronizerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ public interface DataSynchronizerFactory {
1616
* @param dataUpdater the {@link Status.DataUpdater} which pushes data into the {@link DataStorage}
1717
* @return an {@link DataSynchronizer}
1818
*/
19-
DataSynchronizer createUpdateProcessor(Context context, Status.DataUpdater dataUpdater);
19+
DataSynchronizer createDataSynchronizer(Context context, Status.DataUpdater dataUpdater);
2020
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package co.featbit.server;
2+
3+
import co.featbit.server.exterior.FBClient;
4+
import com.google.common.base.Charsets;
5+
import com.google.common.io.Resources;
6+
7+
import java.io.IOException;
8+
9+
public abstract class FBClientBaseTest {
10+
11+
protected static FBClient initClientInOfflineMode() throws IOException {
12+
FBConfig config = new FBConfig.Builder()
13+
.offline(true)
14+
.streamingURL("ws://fake-url")
15+
.eventURL("http://fake-url")
16+
.build();
17+
FBClient client = new FBClientImp("env-secret", config);
18+
client.initializeFromExternalJson(readResource("fbclient_test_data.json"));
19+
return client;
20+
}
21+
22+
protected static String readResource(final String fileName) throws IOException {
23+
return Resources.toString(Resources.getResource(fileName), Charsets.UTF_8);
24+
}
25+
26+
protected static class Dummy{
27+
int code;
28+
String reason;
29+
}
30+
}

0 commit comments

Comments
 (0)