Skip to content

Commit a8c0dc5

Browse files
committed
Add equality methods to LiveVariable and FeatureFlag models to improve ProjectConfigParsing evaluation.
Update the v4 datafile with an empty top level "variables" array and added "status" to all variables in features. Added empty array passed in to ProjectConfig constructor in ValidProjectConfigV4.java ProjectConfigTestUtils now compare feature flags more effectively Signed-off-by: wangjoshuah <wangjoshuah@gmail.com>
1 parent 7c27128 commit a8c0dc5

File tree

8 files changed

+129
-21
lines changed

8 files changed

+129
-21
lines changed

core-api/src/main/java/com/optimizely/ab/config/FeatureFlag.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,30 @@ public String toString() {
7777
", variables=" + variables +
7878
'}';
7979
}
80+
81+
@Override
82+
public boolean equals(Object o) {
83+
if (this == o) return true;
84+
if (o == null || getClass() != o.getClass()) return false;
85+
86+
FeatureFlag that = (FeatureFlag) o;
87+
88+
if (!id.equals(that.id)) return false;
89+
if (!key.equals(that.key)) return false;
90+
if (!layerId.equals(that.layerId)) return false;
91+
if (!experimentIds.equals(that.experimentIds)) return false;
92+
if (!variables.equals(that.variables)) return false;
93+
return variableKeyToLiveVariableMap.equals(that.variableKeyToLiveVariableMap);
94+
}
95+
96+
@Override
97+
public int hashCode() {
98+
int result = id.hashCode();
99+
result = 31 * result + key.hashCode();
100+
result = 31 * result + layerId.hashCode();
101+
result = 31 * result + experimentIds.hashCode();
102+
result = 31 * result + variables.hashCode();
103+
result = 31 * result + variableKeyToLiveVariableMap.hashCode();
104+
return result;
105+
}
80106
}

core-api/src/main/java/com/optimizely/ab/config/LiveVariable.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,28 @@ public String toString() {
150150
", status=" + status +
151151
'}';
152152
}
153+
154+
@Override
155+
public boolean equals(Object o) {
156+
if (this == o) return true;
157+
if (o == null || getClass() != o.getClass()) return false;
158+
159+
LiveVariable variable = (LiveVariable) o;
160+
161+
if (!id.equals(variable.id)) return false;
162+
if (!key.equals(variable.key)) return false;
163+
if (!defaultValue.equals(variable.defaultValue)) return false;
164+
if (type != variable.type) return false;
165+
return status == variable.status;
166+
}
167+
168+
@Override
169+
public int hashCode() {
170+
int result = id.hashCode();
171+
result = 31 * result + key.hashCode();
172+
result = 31 * result + defaultValue.hashCode();
173+
result = 31 * result + type.hashCode();
174+
result = 31 * result + status.hashCode();
175+
return result;
176+
}
153177
}

core-api/src/main/java/com/optimizely/ab/config/ProjectConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ public List<Experiment> getExperimentsForEventKey(String eventKey) {
224224
return Collections.emptyList();
225225
}
226226

227+
public List<FeatureFlag> getFeatureFlags() {
228+
return featureFlags;
229+
}
230+
227231
public List<Attribute> getAttributes() {
228232
return attributes;
229233
}

core-api/src/main/java/com/optimizely/ab/config/parser/ProjectConfigJacksonDeserializer.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
import com.fasterxml.jackson.databind.JsonNode;
2424
import com.fasterxml.jackson.databind.ObjectMapper;
2525
import com.fasterxml.jackson.databind.module.SimpleModule;
26-
2726
import com.optimizely.ab.config.Attribute;
28-
import com.optimizely.ab.config.audience.Audience;
2927
import com.optimizely.ab.config.EventType;
3028
import com.optimizely.ab.config.Experiment;
29+
import com.optimizely.ab.config.FeatureFlag;
3130
import com.optimizely.ab.config.Group;
3231
import com.optimizely.ab.config.LiveVariable;
3332
import com.optimizely.ab.config.ProjectConfig;
33+
import com.optimizely.ab.config.audience.Audience;
3434

