Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit e22edd3

Browse files
LaunchDarklyReleaseBoteli-darklyLaunchDarklyCIgwhelanLDssrm
authored
prepare 5.8.1 release (#264)
* misc cleanup + test improvements * make intVariation and doubleVariation non-nullable * (5.0) don't use jar magic to find out our own version string * fix test * make intVariation and doubleVariation non-nullable * better unit test coverage of LDClient and FeatureFlagsState * test coverage improvements + minor fixes * better temp file handling in file data source tests * revert file data source implementation change for now * revert unnecessary change * comment about file watching on Mac * add slight delay to avoid timing-dependent test flakiness * test fixes/comments * (5.0) use simpler and more stable logger names * better instructions * more convenient way to set EventSource logger name * (5.0) add HTTP default headers method + some component refactoring * don't need to pass the whole config object to describeConfiguration() * simplify test logic for HTTP headers * (5.0) final test coverage improvements, for now, with enforcement * re-simplify DataBuilder * increase timeouts * misc fixes * rm unnecessary override * indents * update benchmark code for API change * support loading file data from a classpath resource * update metadata so Releaser knows about 4.x branch * minor test fixes * make class final * rm beta changelog items * test data source * more info about coverage in CONTRIBUTING.md * misc fixes/tests * use java-sdk-common 1.0.0 * use okhttp-eventsource 2.3.0 * use okhttp-eventsource 2.3.1 for thread fix * fix flaky tests due to change in EventSource error reporting * remove support for indirect put and indirect patch * fix typo in javadoc example code * clean up polling logic, fix status updating after an outage, don't reinit store unnecessarily (#256) * slightly change semantics of boolean setters, improve tests, misc cleanup * avoid NPEs if LDUser was deserialized by Gson (#257) * avoid NPEs if LDUser was deserialized by Gson * add test * fix release metadata * prepare 4.14.1 release (#200) * Releasing version 4.14.1 * exclude Kotlin metadata from jar + fix misc Gradle problems * update CI and Gradle to test with newer JDKs (#259) * update okhttp to 3.14.9 (fixes incompatibility with OpenJDK 8.0.252) * prepare 4.14.2 release (#205) * Releasing version 4.14.2 * update okhttp to 4.8.1 (fixes incompatibility with OpenJDK 8.0.252) * gitignore * Bump SnakeYAML from 1.19 to 1.26 to address CVE-2017-18640 * prepare 4.14.3 release (#209) * Releasing version 4.14.3 * comments * only log initialization message once in polling mode * [ch89935] Correct some logging call format strings (#264) Also adds debug logs for full exception information in a couple locations. * [ch90109] Remove outdated trackMetric comment from before service support. (#265) * Fix compatibility with Java 7. * Remove import that is no longer used. * add Java 7 build (#267) * prepare 4.14.4 release (#214) * Releasing version 4.14.4 * add and use getSocketFactory * alignment * add socketFactory to builder * test socket factory builder * preserve dummy CI config file when pushing to gh-pages (#271) * fix concatenation when base URI has a context path (#270) * fix shaded jar builds to exclude Jackson classes and not modify Jackson return types (#268) * add test httpClientCanUseCustomSocketFactory for DefaultFeatureRequestor * add httpClientCanUseCustomSocketFactory() test for DefaultEventSenderTest * add httpClientCanUseCustomSocketFactory() test to StreamProcessorTest * pass URI to in customSocketFactory event test * make test less ambiguous * copy rules to new FlagBuilder instances (#273) * Bump guava version (#274) * Removed the guides link * increment versions when loading file data, so FlagTracker will work (#275) * increment versions when loading file data, so FlagTracker will work * update doc comment about flag change events with file data * add ability to ignore duplicate keys in file data (#276) * add alias events (#278) * add alias events and function * update tests for new functionality * update javadoc strings * add validation of javadoc build to CI * update commons-codec to 1.15 (#279) * Add support for experiment rollouts * add tests and use seed for allocating user to partition * test serialization and add check for isExperiment * fix PollingProcessorTest test race condition + other test issues (#282) * use launchdarkly-java-sdk-common 1.1.0-alpha-expalloc.2 * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * changes per code review comments * Please enter the commit message for your changes. Lines starting * fix null pointer exception * address code review comments * address more comments * missed a ! for isUntracked() * fix default boolean for json * make untracked FALSE by default * refactoring of bucketing logic to remove the need for an extra result object (#283) * add comment to enum * various JSON fixes, update common-sdk (#284) * simlpify the logic and make it match node/.Net sdks * Update src/main/java/com/launchdarkly/sdk/server/EventFactory.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * add the same comment as the Node SDK * Remove outdated/meaningless doc comment. (#286) * protect against NPEs if flag/segment JSON contains a null value * use java-sdk-common 1.2.0 * fix Jackson-related build issues (again) (#288) * update to okhttp-eventsource patch for stream retry bug, improve tests (#289) * update to okhttp-eventsource patch for stream retry bug, improve test * add test for appropriate stream retry * add public builder for FeatureFlagsState (#290) * add public builder for FeatureFlagsState * javadoc fixes * clarify FileData doc comment to say you shouldn't use offline mode (#291) * improve validation of SDK key so we won't throw an exception that contains the key (#293) * fix javadoc link in FileData comment (#294) * fix PollingProcessor 401 behavior and use new HTTP test helpers (#292) * re-fix metadata to remove Jackson dependencies, also remove Class-Path from manifest (#295) * make FeatureFlagsState.Builder.build() public (#297) * clean up tests using java-test-helpers 1.1.0 (#296) * use Releaser v2 config + newer CI images (#298) * [ch123129] Fix `PollingDataSourceBuilder` example. (#299) * Updates docs URLs * always use US locale when parsing HTTP dates * use Gson 2.8.9 * don't try to send more diagnostic events after an unrecoverable HTTP error * ensure module-info file isn't copied into our jars during build * use Gradle 7 * update build for benchmarks * more Gradle 7 compatibility changes for benchmark job * test with Java 17 in CI (#307) * test with Java 17 in CI * also test in Java 17 for Windows * fix choco install command * do date comparisons as absolute times, regardless of time zone (#310) * fix suppression of nulls in JSON representations (#311) * fix suppression of nulls in JSON representations * distinguish between situations where we do or do not want to suppress nulls * fix identify/track null user key check, also don't create index event for alias * use latest java-sdk-common * fix setting of trackEvents/trackReason in allFlagsState data when there's an experiment * implement contract tests (#314) * Merge Big Segments feature branch for 5.7.0 release (#316) Includes Big Segments implementation and contract test support for the new behavior. * Fix for pom including SDK common library as a dependency. (#317) * Upload JUnit XML to CircleCI on failure (#320) Fix a bug in the CircleCI config that was only uploading JUnit XML on _success_, not failure. * Add application tag support (#319) * Enforce 64 character limit on application tag values (#323) * fix "wrong type" logic in evaluations when default value is null Co-authored-by: Eli Bishop <eli@launchdarkly.com> Co-authored-by: LaunchDarklyCI <dev@launchdarkly.com> Co-authored-by: LaunchDarklyCI <LaunchDarklyCI@users.noreply.github.com> Co-authored-by: Gavin Whelan <gwhelan@launchdarkly.com> Co-authored-by: ssrm <ssrm@users.noreply.github.com> Co-authored-by: Harpo Roeder <hroeder@launchdarkly.com> Co-authored-by: Ben Woskow <48036130+bwoskow-ld@users.noreply.github.com> Co-authored-by: Elliot <35050275+Apache-HB@users.noreply.github.com> Co-authored-by: Robert J. Neal <rneal@launchdarkly.com> Co-authored-by: Robert J. Neal <robertjneal@users.noreply.github.com> Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> Co-authored-by: LaunchDarklyReleaseBot <launchdarklyreleasebot@launchdarkly.com> Co-authored-by: Ember Stevens <ember.stevens@launchdarkly.com> Co-authored-by: ember-stevens <79482775+ember-stevens@users.noreply.github.com> Co-authored-by: Alex Engelberg <alex.benjamin.engelberg@gmail.com>
1 parent 80fa187 commit e22edd3

File tree

4 files changed

+65
-19
lines changed

4 files changed

+65
-19
lines changed

src/main/java/com/launchdarkly/sdk/server/LDClient.java

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.launchdarkly.sdk.EvaluationReason;
1212
import com.launchdarkly.sdk.LDUser;
1313
import com.launchdarkly.sdk.LDValue;
14+
import com.launchdarkly.sdk.LDValueType;
1415
import com.launchdarkly.sdk.server.integrations.EventProcessorBuilder;
1516
import com.launchdarkly.sdk.server.interfaces.BigSegmentStoreStatusProvider;
1617
import com.launchdarkly.sdk.server.interfaces.BigSegmentsConfiguration;
@@ -365,64 +366,65 @@ public FeatureFlagsState allFlagsState(LDUser user, FlagsStateOption... options)
365366

366367
@Override
367368
public boolean boolVariation(String featureKey, LDUser user, boolean defaultValue) {
368-
return evaluate(featureKey, user, LDValue.of(defaultValue), true).booleanValue();
369+
return evaluate(featureKey, user, LDValue.of(defaultValue), LDValueType.BOOLEAN).booleanValue();
369370
}
370371

371372
@Override
372373
public int intVariation(String featureKey, LDUser user, int defaultValue) {
373-
return evaluate(featureKey, user, LDValue.of(defaultValue), true).intValue();
374+
return evaluate(featureKey, user, LDValue.of(defaultValue), LDValueType.NUMBER).intValue();
374375
}
375376

376377
@Override
377378
public double doubleVariation(String featureKey, LDUser user, double defaultValue) {
378-
return evaluate(featureKey, user, LDValue.of(defaultValue), true).doubleValue();
379+
return evaluate(featureKey, user, LDValue.of(defaultValue), LDValueType.NUMBER).doubleValue();
379380
}
380381

381382
@Override
382383
public String stringVariation(String featureKey, LDUser user, String defaultValue) {
383-
return evaluate(featureKey, user, LDValue.of(defaultValue), true).stringValue();
384+
return evaluate(featureKey, user, LDValue.of(defaultValue), LDValueType.STRING).stringValue();
384385
}
385386

386387
@Override
387388
public LDValue jsonValueVariation(String featureKey, LDUser user, LDValue defaultValue) {
388-
return evaluate(featureKey, user, LDValue.normalize(defaultValue), false);
389+
return evaluate(featureKey, user, LDValue.normalize(defaultValue), null);
389390
}
390391

391392
@Override
392393
public EvaluationDetail<Boolean> boolVariationDetail(String featureKey, LDUser user, boolean defaultValue) {
393-
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue), true,
394-
eventFactoryWithReasons);
394+
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue),
395+
LDValueType.BOOLEAN, eventFactoryWithReasons);
395396
return EvaluationDetail.fromValue(result.getValue().booleanValue(),
396397
result.getVariationIndex(), result.getReason());
397398
}
398399

