Skip to content

Commit 2191111

Browse files
authored
Feat: Test SDK Client relays (Android, ios, etc.) with the common test runner (#69)
* prep for client mode, extract SDK relay interface * update docs
1 parent 7db4631 commit 2191111

16 files changed

+631
-95
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
Dockerfile
3+
test-data

package-testing/sdk-test-runner/README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,47 @@ docker run \
2626
SDK_NAME=eppo/php-sdk yarn dev
2727
```
2828

29+
### Client SDK Mode
30+
31+
TODO: Update this section when client testing is available at the test-sdk.sh level (requires build out of custom client build solution).
32+
33+
Limited support is currently available for testing client SDKs. To test an SDK Client Relay, start an API server, start the test runner in client mode, then start up the SDK client.
34+
35+
```shell
36+
docker run \
37+
--rm -d \
38+
-v ./test-data:/app/test-data \
39+
-p 5000:5000 \
40+
-t Eppo-exp/test-api-server:local
41+
42+
../<SDK_DIR>/build-and-run.sh
43+
44+
SDK_NAME=android yarn dev --type=client
45+
46+
# Start client application to auto-connect
47+
```
48+
49+
Or, use the latest docker image of the test runner
50+
51+
```shell
52+
53+
docker run \
54+
--rm \
55+
--name test-runner \
56+
-e SDK_NAME=android \
57+
-p 3000:3000 \
58+
-v ./test-data:/app/test-data:ro \
59+
-t Eppo-exp/sdk-test-runner \
60+
--type=client
61+
62+
```
63+
64+
Once the Client application conencts to the test-runner, it will proceed to send test cases over the established `socket.io` connection.
65+
2966
#### Command line arguments
3067

3168
`--junit=<filepath>` records results in junit xml format to specified file
69+
`--type=<"client"|"server">` SDK relay testing mode. Default: `server`
3270

3371
#### Test Runner Configuration
3472

@@ -54,6 +92,7 @@ The following env variable can be set when running the `test-sdk.sh` script
5492
The following components are required to use the the package test runner with a new SDK
5593

5694
1. An **SDK relay server**. This is a REST server running at `localhost:4000` resonding to the [Asssignment and Bandit Request API](#sdk-relay-server)
95+
1. OR, an **SDK relay client**. This is a client application that connects to the SDK test runner via `socket.io` and responses to [Assignment requests](#sdk-relay-client)
5796
2. A `build-and-run.sh` file which, given a properly configured environment, [builds the SDK Relay Server application](#build-and-runsh) **using the specified version of the SDK package**.
5897

5998
The following are key components derived from above which allow for convenient and consistent dev-ops.
@@ -66,6 +105,75 @@ Finally, these are the advanced items to integrate the new package test into our
66105
1. Github Action to run test configured for SDK (TODO: Create example)
67106
2. Github workflows (in SDK repository and `sdk-test-data` repository) to run the test. (TODO: create example)
68107

108+
### SDK Relay Client
109+
110+
This is a client application which connects to the test runner via `socket.io` and waits for assignment requests ("client" SDKs do not yet support bandits). The interface for assignment request and responses is the same as the server API detailed below, with the exception that requests will be sent to a `socket.io` channel instead of via HTTP POST. The SDK Relay client sends a `READY` message to the test runner and then listens for requests under the same paths as the SDK Server API. See the example below from the Android relay.
111+
112+
```java
113+
114+
// Some code omitted; see repo for full implementation
115+
116+
mSocket.on("/sdk/reset", onSdkReset);
117+
mSocket.on("/flags/v1/assignment", onNewAssignment); // Same path as server request.
118+
119+
private void sendReady() {
120+
mSocket.emit(
121+
"READY",
122+
new String[] {READY_PACKET},
123+
(ackArgs) -> {
124+
Log.d(TAG, "Ready message ack'd");
125+
});
126+
}
127+
128+
private final Emitter.Listener onNewAssignment =
129+
args ->
130+
runOnUiThread(
131+
() -> {
132+
// Ack function for responding to the server.
133+
Ack ack = (Ack) args[args.length - 1];
134+
135+
AssignmentRequest assignmentRequest;
136+
try {
137+
assignmentRequest =
138+
objectMapper.readValue(args[0].toString(), AssignmentRequest.class);
139+
140+
EppoClient client = EppoClient.getInstance();
141+
142+
// Convert the subject attributes map to an `Attributes` instance.
143+
Attributes subject = convertAttributesMapToAttributes(assignmentRequest);
144+
145+
// Wrapper to get call SDK function by `assignmentType`.
146+
Object result = getResult(assignmentRequest, client, subject);
147+
148+
TestResponse testResponse = new TestResponse(result);
149+
150+
// "return" the result.
151+
ack.call(objectMapper.writeValueAsString(testResponse));
152+
} catch (JsonProcessingException e) {
153+
ack.call(genericErrorResponse());
154+
throw new RuntimeException(e);
155+
}
156+
});
157+
158+
159+
@NonNull private Object getResult(
160+
AssignmentRequest assignmentRequest, EppoClient client, Attributes subject)
161+
throws JsonProcessingException {
162+
switch (assignmentRequest.assignmentType) {
163+
case "STRING":
164+
return client.getStringAssignment(
165+
assignmentRequest.flag,
166+
assignmentRequest.subjectKey,
167+
subject,
168+
(String) assignmentRequest.defaultValue);
169+
170+
case "INTEGER":
171+
// etc.
172+
}
173+
}
174+
175+
```
176+
69177
### SDK Relay Server
70178

71179
The test runner sends assignment and bandit action requests to the SDK Relay Server which calls `EppoClient` and returns the results to the test runner. The paths and data packets are outlined below in [API](#api). Environment variables set the host and port for the Relay Server to listen on as well as the Eppo API server and port (for `EppoClient` initialization). For development of the SDK Relay server, start a local copy of the [Test API Server](../testing-api/) to serve the flag/bandit configuration, then use this handy [Postman workspace](https://www.postman.com/material-meteorologist-42730907/typotter-eppo/collection/5bjhdzy/relay-server-testing?action=share&creator=38014089) to issue requests to the relay server without having to blast it with the test runner.

package-testing/sdk-test-runner/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sdk-test-runner",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Test runner for SDK package testing",
55
"main": "src/app.ts",
66
"repository": "https://github.com/Eppo-exp/sdk-test-data",
@@ -20,9 +20,11 @@
2020
"axios": "^1.7.7",
2121
"chalk": "^4",
2222
"dotenv": "^16.4.5",
23+
"http": "^0.0.1-security",
2324
"junit-xml": "^1.2.0",
2425
"lodash": "^4.17.21",
2526
"minimist": "^1.2.8",
27+
"socket.io": "^4.8.0",
2628
"typescript": "^4.4.4"
2729
},
2830
"devDependencies": {

0 commit comments

Comments
 (0)