3535
import java.io.IOException;
3636
import java.util.List;
@@ -51,6 +51,7 @@ public ProjectConfig deserialize(JsonParser parser, DeserializationContext conte
5151
String projectId = node.get("projectId").textValue();
5252
String revision = node.get("revision").textValue();
5353
String version = node.get("version").textValue();
54+
int datafileVersion = Integer.parseInt(version);
5455

5556
List<Group> groups = mapper.readValue(node.get("groups").toString(), new TypeReference<List<Group>>() {});
5657
List<Experiment> experiments = mapper.readValue(node.get("experiments").toString(),
@@ -66,13 +67,31 @@ public ProjectConfig deserialize(JsonParser parser, DeserializationContext conte
6667

6768
boolean anonymizeIP = false;
6869
List<LiveVariable> liveVariables = null;
69-
if (version.equals(ProjectConfig.Version.V3.toString())) {
70+
if (datafileVersion >= 3) {
7071
liveVariables = mapper.readValue(node.get("variables").toString(),
7172
new TypeReference<List<LiveVariable>>() {});
7273
anonymizeIP = node.get("anonymizeIP").asBoolean();
7374
}
7475

75-
return new ProjectConfig(accountId, projectId, version, revision, groups, experiments, attributes, events,
76-
audiences, anonymizeIP, liveVariables);
76+
List<FeatureFlag> featureFlags = null;
77+
if (datafileVersion >= 4) {
78+
featureFlags = mapper.readValue(node.get("featureFlags").toString(),
79+
new TypeReference<List<FeatureFlag>>() {});
80+
}
81+
82+
return new ProjectConfig(
83+
accountId,
84+
anonymizeIP,
85+
projectId,
86+
revision,
87+
version,
88+
attributes,
89+
audiences,
90+
events,
91+
experiments,
92+
featureFlags,
93+
groups,
94+
liveVariables
95+
);
7796
}
7897
}

core-api/src/test/java/com/optimizely/ab/config/ProjectConfigTestUtils.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,12 +450,13 @@ public static void verifyProjectConfig(@CheckForNull ProjectConfig actual, @Nonn
450450
assertThat(actual.getVersion(), is(expected.getVersion()));
451451
assertThat(actual.getRevision(), is(expected.getRevision()));
452452

453-
verifyGroups(actual.getGroups(), expected.getGroups());
454-
verifyExperiments(actual.getExperiments(), expected.getExperiments());
455453
verifyAttributes(actual.getAttributes(), expected.getAttributes());
456-
verifyEvents(actual.getEventTypes(), expected.getEventTypes());
457454
verifyAudiences(actual.getAudiences(), expected.getAudiences());
455+
verifyEvents(actual.getEventTypes(), expected.getEventTypes());
456+
verifyExperiments(actual.getExperiments(), expected.getExperiments());
457+
verifyFeatureFlags(actual.getFeatureFlags(), expected.getFeatureFlags());
458458
verifyLiveVariables(actual.getLiveVariables(), expected.getLiveVariables());
459+
verifyGroups(actual.getGroups(), expected.getGroups());
459460
}
460461

461462
/**
@@ -482,6 +483,16 @@ private static void verifyExperiments(List<Experiment> actual, List<Experiment>
482483
}
483484
}
484485

486+
private static void verifyFeatureFlags(List<FeatureFlag> actual, List<FeatureFlag> expected) {
487+
assertEquals(expected.size(), actual.size());
488+
for (int i = 0; i < actual.size(); i ++) {
489+
FeatureFlag actualFeatureFlag = actual.get(i);
490+
FeatureFlag expectedFeatureFlag = expected.get(i);
491+
492+
assertEquals(expectedFeatureFlag, actualFeatureFlag);
493+
}
494+
}
495+
485496
/**
486497
* Asserts that the provided variation configs are equivalent.
487498
*/

core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public class ValidProjectConfigV4 {
150150
)
151151
);
152152
private static final String FEATURE_MULTI_VARIATE_FEATURE_ID = "3263342226";
153-
private static final String FEATURE_MULTI_VARIATE_FEATURE_KEY = "multi_variate_feature";
153+
public static final String FEATURE_MULTI_VARIATE_FEATURE_KEY = "multi_variate_feature";
154154
private static final String VARIABLE_FIRST_LETTER_ID = "675244127";
155155
private static final String VARIABLE_FIRST_LETTER_KEY = "first_letter";
156156
private static final String VARIABLE_FIRST_LETTER_DEFAULT_VALUE = "H";
@@ -608,7 +608,7 @@ public static ProjectConfig generateValidProjectConfigV4() {
608608
experiments,
609609
featureFlags,
610610
groups,
611-
null
611+
Collections.<LiveVariable>emptyList()
612612
);
613613
}
614614
}

