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

Commit

Permalink
prepare 5.7.0 release (#257)
Browse files Browse the repository at this point in the history
  • Loading branch information
LaunchDarklyReleaseBot authored Jan 29, 2022
1 parent 0fe982c commit 929274e
Show file tree
Hide file tree
Showing 48 changed files with 3,124 additions and 108 deletions.
14 changes: 11 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ jobs:
default: false
docker:
- image: <<parameters.docker-image>>
environment:
TEST_HARNESS_PARAMS: -junit /home/circleci/junit/contract-tests-junit.xml
steps:
- checkout
- run: cp gradle.properties.example gradle.properties
Expand All @@ -78,12 +80,18 @@ jobs:
./gradlew jacocoTestReport
mkdir -p coverage/
cp -r build/reports/jacoco/test/* ./coverage
- run: mkdir -p ~/junit/
- run:
name: Save test results
command: |
mkdir -p ~/junit/
find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} ~/junit/ \;
command: find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} ~/junit/ \;
when: always

- run: make build-contract-tests
- run:
command: make start-contract-test-service
background: true
- run: make run-contract-tests

- store_test_results:
path: ~/junit
- store_artifacts:
Expand Down
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ To build the SDK and run all unit tests:
./gradlew test
```

To run the SDK contract test suite in Linux (see [`contract-tests/README.md`](./contract-tests/README.md)):

```bash
make contract-tests
```

### Benchmarks

The project in the `benchmarks` subdirectory uses [JMH](https://openjdk.java.net/projects/code-tools/jmh/) to generate performance metrics for the SDK. This is run as a CI job, and can also be run manually by running `make` within `benchmarks` and then inspecting `build/reports/jmh`.
Expand Down
29 changes: 29 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

build:
./gradlew jar

clean:
./gradlew clean

test:
./gradlew test

TEMP_TEST_OUTPUT=/tmp/sdk-test-service.log

build-contract-tests:
@cd contract-tests && ../gradlew installDist

start-contract-test-service:
@contract-tests/service/build/install/service/bin/service

start-contract-test-service-bg:
@echo "Test service output will be captured in $(TEMP_TEST_OUTPUT)"
@make start-contract-test-service >$(TEMP_TEST_OUTPUT) 2>&1 &

run-contract-tests:
@curl -s https://raw.githubusercontent.com/launchdarkly/sdk-test-harness/v1.0.0/downloader/run.sh \
| VERSION=v1 PARAMS="-url http://localhost:8000 -debug -stop-service-at-end $(TEST_HARNESS_PARAMS)" sh

contract-tests: build-contract-tests start-contract-test-service-bg run-contract-tests

.PHONY: build-contract-tests start-contract-test-service start-contract-test-service-bg run-contract-tests contract-tests
9 changes: 6 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ext.versions = [
"gson": "2.8.9",
"guava": "30.1-jre",
"jackson": "2.11.2",
"launchdarklyJavaSdkCommon": "1.2.2",
"launchdarklyJavaSdkCommon": "1.3.0",
"okhttp": "4.8.1", // specify this for the SDK build instead of relying on the transitive dependency from okhttp-eventsource
"okhttpEventsource": "2.3.2",
"slf4j": "1.7.21",
Expand Down Expand Up @@ -108,7 +108,6 @@ ext.versions = [
// Jackson in "libraries.optional" because we need to generate OSGi optional import
// headers for it.
libraries.internal = [
"com.launchdarkly:launchdarkly-java-sdk-common:${versions.launchdarklyJavaSdkCommon}",
"commons-codec:commons-codec:${versions.commonsCodec}",
"com.google.code.gson:gson:${versions.gson}",
"com.google.guava:guava:${versions.guava}",
Expand All @@ -117,6 +116,10 @@ libraries.internal = [
"org.yaml:snakeyaml:${versions.snakeyaml}",
]

libraries.common = [
"com.launchdarkly:launchdarkly-java-sdk-common:${versions.launchdarklyJavaSdkCommon}",
]

// Add dependencies to "libraries.external" that are exposed in our public API, or that have
// global state that must be shared between the SDK and the caller. Putting dependencies
// here has the following effects:
Expand Down Expand Up @@ -176,7 +179,7 @@ configurations {

dependencies {
implementation libraries.internal
api libraries.external
api libraries.external, libraries.common
testImplementation libraries.test, libraries.internal, libraries.external
optional libraries.optional

Expand Down
7 changes: 7 additions & 0 deletions contract-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SDK contract test service

This directory contains an implementation of the cross-platform SDK testing protocol defined by https://github.com/launchdarkly/sdk-test-harness. See that project's `README` for details of this protocol, and the kinds of SDK capabilities that are relevant to the contract tests. This code should not need to be updated unless the SDK has added or removed such capabilities.

To run these tests locally, run `make contract-tests` from the SDK project root directory. This downloads the correct version of the test harness tool automatically.

Or, to test against an in-progress local version of the test harness, run `make start-contract-test-service` from the SDK project root directory; then, in the root directory of the `sdk-test-harness` project, build the test harness and run it from the command line.
1 change: 1 addition & 0 deletions contract-tests/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gnsp.disableApplyOnlyOnRootProjectEnforcement=true
40 changes: 40 additions & 0 deletions contract-tests/service/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

plugins {
id "java"
id "application"
}

repositories {
mavenCentral()
maven { url "https://oss.sonatype.org/content/groups/public/" }
}

allprojects {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}

archivesBaseName = "java-sdk-test-service"

application {
mainClassName = "sdktest.TestService"
}

ext.versions = [
"gson": "2.7",
"logback": "1.1.3",
"okhttp": "4.5.0",
"testHelpers": "1.1.0"
]

configurations {
deps.extendsFrom(implementation)
}

dependencies {
implementation project(":sdk")
implementation "ch.qos.logback:logback-classic:${versions.logback}"
implementation "com.google.code.gson:gson:${versions.gson}"
implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}"
implementation "com.launchdarkly:test-helpers:${versions.testHelpers}"
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package sdktest;

import com.launchdarkly.sdk.server.interfaces.BigSegmentStore;
import com.launchdarkly.sdk.server.interfaces.BigSegmentStoreFactory;
import com.launchdarkly.sdk.server.interfaces.BigSegmentStoreTypes.Membership;
import com.launchdarkly.sdk.server.interfaces.BigSegmentStoreTypes.StoreMetadata;
import com.launchdarkly.sdk.server.interfaces.ClientContext;

import java.io.IOException;

import sdktest.CallbackRepresentations.BigSegmentStoreGetMembershipParams;
import sdktest.CallbackRepresentations.BigSegmentStoreGetMembershipResponse;
import sdktest.CallbackRepresentations.BigSegmentStoreGetMetadataResponse;

public class BigSegmentStoreFixture implements BigSegmentStore, BigSegmentStoreFactory {
private final CallbackService service;

public BigSegmentStoreFixture(CallbackService service) {
this.service = service;
}

@Override
public void close() throws IOException {
service.close();
}

@Override
public Membership getMembership(String userHash) {
BigSegmentStoreGetMembershipParams params = new BigSegmentStoreGetMembershipParams();
params.userHash = userHash;
BigSegmentStoreGetMembershipResponse resp =
service.post("/getMembership", params, BigSegmentStoreGetMembershipResponse.class);
return new Membership() {
@Override
public Boolean checkMembership(String segmentRef) {
return resp.values == null ? null : resp.values.get(segmentRef);
}
};
}

@Override
public StoreMetadata getMetadata() {
BigSegmentStoreGetMetadataResponse resp =
service.post("/getMetadata", null, BigSegmentStoreGetMetadataResponse.class);
return new StoreMetadata(resp.lastUpToDate);
}

@Override
public BigSegmentStore createBigSegmentStore(ClientContext context) {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package sdktest;

import java.util.Map;

public abstract class CallbackRepresentations {
public static class BigSegmentStoreGetMetadataResponse {
Long lastUpToDate;
}

public static class BigSegmentStoreGetMembershipParams {
String userHash;
}

public static class BigSegmentStoreGetMembershipResponse {
Map<String, Boolean> values;
}
}
57 changes: 57 additions & 0 deletions contract-tests/service/src/main/java/sdktest/CallbackService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package sdktest;

import java.net.URI;

import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class CallbackService {
private final URI baseUri;

public CallbackService(URI baseUri) {
this.baseUri = baseUri;
}

public void close() {
try {
Request request = new Request.Builder().url(baseUri.toURL()).method("DELETE", null).build();
Response response = TestService.client.newCall(request).execute();
assertOk(response, "");
} catch (Exception e) {
throw new RuntimeException(e); // all errors are unexpected here
}
}

public <T> T post(String path, Object params, Class<T> responseClass) {
try {
String uri = baseUri.toString() + path;
RequestBody body = RequestBody.create(
TestService.gson.toJson(params == null ? "{}" : params),
MediaType.parse("application/json"));
Request request = new Request.Builder().url(uri).
method("POST", body).build();
Response response = TestService.client.newCall(request).execute();
assertOk(response, path);
if (responseClass == null) {
return null;
}
return TestService.gson.fromJson(response.body().string(), responseClass);
} catch (Exception e) {
throw new RuntimeException(e); // all errors are unexpected here
}
}

private void assertOk(Response response, String path) {
if (!response.isSuccessful()) {
String body = "";
if (response.body() != null) {
try {
body = ": " + response.body().string();
} catch (Exception e) {}
}
throw new RuntimeException("HTTP error " + response.code() + " from callback to " + baseUri + path + body);
}
}
}
Loading

0 comments on commit 929274e

Please sign in to comment.