399400
@Override
400401
public EvaluationDetail<Integer> intVariationDetail(String featureKey, LDUser user, int defaultValue) {
401-
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue), true,
402-
eventFactoryWithReasons);
402+
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue),
403+
LDValueType.NUMBER, eventFactoryWithReasons);
403404
return EvaluationDetail.fromValue(result.getValue().intValue(),
404405
result.getVariationIndex(), result.getReason());
405406
}
406407

407408
@Override
408409
public EvaluationDetail<Double> doubleVariationDetail(String featureKey, LDUser user, double defaultValue) {
409-
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue), true,
410-
eventFactoryWithReasons);
410+
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue),
411+
LDValueType.NUMBER, eventFactoryWithReasons);
411412
return EvaluationDetail.fromValue(result.getValue().doubleValue(),
412413
result.getVariationIndex(), result.getReason());
413414
}
414415

415416
@Override
416417
public EvaluationDetail<String> stringVariationDetail(String featureKey, LDUser user, String defaultValue) {
417-
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue), true,
418-
eventFactoryWithReasons);
418+
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.of(defaultValue),
419+
LDValueType.STRING, eventFactoryWithReasons);
419420
return EvaluationDetail.fromValue(result.getValue().stringValue(),
420421
result.getVariationIndex(), result.getReason());
421422
}
422423