core-api/src/test/java/com/optimizely/ab/internal/LogbackVerifier.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
import org.mockito.ArgumentMatcher;
1212
import org.mockito.Mock;
1313
import org.mockito.Mockito;
14+
import org.mockito.verification.VerificationMode;
1415
import org.slf4j.LoggerFactory;
1516

1617
import java.util.LinkedList;
1718
import java.util.List;
1819

1920
import static org.mockito.Matchers.argThat;
21+
import static org.mockito.Mockito.times;
2022
import static org.mockito.Mockito.when;
2123
import static org.mockito.MockitoAnnotations.initMocks;
2224

@@ -51,11 +53,22 @@ public void expectMessage(Level level) {
5153
}
5254

5355
public void expectMessage(Level level, String msg) {
54-
expectMessage(level, msg, null);
56+
expectMessage(level, msg, (Class<? extends Throwable>) null);
5557
}
5658

5759
public void expectMessage(Level level, String msg, Class<? extends Throwable> throwableClass) {
58-
expectedEvents.add(new ExpectedLogEvent(level, msg, throwableClass));
60+
expectMessage(level, msg, null, times(1));
61+
}
62+
63+
public void expectMessage(Level level, String msg, VerificationMode times) {
64+
expectMessage(level, msg, null, times);
65+
}
66+
67+
public void expectMessage(Level level,
68+
String msg,
69+
Class<? extends Throwable> throwableClass,
70+
VerificationMode times) {
71+
expectedEvents.add(new ExpectedLogEvent(level, msg, throwableClass, times));
5972
}
6073

6174
private void before() {
@@ -66,7 +79,7 @@ private void before() {
6679

6780
private void verify() throws Throwable {
6881
for (final ExpectedLogEvent expectedEvent : expectedEvents) {
69-
Mockito.verify(appender).doAppend(argThat(new ArgumentMatcher<ILoggingEvent>() {
82+
Mockito.verify(appender, expectedEvent.times).doAppend(argThat(new ArgumentMatcher<ILoggingEvent>() {
7083
@Override
7184
public boolean matches(final Object argument) {
7285
return expectedEvent.matches((ILoggingEvent) argument);
@@ -83,11 +96,16 @@ private final static class ExpectedLogEvent {
8396
private final String message;
8497
private final Level level;
8598
private final Class<? extends Throwable> throwableClass;
99+
private final VerificationMode times;
86100

87-
private ExpectedLogEvent(Level level, String message, Class<? extends Throwable> throwableClass) {
101+
private ExpectedLogEvent(Level level,
102+
String message,
103+
Class<? extends Throwable> throwableClass,
104+
VerificationMode times) {
88105
this.message = message;
89106
this.level = level;
90107
this.throwableClass = throwableClass;
108+
this.times = times;
91109
}
92110

93111
private boolean matches(ILoggingEvent actual) {

core-api/src/test/resources/config/valid-project-config-v4.json

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,8 @@
320320
"id": "4111654444",
321321
"key": "double_variable",
322322
"type": "double",
323-
"defaultValue": "14.99"
323+
"defaultValue": "14.99",
324+
"status": "active"
324325
}
325326
]
326327
},
@@ -334,7 +335,8 @@
334335
"id": "593964691",
335336
"key": "integer_variable",
336337
"type": "integer",
337-
"defaultValue": "7"
338+
"defaultValue": "7",
339+
"status": "active"
338340
}
339341
]
340342
},
@@ -348,7 +350,8 @@
348350
"id": "3974680341",
349351
"key": "boolean_variable",
350352
"type": "boolean",
351-
"defaultValue": "true"
353+
"defaultValue": "true",
354+
"status": "active"
352355
}
353356
]
354357
},
@@ -362,7 +365,8 @@
362365
"id": "2077511132",
363366
"key": "string_variable",
364367
"type": "string",
365-
"defaultValue": "wingardium leviosa"
368+
"defaultValue": "wingardium leviosa",
369+
"status": "active"
366370
}
367371
]
368372
},
@@ -376,16 +380,18 @@
376380
"id": "675244127",
377381
"key": "first_letter",
378382
"type": "string",
379-
"defaultValue": "H"
383+
"defaultValue": "H",
384+
"status": "active"
380385
},
381386
{
382387
"id": "4052219963",
383388
"key": "rest_of_name",
384389
"type": "string",
385-
"defaultValue": "arry"
390+
"defaultValue": "arry",
391+
"status": "active"
386392
}
387393
]
388394
}
389395
],
390-
"liveVariables": []
396+
"variables": []
391397
}

0 commit comments

Comments
 (0)