423424
@Override
424425
public EvaluationDetail<LDValue> jsonValueVariationDetail(String featureKey, LDUser user, LDValue defaultValue) {
425-
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.normalize(defaultValue), false, eventFactoryWithReasons);
426+
Evaluator.EvalResult result = evaluateInternal(featureKey, user, LDValue.normalize(defaultValue),
427+
null, eventFactoryWithReasons);
426428
return EvaluationDetail.fromValue(result.getValue(), result.getVariationIndex(), result.getReason());
427429
}
428430

@@ -449,16 +451,16 @@ public boolean isFlagKnown(String featureKey) {
449451
return false;
450452
}
451453

452-
private LDValue evaluate(String featureKey, LDUser user, LDValue defaultValue, boolean checkType) {
453-
return evaluateInternal(featureKey, user, defaultValue, checkType, eventFactoryDefault).getValue();
454+
private LDValue evaluate(String featureKey, LDUser user, LDValue defaultValue, LDValueType requireType) {
455+
return evaluateInternal(featureKey, user, defaultValue, requireType, eventFactoryDefault).getValue();
454456
}
455457

456458
private Evaluator.EvalResult errorResult(EvaluationReason.ErrorKind errorKind, final LDValue defaultValue) {
457459
return new Evaluator.EvalResult(defaultValue, NO_VARIATION, EvaluationReason.error(errorKind));
458460
}
459461

460-
private Evaluator.EvalResult evaluateInternal(String featureKey, LDUser user, LDValue defaultValue, boolean checkType,
461-
EventFactory eventFactory) {
462+
private Evaluator.EvalResult evaluateInternal(String featureKey, LDUser user, LDValue defaultValue,
463+
LDValueType requireType, EventFactory eventFactory) {
462464
if (!isInitialized()) {
463465
if (dataStore.isInitialized()) {
464466
Loggers.EVALUATION.warn("Evaluation called before client initialized for feature flag \"{}\"; using last known values from data store", featureKey);
@@ -496,7 +498,9 @@ private Evaluator.EvalResult evaluateInternal(String featureKey, LDUser user, LD
496498
evalResult.setValue(defaultValue);
497499
} else {
498500
LDValue value = evalResult.getValue(); // guaranteed not to be an actual Java null, but can be LDValue.ofNull()
499-
if (checkType && !value.isNull() && !defaultValue.isNull() && defaultValue.getType() != value.getType()) {
501+
if (requireType != null &&
502+
!value.isNull() &&
503+
value.getType() != requireType) {
500504
Loggers.EVALUATION.error("Feature flag evaluation expected result as {}, but got {}", defaultValue.getType(), value.getType());
501505
sendFlagRequestEvent(eventFactory.newUnknownFeatureRequestEvent(featureKey, user, defaultValue,
502506
EvaluationReason.ErrorKind.WRONG_TYPE));

src/main/java/com/launchdarkly/sdk/server/Util.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ static String applicationTagHeader(ApplicationInfo applicationInfo) {
239239
Loggers.MAIN.warn("Value of ApplicationInfo.{} contained invalid characters and was discarded", javaKey);
240240
continue;
241241
}
242+
if (tagVal.length() > 64) {
243+
Loggers.MAIN.warn("Value of ApplicationInfo.{} was longer than 64 characters and was discarded", javaKey);
244+
continue;
245+
}
242246
parts.add(tagKey + "/" + tagVal);
243247
}
244248
return String.join(" ", parts);

src/test/java/com/launchdarkly/sdk/server/LDClientEvaluationTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,21 @@ public void boolVariationReturnsFlagValue() throws Exception {
6464
@Test
6565
public void boolVariationReturnsDefaultValueForUnknownFlag() throws Exception {
6666
assertFalse(client.boolVariation("key", user, false));
67+
68+
assertEquals(EvaluationDetail.fromValue(false, NO_VARIATION,
69+
EvaluationReason.error(EvaluationReason.ErrorKind.FLAG_NOT_FOUND)),
70+
client.boolVariationDetail("key", user, false));
6771
}
6872

6973
@Test
7074
public void boolVariationReturnsDefaultValueForWrongType() throws Exception {
7175
upsertFlag(dataStore, flagWithValue("key", LDValue.of("wrong")));
7276

7377
assertFalse(client.boolVariation("key", user, false));
78+
79+
assertEquals(EvaluationDetail.fromValue(false, NO_VARIATION,
80+
EvaluationReason.error(EvaluationReason.ErrorKind.WRONG_TYPE)),
81+
client.boolVariationDetail("key", user, false));
7482
}
7583

7684
@Test
@@ -103,13 +111,21 @@ public void intVariationFromDoubleRoundsTowardZero() throws Exception {
103111
@Test
104112
public void intVariationReturnsDefaultValueForUnknownFlag() throws Exception {
105113
assertEquals(1, client.intVariation("key", user, 1));
114+
115+
assertEquals(EvaluationDetail.fromValue(1, NO_VARIATION,
116+
EvaluationReason.error(EvaluationReason.ErrorKind.FLAG_NOT_FOUND)),
117+
client.intVariationDetail("key", user, 1));
106118
}
107119

108120
@Test
109121
public void intVariationReturnsDefaultValueForWrongType() throws Exception {
110122
upsertFlag(dataStore, flagWithValue("key", LDValue.of("wrong")));
111123

112124
assertEquals(1, client.intVariation("key", user, 1));
125+
126+
assertEquals(EvaluationDetail.fromValue(1, NO_VARIATION,
127+
EvaluationReason.error(EvaluationReason.ErrorKind.WRONG_TYPE)),
128+
client.intVariationDetail("key", user, 1));
113129
}
114130

115131
@Test
@@ -129,13 +145,21 @@ public void doubleVariationReturnsFlagValueEvenIfEncodedAsInt() throws Exception
129145
@Test
130146
public void doubleVariationReturnsDefaultValueForUnknownFlag() throws Exception {
131147
assertEquals(1.0d, client.doubleVariation("key", user, 1.0d), 0d);
148+
149+
assertEquals(EvaluationDetail.fromValue(1.0d, NO_VARIATION,
150+
EvaluationReason.error(EvaluationReason.ErrorKind.FLAG_NOT_FOUND)),
151+
client.doubleVariationDetail("key", user, 1.0d));
132152
}
133153

134154
@Test
135155
public void doubleVariationReturnsDefaultValueForWrongType() throws Exception {
136156
upsertFlag(dataStore, flagWithValue("key", LDValue.of("wrong")));
137157

138158
assertEquals(1.0d, client.doubleVariation("key", user, 1.0d), 0d);
159+
160+
assertEquals(EvaluationDetail.fromValue(1.0d, NO_VARIATION,
161+
EvaluationReason.error(EvaluationReason.ErrorKind.WRONG_TYPE)),
162+
client.doubleVariationDetail("key", user, 1.0d));
139163
}
140164

141165
@Test
@@ -160,20 +184,32 @@ public void stringVariationReturnsDefaultValueForUnknownFlag() throws Exception
160184
@Test
161185
public void stringVariationWithNullDefaultReturnsDefaultValueForUnknownFlag() throws Exception {
162186
assertNull(client.stringVariation("key", user, null));
187+
188+
assertEquals(EvaluationDetail.fromValue((String)null, NO_VARIATION,
189+
EvaluationReason.error(EvaluationReason.ErrorKind.FLAG_NOT_FOUND)),
190+
client.stringVariationDetail("key", user, null));
163191
}
164192

165193
@Test
166194
public void stringVariationReturnsDefaultValueForWrongType() throws Exception {
167195
upsertFlag(dataStore, flagWithValue("key", LDValue.of(true)));
168196

169197
assertEquals("a", client.stringVariation("key", user, "a"));
198+
199+
assertEquals(EvaluationDetail.fromValue("a", NO_VARIATION,
200+
EvaluationReason.error(EvaluationReason.ErrorKind.WRONG_TYPE)),
201+
client.stringVariationDetail("key", user, "a"));
170202
}
171203

172204
@Test
173205
public void stringVariationWithNullDefaultReturnsDefaultValueForWrongType() throws Exception {
174206
upsertFlag(dataStore, flagWithValue("key", LDValue.of(true)));
175207

176208
assertNull(client.stringVariation("key", user, null));
209+
210+
assertEquals(EvaluationDetail.fromValue((String)null, NO_VARIATION,
211+
EvaluationReason.error(EvaluationReason.ErrorKind.WRONG_TYPE)),
212+
client.stringVariationDetail("key", user, null));
177213
}
178214

179215
@Test

src/test/java/com/launchdarkly/sdk/server/UtilTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ public void applicationTagHeader() {
100100
assertEquals("application-id/foo application-version/1.0.0", Util.applicationTagHeader(new ApplicationInfo("foo", "1.0.0")));
101101
// Values with invalid characters get discarded
102102
assertEquals("", Util.applicationTagHeader(new ApplicationInfo("invalid name", "lol!")));
103+
// Values over 64 chars get discarded
104+
assertEquals("", Util.applicationTagHeader(new ApplicationInfo("look-at-this-incredibly-long-application-id-like-wow-it-sure-is-verbose", null)));
103105
// Empty values get discarded
104106
assertEquals("", Util.applicationTagHeader(new ApplicationInfo("", "")));
105107
}

0 commit comments

Comments
 (0)